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 7434 0.0 %
Date: 2024-04-01 19:00:53 Functions: 0 285 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 5962 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_common.h>
      12                 :            : #include <rte_ether.h>
      13                 :            : #include <ethdev_driver.h>
      14                 :            : #include <rte_flow.h>
      15                 :            : #include <rte_flow_driver.h>
      16                 :            : #include <rte_malloc.h>
      17                 :            : #include <rte_cycles.h>
      18                 :            : #include <bus_pci_driver.h>
      19                 :            : #include <rte_ip.h>
      20                 :            : #include <rte_gre.h>
      21                 :            : #include <rte_vxlan.h>
      22                 :            : #include <rte_gtp.h>
      23                 :            : #include <rte_eal_paging.h>
      24                 :            : #include <rte_mpls.h>
      25                 :            : #include <rte_mtr.h>
      26                 :            : #include <rte_mtr_driver.h>
      27                 :            : #include <rte_tailq.h>
      28                 :            : 
      29                 :            : #include <mlx5_glue.h>
      30                 :            : #include <mlx5_devx_cmds.h>
      31                 :            : #include <mlx5_prm.h>
      32                 :            : #include <mlx5_malloc.h>
      33                 :            : 
      34                 :            : #include "mlx5_defs.h"
      35                 :            : #include "mlx5.h"
      36                 :            : #include "mlx5_common_os.h"
      37                 :            : #include "mlx5_flow.h"
      38                 :            : #include "mlx5_flow_os.h"
      39                 :            : #include "mlx5_rx.h"
      40                 :            : #include "mlx5_tx.h"
      41                 :            : #include "rte_pmd_mlx5.h"
      42                 :            : 
      43                 :            : #if defined(HAVE_IBV_FLOW_DV_SUPPORT) || !defined(HAVE_INFINIBAND_VERBS_H)
      44                 :            : 
      45                 :            : #ifndef HAVE_IBV_FLOW_DEVX_COUNTERS
      46                 :            : #define MLX5DV_FLOW_ACTION_COUNTERS_DEVX 0
      47                 :            : #endif
      48                 :            : 
      49                 :            : #ifndef HAVE_MLX5DV_DR_ESWITCH
      50                 :            : #ifndef MLX5DV_FLOW_TABLE_TYPE_FDB
      51                 :            : #define MLX5DV_FLOW_TABLE_TYPE_FDB 0
      52                 :            : #endif
      53                 :            : #endif
      54                 :            : 
      55                 :            : #ifndef HAVE_MLX5DV_DR
      56                 :            : #define MLX5DV_DR_ACTION_FLAGS_ROOT_LEVEL 1
      57                 :            : #endif
      58                 :            : 
      59                 :            : /* VLAN header definitions */
      60                 :            : #define MLX5DV_FLOW_VLAN_PCP_SHIFT 13
      61                 :            : #define MLX5DV_FLOW_VLAN_PCP_MASK (0x7 << MLX5DV_FLOW_VLAN_PCP_SHIFT)
      62                 :            : #define MLX5DV_FLOW_VLAN_VID_MASK 0x0fff
      63                 :            : #define MLX5DV_FLOW_VLAN_PCP_MASK_BE RTE_BE16(MLX5DV_FLOW_VLAN_PCP_MASK)
      64                 :            : #define MLX5DV_FLOW_VLAN_VID_MASK_BE RTE_BE16(MLX5DV_FLOW_VLAN_VID_MASK)
      65                 :            : 
      66                 :            : #define MLX5_ITEM_VALID(item, key_type) \
      67                 :            :         (((MLX5_SET_MATCHER_SW & (key_type)) && !((item)->spec)) || \
      68                 :            :          ((MLX5_SET_MATCHER_HS_V == (key_type)) && !((item)->spec)) || \
      69                 :            :          ((MLX5_SET_MATCHER_HS_M == (key_type)) && !((item)->mask)))
      70                 :            : 
      71                 :            : #define MLX5_ITEM_UPDATE(item, key_type, v, m, gm) \
      72                 :            :         do { \
      73                 :            :                 if ((key_type) == MLX5_SET_MATCHER_SW_V) { \
      74                 :            :                         v = (item)->spec; \
      75                 :            :                         m = (item)->mask ? (item)->mask : (gm); \
      76                 :            :                 } else if ((key_type) == MLX5_SET_MATCHER_HS_V) { \
      77                 :            :                         v = (item)->spec; \
      78                 :            :                         m = (v); \
      79                 :            :                 } else { \
      80                 :            :                         v = (item)->mask ? (item)->mask : (gm); \
      81                 :            :                         m = (v); \
      82                 :            :                 } \
      83                 :            :         } while (0)
      84                 :            : 
      85                 :            : #define CALC_MODI_ID(field, level) \
      86                 :            :         (((level) > 1) ? MLX5_MODI_IN_##field : MLX5_MODI_OUT_##field)
      87                 :            : 
      88                 :            : union flow_dv_attr {
      89                 :            :         struct {
      90                 :            :                 uint32_t valid:1;
      91                 :            :                 uint32_t ipv4:1;
      92                 :            :                 uint32_t ipv6:1;
      93                 :            :                 uint32_t tcp:1;
      94                 :            :                 uint32_t udp:1;
      95                 :            :                 uint32_t reserved:27;
      96                 :            :         };
      97                 :            :         uint32_t attr;
      98                 :            : };
      99                 :            : 
     100                 :            : static int
     101                 :            : flow_dv_encap_decap_resource_release(struct rte_eth_dev *dev,
     102                 :            :                                      uint32_t encap_decap_idx);
     103                 :            : 
     104                 :            : static int
     105                 :            : flow_dv_port_id_action_resource_release(struct rte_eth_dev *dev,
     106                 :            :                                         uint32_t port_id);
     107                 :            : static void
     108                 :            : flow_dv_shared_rss_action_release(struct rte_eth_dev *dev, uint32_t srss);
     109                 :            : 
     110                 :            : static int
     111                 :            : flow_dv_jump_tbl_resource_release(struct rte_eth_dev *dev,
     112                 :            :                                   uint32_t rix_jump);
     113                 :            : 
     114                 :            : /**
     115                 :            :  * Initialize flow attributes structure according to flow items' types.
     116                 :            :  *
     117                 :            :  * flow_dv_validate() avoids multiple L3/L4 layers cases other than tunnel
     118                 :            :  * mode. For tunnel mode, the items to be modified are the outermost ones.
     119                 :            :  *
     120                 :            :  * @param[in] item
     121                 :            :  *   Pointer to item specification.
     122                 :            :  * @param[out] attr
     123                 :            :  *   Pointer to flow attributes structure.
     124                 :            :  * @param[in] dev_flow
     125                 :            :  *   Pointer to the sub flow.
     126                 :            :  * @param[in] tunnel_decap
     127                 :            :  *   Whether action is after tunnel decapsulation.
     128                 :            :  */
     129                 :            : static void
     130                 :          0 : flow_dv_attr_init(const struct rte_flow_item *item, union flow_dv_attr *attr,
     131                 :            :                   struct mlx5_flow *dev_flow, bool tunnel_decap)
     132                 :            : {
     133                 :          0 :         uint64_t layers = dev_flow->handle->layers;
     134                 :            :         bool tunnel_match = false;
     135                 :            : 
     136                 :            :         /*
     137                 :            :          * If layers is already initialized, it means this dev_flow is the
     138                 :            :          * suffix flow, the layers flags is set by the prefix flow. Need to
     139                 :            :          * use the layer flags from prefix flow as the suffix flow may not
     140                 :            :          * have the user defined items as the flow is split.
     141                 :            :          */
     142         [ #  # ]:          0 :         if (layers) {
     143         [ #  # ]:          0 :                 if (tunnel_decap) {
     144                 :            :                         /*
     145                 :            :                          * If decap action before modify, it means the driver
     146                 :            :                          * should take the inner as outer for the modify actions.
     147                 :            :                          */
     148                 :          0 :                         layers = ((layers >> 6) & MLX5_FLOW_LAYER_OUTER);
     149                 :            :                 }
     150         [ #  # ]:          0 :                 if (layers & MLX5_FLOW_LAYER_OUTER_L3_IPV4)
     151                 :          0 :                         attr->ipv4 = 1;
     152         [ #  # ]:          0 :                 else if (layers & MLX5_FLOW_LAYER_OUTER_L3_IPV6)
     153                 :          0 :                         attr->ipv6 = 1;
     154         [ #  # ]:          0 :                 if (layers & MLX5_FLOW_LAYER_OUTER_L4_TCP)
     155                 :          0 :                         attr->tcp = 1;
     156         [ #  # ]:          0 :                 else if (layers & MLX5_FLOW_LAYER_OUTER_L4_UDP)
     157                 :          0 :                         attr->udp = 1;
     158                 :          0 :                 attr->valid = 1;
     159                 :          0 :                 return;
     160                 :            :         }
     161         [ #  # ]:          0 :         for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
     162                 :            :                 uint8_t next_protocol = 0xff;
     163   [ #  #  #  #  :          0 :                 switch (item->type) {
                   #  # ]
     164                 :          0 :                 case RTE_FLOW_ITEM_TYPE_GRE:
     165                 :            :                 case RTE_FLOW_ITEM_TYPE_NVGRE:
     166                 :            :                 case RTE_FLOW_ITEM_TYPE_VXLAN:
     167                 :            :                 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
     168                 :            :                 case RTE_FLOW_ITEM_TYPE_GENEVE:
     169                 :            :                 case RTE_FLOW_ITEM_TYPE_MPLS:
     170                 :            :                 case RTE_FLOW_ITEM_TYPE_GTP:
     171         [ #  # ]:          0 :                         if (tunnel_decap) {
     172                 :          0 :                                 attr->attr = 0;
     173                 :            :                                 tunnel_match = true;
     174                 :            :                         }
     175                 :            :                         break;
     176                 :          0 :                 case RTE_FLOW_ITEM_TYPE_IPV4:
     177         [ #  # ]:          0 :                         if (!attr->ipv6)
     178                 :          0 :                                 attr->ipv4 = 1;
     179         [ #  # ]:          0 :                         if (item->mask != NULL &&
     180                 :            :                             ((const struct rte_flow_item_ipv4 *)
     181         [ #  # ]:          0 :                             item->mask)->hdr.next_proto_id)
     182                 :          0 :                                 next_protocol =
     183                 :            :                                     ((const struct rte_flow_item_ipv4 *)
     184                 :          0 :                                       (item->spec))->hdr.next_proto_id &
     185                 :            :                                     ((const struct rte_flow_item_ipv4 *)
     186                 :            :                                       (item->mask))->hdr.next_proto_id;
     187                 :          0 :                         if ((next_protocol == IPPROTO_IPIP ||
     188         [ #  # ]:          0 :                             next_protocol == IPPROTO_IPV6) && tunnel_decap &&
     189         [ #  # ]:          0 :                             !tunnel_match)
     190                 :          0 :                                 attr->attr = 0;
     191                 :            :                         break;
     192                 :          0 :                 case RTE_FLOW_ITEM_TYPE_IPV6:
     193         [ #  # ]:          0 :                         if (!attr->ipv4)
     194                 :          0 :                                 attr->ipv6 = 1;
     195         [ #  # ]:          0 :                         if (item->mask != NULL &&
     196                 :            :                             ((const struct rte_flow_item_ipv6 *)
     197         [ #  # ]:          0 :                             item->mask)->hdr.proto)
     198                 :          0 :                                 next_protocol =
     199                 :            :                                     ((const struct rte_flow_item_ipv6 *)
     200                 :          0 :                                       (item->spec))->hdr.proto &
     201                 :            :                                     ((const struct rte_flow_item_ipv6 *)
     202                 :            :                                       (item->mask))->hdr.proto;
     203                 :          0 :                         if ((next_protocol == IPPROTO_IPIP ||
     204         [ #  # ]:          0 :                             next_protocol == IPPROTO_IPV6) && tunnel_decap &&
     205         [ #  # ]:          0 :                             !tunnel_match)
     206                 :          0 :                                 attr->attr = 0;
     207                 :            :                         break;
     208                 :          0 :                 case RTE_FLOW_ITEM_TYPE_UDP:
     209         [ #  # ]:          0 :                         if (!attr->tcp)
     210                 :          0 :                                 attr->udp = 1;
     211                 :            :                         break;
     212                 :          0 :                 case RTE_FLOW_ITEM_TYPE_TCP:
     213         [ #  # ]:          0 :                         if (!attr->udp)
     214                 :          0 :                                 attr->tcp = 1;
     215                 :            :                         break;
     216                 :            :                 default:
     217                 :            :                         break;
     218                 :            :                 }
     219                 :            :         }
     220                 :          0 :         attr->valid = 1;
     221                 :            : }
     222                 :            : 
     223                 :            : struct field_modify_info modify_eth[] = {
     224                 :            :         {4,  0, MLX5_MODI_OUT_DMAC_47_16},
     225                 :            :         {2,  4, MLX5_MODI_OUT_DMAC_15_0},
     226                 :            :         {4,  6, MLX5_MODI_OUT_SMAC_47_16},
     227                 :            :         {2, 10, MLX5_MODI_OUT_SMAC_15_0},
     228                 :            :         {0, 0, 0},
     229                 :            : };
     230                 :            : 
     231                 :            : struct field_modify_info modify_vlan_out_first_vid[] = {
     232                 :            :         /* Size in bits !!! */
     233                 :            :         {12, 0, MLX5_MODI_OUT_FIRST_VID},
     234                 :            :         {0, 0, 0},
     235                 :            : };
     236                 :            : 
     237                 :            : struct field_modify_info modify_ipv4[] = {
     238                 :            :         {1,  1, MLX5_MODI_OUT_IP_DSCP},
     239                 :            :         {1,  8, MLX5_MODI_OUT_IPV4_TTL},
     240                 :            :         {4, 12, MLX5_MODI_OUT_SIPV4},
     241                 :            :         {4, 16, MLX5_MODI_OUT_DIPV4},
     242                 :            :         {0, 0, 0},
     243                 :            : };
     244                 :            : 
     245                 :            : struct field_modify_info modify_ipv6[] = {
     246                 :            :         {1,  0, MLX5_MODI_OUT_IP_DSCP},
     247                 :            :         {1,  7, MLX5_MODI_OUT_IPV6_HOPLIMIT},
     248                 :            :         {4,  8, MLX5_MODI_OUT_SIPV6_127_96},
     249                 :            :         {4, 12, MLX5_MODI_OUT_SIPV6_95_64},
     250                 :            :         {4, 16, MLX5_MODI_OUT_SIPV6_63_32},
     251                 :            :         {4, 20, MLX5_MODI_OUT_SIPV6_31_0},
     252                 :            :         {4, 24, MLX5_MODI_OUT_DIPV6_127_96},
     253                 :            :         {4, 28, MLX5_MODI_OUT_DIPV6_95_64},
     254                 :            :         {4, 32, MLX5_MODI_OUT_DIPV6_63_32},
     255                 :            :         {4, 36, MLX5_MODI_OUT_DIPV6_31_0},
     256                 :            :         {0, 0, 0},
     257                 :            : };
     258                 :            : 
     259                 :            : struct field_modify_info modify_ipv6_traffic_class[] = {
     260                 :            :         {1,  0, MLX5_MODI_OUT_IPV6_TRAFFIC_CLASS},
     261                 :            :         {0, 0, 0},
     262                 :            : };
     263                 :            : 
     264                 :            : struct field_modify_info modify_udp[] = {
     265                 :            :         {2, 0, MLX5_MODI_OUT_UDP_SPORT},
     266                 :            :         {2, 2, MLX5_MODI_OUT_UDP_DPORT},
     267                 :            :         {0, 0, 0},
     268                 :            : };
     269                 :            : 
     270                 :            : struct field_modify_info modify_tcp[] = {
     271                 :            :         {2, 0, MLX5_MODI_OUT_TCP_SPORT},
     272                 :            :         {2, 2, MLX5_MODI_OUT_TCP_DPORT},
     273                 :            :         {4, 4, MLX5_MODI_OUT_TCP_SEQ_NUM},
     274                 :            :         {4, 8, MLX5_MODI_OUT_TCP_ACK_NUM},
     275                 :            :         {0, 0, 0},
     276                 :            : };
     277                 :            : 
     278                 :            : enum mlx5_l3_tunnel_detection {
     279                 :            :         l3_tunnel_none,
     280                 :            :         l3_tunnel_outer,
     281                 :            :         l3_tunnel_inner
     282                 :            : };
     283                 :            : 
     284                 :            : static enum mlx5_l3_tunnel_detection
     285                 :            : mlx5_flow_tunnel_ip_check(const struct rte_flow_item *item __rte_unused,
     286                 :            :                           uint8_t next_protocol, uint64_t item_flags,
     287                 :            :                           uint64_t *l3_tunnel_flag)
     288                 :            : {
     289                 :            :         enum mlx5_l3_tunnel_detection td = l3_tunnel_none;
     290                 :            : 
     291                 :            :         MLX5_ASSERT(item->type == RTE_FLOW_ITEM_TYPE_IPV4 ||
     292                 :            :                     item->type == RTE_FLOW_ITEM_TYPE_IPV6);
     293   [ #  #  #  #  :          0 :         if ((item_flags & MLX5_FLOW_LAYER_OUTER_L3) == 0) {
             #  #  #  # ]
     294   [ #  #  #  #  :          0 :                 switch (next_protocol) {
          #  #  #  #  #  
                #  #  # ]
     295                 :            :                 case IPPROTO_IPIP:
     296                 :            :                         td = l3_tunnel_outer;
     297                 :            :                         *l3_tunnel_flag = MLX5_FLOW_LAYER_IPIP;
     298                 :            :                         break;
     299                 :            :                 case IPPROTO_IPV6:
     300                 :            :                         td = l3_tunnel_outer;
     301                 :            :                         *l3_tunnel_flag = MLX5_FLOW_LAYER_IPV6_ENCAP;
     302                 :            :                         break;
     303                 :            :                 default:
     304                 :            :                         break;
     305                 :            :                 }
     306                 :            :         } else {
     307                 :            :                 td = l3_tunnel_inner;
     308                 :            :                 *l3_tunnel_flag = item->type == RTE_FLOW_ITEM_TYPE_IPV4 ?
     309                 :            :                                   MLX5_FLOW_LAYER_IPIP :
     310                 :            :                                   MLX5_FLOW_LAYER_IPV6_ENCAP;
     311                 :            :         }
     312                 :            :         return td;
     313                 :            : }
     314                 :            : 
     315                 :            : static inline struct mlx5_hlist *
     316                 :          0 : flow_dv_hlist_prepare(struct mlx5_dev_ctx_shared *sh, struct mlx5_hlist **phl,
     317                 :            :                      const char *name, uint32_t size, bool direct_key,
     318                 :            :                      bool lcores_share, void *ctx,
     319                 :            :                      mlx5_list_create_cb cb_create,
     320                 :            :                      mlx5_list_match_cb cb_match,
     321                 :            :                      mlx5_list_remove_cb cb_remove,
     322                 :            :                      mlx5_list_clone_cb cb_clone,
     323                 :            :                      mlx5_list_clone_free_cb cb_clone_free,
     324                 :            :                      struct rte_flow_error *error)
     325                 :            : {
     326                 :            :         struct mlx5_hlist *hl;
     327                 :            :         struct mlx5_hlist *expected = NULL;
     328                 :            :         char s[MLX5_NAME_SIZE];
     329                 :            : 
     330                 :          0 :         hl = __atomic_load_n(phl, __ATOMIC_SEQ_CST);
     331         [ #  # ]:          0 :         if (likely(hl))
     332                 :            :                 return hl;
     333                 :          0 :         snprintf(s, sizeof(s), "%s_%s", sh->ibdev_name, name);
     334                 :          0 :         hl = mlx5_hlist_create(s, size, direct_key, lcores_share,
     335                 :            :                         ctx, cb_create, cb_match, cb_remove, cb_clone,
     336                 :            :                         cb_clone_free);
     337         [ #  # ]:          0 :         if (!hl) {
     338                 :          0 :                 DRV_LOG(ERR, "%s hash creation failed", name);
     339                 :          0 :                 rte_flow_error_set(error, ENOMEM,
     340                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
     341                 :            :                                    "cannot allocate resource memory");
     342                 :          0 :                 return NULL;
     343                 :            :         }
     344         [ #  # ]:          0 :         if (!__atomic_compare_exchange_n(phl, &expected, hl, false,
     345                 :            :                                          __ATOMIC_SEQ_CST,
     346                 :            :                                          __ATOMIC_SEQ_CST)) {
     347                 :          0 :                 mlx5_hlist_destroy(hl);
     348                 :          0 :                 hl = __atomic_load_n(phl, __ATOMIC_SEQ_CST);
     349                 :            :         }
     350                 :            :         return hl;
     351                 :            : }
     352                 :            : 
     353                 :            : /* Update VLAN's VID/PCP based on input rte_flow_action.
     354                 :            :  *
     355                 :            :  * @param[in] action
     356                 :            :  *   Pointer to struct rte_flow_action.
     357                 :            :  * @param[out] vlan
     358                 :            :  *   Pointer to struct rte_vlan_hdr.
     359                 :            :  */
     360                 :            : static void
     361                 :          0 : mlx5_update_vlan_vid_pcp(const struct rte_flow_action *action,
     362                 :            :                          struct rte_vlan_hdr *vlan)
     363                 :            : {
     364                 :            :         uint16_t vlan_tci;
     365         [ #  # ]:          0 :         if (action->type == RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP) {
     366                 :          0 :                 vlan_tci =
     367                 :            :                     ((const struct rte_flow_action_of_set_vlan_pcp *)
     368                 :          0 :                                                action->conf)->vlan_pcp;
     369                 :          0 :                 vlan_tci = vlan_tci << MLX5DV_FLOW_VLAN_PCP_SHIFT;
     370                 :          0 :                 vlan->vlan_tci &= ~MLX5DV_FLOW_VLAN_PCP_MASK;
     371                 :          0 :                 vlan->vlan_tci |= vlan_tci;
     372         [ #  # ]:          0 :         } else if (action->type == RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID) {
     373                 :          0 :                 vlan->vlan_tci &= ~MLX5DV_FLOW_VLAN_VID_MASK;
     374         [ #  # ]:          0 :                 vlan->vlan_tci |= rte_be_to_cpu_16
     375                 :            :                     (((const struct rte_flow_action_of_set_vlan_vid *)
     376                 :            :                                              action->conf)->vlan_vid);
     377                 :            :         }
     378                 :          0 : }
     379                 :            : 
     380                 :            : /**
     381                 :            :  * Convert modify-header action to DV specification.
     382                 :            :  *
     383                 :            :  * Data length of each action is determined by provided field description
     384                 :            :  * and the item mask. Data bit offset and width of each action is determined
     385                 :            :  * by provided item mask.
     386                 :            :  *
     387                 :            :  * @param[in] item
     388                 :            :  *   Pointer to item specification.
     389                 :            :  * @param[in] field
     390                 :            :  *   Pointer to field modification information.
     391                 :            :  *     For MLX5_MODIFICATION_TYPE_SET specifies destination field.
     392                 :            :  *     For MLX5_MODIFICATION_TYPE_ADD specifies destination field.
     393                 :            :  *     For MLX5_MODIFICATION_TYPE_COPY specifies source field.
     394                 :            :  *     For MLX5_MODIFICATION_TYPE_ADD_FIELD specifies source field.
     395                 :            :  * @param[in] dest
     396                 :            :  *   Destination field info for MLX5_MODIFICATION_TYPE_COPY and
     397                 :            :  *   MLX5_MODIFICATION_TYPE_ADD_FIELD in @type.
     398                 :            :  *   Negative offset value sets the same offset as source offset.
     399                 :            :  *   size field is ignored, value is taken from source field.
     400                 :            :  * @param[in,out] resource
     401                 :            :  *   Pointer to the modify-header resource.
     402                 :            :  * @param[in] type
     403                 :            :  *   Type of modification.
     404                 :            :  * @param[out] error
     405                 :            :  *   Pointer to the error structure.
     406                 :            :  *
     407                 :            :  * @return
     408                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
     409                 :            :  */
     410                 :            : int
     411                 :          0 : flow_dv_convert_modify_action(struct rte_flow_item *item,
     412                 :            :                               struct field_modify_info *field,
     413                 :            :                               struct field_modify_info *dest,
     414                 :            :                               struct mlx5_flow_dv_modify_hdr_resource *resource,
     415                 :            :                               uint32_t type, struct rte_flow_error *error)
     416                 :            : {
     417                 :          0 :         uint32_t i = resource->actions_num;
     418                 :          0 :         struct mlx5_modification_cmd *actions = resource->actions;
     419                 :            :         uint32_t carry_b = 0;
     420                 :            :         bool to_dest;
     421                 :            : 
     422                 :            :         /*
     423                 :            :          * The item and mask are provided in big-endian format.
     424                 :            :          * The fields should be presented as in big-endian format either.
     425                 :            :          * Mask must be always present, it defines the actual field width.
     426                 :            :          */
     427                 :            :         MLX5_ASSERT(item->mask);
     428                 :            :         MLX5_ASSERT(field->size);
     429                 :          0 :         to_dest = type == MLX5_MODIFICATION_TYPE_COPY ||
     430                 :          0 :                   type == MLX5_MODIFICATION_TYPE_ADD_FIELD;
     431                 :            :         do {
     432                 :            :                 uint32_t size_b;
     433                 :            :                 uint32_t off_b;
     434                 :            :                 uint32_t mask;
     435                 :            :                 uint32_t data;
     436                 :            :                 bool next_field = true;
     437                 :            :                 bool next_dest = true;
     438                 :            : 
     439         [ #  # ]:          0 :                 if (i >= MLX5_MAX_MODIFY_NUM)
     440                 :          0 :                         return rte_flow_error_set(error, EINVAL,
     441                 :            :                                  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
     442                 :            :                                  "too many items to modify");
     443                 :            :                 /* Fetch variable byte size mask from the array. */
     444                 :          0 :                 mask = flow_dv_fetch_field((const uint8_t *)item->mask +
     445                 :          0 :                                            field->offset, field->size);
     446         [ #  # ]:          0 :                 if (!mask) {
     447                 :          0 :                         ++field;
     448                 :            :                         continue;
     449                 :            :                 }
     450   [ #  #  #  # ]:          0 :                 if (to_dest && field->is_flex) {
     451                 :          0 :                         off_b = 32 - field->shift + carry_b - field->size * CHAR_BIT;
     452                 :          0 :                         size_b = field->size * CHAR_BIT - carry_b;
     453                 :            :                 } else {
     454                 :            :                         /* Deduce actual data width in bits from mask value. */
     455                 :          0 :                         off_b = rte_bsf32(mask) + carry_b;
     456                 :          0 :                         size_b = sizeof(uint32_t) * CHAR_BIT -
     457                 :          0 :                                  off_b - rte_clz32(mask);
     458                 :            :                 }
     459                 :            :                 MLX5_ASSERT(size_b);
     460                 :          0 :                 actions[i] = (struct mlx5_modification_cmd) {
     461                 :            :                         .action_type = type,
     462                 :          0 :                         .field = field->id,
     463                 :            :                         .offset = off_b,
     464                 :            :                         .length = (size_b == sizeof(uint32_t) * CHAR_BIT) ?
     465         [ #  # ]:          0 :                                 0 : size_b,
     466                 :            :                 };
     467         [ #  # ]:          0 :                 if (to_dest) {
     468                 :            :                         MLX5_ASSERT(dest);
     469                 :          0 :                         actions[i].dst_field = dest->id;
     470                 :          0 :                         actions[i].dst_offset =
     471         [ #  # ]:          0 :                                 (int)dest->offset < 0 ? off_b : dest->offset;
     472                 :            :                         /* Convert entire record to big-endian format. */
     473         [ #  # ]:          0 :                         actions[i].data1 = rte_cpu_to_be_32(actions[i].data1);
     474                 :            :                         /*
     475                 :            :                          * Destination field overflow. Copy leftovers of
     476                 :            :                          * a source field to the next destination field.
     477                 :            :                          */
     478   [ #  #  #  # ]:          0 :                         if ((size_b > dest->size * CHAR_BIT - dest->offset) &&
     479                 :            :                             dest->size != 0) {
     480                 :          0 :                                 actions[i].length =
     481                 :          0 :                                         dest->size * CHAR_BIT - dest->offset;
     482                 :          0 :                                 carry_b += actions[i].length;
     483                 :          0 :                                 next_field = false;
     484                 :            :                         } else {
     485                 :            :                                 carry_b = 0;
     486                 :            :                         }
     487                 :            :                         /*
     488                 :            :                          * Not enough bits in a source filed to fill a
     489                 :            :                          * destination field. Switch to the next source.
     490                 :            :                          */
     491         [ #  # ]:          0 :                         if ((size_b < dest->size * CHAR_BIT - dest->offset) &&
     492         [ #  # ]:          0 :                             ((size_b == field->size * CHAR_BIT - off_b) ||
     493         [ #  # ]:          0 :                              field->is_flex)) {
     494                 :          0 :                                 actions[i].length = size_b;
     495                 :          0 :                                 dest->offset += actions[i].length;
     496                 :            :                                 next_dest = false;
     497                 :            :                         }
     498                 :            :                 } else {
     499                 :            :                         MLX5_ASSERT(item->spec);
     500                 :          0 :                         data = flow_dv_fetch_field((const uint8_t *)item->spec +
     501                 :            :                                                    field->offset, field->size);
     502                 :            :                         /* Shift out the trailing masked bits from data. */
     503                 :          0 :                         data = (data & mask) >> off_b;
     504         [ #  # ]:          0 :                         if (field->is_flex)
     505                 :          0 :                                 actions[i].offset = 32 - field->shift - field->size * CHAR_BIT;
     506         [ #  # ]:          0 :                         actions[i].data1 = rte_cpu_to_be_32(data);
     507                 :            :                 }
     508                 :            :                 /* Convert entire record to expected big-endian format. */
     509         [ #  # ]:          0 :                 actions[i].data0 = rte_cpu_to_be_32(actions[i].data0);
     510         [ #  # ]:          0 :                 if ((!to_dest ||
     511   [ #  #  #  # ]:          0 :                      dest->id != (enum mlx5_modification_field)UINT32_MAX) &&
     512                 :            :                     field->id != (enum mlx5_modification_field)UINT32_MAX)
     513                 :          0 :                         ++i;
     514         [ #  # ]:          0 :                 if (next_dest && to_dest)
     515                 :          0 :                         ++dest;
     516         [ #  # ]:          0 :                 if (next_field)
     517                 :          0 :                         ++field;
     518         [ #  # ]:          0 :         } while (field->size);
     519         [ #  # ]:          0 :         if (resource->actions_num == i)
     520                 :          0 :                 return rte_flow_error_set(error, EINVAL,
     521                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
     522                 :            :                                           "invalid modification flow item");
     523                 :          0 :         resource->actions_num = i;
     524                 :          0 :         return 0;
     525                 :            : }
     526                 :            : 
     527                 :            : /**
     528                 :            :  * Convert modify-header set IPv4 address action to DV specification.
     529                 :            :  *
     530                 :            :  * @param[in,out] resource
     531                 :            :  *   Pointer to the modify-header resource.
     532                 :            :  * @param[in] action
     533                 :            :  *   Pointer to action specification.
     534                 :            :  * @param[out] error
     535                 :            :  *   Pointer to the error structure.
     536                 :            :  *
     537                 :            :  * @return
     538                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
     539                 :            :  */
     540                 :            : static int
     541                 :          0 : flow_dv_convert_action_modify_ipv4
     542                 :            :                         (struct mlx5_flow_dv_modify_hdr_resource *resource,
     543                 :            :                          const struct rte_flow_action *action,
     544                 :            :                          struct rte_flow_error *error)
     545                 :            : {
     546                 :          0 :         const struct rte_flow_action_set_ipv4 *conf =
     547                 :            :                 (const struct rte_flow_action_set_ipv4 *)(action->conf);
     548         [ #  # ]:          0 :         struct rte_flow_item item = { .type = RTE_FLOW_ITEM_TYPE_IPV4 };
     549                 :            :         struct rte_flow_item_ipv4 ipv4;
     550                 :            :         struct rte_flow_item_ipv4 ipv4_mask;
     551                 :            : 
     552                 :            :         memset(&ipv4, 0, sizeof(ipv4));
     553                 :            :         memset(&ipv4_mask, 0, sizeof(ipv4_mask));
     554         [ #  # ]:          0 :         if (action->type == RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC) {
     555                 :          0 :                 ipv4.hdr.src_addr = conf->ipv4_addr;
     556                 :          0 :                 ipv4_mask.hdr.src_addr = rte_flow_item_ipv4_mask.hdr.src_addr;
     557                 :            :         } else {
     558                 :          0 :                 ipv4.hdr.dst_addr = conf->ipv4_addr;
     559                 :          0 :                 ipv4_mask.hdr.dst_addr = rte_flow_item_ipv4_mask.hdr.dst_addr;
     560                 :            :         }
     561                 :          0 :         item.spec = &ipv4;
     562                 :          0 :         item.mask = &ipv4_mask;
     563                 :          0 :         return flow_dv_convert_modify_action(&item, modify_ipv4, NULL, resource,
     564                 :            :                                              MLX5_MODIFICATION_TYPE_SET, error);
     565                 :            : }
     566                 :            : 
     567                 :            : /**
     568                 :            :  * Convert modify-header set IPv6 address action to DV specification.
     569                 :            :  *
     570                 :            :  * @param[in,out] resource
     571                 :            :  *   Pointer to the modify-header resource.
     572                 :            :  * @param[in] action
     573                 :            :  *   Pointer to action specification.
     574                 :            :  * @param[out] error
     575                 :            :  *   Pointer to the error structure.
     576                 :            :  *
     577                 :            :  * @return
     578                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
     579                 :            :  */
     580                 :            : static int
     581                 :          0 : flow_dv_convert_action_modify_ipv6
     582                 :            :                         (struct mlx5_flow_dv_modify_hdr_resource *resource,
     583                 :            :                          const struct rte_flow_action *action,
     584                 :            :                          struct rte_flow_error *error)
     585                 :            : {
     586                 :          0 :         const struct rte_flow_action_set_ipv6 *conf =
     587                 :            :                 (const struct rte_flow_action_set_ipv6 *)(action->conf);
     588         [ #  # ]:          0 :         struct rte_flow_item item = { .type = RTE_FLOW_ITEM_TYPE_IPV6 };
     589                 :            :         struct rte_flow_item_ipv6 ipv6;
     590                 :            :         struct rte_flow_item_ipv6 ipv6_mask;
     591                 :            : 
     592                 :            :         memset(&ipv6, 0, sizeof(ipv6));
     593                 :            :         memset(&ipv6_mask, 0, sizeof(ipv6_mask));
     594         [ #  # ]:          0 :         if (action->type == RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC) {
     595                 :            :                 memcpy(&ipv6.hdr.src_addr, &conf->ipv6_addr,
     596                 :            :                        sizeof(ipv6.hdr.src_addr));
     597                 :            :                 memcpy(&ipv6_mask.hdr.src_addr,
     598                 :            :                        &rte_flow_item_ipv6_mask.hdr.src_addr,
     599                 :            :                        sizeof(ipv6.hdr.src_addr));
     600                 :            :         } else {
     601                 :            :                 memcpy(&ipv6.hdr.dst_addr, &conf->ipv6_addr,
     602                 :            :                        sizeof(ipv6.hdr.dst_addr));
     603                 :            :                 memcpy(&ipv6_mask.hdr.dst_addr,
     604                 :            :                        &rte_flow_item_ipv6_mask.hdr.dst_addr,
     605                 :            :                        sizeof(ipv6.hdr.dst_addr));
     606                 :            :         }
     607                 :          0 :         item.spec = &ipv6;
     608                 :          0 :         item.mask = &ipv6_mask;
     609                 :          0 :         return flow_dv_convert_modify_action(&item, modify_ipv6, NULL, resource,
     610                 :            :                                              MLX5_MODIFICATION_TYPE_SET, error);
     611                 :            : }
     612                 :            : 
     613                 :            : /**
     614                 :            :  * Convert modify-header set MAC address action to DV specification.
     615                 :            :  *
     616                 :            :  * @param[in,out] resource
     617                 :            :  *   Pointer to the modify-header resource.
     618                 :            :  * @param[in] action
     619                 :            :  *   Pointer to action specification.
     620                 :            :  * @param[out] error
     621                 :            :  *   Pointer to the error structure.
     622                 :            :  *
     623                 :            :  * @return
     624                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
     625                 :            :  */
     626                 :            : static int
     627                 :          0 : flow_dv_convert_action_modify_mac
     628                 :            :                         (struct mlx5_flow_dv_modify_hdr_resource *resource,
     629                 :            :                          const struct rte_flow_action *action,
     630                 :            :                          struct rte_flow_error *error)
     631                 :            : {
     632                 :          0 :         const struct rte_flow_action_set_mac *conf =
     633                 :            :                 (const struct rte_flow_action_set_mac *)(action->conf);
     634         [ #  # ]:          0 :         struct rte_flow_item item = { .type = RTE_FLOW_ITEM_TYPE_ETH };
     635                 :            :         struct rte_flow_item_eth eth;
     636                 :            :         struct rte_flow_item_eth eth_mask;
     637                 :            : 
     638                 :            :         memset(&eth, 0, sizeof(eth));
     639                 :            :         memset(&eth_mask, 0, sizeof(eth_mask));
     640         [ #  # ]:          0 :         if (action->type == RTE_FLOW_ACTION_TYPE_SET_MAC_SRC) {
     641                 :            :                 memcpy(&eth.hdr.src_addr.addr_bytes, &conf->mac_addr,
     642                 :            :                        sizeof(eth.hdr.src_addr.addr_bytes));
     643                 :            :                 memcpy(&eth_mask.hdr.src_addr.addr_bytes,
     644                 :            :                        &rte_flow_item_eth_mask.hdr.src_addr.addr_bytes,
     645                 :            :                        sizeof(eth_mask.hdr.src_addr.addr_bytes));
     646                 :            :         } else {
     647                 :            :                 memcpy(&eth.hdr.dst_addr.addr_bytes, &conf->mac_addr,
     648                 :            :                        sizeof(eth.hdr.dst_addr.addr_bytes));
     649                 :            :                 memcpy(&eth_mask.hdr.dst_addr.addr_bytes,
     650                 :            :                        &rte_flow_item_eth_mask.hdr.dst_addr.addr_bytes,
     651                 :            :                        sizeof(eth_mask.hdr.dst_addr.addr_bytes));
     652                 :            :         }
     653                 :          0 :         item.spec = &eth;
     654                 :          0 :         item.mask = &eth_mask;
     655                 :          0 :         return flow_dv_convert_modify_action(&item, modify_eth, NULL, resource,
     656                 :            :                                              MLX5_MODIFICATION_TYPE_SET, error);
     657                 :            : }
     658                 :            : 
     659                 :            : /**
     660                 :            :  * Convert modify-header set VLAN VID action to DV specification.
     661                 :            :  *
     662                 :            :  * @param[in,out] resource
     663                 :            :  *   Pointer to the modify-header resource.
     664                 :            :  * @param[in] action
     665                 :            :  *   Pointer to action specification.
     666                 :            :  * @param[out] error
     667                 :            :  *   Pointer to the error structure.
     668                 :            :  *
     669                 :            :  * @return
     670                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
     671                 :            :  */
     672                 :            : static int
     673                 :          0 : flow_dv_convert_action_modify_vlan_vid
     674                 :            :                         (struct mlx5_flow_dv_modify_hdr_resource *resource,
     675                 :            :                          const struct rte_flow_action *action,
     676                 :            :                          struct rte_flow_error *error)
     677                 :            : {
     678                 :          0 :         const struct rte_flow_action_of_set_vlan_vid *conf =
     679                 :            :                 (const struct rte_flow_action_of_set_vlan_vid *)(action->conf);
     680                 :          0 :         int i = resource->actions_num;
     681                 :          0 :         struct mlx5_modification_cmd *actions = resource->actions;
     682                 :            :         struct field_modify_info *field = modify_vlan_out_first_vid;
     683                 :            : 
     684         [ #  # ]:          0 :         if (i >= MLX5_MAX_MODIFY_NUM)
     685                 :          0 :                 return rte_flow_error_set(error, EINVAL,
     686                 :            :                          RTE_FLOW_ERROR_TYPE_ACTION, NULL,
     687                 :            :                          "too many items to modify");
     688                 :          0 :         actions[i] = (struct mlx5_modification_cmd) {
     689                 :            :                 .action_type = MLX5_MODIFICATION_TYPE_SET,
     690                 :          0 :                 .field = field->id,
     691                 :          0 :                 .length = field->size,
     692                 :          0 :                 .offset = field->offset,
     693                 :            :         };
     694         [ #  # ]:          0 :         actions[i].data0 = rte_cpu_to_be_32(actions[i].data0);
     695                 :          0 :         actions[i].data1 = conf->vlan_vid;
     696                 :          0 :         actions[i].data1 = actions[i].data1 << 16;
     697                 :          0 :         resource->actions_num = ++i;
     698                 :          0 :         return 0;
     699                 :            : }
     700                 :            : 
     701                 :            : /**
     702                 :            :  * Convert modify-header set TP action to DV specification.
     703                 :            :  *
     704                 :            :  * @param[in,out] resource
     705                 :            :  *   Pointer to the modify-header resource.
     706                 :            :  * @param[in] action
     707                 :            :  *   Pointer to action specification.
     708                 :            :  * @param[in] items
     709                 :            :  *   Pointer to rte_flow_item objects list.
     710                 :            :  * @param[in] attr
     711                 :            :  *   Pointer to flow attributes structure.
     712                 :            :  * @param[in] dev_flow
     713                 :            :  *   Pointer to the sub flow.
     714                 :            :  * @param[in] tunnel_decap
     715                 :            :  *   Whether action is after tunnel decapsulation.
     716                 :            :  * @param[out] error
     717                 :            :  *   Pointer to the error structure.
     718                 :            :  *
     719                 :            :  * @return
     720                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
     721                 :            :  */
     722                 :            : static int
     723                 :          0 : flow_dv_convert_action_modify_tp
     724                 :            :                         (struct mlx5_flow_dv_modify_hdr_resource *resource,
     725                 :            :                          const struct rte_flow_action *action,
     726                 :            :                          const struct rte_flow_item *items,
     727                 :            :                          union flow_dv_attr *attr, struct mlx5_flow *dev_flow,
     728                 :            :                          bool tunnel_decap, struct rte_flow_error *error)
     729                 :            : {
     730                 :          0 :         const struct rte_flow_action_set_tp *conf =
     731                 :            :                 (const struct rte_flow_action_set_tp *)(action->conf);
     732                 :            :         struct rte_flow_item item;
     733                 :            :         struct rte_flow_item_udp udp;
     734                 :            :         struct rte_flow_item_udp udp_mask;
     735                 :            :         struct rte_flow_item_tcp tcp;
     736                 :            :         struct rte_flow_item_tcp tcp_mask;
     737                 :            :         struct field_modify_info *field;
     738                 :            : 
     739         [ #  # ]:          0 :         if (!attr->valid)
     740                 :          0 :                 flow_dv_attr_init(items, attr, dev_flow, tunnel_decap);
     741         [ #  # ]:          0 :         if (attr->udp) {
     742                 :            :                 memset(&udp, 0, sizeof(udp));
     743                 :            :                 memset(&udp_mask, 0, sizeof(udp_mask));
     744         [ #  # ]:          0 :                 if (action->type == RTE_FLOW_ACTION_TYPE_SET_TP_SRC) {
     745                 :          0 :                         udp.hdr.src_port = conf->port;
     746                 :          0 :                         udp_mask.hdr.src_port =
     747                 :            :                                         rte_flow_item_udp_mask.hdr.src_port;
     748                 :            :                 } else {
     749                 :          0 :                         udp.hdr.dst_port = conf->port;
     750                 :          0 :                         udp_mask.hdr.dst_port =
     751                 :            :                                         rte_flow_item_udp_mask.hdr.dst_port;
     752                 :            :                 }
     753                 :          0 :                 item.type = RTE_FLOW_ITEM_TYPE_UDP;
     754                 :          0 :                 item.spec = &udp;
     755                 :          0 :                 item.mask = &udp_mask;
     756                 :            :                 field = modify_udp;
     757                 :            :         } else {
     758                 :            :                 MLX5_ASSERT(attr->tcp);
     759                 :            :                 memset(&tcp, 0, sizeof(tcp));
     760                 :            :                 memset(&tcp_mask, 0, sizeof(tcp_mask));
     761         [ #  # ]:          0 :                 if (action->type == RTE_FLOW_ACTION_TYPE_SET_TP_SRC) {
     762                 :          0 :                         tcp.hdr.src_port = conf->port;
     763                 :          0 :                         tcp_mask.hdr.src_port =
     764                 :            :                                         rte_flow_item_tcp_mask.hdr.src_port;
     765                 :            :                 } else {
     766                 :          0 :                         tcp.hdr.dst_port = conf->port;
     767                 :          0 :                         tcp_mask.hdr.dst_port =
     768                 :            :                                         rte_flow_item_tcp_mask.hdr.dst_port;
     769                 :            :                 }
     770                 :          0 :                 item.type = RTE_FLOW_ITEM_TYPE_TCP;
     771                 :          0 :                 item.spec = &tcp;
     772                 :          0 :                 item.mask = &tcp_mask;
     773                 :            :                 field = modify_tcp;
     774                 :            :         }
     775                 :          0 :         return flow_dv_convert_modify_action(&item, field, NULL, resource,
     776                 :            :                                              MLX5_MODIFICATION_TYPE_SET, error);
     777                 :            : }
     778                 :            : 
     779                 :            : /**
     780                 :            :  * Convert modify-header set TTL action to DV specification.
     781                 :            :  *
     782                 :            :  * @param[in,out] resource
     783                 :            :  *   Pointer to the modify-header resource.
     784                 :            :  * @param[in] action
     785                 :            :  *   Pointer to action specification.
     786                 :            :  * @param[in] items
     787                 :            :  *   Pointer to rte_flow_item objects list.
     788                 :            :  * @param[in] attr
     789                 :            :  *   Pointer to flow attributes structure.
     790                 :            :  * @param[in] dev_flow
     791                 :            :  *   Pointer to the sub flow.
     792                 :            :  * @param[in] tunnel_decap
     793                 :            :  *   Whether action is after tunnel decapsulation.
     794                 :            :  * @param[out] error
     795                 :            :  *   Pointer to the error structure.
     796                 :            :  *
     797                 :            :  * @return
     798                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
     799                 :            :  */
     800                 :            : static int
     801                 :          0 : flow_dv_convert_action_modify_ttl
     802                 :            :                         (struct mlx5_flow_dv_modify_hdr_resource *resource,
     803                 :            :                          const struct rte_flow_action *action,
     804                 :            :                          const struct rte_flow_item *items,
     805                 :            :                          union flow_dv_attr *attr, struct mlx5_flow *dev_flow,
     806                 :            :                          bool tunnel_decap, struct rte_flow_error *error)
     807                 :            : {
     808                 :          0 :         const struct rte_flow_action_set_ttl *conf =
     809                 :            :                 (const struct rte_flow_action_set_ttl *)(action->conf);
     810                 :            :         struct rte_flow_item item;
     811                 :            :         struct rte_flow_item_ipv4 ipv4;
     812                 :            :         struct rte_flow_item_ipv4 ipv4_mask;
     813                 :            :         struct rte_flow_item_ipv6 ipv6;
     814                 :            :         struct rte_flow_item_ipv6 ipv6_mask;
     815                 :            :         struct field_modify_info *field;
     816                 :            : 
     817         [ #  # ]:          0 :         if (!attr->valid)
     818                 :          0 :                 flow_dv_attr_init(items, attr, dev_flow, tunnel_decap);
     819         [ #  # ]:          0 :         if (attr->ipv4) {
     820                 :            :                 memset(&ipv4, 0, sizeof(ipv4));
     821                 :            :                 memset(&ipv4_mask, 0, sizeof(ipv4_mask));
     822                 :          0 :                 ipv4.hdr.time_to_live = conf->ttl_value;
     823                 :          0 :                 ipv4_mask.hdr.time_to_live = 0xFF;
     824                 :          0 :                 item.type = RTE_FLOW_ITEM_TYPE_IPV4;
     825                 :          0 :                 item.spec = &ipv4;
     826                 :          0 :                 item.mask = &ipv4_mask;
     827                 :            :                 field = modify_ipv4;
     828                 :            :         } else {
     829                 :            :                 MLX5_ASSERT(attr->ipv6);
     830                 :            :                 memset(&ipv6, 0, sizeof(ipv6));
     831                 :            :                 memset(&ipv6_mask, 0, sizeof(ipv6_mask));
     832                 :          0 :                 ipv6.hdr.hop_limits = conf->ttl_value;
     833                 :          0 :                 ipv6_mask.hdr.hop_limits = 0xFF;
     834                 :          0 :                 item.type = RTE_FLOW_ITEM_TYPE_IPV6;
     835                 :          0 :                 item.spec = &ipv6;
     836                 :          0 :                 item.mask = &ipv6_mask;
     837                 :            :                 field = modify_ipv6;
     838                 :            :         }
     839                 :          0 :         return flow_dv_convert_modify_action(&item, field, NULL, resource,
     840                 :            :                                              MLX5_MODIFICATION_TYPE_SET, error);
     841                 :            : }
     842                 :            : 
     843                 :            : /**
     844                 :            :  * Convert modify-header decrement TTL action to DV specification.
     845                 :            :  *
     846                 :            :  * @param[in,out] resource
     847                 :            :  *   Pointer to the modify-header resource.
     848                 :            :  * @param[in] action
     849                 :            :  *   Pointer to action specification.
     850                 :            :  * @param[in] items
     851                 :            :  *   Pointer to rte_flow_item objects list.
     852                 :            :  * @param[in] attr
     853                 :            :  *   Pointer to flow attributes structure.
     854                 :            :  * @param[in] dev_flow
     855                 :            :  *   Pointer to the sub flow.
     856                 :            :  * @param[in] tunnel_decap
     857                 :            :  *   Whether action is after tunnel decapsulation.
     858                 :            :  * @param[out] error
     859                 :            :  *   Pointer to the error structure.
     860                 :            :  *
     861                 :            :  * @return
     862                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
     863                 :            :  */
     864                 :            : static int
     865                 :          0 : flow_dv_convert_action_modify_dec_ttl
     866                 :            :                         (struct mlx5_flow_dv_modify_hdr_resource *resource,
     867                 :            :                          const struct rte_flow_item *items,
     868                 :            :                          union flow_dv_attr *attr, struct mlx5_flow *dev_flow,
     869                 :            :                          bool tunnel_decap, struct rte_flow_error *error)
     870                 :            : {
     871                 :            :         struct rte_flow_item item;
     872                 :            :         struct rte_flow_item_ipv4 ipv4;
     873                 :            :         struct rte_flow_item_ipv4 ipv4_mask;
     874                 :            :         struct rte_flow_item_ipv6 ipv6;
     875                 :            :         struct rte_flow_item_ipv6 ipv6_mask;
     876                 :            :         struct field_modify_info *field;
     877                 :            : 
     878         [ #  # ]:          0 :         if (!attr->valid)
     879                 :          0 :                 flow_dv_attr_init(items, attr, dev_flow, tunnel_decap);
     880         [ #  # ]:          0 :         if (attr->ipv4) {
     881                 :            :                 memset(&ipv4, 0, sizeof(ipv4));
     882                 :            :                 memset(&ipv4_mask, 0, sizeof(ipv4_mask));
     883                 :          0 :                 ipv4.hdr.time_to_live = 0xFF;
     884                 :          0 :                 ipv4_mask.hdr.time_to_live = 0xFF;
     885                 :          0 :                 item.type = RTE_FLOW_ITEM_TYPE_IPV4;
     886                 :          0 :                 item.spec = &ipv4;
     887                 :          0 :                 item.mask = &ipv4_mask;
     888                 :            :                 field = modify_ipv4;
     889                 :            :         } else {
     890                 :            :                 MLX5_ASSERT(attr->ipv6);
     891                 :            :                 memset(&ipv6, 0, sizeof(ipv6));
     892                 :            :                 memset(&ipv6_mask, 0, sizeof(ipv6_mask));
     893                 :          0 :                 ipv6.hdr.hop_limits = 0xFF;
     894                 :          0 :                 ipv6_mask.hdr.hop_limits = 0xFF;
     895                 :          0 :                 item.type = RTE_FLOW_ITEM_TYPE_IPV6;
     896                 :          0 :                 item.spec = &ipv6;
     897                 :          0 :                 item.mask = &ipv6_mask;
     898                 :            :                 field = modify_ipv6;
     899                 :            :         }
     900                 :          0 :         return flow_dv_convert_modify_action(&item, field, NULL, resource,
     901                 :            :                                              MLX5_MODIFICATION_TYPE_ADD, error);
     902                 :            : }
     903                 :            : 
     904                 :            : /**
     905                 :            :  * Convert modify-header increment/decrement TCP Sequence number
     906                 :            :  * to DV specification.
     907                 :            :  *
     908                 :            :  * @param[in,out] resource
     909                 :            :  *   Pointer to the modify-header resource.
     910                 :            :  * @param[in] action
     911                 :            :  *   Pointer to action specification.
     912                 :            :  * @param[out] error
     913                 :            :  *   Pointer to the error structure.
     914                 :            :  *
     915                 :            :  * @return
     916                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
     917                 :            :  */
     918                 :            : static int
     919                 :          0 : flow_dv_convert_action_modify_tcp_seq
     920                 :            :                         (struct mlx5_flow_dv_modify_hdr_resource *resource,
     921                 :            :                          const struct rte_flow_action *action,
     922                 :            :                          struct rte_flow_error *error)
     923                 :            : {
     924                 :          0 :         const rte_be32_t *conf = (const rte_be32_t *)(action->conf);
     925         [ #  # ]:          0 :         uint64_t value = rte_be_to_cpu_32(*conf);
     926                 :            :         struct rte_flow_item item;
     927                 :            :         struct rte_flow_item_tcp tcp;
     928                 :            :         struct rte_flow_item_tcp tcp_mask;
     929                 :            : 
     930                 :            :         memset(&tcp, 0, sizeof(tcp));
     931                 :            :         memset(&tcp_mask, 0, sizeof(tcp_mask));
     932         [ #  # ]:          0 :         if (action->type == RTE_FLOW_ACTION_TYPE_DEC_TCP_SEQ)
     933                 :            :                 /*
     934                 :            :                  * The HW has no decrement operation, only increment operation.
     935                 :            :                  * To simulate decrement X from Y using increment operation
     936                 :            :                  * we need to add UINT32_MAX X times to Y.
     937                 :            :                  * Each adding of UINT32_MAX decrements Y by 1.
     938                 :            :                  */
     939                 :          0 :                 value *= UINT32_MAX;
     940         [ #  # ]:          0 :         tcp.hdr.sent_seq = rte_cpu_to_be_32((uint32_t)value);
     941                 :          0 :         tcp_mask.hdr.sent_seq = RTE_BE32(UINT32_MAX);
     942                 :          0 :         item.type = RTE_FLOW_ITEM_TYPE_TCP;
     943                 :          0 :         item.spec = &tcp;
     944                 :          0 :         item.mask = &tcp_mask;
     945                 :          0 :         return flow_dv_convert_modify_action(&item, modify_tcp, NULL, resource,
     946                 :            :                                              MLX5_MODIFICATION_TYPE_ADD, error);
     947                 :            : }
     948                 :            : 
     949                 :            : /**
     950                 :            :  * Convert modify-header increment/decrement TCP Acknowledgment number
     951                 :            :  * to DV specification.
     952                 :            :  *
     953                 :            :  * @param[in,out] resource
     954                 :            :  *   Pointer to the modify-header resource.
     955                 :            :  * @param[in] action
     956                 :            :  *   Pointer to action specification.
     957                 :            :  * @param[out] error
     958                 :            :  *   Pointer to the error structure.
     959                 :            :  *
     960                 :            :  * @return
     961                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
     962                 :            :  */
     963                 :            : static int
     964                 :          0 : flow_dv_convert_action_modify_tcp_ack
     965                 :            :                         (struct mlx5_flow_dv_modify_hdr_resource *resource,
     966                 :            :                          const struct rte_flow_action *action,
     967                 :            :                          struct rte_flow_error *error)
     968                 :            : {
     969                 :          0 :         const rte_be32_t *conf = (const rte_be32_t *)(action->conf);
     970         [ #  # ]:          0 :         uint64_t value = rte_be_to_cpu_32(*conf);
     971                 :            :         struct rte_flow_item item;
     972                 :            :         struct rte_flow_item_tcp tcp;
     973                 :            :         struct rte_flow_item_tcp tcp_mask;
     974                 :            : 
     975                 :            :         memset(&tcp, 0, sizeof(tcp));
     976                 :            :         memset(&tcp_mask, 0, sizeof(tcp_mask));
     977         [ #  # ]:          0 :         if (action->type == RTE_FLOW_ACTION_TYPE_DEC_TCP_ACK)
     978                 :            :                 /*
     979                 :            :                  * The HW has no decrement operation, only increment operation.
     980                 :            :                  * To simulate decrement X from Y using increment operation
     981                 :            :                  * we need to add UINT32_MAX X times to Y.
     982                 :            :                  * Each adding of UINT32_MAX decrements Y by 1.
     983                 :            :                  */
     984                 :          0 :                 value *= UINT32_MAX;
     985         [ #  # ]:          0 :         tcp.hdr.recv_ack = rte_cpu_to_be_32((uint32_t)value);
     986                 :          0 :         tcp_mask.hdr.recv_ack = RTE_BE32(UINT32_MAX);
     987                 :          0 :         item.type = RTE_FLOW_ITEM_TYPE_TCP;
     988                 :          0 :         item.spec = &tcp;
     989                 :          0 :         item.mask = &tcp_mask;
     990                 :          0 :         return flow_dv_convert_modify_action(&item, modify_tcp, NULL, resource,
     991                 :            :                                              MLX5_MODIFICATION_TYPE_ADD, error);
     992                 :            : }
     993                 :            : 
     994                 :            : enum mlx5_modification_field reg_to_field[] = {
     995                 :            :         [REG_NON] = MLX5_MODI_OUT_NONE,
     996                 :            :         [REG_A] = MLX5_MODI_META_DATA_REG_A,
     997                 :            :         [REG_B] = MLX5_MODI_META_DATA_REG_B,
     998                 :            :         [REG_C_0] = MLX5_MODI_META_REG_C_0,
     999                 :            :         [REG_C_1] = MLX5_MODI_META_REG_C_1,
    1000                 :            :         [REG_C_2] = MLX5_MODI_META_REG_C_2,
    1001                 :            :         [REG_C_3] = MLX5_MODI_META_REG_C_3,
    1002                 :            :         [REG_C_4] = MLX5_MODI_META_REG_C_4,
    1003                 :            :         [REG_C_5] = MLX5_MODI_META_REG_C_5,
    1004                 :            :         [REG_C_6] = MLX5_MODI_META_REG_C_6,
    1005                 :            :         [REG_C_7] = MLX5_MODI_META_REG_C_7,
    1006                 :            :         [REG_C_8] = MLX5_MODI_META_REG_C_8,
    1007                 :            :         [REG_C_9] = MLX5_MODI_META_REG_C_9,
    1008                 :            :         [REG_C_10] = MLX5_MODI_META_REG_C_10,
    1009                 :            :         [REG_C_11] = MLX5_MODI_META_REG_C_11,
    1010                 :            : };
    1011                 :            : 
    1012                 :            : const size_t mlx5_mod_reg_size = RTE_DIM(reg_to_field);
    1013                 :            : 
    1014                 :            : /**
    1015                 :            :  * Convert register set to DV specification.
    1016                 :            :  *
    1017                 :            :  * @param[in,out] resource
    1018                 :            :  *   Pointer to the modify-header resource.
    1019                 :            :  * @param[in] action
    1020                 :            :  *   Pointer to action specification.
    1021                 :            :  * @param[out] error
    1022                 :            :  *   Pointer to the error structure.
    1023                 :            :  *
    1024                 :            :  * @return
    1025                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    1026                 :            :  */
    1027                 :            : static int
    1028                 :          0 : flow_dv_convert_action_set_reg
    1029                 :            :                         (struct mlx5_flow_dv_modify_hdr_resource *resource,
    1030                 :            :                          const struct rte_flow_action *action,
    1031                 :            :                          struct rte_flow_error *error)
    1032                 :            : {
    1033                 :          0 :         const struct mlx5_rte_flow_action_set_tag *conf = action->conf;
    1034                 :          0 :         struct mlx5_modification_cmd *actions = resource->actions;
    1035                 :          0 :         uint32_t i = resource->actions_num;
    1036                 :            : 
    1037         [ #  # ]:          0 :         if (i >= MLX5_MAX_MODIFY_NUM)
    1038                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    1039                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    1040                 :            :                                           "too many items to modify");
    1041                 :            :         MLX5_ASSERT(conf->id != REG_NON);
    1042                 :            :         MLX5_ASSERT(conf->id < (enum modify_reg)RTE_DIM(reg_to_field));
    1043                 :          0 :         actions[i] = (struct mlx5_modification_cmd) {
    1044                 :            :                 .action_type = MLX5_MODIFICATION_TYPE_SET,
    1045                 :          0 :                 .field = reg_to_field[conf->id],
    1046                 :          0 :                 .offset = conf->offset,
    1047                 :          0 :                 .length = conf->length,
    1048                 :            :         };
    1049         [ #  # ]:          0 :         actions[i].data0 = rte_cpu_to_be_32(actions[i].data0);
    1050         [ #  # ]:          0 :         actions[i].data1 = rte_cpu_to_be_32(conf->data);
    1051                 :            :         ++i;
    1052                 :          0 :         resource->actions_num = i;
    1053                 :          0 :         return 0;
    1054                 :            : }
    1055                 :            : 
    1056                 :            : /**
    1057                 :            :  * Convert SET_TAG action to DV specification.
    1058                 :            :  *
    1059                 :            :  * @param[in] dev
    1060                 :            :  *   Pointer to the rte_eth_dev structure.
    1061                 :            :  * @param[in,out] resource
    1062                 :            :  *   Pointer to the modify-header resource.
    1063                 :            :  * @param[in] conf
    1064                 :            :  *   Pointer to action specification.
    1065                 :            :  * @param[out] error
    1066                 :            :  *   Pointer to the error structure.
    1067                 :            :  *
    1068                 :            :  * @return
    1069                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    1070                 :            :  */
    1071                 :            : static int
    1072                 :          0 : flow_dv_convert_action_set_tag
    1073                 :            :                         (struct rte_eth_dev *dev,
    1074                 :            :                          struct mlx5_flow_dv_modify_hdr_resource *resource,
    1075                 :            :                          const struct rte_flow_action_set_tag *conf,
    1076                 :            :                          struct rte_flow_error *error)
    1077                 :            : {
    1078         [ #  # ]:          0 :         rte_be32_t data = rte_cpu_to_be_32(conf->data);
    1079         [ #  # ]:          0 :         rte_be32_t mask = rte_cpu_to_be_32(conf->mask);
    1080                 :          0 :         struct rte_flow_item item = {
    1081                 :            :                 .spec = &data,
    1082                 :            :                 .mask = &mask,
    1083                 :            :         };
    1084                 :          0 :         struct field_modify_info reg_c_x[] = {
    1085                 :            :                 [1] = {0, 0, 0},
    1086                 :            :         };
    1087                 :            :         enum mlx5_modification_field reg_type;
    1088                 :            :         int ret;
    1089                 :            : 
    1090                 :          0 :         ret = mlx5_flow_get_reg_id(dev, MLX5_APP_TAG, conf->index, error);
    1091         [ #  # ]:          0 :         if (ret < 0)
    1092                 :            :                 return ret;
    1093                 :            :         MLX5_ASSERT(ret != REG_NON);
    1094                 :            :         MLX5_ASSERT((unsigned int)ret < RTE_DIM(reg_to_field));
    1095                 :          0 :         reg_type = 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 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, reg_to_field[conf->src]},
    1131                 :            :                 {0, 0, 0},
    1132                 :            :         };
    1133                 :          0 :         struct field_modify_info reg_dst = {
    1134                 :            :                 .offset = 0,
    1135                 :          0 :                 .id = 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 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, reg_to_field[reg]};
    1213                 :          0 :         return 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, reg_to_field[reg]};
    1299                 :            :         /* The routine expects parameters in memory as big-endian ones. */
    1300                 :          0 :         return 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 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 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                 :            :         case RTE_FLOW_FIELD_GTP_TEID:
    1443                 :            :         case RTE_FLOW_FIELD_MPLS:
    1444                 :            :         case RTE_FLOW_FIELD_TAG:
    1445                 :            :         case RTE_FLOW_FIELD_ESP_SPI:
    1446                 :            :         case RTE_FLOW_FIELD_ESP_SEQ_NUM:
    1447                 :            :                 return 32;
    1448                 :          0 :         case RTE_FLOW_FIELD_ESP_PROTO:
    1449                 :          0 :                 return 8;
    1450                 :          0 :         case RTE_FLOW_FIELD_MARK:
    1451                 :          0 :                 return rte_popcount32(priv->sh->dv_mark_mask);
    1452                 :          0 :         case RTE_FLOW_FIELD_META:
    1453                 :          0 :                 return (flow_dv_get_metadata_reg(dev, attr, error) == REG_C_0) ?
    1454         [ #  # ]:          0 :                         rte_popcount32(priv->sh->dv_meta_mask) : 32;
    1455                 :          0 :         case RTE_FLOW_FIELD_POINTER:
    1456                 :            :         case RTE_FLOW_FIELD_VALUE:
    1457                 :          0 :                 return inherit < 0 ? 0 : inherit;
    1458                 :          0 :         case RTE_FLOW_FIELD_IPV4_ECN:
    1459                 :            :         case RTE_FLOW_FIELD_IPV6_ECN:
    1460                 :            :         case RTE_FLOW_FIELD_METER_COLOR:
    1461                 :          0 :                 return 2;
    1462                 :            :         case RTE_FLOW_FIELD_HASH_RESULT:
    1463                 :            :                 return 32;
    1464                 :          0 :         default:
    1465                 :            :                 MLX5_ASSERT(false);
    1466                 :            :         }
    1467                 :          0 :         return 0;
    1468                 :            : }
    1469                 :            : 
    1470                 :            : static __rte_always_inline uint8_t
    1471                 :            : flow_modify_info_mask_8(uint32_t length, uint32_t off)
    1472                 :            : {
    1473                 :          0 :         return (0xffu >> (8 - length)) << off;
    1474                 :            : }
    1475                 :            : 
    1476                 :            : static __rte_always_inline uint16_t
    1477                 :            : flow_modify_info_mask_16(uint32_t length, uint32_t off)
    1478                 :            : {
    1479   [ #  #  #  #  :          0 :         return rte_cpu_to_be_16((0xffffu >> (16 - length)) << off);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
    1480                 :            : }
    1481                 :            : 
    1482                 :            : static __rte_always_inline uint32_t
    1483                 :            : flow_modify_info_mask_32(uint32_t length, uint32_t off)
    1484                 :            : {
    1485   [ #  #  #  #  :          0 :         return rte_cpu_to_be_32((0xffffffffu >> (32 - length)) << off);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    1486                 :            : }
    1487                 :            : 
    1488                 :            : static __rte_always_inline uint32_t
    1489                 :            : flow_modify_info_mask_32_masked(uint32_t length, uint32_t off, uint32_t post_mask)
    1490                 :            : {
    1491                 :          0 :         uint32_t mask = (0xffffffffu >> (32 - length)) << off;
    1492                 :          0 :         return rte_cpu_to_be_32(mask & post_mask);
    1493                 :            : }
    1494                 :            : 
    1495                 :            : static __rte_always_inline enum mlx5_modification_field
    1496                 :            : mlx5_mpls_modi_field_get(const struct rte_flow_field_data *data)
    1497                 :            : {
    1498                 :          0 :         return MLX5_MODI_IN_MPLS_LABEL_0 + data->tag_index;
    1499                 :            : }
    1500                 :            : 
    1501                 :            : static __rte_always_inline int
    1502                 :            : flow_geneve_opt_modi_field_get(struct mlx5_priv *priv,
    1503                 :            :                                const struct rte_flow_field_data *data)
    1504                 :            : {
    1505                 :            : #ifdef HAVE_MLX5_HWS_SUPPORT
    1506                 :          0 :         return mlx5_geneve_opt_modi_field_get(priv, data);
    1507                 :            : #else
    1508                 :            :         (void)priv;
    1509                 :            :         (void)data;
    1510                 :            :         DRV_LOG(ERR, "GENEVE option modification is not supported.");
    1511                 :            :         rte_errno = ENOTSUP;
    1512                 :            :         return -rte_errno;
    1513                 :            : #endif
    1514                 :            : }
    1515                 :            : 
    1516                 :            : static void
    1517                 :          0 : mlx5_modify_flex_item(const struct rte_eth_dev *dev,
    1518                 :            :                       const struct mlx5_flex_item *flex,
    1519                 :            :                       const struct rte_flow_field_data *data,
    1520                 :            :                       struct field_modify_info *info,
    1521                 :            :                       uint32_t *mask, uint32_t width)
    1522                 :            : {
    1523                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    1524                 :          0 :         struct mlx5_hca_flex_attr *attr = &priv->sh->cdev->config.hca_attr.flex;
    1525                 :            :         uint32_t i, j;
    1526                 :            :         int id = 0;
    1527                 :          0 :         uint32_t pos = 0;
    1528                 :            :         const struct mlx5_flex_pattern_field *map;
    1529                 :          0 :         uint32_t offset = data->offset;
    1530                 :            :         uint32_t width_left = width;
    1531                 :            :         uint32_t def;
    1532                 :            :         uint32_t cur_width = 0;
    1533                 :            :         uint32_t tmp_ofs;
    1534                 :            :         uint32_t idx = 0;
    1535                 :            :         struct field_modify_info tmp;
    1536                 :            :         int tmp_id;
    1537                 :            : 
    1538         [ #  # ]:          0 :         if (!attr->query_match_sample_info) {
    1539                 :          0 :                 DRV_LOG(ERR, "FW doesn't support modify field with flex item.");
    1540                 :          0 :                 return;
    1541                 :            :         }
    1542                 :            :         /*
    1543                 :            :          * search for the mapping instance until Accumulated width is no
    1544                 :            :          * less than data->offset.
    1545                 :            :          */
    1546         [ #  # ]:          0 :         for (i = 0; i < flex->mapnum; i++) {
    1547         [ #  # ]:          0 :                 if (flex->map[i].width + pos > data->offset)
    1548                 :            :                         break;
    1549                 :          0 :                 pos += flex->map[i].width;
    1550                 :            :         }
    1551         [ #  # ]:          0 :         if (i >= flex->mapnum)
    1552                 :            :                 return;
    1553         [ #  # ]:          0 :         tmp_ofs = pos < data->offset ? data->offset - pos : 0;
    1554   [ #  #  #  # ]:          0 :         for (j = i; i < flex->mapnum && width_left > 0; ) {
    1555                 :          0 :                 map = flex->map + i;
    1556                 :          0 :                 id = mlx5_flex_get_sample_id(flex, i, &pos, false, &def);
    1557         [ #  # ]:          0 :                 if (id == -1) {
    1558                 :          0 :                         i++;
    1559                 :            :                         /* All left length is dummy */
    1560         [ #  # ]:          0 :                         if (pos >= data->offset + width)
    1561                 :            :                                 return;
    1562                 :          0 :                         cur_width = map->width;
    1563                 :            :                 /* One mapping instance covers the whole width. */
    1564         [ #  # ]:          0 :                 } else if (pos + map->width >= (data->offset + width)) {
    1565                 :            :                         cur_width = width_left;
    1566                 :            :                 } else {
    1567                 :          0 :                         cur_width = cur_width + map->width - tmp_ofs;
    1568                 :          0 :                         pos += map->width;
    1569                 :            :                         /*
    1570                 :            :                          * Continue to search next until:
    1571                 :            :                          * 1. Another flex parser ID.
    1572                 :            :                          * 2. Width has been covered.
    1573                 :            :                          */
    1574         [ #  # ]:          0 :                         for (j = i + 1; j < flex->mapnum; j++) {
    1575                 :          0 :                                 tmp_id = mlx5_flex_get_sample_id(flex, j, &pos, false, &def);
    1576         [ #  # ]:          0 :                                 if (tmp_id == -1) {
    1577                 :            :                                         i = j;
    1578                 :          0 :                                         pos -= flex->map[j].width;
    1579                 :          0 :                                         break;
    1580                 :            :                                 }
    1581   [ #  #  #  # ]:          0 :                                 if (id >= (int)flex->devx_fp->num_samples ||
    1582         [ #  # ]:          0 :                                     id >= MLX5_GRAPH_NODE_SAMPLE_NUM ||
    1583         [ #  # ]:          0 :                                     tmp_id >= (int)flex->devx_fp->num_samples ||
    1584                 :            :                                     tmp_id >= MLX5_GRAPH_NODE_SAMPLE_NUM)
    1585                 :            :                                         return;
    1586                 :          0 :                                 if (flex->devx_fp->sample_info[id].modify_field_id !=
    1587         [ #  # ]:          0 :                                     flex->devx_fp->sample_info[tmp_id].modify_field_id ||
    1588                 :          0 :                                     flex->map[j].shift != flex->map[j - 1].width +
    1589         [ #  # ]:          0 :                                                           flex->map[j - 1].shift) {
    1590                 :            :                                         i = j;
    1591                 :            :                                         break;
    1592                 :            :                                 }
    1593         [ #  # ]:          0 :                                 if ((pos + flex->map[j].width) >= (data->offset + width)) {
    1594                 :            :                                         cur_width = width_left;
    1595                 :            :                                         break;
    1596                 :            :                                 }
    1597                 :          0 :                                 pos += flex->map[j].width;
    1598                 :          0 :                                 cur_width += flex->map[j].width;
    1599                 :            :                         }
    1600                 :            :                 }
    1601         [ #  # ]:          0 :                 if (cur_width > width_left)
    1602                 :            :                         cur_width = width_left;
    1603   [ #  #  #  #  :          0 :                 else if (cur_width < width_left && (j == flex->mapnum || i == flex->mapnum))
                   #  # ]
    1604                 :            :                         return;
    1605                 :            : 
    1606                 :            :                 MLX5_ASSERT(id < (int)flex->devx_fp->num_samples);
    1607   [ #  #  #  # ]:          0 :                 if (id >= (int)flex->devx_fp->num_samples || id >= MLX5_GRAPH_NODE_SAMPLE_NUM)
    1608                 :            :                         return;
    1609                 :            :                 /* Use invalid entry as placeholder for DUMMY mapping. */
    1610                 :          0 :                 info[idx] = (struct field_modify_info){cur_width / CHAR_BIT, offset / CHAR_BIT,
    1611         [ #  # ]:          0 :                              id == -1 ? MLX5_MODI_INVALID :
    1612                 :            :                              (enum mlx5_modification_field)
    1613                 :          0 :                              flex->devx_fp->sample_info[id].modify_field_id,
    1614                 :          0 :                              map->shift + tmp_ofs, 1};
    1615                 :          0 :                 offset += cur_width;
    1616                 :          0 :                 width_left -= cur_width;
    1617         [ #  # ]:          0 :                 if (!mask) {
    1618                 :          0 :                         info[idx].offset = (32 - cur_width - map->shift - tmp_ofs);
    1619                 :          0 :                         info[idx].size = cur_width / CHAR_BIT + info[idx].offset / CHAR_BIT;
    1620                 :            :                 }
    1621                 :            :                 cur_width = 0;
    1622                 :            :                 tmp_ofs = 0;
    1623                 :          0 :                 idx++;
    1624                 :            :         }
    1625         [ #  # ]:          0 :         if (unlikely(width_left > 0)) {
    1626                 :            :                 MLX5_ASSERT(false);
    1627                 :            :                 return;
    1628                 :            :         }
    1629         [ #  # ]:          0 :         if (mask)
    1630                 :          0 :                 memset(mask, 0xff, data->offset / CHAR_BIT + width / CHAR_BIT);
    1631                 :            :         /* Re-order the info to follow IPv6 address. */
    1632         [ #  # ]:          0 :         for (i = 0; i < idx / 2; i++) {
    1633                 :          0 :                 tmp = info[i];
    1634                 :            :                 MLX5_ASSERT(info[i].id);
    1635                 :            :                 MLX5_ASSERT(info[idx - 1 - i].id);
    1636                 :          0 :                 info[i] = info[idx - 1 - i];
    1637                 :          0 :                 info[idx - 1 - i] = tmp;
    1638                 :            :         }
    1639                 :            : }
    1640                 :            : 
    1641                 :            : static inline bool
    1642                 :            : mlx5_dv_modify_ipv6_traffic_class_supported(struct mlx5_priv *priv)
    1643                 :            : {
    1644                 :          0 :         return priv->sh->phdev->config.ipv6_tc_fallback == MLX5_IPV6_TC_OK;
    1645                 :            : }
    1646                 :            : 
    1647                 :            : void
    1648                 :          0 : mlx5_flow_field_id_to_modify_info
    1649                 :            :                 (const struct rte_flow_field_data *data,
    1650                 :            :                  struct field_modify_info *info, uint32_t *mask,
    1651                 :            :                  uint32_t width, struct rte_eth_dev *dev,
    1652                 :            :                  const struct rte_flow_attr *attr, struct rte_flow_error *error)
    1653                 :            : {
    1654                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    1655                 :            :         enum mlx5_modification_field modi_id;
    1656                 :            :         uint32_t idx = 0;
    1657                 :            :         uint32_t off_be = 0;
    1658                 :            :         uint32_t length = 0;
    1659                 :            : 
    1660   [ #  #  #  #  :          0 :         switch ((int)data->field) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    1661                 :            :         case RTE_FLOW_FIELD_START:
    1662                 :            :                 /* not supported yet */
    1663                 :            :                 MLX5_ASSERT(false);
    1664                 :            :                 break;
    1665                 :          0 :         case RTE_FLOW_FIELD_MAC_DST:
    1666                 :            :                 MLX5_ASSERT(data->offset + width <= 48);
    1667                 :          0 :                 off_be = 48 - (data->offset + width);
    1668         [ #  # ]:          0 :                 if (off_be < 16) {
    1669         [ #  # ]:          0 :                         modi_id = CALC_MODI_ID(DMAC_15_0, data->level);
    1670                 :          0 :                         info[idx] = (struct field_modify_info){2, 4, modi_id};
    1671         [ #  # ]:          0 :                         length = off_be + width <= 16 ? width : 16 - off_be;
    1672         [ #  # ]:          0 :                         if (mask)
    1673                 :          0 :                                 mask[1] = flow_modify_info_mask_16(length,
    1674                 :            :                                                                    off_be);
    1675                 :            :                         else
    1676                 :          0 :                                 info[idx].offset = off_be;
    1677                 :          0 :                         width -= length;
    1678         [ #  # ]:          0 :                         if (!width)
    1679                 :            :                                 break;
    1680                 :            :                         off_be = 0;
    1681                 :            :                         idx++;
    1682                 :            :                 } else {
    1683                 :          0 :                         off_be -= 16;
    1684                 :            :                 }
    1685         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(DMAC_47_16, data->level);
    1686                 :          0 :                 info[idx] = (struct field_modify_info){4, 0, modi_id};
    1687         [ #  # ]:          0 :                 if (mask)
    1688                 :          0 :                         mask[0] = flow_modify_info_mask_32(width, off_be);
    1689                 :            :                 else
    1690                 :          0 :                         info[idx].offset = off_be;
    1691                 :            :                 break;
    1692                 :          0 :         case RTE_FLOW_FIELD_MAC_SRC:
    1693                 :            :                 MLX5_ASSERT(data->offset + width <= 48);
    1694                 :          0 :                 off_be = 48 - (data->offset + width);
    1695         [ #  # ]:          0 :                 if (off_be < 16) {
    1696         [ #  # ]:          0 :                         modi_id = CALC_MODI_ID(SMAC_15_0, data->level);
    1697                 :          0 :                         info[idx] = (struct field_modify_info){2, 4, modi_id};
    1698         [ #  # ]:          0 :                         length = off_be + width <= 16 ? width : 16 - off_be;
    1699         [ #  # ]:          0 :                         if (mask)
    1700                 :          0 :                                 mask[1] = flow_modify_info_mask_16(length,
    1701                 :            :                                                                    off_be);
    1702                 :            :                         else
    1703                 :          0 :                                 info[idx].offset = off_be;
    1704                 :          0 :                         width -= length;
    1705         [ #  # ]:          0 :                         if (!width)
    1706                 :            :                                 break;
    1707                 :            :                         off_be = 0;
    1708                 :            :                         idx++;
    1709                 :            :                 } else {
    1710                 :          0 :                         off_be -= 16;
    1711                 :            :                 }
    1712         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(SMAC_47_16, data->level);
    1713                 :          0 :                 info[idx] = (struct field_modify_info){4, 0, modi_id};
    1714         [ #  # ]:          0 :                 if (mask)
    1715                 :          0 :                         mask[0] = flow_modify_info_mask_32(width, off_be);
    1716                 :            :                 else
    1717                 :          0 :                         info[idx].offset = off_be;
    1718                 :            :                 break;
    1719                 :            :         case RTE_FLOW_FIELD_VLAN_TYPE:
    1720                 :            :                 /* not supported yet */
    1721                 :            :                 break;
    1722                 :          0 :         case RTE_FLOW_FIELD_VLAN_ID:
    1723                 :            :                 MLX5_ASSERT(data->offset + width <= 12);
    1724                 :          0 :                 off_be = 12 - (data->offset + width);
    1725                 :          0 :                 info[idx] = (struct field_modify_info){2, 0,
    1726                 :            :                                         MLX5_MODI_OUT_FIRST_VID};
    1727         [ #  # ]:          0 :                 if (mask)
    1728                 :          0 :                         mask[idx] = flow_modify_info_mask_16(width, off_be);
    1729                 :            :                 else
    1730                 :          0 :                         info[idx].offset = off_be;
    1731                 :            :                 break;
    1732                 :          0 :         case RTE_FLOW_FIELD_MAC_TYPE:
    1733                 :            :                 MLX5_ASSERT(data->offset + width <= 16);
    1734                 :          0 :                 off_be = 16 - (data->offset + width);
    1735         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(ETHERTYPE, data->level);
    1736                 :          0 :                 info[idx] = (struct field_modify_info){2, 0, modi_id};
    1737         [ #  # ]:          0 :                 if (mask)
    1738                 :          0 :                         mask[idx] = flow_modify_info_mask_16(width, off_be);
    1739                 :            :                 else
    1740                 :          0 :                         info[idx].offset = off_be;
    1741                 :            :                 break;
    1742                 :          0 :         case RTE_FLOW_FIELD_IPV4_IHL:
    1743                 :            :                 MLX5_ASSERT(data->offset + width <= 4);
    1744                 :          0 :                 off_be = 4 - (data->offset + width);
    1745         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(IPV4_IHL, data->level);
    1746                 :          0 :                 info[idx] = (struct field_modify_info){1, 0, modi_id};
    1747         [ #  # ]:          0 :                 if (mask)
    1748                 :          0 :                         mask[idx] = flow_modify_info_mask_8(width, off_be);
    1749                 :            :                 else
    1750                 :          0 :                         info[idx].offset = off_be;
    1751                 :            :                 break;
    1752                 :          0 :         case RTE_FLOW_FIELD_IPV4_DSCP:
    1753                 :            :                 MLX5_ASSERT(data->offset + width <= 6);
    1754                 :          0 :                 off_be = 6 - (data->offset + width);
    1755         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(IP_DSCP, data->level);
    1756                 :          0 :                 info[idx] = (struct field_modify_info){1, 0, modi_id};
    1757         [ #  # ]:          0 :                 if (mask)
    1758                 :          0 :                         mask[idx] = flow_modify_info_mask_8(width, off_be);
    1759                 :            :                 else
    1760                 :          0 :                         info[idx].offset = off_be;
    1761                 :            :                 break;
    1762                 :          0 :         case RTE_FLOW_FIELD_IPV4_TOTAL_LEN:
    1763                 :            :                 MLX5_ASSERT(data->offset + width <= 16);
    1764                 :          0 :                 off_be = 16 - (data->offset + width);
    1765         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(IPV4_TOTAL_LEN, data->level);
    1766                 :          0 :                 info[idx] = (struct field_modify_info){2, 0, modi_id};
    1767         [ #  # ]:          0 :                 if (mask)
    1768                 :          0 :                         mask[idx] = flow_modify_info_mask_16(width, off_be);
    1769                 :            :                 else
    1770                 :          0 :                         info[idx].offset = off_be;
    1771                 :            :                 break;
    1772                 :          0 :         case RTE_FLOW_FIELD_IPV4_TTL:
    1773                 :            :                 MLX5_ASSERT(data->offset + width <= 8);
    1774                 :          0 :                 off_be = 8 - (data->offset + width);
    1775         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(IPV4_TTL, data->level);
    1776                 :          0 :                 info[idx] = (struct field_modify_info){1, 0, modi_id};
    1777         [ #  # ]:          0 :                 if (mask)
    1778                 :          0 :                         mask[idx] = flow_modify_info_mask_8(width, off_be);
    1779                 :            :                 else
    1780                 :          0 :                         info[idx].offset = off_be;
    1781                 :            :                 break;
    1782                 :          0 :         case RTE_FLOW_FIELD_IPV4_SRC:
    1783                 :            :                 MLX5_ASSERT(data->offset + width <= 32);
    1784                 :          0 :                 off_be = 32 - (data->offset + width);
    1785         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(SIPV4, data->level);
    1786                 :          0 :                 info[idx] = (struct field_modify_info){4, 0, modi_id};
    1787         [ #  # ]:          0 :                 if (mask)
    1788                 :          0 :                         mask[idx] = flow_modify_info_mask_32(width, off_be);
    1789                 :            :                 else
    1790                 :          0 :                         info[idx].offset = off_be;
    1791                 :            :                 break;
    1792                 :          0 :         case RTE_FLOW_FIELD_IPV4_DST:
    1793                 :            :                 MLX5_ASSERT(data->offset + width <= 32);
    1794                 :          0 :                 off_be = 32 - (data->offset + width);
    1795         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(DIPV4, data->level);
    1796                 :          0 :                 info[idx] = (struct field_modify_info){4, 0, modi_id};
    1797         [ #  # ]:          0 :                 if (mask)
    1798                 :          0 :                         mask[idx] = flow_modify_info_mask_32(width, off_be);
    1799                 :            :                 else
    1800                 :          0 :                         info[idx].offset = off_be;
    1801                 :            :                 break;
    1802                 :            :         case RTE_FLOW_FIELD_IPV6_DSCP:
    1803                 :            :                 MLX5_ASSERT(data->offset + width <= 6);
    1804                 :            :                 /*
    1805                 :            :                  * IPv6 DSCP uses OUT_IPV6_TRAFFIC_CLASS as ID but it starts from 2
    1806                 :            :                  * bits left. Shift the mask left for IPv6 DSCP. Do it here because
    1807                 :            :                  * it's needed to distinguish DSCP from ECN in data field construct
    1808                 :            :                  */
    1809         [ #  # ]:          0 :                 if (mlx5_dv_modify_ipv6_traffic_class_supported(priv)) {
    1810                 :          0 :                         off_be = 6 - (data->offset + width) + MLX5_IPV6_HDR_DSCP_SHIFT;
    1811                 :          0 :                         info[idx] = (struct field_modify_info){1, 0,
    1812                 :            :                                                 MLX5_MODI_OUT_IPV6_TRAFFIC_CLASS};
    1813                 :            :                 } else {
    1814                 :          0 :                         off_be = 6 - (data->offset + width);
    1815                 :          0 :                         info[idx] = (struct field_modify_info){1, 0,
    1816                 :            :                                                 MLX5_MODI_OUT_IP_DSCP};
    1817                 :            :                 }
    1818         [ #  # ]:          0 :                 if (mask)
    1819                 :          0 :                         mask[idx] = flow_modify_info_mask_8(width, off_be);
    1820                 :            :                 else
    1821                 :          0 :                         info[idx].offset = off_be;
    1822                 :            :                 break;
    1823                 :          0 :         case RTE_FLOW_FIELD_IPV6_TRAFFIC_CLASS:
    1824                 :            :                 MLX5_ASSERT(data->offset + width <= 8);
    1825                 :          0 :                 off_be = 8 - (data->offset + width);
    1826         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(IPV6_TRAFFIC_CLASS, data->level);
    1827                 :          0 :                 info[idx] = (struct field_modify_info){1, 0, modi_id};
    1828         [ #  # ]:          0 :                 if (mask)
    1829                 :          0 :                         mask[idx] = flow_modify_info_mask_8(width, off_be);
    1830                 :            :                 else
    1831                 :          0 :                         info[idx].offset = off_be;
    1832                 :            :                 break;
    1833                 :          0 :         case RTE_FLOW_FIELD_IPV6_FLOW_LABEL:
    1834                 :            :                 MLX5_ASSERT(data->offset + width <= 20);
    1835                 :          0 :                 off_be = 20 - (data->offset + width);
    1836         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(IPV6_FLOW_LABEL, data->level);
    1837                 :          0 :                 info[idx] = (struct field_modify_info){4, 0, modi_id};
    1838         [ #  # ]:          0 :                 if (mask)
    1839                 :          0 :                         mask[idx] = flow_modify_info_mask_32(width, off_be);
    1840                 :            :                 else
    1841                 :          0 :                         info[idx].offset = off_be;
    1842                 :            :                 break;
    1843                 :          0 :         case RTE_FLOW_FIELD_IPV6_PAYLOAD_LEN:
    1844                 :            :                 MLX5_ASSERT(data->offset + width <= 16);
    1845                 :          0 :                 off_be = 16 - (data->offset + width);
    1846         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(IPV6_PAYLOAD_LEN, data->level);
    1847                 :          0 :                 info[idx] = (struct field_modify_info){2, 0, modi_id};
    1848         [ #  # ]:          0 :                 if (mask)
    1849                 :          0 :                         mask[idx] = flow_modify_info_mask_16(width, off_be);
    1850                 :            :                 else
    1851                 :          0 :                         info[idx].offset = off_be;
    1852                 :            :                 break;
    1853                 :          0 :         case RTE_FLOW_FIELD_IPV6_HOPLIMIT:
    1854                 :            :                 MLX5_ASSERT(data->offset + width <= 8);
    1855                 :          0 :                 off_be = 8 - (data->offset + width);
    1856         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(IPV6_HOPLIMIT, data->level);
    1857                 :          0 :                 info[idx] = (struct field_modify_info){1, 0, modi_id};
    1858         [ #  # ]:          0 :                 if (mask)
    1859                 :          0 :                         mask[idx] = flow_modify_info_mask_8(width, off_be);
    1860                 :            :                 else
    1861                 :          0 :                         info[idx].offset = off_be;
    1862                 :            :                 break;
    1863                 :          0 :         case RTE_FLOW_FIELD_IPV6_SRC: {
    1864                 :            :                 /*
    1865                 :            :                  * Fields corresponding to IPv6 source address bytes
    1866                 :            :                  * arranged according to network byte ordering.
    1867                 :            :                  */
    1868                 :          0 :                 struct field_modify_info fields[] = {
    1869         [ #  # ]:          0 :                         { 4, 0, CALC_MODI_ID(SIPV6_127_96, data->level)},
    1870         [ #  # ]:          0 :                         { 4, 4, CALC_MODI_ID(SIPV6_95_64, data->level)},
    1871         [ #  # ]:          0 :                         { 4, 8, CALC_MODI_ID(SIPV6_63_32, data->level)},
    1872         [ #  # ]:          0 :                         { 4, 12, CALC_MODI_ID(SIPV6_31_0, data->level)},
    1873                 :            :                 };
    1874                 :            :                 /* First mask to be modified is the mask of 4th address byte. */
    1875                 :            :                 uint32_t midx = 3;
    1876                 :            : 
    1877                 :            :                 MLX5_ASSERT(data->offset + width <= 128);
    1878                 :          0 :                 off_be = 128 - (data->offset + width);
    1879         [ #  # ]:          0 :                 while (width > 0 && midx > 0) {
    1880         [ #  # ]:          0 :                         if (off_be < 32) {
    1881                 :          0 :                                 info[idx] = fields[midx];
    1882                 :          0 :                                 length = off_be + width <= 32 ?
    1883         [ #  # ]:          0 :                                          width : 32 - off_be;
    1884         [ #  # ]:          0 :                                 if (mask)
    1885         [ #  # ]:          0 :                                         mask[midx] = flow_modify_info_mask_32
    1886                 :            :                                                 (length, off_be);
    1887                 :            :                                 else
    1888                 :          0 :                                         info[idx].offset = off_be;
    1889                 :          0 :                                 width -= length;
    1890                 :            :                                 off_be = 0;
    1891                 :          0 :                                 idx++;
    1892                 :            :                         } else {
    1893                 :          0 :                                 off_be -= 32;
    1894                 :            :                         }
    1895                 :          0 :                         midx--;
    1896                 :            :                 }
    1897         [ #  # ]:          0 :                 if (!width)
    1898                 :            :                         break;
    1899                 :          0 :                 info[idx] = fields[midx];
    1900         [ #  # ]:          0 :                 if (mask)
    1901         [ #  # ]:          0 :                         mask[midx] = flow_modify_info_mask_32(width, off_be);
    1902                 :            :                 else
    1903                 :          0 :                         info[idx].offset = off_be;
    1904                 :            :                 break;
    1905                 :            :         }
    1906                 :          0 :         case RTE_FLOW_FIELD_IPV6_DST: {
    1907                 :            :                 /*
    1908                 :            :                  * Fields corresponding to IPv6 destination address bytes
    1909                 :            :                  * arranged according to network byte ordering.
    1910                 :            :                  */
    1911                 :          0 :                 struct field_modify_info fields[] = {
    1912         [ #  # ]:          0 :                         { 4, 0, CALC_MODI_ID(DIPV6_127_96, data->level)},
    1913         [ #  # ]:          0 :                         { 4, 4, CALC_MODI_ID(DIPV6_95_64, data->level)},
    1914         [ #  # ]:          0 :                         { 4, 8, CALC_MODI_ID(DIPV6_63_32, data->level)},
    1915         [ #  # ]:          0 :                         { 4, 12, CALC_MODI_ID(DIPV6_31_0, data->level)},
    1916                 :            :                 };
    1917                 :            :                 /* First mask to be modified is the mask of 4th address byte. */
    1918                 :            :                 uint32_t midx = 3;
    1919                 :            : 
    1920                 :            :                 MLX5_ASSERT(data->offset + width <= 128);
    1921                 :          0 :                 off_be = 128 - (data->offset + width);
    1922         [ #  # ]:          0 :                 while (width > 0 && midx > 0) {
    1923         [ #  # ]:          0 :                         if (off_be < 32) {
    1924                 :          0 :                                 info[idx] = fields[midx];
    1925                 :          0 :                                 length = off_be + width <= 32 ?
    1926         [ #  # ]:          0 :                                          width : 32 - off_be;
    1927         [ #  # ]:          0 :                                 if (mask)
    1928         [ #  # ]:          0 :                                         mask[midx] = flow_modify_info_mask_32
    1929                 :            :                                                 (length, off_be);
    1930                 :            :                                 else
    1931                 :          0 :                                         info[idx].offset = off_be;
    1932                 :          0 :                                 width -= length;
    1933                 :            :                                 off_be = 0;
    1934                 :          0 :                                 idx++;
    1935                 :            :                         } else {
    1936                 :          0 :                                 off_be -= 32;
    1937                 :            :                         }
    1938                 :          0 :                         midx--;
    1939                 :            :                 }
    1940         [ #  # ]:          0 :                 if (!width)
    1941                 :            :                         break;
    1942                 :          0 :                 info[idx] = fields[midx];
    1943         [ #  # ]:          0 :                 if (mask)
    1944         [ #  # ]:          0 :                         mask[midx] = flow_modify_info_mask_32(width, off_be);
    1945                 :            :                 else
    1946                 :          0 :                         info[idx].offset = off_be;
    1947                 :            :                 break;
    1948                 :            :         }
    1949                 :          0 :         case RTE_FLOW_FIELD_TCP_PORT_SRC:
    1950                 :            :                 MLX5_ASSERT(data->offset + width <= 16);
    1951                 :          0 :                 off_be = 16 - (data->offset + width);
    1952         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(TCP_SPORT, data->level);
    1953                 :          0 :                 info[idx] = (struct field_modify_info){2, 0, modi_id};
    1954         [ #  # ]:          0 :                 if (mask)
    1955                 :          0 :                         mask[idx] = flow_modify_info_mask_16(width, off_be);
    1956                 :            :                 else
    1957                 :          0 :                         info[idx].offset = off_be;
    1958                 :            :                 break;
    1959                 :          0 :         case RTE_FLOW_FIELD_TCP_PORT_DST:
    1960                 :            :                 MLX5_ASSERT(data->offset + width <= 16);
    1961                 :          0 :                 off_be = 16 - (data->offset + width);
    1962         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(TCP_DPORT, data->level);
    1963                 :          0 :                 info[idx] = (struct field_modify_info){2, 0, modi_id};
    1964         [ #  # ]:          0 :                 if (mask)
    1965                 :          0 :                         mask[idx] = flow_modify_info_mask_16(width, off_be);
    1966                 :            :                 else
    1967                 :          0 :                         info[idx].offset = off_be;
    1968                 :            :                 break;
    1969                 :          0 :         case RTE_FLOW_FIELD_TCP_SEQ_NUM:
    1970                 :            :                 MLX5_ASSERT(data->offset + width <= 32);
    1971                 :          0 :                 off_be = 32 - (data->offset + width);
    1972         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(TCP_SEQ_NUM, data->level);
    1973                 :          0 :                 info[idx] = (struct field_modify_info){4, 0, modi_id};
    1974         [ #  # ]:          0 :                 if (mask)
    1975                 :          0 :                         mask[idx] = flow_modify_info_mask_32(width, off_be);
    1976                 :            :                 else
    1977                 :          0 :                         info[idx].offset = off_be;
    1978                 :            :                 break;
    1979                 :          0 :         case RTE_FLOW_FIELD_TCP_ACK_NUM:
    1980                 :            :                 MLX5_ASSERT(data->offset + width <= 32);
    1981                 :          0 :                 off_be = 32 - (data->offset + width);
    1982         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(TCP_ACK_NUM, data->level);
    1983                 :          0 :                 info[idx] = (struct field_modify_info){4, 0, modi_id};
    1984         [ #  # ]:          0 :                 if (mask)
    1985                 :          0 :                         mask[idx] = flow_modify_info_mask_32(width, off_be);
    1986                 :            :                 else
    1987                 :          0 :                         info[idx].offset = off_be;
    1988                 :            :                 break;
    1989                 :          0 :         case RTE_FLOW_FIELD_TCP_FLAGS:
    1990                 :            :                 MLX5_ASSERT(data->offset + width <= 9);
    1991                 :          0 :                 off_be = 9 - (data->offset + width);
    1992         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(TCP_FLAGS, data->level);
    1993                 :          0 :                 info[idx] = (struct field_modify_info){2, 0, modi_id};
    1994         [ #  # ]:          0 :                 if (mask)
    1995                 :          0 :                         mask[idx] = flow_modify_info_mask_16(width, off_be);
    1996                 :            :                 else
    1997                 :          0 :                         info[idx].offset = off_be;
    1998                 :            :                 break;
    1999                 :          0 :         case RTE_FLOW_FIELD_TCP_DATA_OFFSET:
    2000                 :            :                 MLX5_ASSERT(data->offset + width <= 4);
    2001                 :          0 :                 off_be = 4 - (data->offset + width);
    2002         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(TCP_DATA_OFFSET, data->level);
    2003                 :          0 :                 info[idx] = (struct field_modify_info){1, 0, modi_id};
    2004         [ #  # ]:          0 :                 if (mask)
    2005                 :          0 :                         mask[idx] = flow_modify_info_mask_8(width, off_be);
    2006                 :            :                 else
    2007                 :          0 :                         info[idx].offset = off_be;
    2008                 :            :                 break;
    2009                 :          0 :         case RTE_FLOW_FIELD_UDP_PORT_SRC:
    2010                 :            :                 MLX5_ASSERT(data->offset + width <= 16);
    2011                 :          0 :                 off_be = 16 - (data->offset + width);
    2012         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(UDP_SPORT, data->level);
    2013                 :          0 :                 info[idx] = (struct field_modify_info){2, 0, modi_id};
    2014         [ #  # ]:          0 :                 if (mask)
    2015                 :          0 :                         mask[idx] = flow_modify_info_mask_16(width, off_be);
    2016                 :            :                 else
    2017                 :          0 :                         info[idx].offset = off_be;
    2018                 :            :                 break;
    2019                 :          0 :         case RTE_FLOW_FIELD_UDP_PORT_DST:
    2020                 :            :                 MLX5_ASSERT(data->offset + width <= 16);
    2021                 :          0 :                 off_be = 16 - (data->offset + width);
    2022         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(UDP_DPORT, data->level);
    2023                 :          0 :                 info[idx] = (struct field_modify_info){2, 0, modi_id};
    2024         [ #  # ]:          0 :                 if (mask)
    2025                 :          0 :                         mask[idx] = flow_modify_info_mask_16(width, off_be);
    2026                 :            :                 else
    2027                 :          0 :                         info[idx].offset = off_be;
    2028                 :            :                 break;
    2029                 :          0 :         case RTE_FLOW_FIELD_VXLAN_VNI:
    2030                 :            :         case RTE_FLOW_FIELD_GENEVE_VNI:
    2031                 :            :                 MLX5_ASSERT(data->offset + width <= 24);
    2032                 :            :                 /* VNI is on bits 31-8 of TUNNEL_HDR_DW_1. */
    2033                 :          0 :                 off_be = 24 - (data->offset + width) + 8;
    2034                 :          0 :                 info[idx] = (struct field_modify_info){4, 0,
    2035                 :            :                                         MLX5_MODI_TUNNEL_HDR_DW_1};
    2036         [ #  # ]:          0 :                 if (mask)
    2037                 :          0 :                         mask[idx] = flow_modify_info_mask_32(width, off_be);
    2038                 :            :                 else
    2039                 :          0 :                         info[idx].offset = off_be;
    2040                 :            :                 break;
    2041                 :            :         case RTE_FLOW_FIELD_GENEVE_OPT_TYPE:
    2042                 :            :                 MLX5_ASSERT(data->offset + width <= 8);
    2043                 :            :                 modi_id = flow_geneve_opt_modi_field_get(priv, data);
    2044         [ #  # ]:          0 :                 if (modi_id < 0)
    2045                 :            :                         return;
    2046                 :            :                 /* Type is on bits 16-8 of GENEVE option header (DW0). */
    2047                 :          0 :                 off_be = 32 - (16 + data->offset + width);
    2048                 :          0 :                 info[idx] = (struct field_modify_info){4, 0, modi_id};
    2049         [ #  # ]:          0 :                 if (mask)
    2050                 :          0 :                         mask[idx] = flow_modify_info_mask_32(width, off_be);
    2051                 :            :                 else
    2052                 :          0 :                         info[idx].offset = off_be;
    2053                 :            :                 break;
    2054                 :            :         case RTE_FLOW_FIELD_GENEVE_OPT_CLASS:
    2055                 :            :                 MLX5_ASSERT(data->offset + width <= 16);
    2056                 :            :                 modi_id = flow_geneve_opt_modi_field_get(priv, data);
    2057         [ #  # ]:          0 :                 if (modi_id < 0)
    2058                 :            :                         return;
    2059                 :            :                 /* Class is on bits 31-16 of GENEVE option header (DW0). */
    2060                 :          0 :                 off_be = 32 - (data->offset + width);
    2061                 :          0 :                 info[idx] = (struct field_modify_info){4, 0, modi_id};
    2062         [ #  # ]:          0 :                 if (mask)
    2063                 :          0 :                         mask[idx] = flow_modify_info_mask_32(width, off_be);
    2064                 :            :                 else
    2065                 :          0 :                         info[idx].offset = off_be;
    2066                 :            :                 break;
    2067                 :          0 :         case RTE_FLOW_FIELD_GENEVE_OPT_DATA:
    2068         [ #  # ]:          0 :                 if ((data->offset % 32) + width > 32) {
    2069                 :          0 :                         DRV_LOG(ERR, "Geneve TLV option data is per DW.");
    2070                 :          0 :                         return;
    2071                 :            :                 }
    2072                 :            :                 modi_id = flow_geneve_opt_modi_field_get(priv, data);
    2073         [ #  # ]:          0 :                 if (modi_id < 0)
    2074                 :            :                         return;
    2075                 :            :                 /* Use offset inside DW. */
    2076                 :          0 :                 off_be = 32 - ((data->offset % 32) + width);
    2077                 :          0 :                 info[idx] = (struct field_modify_info){4, 0, modi_id};
    2078         [ #  # ]:          0 :                 if (mask)
    2079                 :          0 :                         mask[idx] = flow_modify_info_mask_32(width, off_be);
    2080                 :            :                 else
    2081                 :          0 :                         info[idx].offset = off_be;
    2082                 :            :                 break;
    2083                 :          0 :         case RTE_FLOW_FIELD_GTP_TEID:
    2084                 :            :                 MLX5_ASSERT(data->offset + width <= 32);
    2085                 :          0 :                 off_be = 32 - (data->offset + width);
    2086                 :          0 :                 info[idx] = (struct field_modify_info){4, 0,
    2087                 :            :                                         MLX5_MODI_GTP_TEID};
    2088         [ #  # ]:          0 :                 if (mask)
    2089                 :          0 :                         mask[idx] = flow_modify_info_mask_32(width, off_be);
    2090                 :            :                 else
    2091                 :          0 :                         info[idx].offset = off_be;
    2092                 :            :                 break;
    2093                 :          0 :         case RTE_FLOW_FIELD_MPLS:
    2094                 :            :                 MLX5_ASSERT(data->offset + width <= 32);
    2095                 :          0 :                 off_be = 32 - (data->offset + width);
    2096                 :            :                 modi_id = mlx5_mpls_modi_field_get(data);
    2097                 :          0 :                 info[idx] = (struct field_modify_info){4, 0, modi_id};
    2098         [ #  # ]:          0 :                 if (mask)
    2099                 :          0 :                         mask[idx] = flow_modify_info_mask_32(width, off_be);
    2100                 :            :                 else
    2101                 :          0 :                         info[idx].offset = off_be;
    2102                 :            :                 break;
    2103                 :            :         case RTE_FLOW_FIELD_TAG:
    2104                 :            :                 {
    2105                 :            :                         MLX5_ASSERT(data->offset + width <= 32);
    2106                 :            :                         uint8_t tag_index = flow_tag_index_get(data);
    2107                 :            :                         int reg;
    2108                 :            : 
    2109                 :            :                         off_be = (tag_index == RTE_PMD_MLX5_LINEAR_HASH_TAG_INDEX) ?
    2110         [ #  # ]:          0 :                                  16 - (data->offset + width) + 16 : data->offset;
    2111         [ #  # ]:          0 :                         if (priv->sh->config.dv_flow_en == 2)
    2112         [ #  # ]:          0 :                                 reg = flow_hw_get_reg_id(dev,
    2113                 :            :                                                          RTE_FLOW_ITEM_TYPE_TAG,
    2114                 :            :                                                          tag_index);
    2115                 :            :                         else
    2116                 :          0 :                                 reg = mlx5_flow_get_reg_id(dev, MLX5_APP_TAG,
    2117                 :            :                                                            tag_index, error);
    2118         [ #  # ]:          0 :                         if (reg < 0)
    2119                 :            :                                 return;
    2120                 :            :                         MLX5_ASSERT(reg != REG_NON);
    2121                 :            :                         MLX5_ASSERT((unsigned int)reg < RTE_DIM(reg_to_field));
    2122                 :          0 :                         info[idx] = (struct field_modify_info){4, 0,
    2123                 :          0 :                                                 reg_to_field[reg]};
    2124         [ #  # ]:          0 :                         if (mask)
    2125                 :          0 :                                 mask[idx] = flow_modify_info_mask_32
    2126                 :            :                                         (width, off_be);
    2127                 :            :                         else
    2128                 :          0 :                                 info[idx].offset = off_be;
    2129                 :            :                 }
    2130                 :            :                 break;
    2131                 :          0 :         case RTE_FLOW_FIELD_MARK:
    2132                 :            :                 {
    2133                 :          0 :                         uint32_t mark_mask = priv->sh->dv_mark_mask;
    2134                 :            :                         uint32_t mark_count = rte_popcount32(mark_mask);
    2135                 :            :                         RTE_SET_USED(mark_count);
    2136                 :            :                         MLX5_ASSERT(data->offset + width <= mark_count);
    2137                 :          0 :                         int reg = mlx5_flow_get_reg_id(dev, MLX5_FLOW_MARK,
    2138                 :            :                                                        0, error);
    2139         [ #  # ]:          0 :                         if (reg < 0)
    2140                 :            :                                 return;
    2141                 :            :                         MLX5_ASSERT(reg != REG_NON);
    2142                 :            :                         MLX5_ASSERT((unsigned int)reg < RTE_DIM(reg_to_field));
    2143                 :          0 :                         info[idx] = (struct field_modify_info){4, 0,
    2144                 :          0 :                                                 reg_to_field[reg]};
    2145         [ #  # ]:          0 :                         if (mask)
    2146                 :          0 :                                 mask[idx] = flow_modify_info_mask_32_masked
    2147         [ #  # ]:          0 :                                         (width, data->offset, mark_mask);
    2148                 :            :                         else
    2149                 :          0 :                                 info[idx].offset = data->offset;
    2150                 :            :                 }
    2151                 :            :                 break;
    2152                 :          0 :         case RTE_FLOW_FIELD_META:
    2153                 :            :                 {
    2154                 :          0 :                         uint32_t meta_mask = priv->sh->dv_meta_mask;
    2155                 :            :                         uint32_t meta_count = rte_popcount32(meta_mask);
    2156                 :            :                         RTE_SET_USED(meta_count);
    2157                 :            :                         MLX5_ASSERT(data->offset + width <= meta_count);
    2158                 :          0 :                         int reg = flow_dv_get_metadata_reg(dev, attr, error);
    2159         [ #  # ]:          0 :                         if (reg < 0)
    2160                 :            :                                 return;
    2161                 :            :                         MLX5_ASSERT(reg != REG_NON);
    2162                 :            :                         MLX5_ASSERT((unsigned int)reg < RTE_DIM(reg_to_field));
    2163                 :          0 :                         info[idx] = (struct field_modify_info){4, 0,
    2164                 :          0 :                                                 reg_to_field[reg]};
    2165         [ #  # ]:          0 :                         if (mask)
    2166                 :          0 :                                 mask[idx] = flow_modify_info_mask_32_masked
    2167         [ #  # ]:          0 :                                         (width, data->offset, meta_mask);
    2168                 :            :                         else
    2169                 :          0 :                                 info[idx].offset = data->offset;
    2170                 :            :                 }
    2171                 :            :                 break;
    2172                 :          0 :         case RTE_FLOW_FIELD_IPV4_ECN:
    2173                 :            :                 MLX5_ASSERT(data->offset + width <= 2);
    2174                 :          0 :                 off_be = 2 - (data->offset + width);
    2175         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(IP_ECN, data->level);
    2176                 :          0 :                 info[idx] = (struct field_modify_info){1, 0, modi_id};
    2177         [ #  # ]:          0 :                 if (mask)
    2178                 :          0 :                         mask[idx] = flow_modify_info_mask_8(width, off_be);
    2179                 :            :                 else
    2180                 :          0 :                         info[idx].offset = off_be;
    2181                 :            :                 break;
    2182                 :          0 :         case RTE_FLOW_FIELD_IPV6_ECN:
    2183                 :            :                 MLX5_ASSERT(data->offset + width <= 2);
    2184                 :          0 :                 off_be = 2 - (data->offset + width);
    2185         [ #  # ]:          0 :                 if (mlx5_dv_modify_ipv6_traffic_class_supported(priv))
    2186                 :          0 :                         info[idx] = (struct field_modify_info){1, 0,
    2187                 :            :                                                 MLX5_MODI_OUT_IPV6_TRAFFIC_CLASS};
    2188                 :            :                 else
    2189                 :          0 :                         info[idx] = (struct field_modify_info){1, 0,
    2190                 :            :                                                 MLX5_MODI_OUT_IP_ECN};
    2191         [ #  # ]:          0 :                 if (mask)
    2192                 :          0 :                         mask[idx] = flow_modify_info_mask_8(width, off_be);
    2193                 :            :                 else
    2194                 :          0 :                         info[idx].offset = off_be;
    2195                 :            :                 break;
    2196                 :          0 :         case RTE_FLOW_FIELD_GTP_PSC_QFI:
    2197                 :            :                 MLX5_ASSERT(data->offset + width <= 8);
    2198                 :          0 :                 off_be = data->offset + 8;
    2199                 :          0 :                 info[idx] = (struct field_modify_info){4, 0,
    2200                 :            :                                         MLX5_MODI_GTPU_FIRST_EXT_DW_0};
    2201         [ #  # ]:          0 :                 if (mask)
    2202                 :          0 :                         mask[idx] = flow_modify_info_mask_32(width, off_be);
    2203                 :            :                 else
    2204                 :          0 :                         info[idx].offset = off_be;
    2205                 :            :                 break;
    2206                 :          0 :         case MLX5_RTE_FLOW_FIELD_META_REG:
    2207                 :            :                 {
    2208         [ #  # ]:          0 :                         uint32_t meta_mask = priv->sh->dv_meta_mask;
    2209                 :            :                         uint32_t meta_count = rte_popcount32(meta_mask);
    2210                 :            :                         uint8_t reg = flow_tag_index_get(data);
    2211                 :            : 
    2212                 :            :                         RTE_SET_USED(meta_count);
    2213                 :            :                         MLX5_ASSERT(data->offset + width <= meta_count);
    2214                 :            :                         MLX5_ASSERT(reg != REG_NON);
    2215                 :            :                         MLX5_ASSERT(reg < RTE_DIM(reg_to_field));
    2216                 :          0 :                         info[idx] = (struct field_modify_info){4, 0, reg_to_field[reg]};
    2217         [ #  # ]:          0 :                         if (mask)
    2218                 :          0 :                                 mask[idx] = flow_modify_info_mask_32_masked
    2219         [ #  # ]:          0 :                                         (width, data->offset, meta_mask);
    2220                 :            :                         else
    2221                 :          0 :                                 info[idx].offset = data->offset;
    2222                 :            :                 }
    2223                 :            :                 break;
    2224                 :          0 :         case RTE_FLOW_FIELD_METER_COLOR:
    2225                 :            :                 {
    2226                 :            :                         const uint32_t color_mask =
    2227                 :            :                                 (UINT32_C(1) << MLX5_MTR_COLOR_BITS) - 1;
    2228                 :            :                         int reg;
    2229                 :            : 
    2230         [ #  # ]:          0 :                         if (priv->sh->config.dv_flow_en == 2)
    2231                 :            :                                 reg = flow_hw_get_reg_id
    2232                 :            :                                         (dev,
    2233                 :            :                                          RTE_FLOW_ITEM_TYPE_METER_COLOR, 0);
    2234                 :            :                         else
    2235                 :          0 :                                 reg = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR,
    2236                 :            :                                                        0, error);
    2237         [ #  # ]:          0 :                         if (reg < 0)
    2238                 :            :                                 return;
    2239                 :            :                         MLX5_ASSERT(reg != REG_NON);
    2240                 :            :                         MLX5_ASSERT((unsigned int)reg < RTE_DIM(reg_to_field));
    2241                 :          0 :                         info[idx] = (struct field_modify_info){4, 0,
    2242                 :          0 :                                                 reg_to_field[reg]};
    2243         [ #  # ]:          0 :                         if (mask)
    2244                 :          0 :                                 mask[idx] = flow_modify_info_mask_32_masked
    2245         [ #  # ]:          0 :                                         (width, data->offset, color_mask);
    2246                 :            :                         else
    2247                 :          0 :                                 info[idx].offset = data->offset;
    2248                 :            :                 }
    2249                 :            :                 break;
    2250                 :          0 :         case RTE_FLOW_FIELD_IPV4_PROTO: /* Fall-through. */
    2251                 :            :         case RTE_FLOW_FIELD_IPV6_PROTO:
    2252                 :            :                 MLX5_ASSERT(data->offset + width <= 8);
    2253                 :          0 :                 off_be = 8 - (data->offset + width);
    2254                 :          0 :                 info[idx] = (struct field_modify_info){1, 0, MLX5_MODI_OUT_IP_PROTOCOL};
    2255         [ #  # ]:          0 :                 if (mask)
    2256                 :          0 :                         mask[idx] = flow_modify_info_mask_8(width, off_be);
    2257                 :            :                 else
    2258                 :          0 :                         info[idx].offset = off_be;
    2259                 :            :                 break;
    2260                 :          0 :         case RTE_FLOW_FIELD_ESP_PROTO:
    2261                 :            :                 MLX5_ASSERT(data->offset + width <= 8);
    2262                 :          0 :                 off_be = 8 - (data->offset + width);
    2263                 :          0 :                 info[idx] = (struct field_modify_info){1, 0, MLX5_MODI_OUT_IPSEC_NEXT_HDR};
    2264         [ #  # ]:          0 :                 if (mask)
    2265                 :          0 :                         mask[idx] = flow_modify_info_mask_8(width, off_be);
    2266                 :            :                 else
    2267                 :          0 :                         info[idx].offset = off_be;
    2268                 :            :                 break;
    2269                 :          0 :         case RTE_FLOW_FIELD_ESP_SPI:
    2270                 :            :                 MLX5_ASSERT(data->offset + width <= 32);
    2271                 :          0 :                 off_be = 32 - (data->offset + width);
    2272         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(ESP_SPI, data->level);
    2273                 :          0 :                 info[idx] = (struct field_modify_info){4, 0, modi_id};
    2274         [ #  # ]:          0 :                 if (mask)
    2275                 :          0 :                         mask[idx] = flow_modify_info_mask_32(width, off_be);
    2276                 :            :                 else
    2277                 :          0 :                         info[idx].offset = off_be;
    2278                 :            :                 break;
    2279                 :          0 :         case RTE_FLOW_FIELD_ESP_SEQ_NUM:
    2280                 :            :                 MLX5_ASSERT(data->offset + width <= 32);
    2281                 :          0 :                 off_be = 32 - (data->offset + width);
    2282         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(ESP_SEQ_NUM, data->level);
    2283                 :          0 :                 info[idx] = (struct field_modify_info){4, 0, modi_id};
    2284         [ #  # ]:          0 :                 if (mask)
    2285                 :          0 :                         mask[idx] = flow_modify_info_mask_32(width, off_be);
    2286                 :            :                 else
    2287                 :          0 :                         info[idx].offset = off_be;
    2288                 :            :                 break;
    2289                 :          0 :         case RTE_FLOW_FIELD_FLEX_ITEM:
    2290                 :            :                 MLX5_ASSERT(data->flex_handle != NULL && !(data->offset & 0x7));
    2291                 :          0 :                 mlx5_modify_flex_item(dev, (const struct mlx5_flex_item *)data->flex_handle,
    2292                 :            :                                       data, info, mask, width);
    2293                 :          0 :                 break;
    2294                 :          0 :         case RTE_FLOW_FIELD_HASH_RESULT:
    2295                 :            :                 MLX5_ASSERT(data->offset + width <= 32);
    2296                 :          0 :                 off_be = 32 - (data->offset + width);
    2297                 :          0 :                 info[idx] = (struct field_modify_info){4, 0,
    2298                 :            :                                                        MLX5_MODI_HASH_RESULT};
    2299         [ #  # ]:          0 :                 if (mask)
    2300                 :          0 :                         mask[idx] = flow_modify_info_mask_32(width, off_be);
    2301                 :            :                 else
    2302                 :          0 :                         info[idx].offset = off_be;
    2303                 :            :                 break;
    2304                 :            :         case RTE_FLOW_FIELD_POINTER:
    2305                 :            :         case RTE_FLOW_FIELD_VALUE:
    2306                 :            :         default:
    2307                 :            :                 MLX5_ASSERT(false);
    2308                 :            :                 break;
    2309                 :            :         }
    2310                 :            : }
    2311                 :            : 
    2312                 :            : /**
    2313                 :            :  * Convert modify_field action to DV specification.
    2314                 :            :  *
    2315                 :            :  * @param[in] dev
    2316                 :            :  *   Pointer to the rte_eth_dev structure.
    2317                 :            :  * @param[in,out] resource
    2318                 :            :  *   Pointer to the modify-header resource.
    2319                 :            :  * @param[in] action
    2320                 :            :  *   Pointer to action specification.
    2321                 :            :  * @param[in] attr
    2322                 :            :  *   Attributes of flow that includes this item.
    2323                 :            :  * @param[out] error
    2324                 :            :  *   Pointer to the error structure.
    2325                 :            :  *
    2326                 :            :  * @return
    2327                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    2328                 :            :  */
    2329                 :            : static int
    2330                 :          0 : flow_dv_convert_action_modify_field
    2331                 :            :                         (struct rte_eth_dev *dev,
    2332                 :            :                          struct mlx5_flow_dv_modify_hdr_resource *resource,
    2333                 :            :                          const struct rte_flow_action *action,
    2334                 :            :                          const struct rte_flow_attr *attr,
    2335                 :            :                          struct rte_flow_error *error)
    2336                 :            : {
    2337                 :          0 :         const struct rte_flow_action_modify_field *conf =
    2338                 :            :                 (const struct rte_flow_action_modify_field *)(action->conf);
    2339                 :          0 :         struct rte_flow_item item = {
    2340                 :            :                 .spec = NULL,
    2341                 :            :                 .mask = NULL
    2342                 :            :         };
    2343                 :          0 :         struct field_modify_info field[MLX5_ACT_MAX_MOD_FIELDS] = {
    2344                 :            :                                                                 {0, 0, 0} };
    2345                 :          0 :         struct field_modify_info dcopy[MLX5_ACT_MAX_MOD_FIELDS] = {
    2346                 :            :                                                                 {0, 0, 0} };
    2347                 :          0 :         uint32_t mask[MLX5_ACT_MAX_MOD_FIELDS] = {0, 0, 0, 0, 0};
    2348                 :          0 :         uint32_t type, meta = 0, dscp = 0;
    2349                 :            : 
    2350         [ #  # ]:          0 :         if (conf->src.field == RTE_FLOW_FIELD_POINTER ||
    2351                 :            :             conf->src.field == RTE_FLOW_FIELD_VALUE) {
    2352                 :          0 :                 type = conf->operation == RTE_FLOW_MODIFY_SET ?
    2353         [ #  # ]:          0 :                         MLX5_MODIFICATION_TYPE_SET : MLX5_MODIFICATION_TYPE_ADD;
    2354                 :            :                 /** For SET fill the destination field (field) first. */
    2355                 :          0 :                 mlx5_flow_field_id_to_modify_info(&conf->dst, field, mask,
    2356                 :          0 :                                                   conf->width, dev,
    2357                 :            :                                                   attr, error);
    2358                 :          0 :                 item.spec = conf->src.field == RTE_FLOW_FIELD_POINTER ?
    2359         [ #  # ]:          0 :                                         (void *)(uintptr_t)conf->src.pvalue :
    2360                 :            :                                         (void *)(uintptr_t)&conf->src.value;
    2361         [ #  # ]:          0 :                 if (conf->dst.field == RTE_FLOW_FIELD_META ||
    2362         [ #  # ]:          0 :                     conf->dst.field == RTE_FLOW_FIELD_TAG ||
    2363                 :            :                     conf->dst.field == RTE_FLOW_FIELD_METER_COLOR) {
    2364                 :          0 :                         meta = *(const unaligned_uint32_t *)item.spec;
    2365         [ #  # ]:          0 :                         meta = rte_cpu_to_be_32(meta);
    2366                 :          0 :                         item.spec = &meta;
    2367                 :            :                 }
    2368   [ #  #  #  # ]:          0 :                 if (mlx5_dv_modify_ipv6_traffic_class_supported(dev->data->dev_private) &&
    2369                 :          0 :                     conf->dst.field == RTE_FLOW_FIELD_IPV6_DSCP &&
    2370         [ #  # ]:          0 :                     !(mask[0] & MLX5_IPV6_HDR_ECN_MASK)) {
    2371                 :          0 :                         dscp = *(const unaligned_uint32_t *)item.spec;
    2372                 :            :                         /*
    2373                 :            :                          * IPv6 DSCP uses OUT_IPV6_TRAFFIC_CLASS as ID but it starts from 2
    2374                 :            :                          * bits left. Shift the data left for IPv6 DSCP
    2375                 :            :                          */
    2376                 :          0 :                         dscp <<= MLX5_IPV6_HDR_DSCP_SHIFT;
    2377                 :          0 :                         item.spec = &dscp;
    2378                 :            :                 }
    2379                 :            :         } else {
    2380                 :            :                 type = MLX5_MODIFICATION_TYPE_COPY;
    2381                 :            :                 /** For COPY fill the destination field (dcopy) without mask. */
    2382                 :          0 :                 mlx5_flow_field_id_to_modify_info(&conf->dst, dcopy, NULL,
    2383                 :          0 :                                                   conf->width, dev,
    2384                 :            :                                                   attr, error);
    2385                 :            :                 /** Then construct the source field (field) with mask. */
    2386                 :          0 :                 mlx5_flow_field_id_to_modify_info(&conf->src, field, mask,
    2387                 :          0 :                                                   conf->width, dev,
    2388                 :            :                                                   attr, error);
    2389                 :            :         }
    2390                 :          0 :         item.mask = &mask;
    2391                 :          0 :         return flow_dv_convert_modify_action(&item,
    2392                 :            :                         field, dcopy, resource, type, error);
    2393                 :            : }
    2394                 :            : 
    2395                 :            : /**
    2396                 :            :  * Validate MARK item.
    2397                 :            :  *
    2398                 :            :  * @param[in] dev
    2399                 :            :  *   Pointer to the rte_eth_dev structure.
    2400                 :            :  * @param[in] item
    2401                 :            :  *   Item specification.
    2402                 :            :  * @param[in] attr
    2403                 :            :  *   Attributes of flow that includes this item.
    2404                 :            :  * @param[out] error
    2405                 :            :  *   Pointer to error structure.
    2406                 :            :  *
    2407                 :            :  * @return
    2408                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    2409                 :            :  */
    2410                 :            : static int
    2411                 :          0 : flow_dv_validate_item_mark(struct rte_eth_dev *dev,
    2412                 :            :                            const struct rte_flow_item *item,
    2413                 :            :                            const struct rte_flow_attr *attr __rte_unused,
    2414                 :            :                            struct rte_flow_error *error)
    2415                 :            : {
    2416                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    2417                 :          0 :         struct mlx5_sh_config *config = &priv->sh->config;
    2418                 :          0 :         const struct rte_flow_item_mark *spec = item->spec;
    2419                 :          0 :         const struct rte_flow_item_mark *mask = item->mask;
    2420                 :          0 :         const struct rte_flow_item_mark nic_mask = {
    2421                 :          0 :                 .id = priv->sh->dv_mark_mask,
    2422                 :            :         };
    2423                 :            :         int ret;
    2424                 :            : 
    2425         [ #  # ]:          0 :         if (config->dv_xmeta_en == MLX5_XMETA_MODE_LEGACY)
    2426                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    2427                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2428                 :            :                                           "extended metadata feature"
    2429                 :            :                                           " isn't enabled");
    2430         [ #  # ]:          0 :         if (!mlx5_flow_ext_mreg_supported(dev))
    2431                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    2432                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2433                 :            :                                           "extended metadata register"
    2434                 :            :                                           " isn't supported");
    2435         [ #  # ]:          0 :         if (!nic_mask.id)
    2436                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    2437                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2438                 :            :                                           "extended metadata register"
    2439                 :            :                                           " isn't available");
    2440                 :          0 :         ret = mlx5_flow_get_reg_id(dev, MLX5_FLOW_MARK, 0, error);
    2441         [ #  # ]:          0 :         if (ret < 0)
    2442                 :            :                 return ret;
    2443         [ #  # ]:          0 :         if (!spec)
    2444                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2445                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
    2446                 :          0 :                                           item->spec,
    2447                 :            :                                           "data cannot be empty");
    2448         [ #  # ]:          0 :         if (spec->id >= (MLX5_FLOW_MARK_MAX & nic_mask.id))
    2449                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2450                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF,
    2451                 :          0 :                                           &spec->id,
    2452                 :            :                                           "mark id exceeds the limit");
    2453         [ #  # ]:          0 :         if (!mask)
    2454                 :            :                 mask = &nic_mask;
    2455         [ #  # ]:          0 :         if (!mask->id)
    2456                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2457                 :            :                                         RTE_FLOW_ERROR_TYPE_ITEM_SPEC, NULL,
    2458                 :            :                                         "mask cannot be zero");
    2459                 :            : 
    2460                 :          0 :         ret = mlx5_flow_item_acceptable(item, (const uint8_t *)mask,
    2461                 :            :                                         (const uint8_t *)&nic_mask,
    2462                 :            :                                         sizeof(struct rte_flow_item_mark),
    2463                 :            :                                         MLX5_ITEM_RANGE_NOT_ACCEPTED, error);
    2464                 :            :         if (ret < 0)
    2465                 :            :                 return ret;
    2466                 :            :         return 0;
    2467                 :            : }
    2468                 :            : 
    2469                 :            : /**
    2470                 :            :  * Validate META item.
    2471                 :            :  *
    2472                 :            :  * @param[in] dev
    2473                 :            :  *   Pointer to the rte_eth_dev structure.
    2474                 :            :  * @param[in] item
    2475                 :            :  *   Item specification.
    2476                 :            :  * @param[in] attr
    2477                 :            :  *   Attributes of flow that includes this item.
    2478                 :            :  * @param[out] error
    2479                 :            :  *   Pointer to error structure.
    2480                 :            :  *
    2481                 :            :  * @return
    2482                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    2483                 :            :  */
    2484                 :            : static int
    2485                 :          0 : flow_dv_validate_item_meta(struct rte_eth_dev *dev __rte_unused,
    2486                 :            :                            const struct rte_flow_item *item,
    2487                 :            :                            const struct rte_flow_attr *attr,
    2488                 :            :                            struct rte_flow_error *error)
    2489                 :            : {
    2490                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    2491                 :          0 :         struct mlx5_sh_config *config = &priv->sh->config;
    2492                 :          0 :         const struct rte_flow_item_meta *spec = item->spec;
    2493                 :          0 :         const struct rte_flow_item_meta *mask = item->mask;
    2494                 :          0 :         struct rte_flow_item_meta nic_mask = {
    2495                 :            :                 .data = UINT32_MAX
    2496                 :            :         };
    2497                 :            :         int reg;
    2498                 :            :         int ret;
    2499                 :            : 
    2500         [ #  # ]:          0 :         if (!spec)
    2501                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2502                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
    2503                 :            :                                           item->spec,
    2504                 :            :                                           "data cannot be empty");
    2505         [ #  # ]:          0 :         if (config->dv_xmeta_en != MLX5_XMETA_MODE_LEGACY) {
    2506         [ #  # ]:          0 :                 if (!mlx5_flow_ext_mreg_supported(dev))
    2507                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    2508                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2509                 :            :                                           "extended metadata register"
    2510                 :            :                                           " isn't supported");
    2511                 :          0 :                 reg = flow_dv_get_metadata_reg(dev, attr, error);
    2512         [ #  # ]:          0 :                 if (reg < 0)
    2513                 :            :                         return reg;
    2514         [ #  # ]:          0 :                 if (reg == REG_NON)
    2515                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    2516                 :            :                                         RTE_FLOW_ERROR_TYPE_ITEM, item,
    2517                 :            :                                         "unavailable extended metadata register");
    2518         [ #  # ]:          0 :                 if (reg == REG_B)
    2519                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    2520                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2521                 :            :                                           "match on reg_b "
    2522                 :            :                                           "isn't supported");
    2523         [ #  # ]:          0 :                 if (reg != REG_A)
    2524                 :          0 :                         nic_mask.data = priv->sh->dv_meta_mask;
    2525                 :            :         } else {
    2526         [ #  # ]:          0 :                 if (attr->transfer)
    2527                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    2528                 :            :                                         RTE_FLOW_ERROR_TYPE_ITEM, item,
    2529                 :            :                                         "extended metadata feature "
    2530                 :            :                                         "should be enabled when "
    2531                 :            :                                         "meta item is requested "
    2532                 :            :                                         "with e-switch mode ");
    2533         [ #  # ]:          0 :                 if (attr->ingress)
    2534                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    2535                 :            :                                         RTE_FLOW_ERROR_TYPE_ITEM, item,
    2536                 :            :                                         "match on metadata for ingress "
    2537                 :            :                                         "is not supported in legacy "
    2538                 :            :                                         "metadata mode");
    2539                 :            :         }
    2540         [ #  # ]:          0 :         if (!mask)
    2541                 :            :                 mask = &rte_flow_item_meta_mask;
    2542         [ #  # ]:          0 :         if (!mask->data)
    2543                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2544                 :            :                                         RTE_FLOW_ERROR_TYPE_ITEM_SPEC, NULL,
    2545                 :            :                                         "mask cannot be zero");
    2546                 :            : 
    2547                 :          0 :         ret = mlx5_flow_item_acceptable(item, (const uint8_t *)mask,
    2548                 :            :                                         (const uint8_t *)&nic_mask,
    2549                 :            :                                         sizeof(struct rte_flow_item_meta),
    2550                 :            :                                         MLX5_ITEM_RANGE_NOT_ACCEPTED, error);
    2551                 :          0 :         return ret;
    2552                 :            : }
    2553                 :            : 
    2554                 :            : /**
    2555                 :            :  * Validate TAG item.
    2556                 :            :  *
    2557                 :            :  * @param[in] dev
    2558                 :            :  *   Pointer to the rte_eth_dev structure.
    2559                 :            :  * @param[in] item
    2560                 :            :  *   Item specification.
    2561                 :            :  * @param[in] tag_bitmap
    2562                 :            :  *   Tag index bitmap.
    2563                 :            :  * @param[in] attr
    2564                 :            :  *   Attributes of flow that includes this item.
    2565                 :            :  * @param[out] error
    2566                 :            :  *   Pointer to error structure.
    2567                 :            :  *
    2568                 :            :  * @return
    2569                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    2570                 :            :  */
    2571                 :            : static int
    2572                 :          0 : flow_dv_validate_item_tag(struct rte_eth_dev *dev,
    2573                 :            :                           const struct rte_flow_item *item,
    2574                 :            :                           uint32_t *tag_bitmap,
    2575                 :            :                           const struct rte_flow_attr *attr __rte_unused,
    2576                 :            :                           struct rte_flow_error *error)
    2577                 :            : {
    2578                 :          0 :         const struct rte_flow_item_tag *spec = item->spec;
    2579                 :          0 :         const struct rte_flow_item_tag *mask = item->mask;
    2580                 :          0 :         const struct rte_flow_item_tag nic_mask = {
    2581                 :            :                 .data = RTE_BE32(UINT32_MAX),
    2582                 :            :                 .index = 0xff,
    2583                 :            :         };
    2584                 :            :         int ret;
    2585                 :            : 
    2586         [ #  # ]:          0 :         if (!mlx5_flow_ext_mreg_supported(dev))
    2587                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    2588                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2589                 :            :                                           "extensive metadata register"
    2590                 :            :                                           " isn't supported");
    2591         [ #  # ]:          0 :         if (!spec)
    2592                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2593                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
    2594                 :          0 :                                           item->spec,
    2595                 :            :                                           "data cannot be empty");
    2596         [ #  # ]:          0 :         if (!mask)
    2597                 :            :                 mask = &rte_flow_item_tag_mask;
    2598         [ #  # ]:          0 :         if (!mask->data)
    2599                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2600                 :            :                                         RTE_FLOW_ERROR_TYPE_ITEM_SPEC, NULL,
    2601                 :            :                                         "mask cannot be zero");
    2602                 :            : 
    2603                 :          0 :         ret = mlx5_flow_item_acceptable(item, (const uint8_t *)mask,
    2604                 :            :                                         (const uint8_t *)&nic_mask,
    2605                 :            :                                         sizeof(struct rte_flow_item_tag),
    2606                 :            :                                         MLX5_ITEM_RANGE_NOT_ACCEPTED, error);
    2607         [ #  # ]:          0 :         if (ret < 0)
    2608                 :            :                 return ret;
    2609         [ #  # ]:          0 :         if (mask->index != 0xff)
    2610                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2611                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_SPEC, NULL,
    2612                 :            :                                           "partial mask for tag index"
    2613                 :            :                                           " is not supported");
    2614                 :          0 :         ret = mlx5_flow_get_reg_id(dev, MLX5_APP_TAG, spec->index, error);
    2615         [ #  # ]:          0 :         if (ret < 0)
    2616                 :            :                 return ret;
    2617                 :            :         MLX5_ASSERT(ret != REG_NON);
    2618         [ #  # ]:          0 :         if (*tag_bitmap & (1 << ret))
    2619                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2620                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
    2621                 :          0 :                                           item->spec,
    2622                 :            :                                           "Duplicated tag index");
    2623                 :          0 :         *tag_bitmap |= 1 << ret;
    2624                 :          0 :         return 0;
    2625                 :            : }
    2626                 :            : 
    2627                 :            : /**
    2628                 :            :  * Validate vport item.
    2629                 :            :  *
    2630                 :            :  * @param[in] dev
    2631                 :            :  *   Pointer to the rte_eth_dev structure.
    2632                 :            :  * @param[in] item
    2633                 :            :  *   Item specification.
    2634                 :            :  * @param[in] attr
    2635                 :            :  *   Attributes of flow that includes this item.
    2636                 :            :  * @param[in] item_flags
    2637                 :            :  *   Bit-fields that holds the items detected until now.
    2638                 :            :  * @param[out] error
    2639                 :            :  *   Pointer to error structure.
    2640                 :            :  *
    2641                 :            :  * @return
    2642                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    2643                 :            :  */
    2644                 :            : static int
    2645                 :          0 : flow_dv_validate_item_port_id(struct rte_eth_dev *dev,
    2646                 :            :                               const struct rte_flow_item *item,
    2647                 :            :                               const struct rte_flow_attr *attr,
    2648                 :            :                               uint64_t item_flags,
    2649                 :            :                               struct mlx5_priv **act_priv,
    2650                 :            :                               struct rte_flow_error *error)
    2651                 :            : {
    2652                 :          0 :         const struct rte_flow_item_port_id *spec = item->spec;
    2653                 :          0 :         const struct rte_flow_item_port_id *mask = item->mask;
    2654                 :          0 :         const struct rte_flow_item_port_id switch_mask = {
    2655                 :            :                         .id = 0xffffffff,
    2656                 :            :         };
    2657                 :            :         struct mlx5_priv *esw_priv;
    2658                 :            :         struct mlx5_priv *dev_priv;
    2659                 :            :         int ret;
    2660                 :            : 
    2661         [ #  # ]:          0 :         if (!attr->transfer)
    2662                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2663                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM,
    2664                 :            :                                           NULL,
    2665                 :            :                                           "match on port id is valid only"
    2666                 :            :                                           " when transfer flag is enabled");
    2667         [ #  # ]:          0 :         if (item_flags & MLX5_FLOW_ITEM_PORT_ID)
    2668                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    2669                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2670                 :            :                                           "multiple source ports are not"
    2671                 :            :                                           " supported");
    2672         [ #  # ]:          0 :         if (!mask)
    2673                 :            :                 mask = &switch_mask;
    2674         [ #  # ]:          0 :         if (mask->id != 0xffffffff)
    2675                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    2676                 :            :                                            RTE_FLOW_ERROR_TYPE_ITEM_MASK,
    2677                 :            :                                            mask,
    2678                 :            :                                            "no support for partial mask on"
    2679                 :            :                                            " \"id\" field");
    2680                 :          0 :         ret = mlx5_flow_item_acceptable
    2681                 :            :                                 (item, (const uint8_t *)mask,
    2682                 :            :                                  (const uint8_t *)&rte_flow_item_port_id_mask,
    2683                 :            :                                  sizeof(struct rte_flow_item_port_id),
    2684                 :            :                                  MLX5_ITEM_RANGE_NOT_ACCEPTED, error);
    2685         [ #  # ]:          0 :         if (ret)
    2686                 :            :                 return ret;
    2687         [ #  # ]:          0 :         if (!spec)
    2688                 :            :                 return 0;
    2689         [ #  # ]:          0 :         if (spec->id == MLX5_PORT_ESW_MGR)
    2690                 :            :                 return 0;
    2691                 :          0 :         esw_priv = mlx5_port_to_eswitch_info(spec->id, false);
    2692         [ #  # ]:          0 :         if (!esw_priv)
    2693                 :          0 :                 return rte_flow_error_set(error, rte_errno,
    2694                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_SPEC, spec,
    2695                 :            :                                           "failed to obtain E-Switch info for"
    2696                 :            :                                           " port");
    2697                 :          0 :         dev_priv = mlx5_dev_to_eswitch_info(dev);
    2698         [ #  # ]:          0 :         if (!dev_priv)
    2699                 :          0 :                 return rte_flow_error_set(error, rte_errno,
    2700                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    2701                 :            :                                           NULL,
    2702                 :            :                                           "failed to obtain E-Switch info");
    2703         [ #  # ]:          0 :         if (esw_priv->domain_id != dev_priv->domain_id)
    2704                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2705                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_SPEC, spec,
    2706                 :            :                                           "cannot match on a port from a"
    2707                 :            :                                           " different E-Switch");
    2708                 :          0 :         *act_priv = esw_priv;
    2709                 :          0 :         return 0;
    2710                 :            : }
    2711                 :            : 
    2712                 :            : /**
    2713                 :            :  * Validate represented port item.
    2714                 :            :  *
    2715                 :            :  * @param[in] dev
    2716                 :            :  *   Pointer to the rte_eth_dev structure.
    2717                 :            :  * @param[in] item
    2718                 :            :  *   Item specification.
    2719                 :            :  * @param[in] attr
    2720                 :            :  *   Attributes of flow that includes this item.
    2721                 :            :  * @param[in] item_flags
    2722                 :            :  *   Bit-fields that holds the items detected until now.
    2723                 :            :  * @param[out] error
    2724                 :            :  *   Pointer to error structure.
    2725                 :            :  *
    2726                 :            :  * @return
    2727                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    2728                 :            :  */
    2729                 :            : static int
    2730                 :          0 : flow_dv_validate_item_represented_port(struct rte_eth_dev *dev,
    2731                 :            :                                        const struct rte_flow_item *item,
    2732                 :            :                                        const struct rte_flow_attr *attr,
    2733                 :            :                                        uint64_t item_flags,
    2734                 :            :                                        struct mlx5_priv **act_priv,
    2735                 :            :                                        struct rte_flow_error *error)
    2736                 :            : {
    2737                 :          0 :         const struct rte_flow_item_ethdev *spec = item->spec;
    2738                 :          0 :         const struct rte_flow_item_ethdev *mask = item->mask;
    2739                 :          0 :         const struct rte_flow_item_ethdev switch_mask = {
    2740                 :            :                         .port_id = UINT16_MAX,
    2741                 :            :         };
    2742                 :            :         struct mlx5_priv *esw_priv;
    2743                 :            :         struct mlx5_priv *dev_priv;
    2744                 :            :         int ret;
    2745                 :            : 
    2746         [ #  # ]:          0 :         if (!attr->transfer)
    2747                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2748                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    2749                 :            :                                           "match on port id is valid only when transfer flag is enabled");
    2750         [ #  # ]:          0 :         if (item_flags & MLX5_FLOW_ITEM_REPRESENTED_PORT)
    2751                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    2752                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2753                 :            :                                           "multiple source ports are not supported");
    2754         [ #  # ]:          0 :         if (!mask)
    2755                 :            :                 mask = &switch_mask;
    2756         [ #  # ]:          0 :         if (mask->port_id != UINT16_MAX)
    2757                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    2758                 :            :                                            RTE_FLOW_ERROR_TYPE_ITEM_MASK, mask,
    2759                 :            :                                            "no support for partial mask on \"id\" field");
    2760                 :          0 :         ret = mlx5_flow_item_acceptable
    2761                 :            :                                 (item, (const uint8_t *)mask,
    2762                 :            :                                  (const uint8_t *)&rte_flow_item_ethdev_mask,
    2763                 :            :                                  sizeof(struct rte_flow_item_ethdev),
    2764                 :            :                                  MLX5_ITEM_RANGE_NOT_ACCEPTED, error);
    2765         [ #  # ]:          0 :         if (ret)
    2766                 :            :                 return ret;
    2767   [ #  #  #  # ]:          0 :         if (!spec || spec->port_id == UINT16_MAX)
    2768                 :            :                 return 0;
    2769                 :          0 :         esw_priv = mlx5_port_to_eswitch_info(spec->port_id, false);
    2770         [ #  # ]:          0 :         if (!esw_priv)
    2771                 :          0 :                 return rte_flow_error_set(error, rte_errno,
    2772                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_SPEC, spec,
    2773                 :            :                                           "failed to obtain E-Switch info for port");
    2774                 :          0 :         dev_priv = mlx5_dev_to_eswitch_info(dev);
    2775         [ #  # ]:          0 :         if (!dev_priv)
    2776                 :          0 :                 return rte_flow_error_set(error, rte_errno,
    2777                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    2778                 :            :                                           NULL,
    2779                 :            :                                           "failed to obtain E-Switch info");
    2780         [ #  # ]:          0 :         if (esw_priv->domain_id != dev_priv->domain_id)
    2781                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2782                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_SPEC, spec,
    2783                 :            :                                           "cannot match on a port from a different E-Switch");
    2784                 :          0 :         *act_priv = esw_priv;
    2785                 :          0 :         return 0;
    2786                 :            : }
    2787                 :            : 
    2788                 :            : /**
    2789                 :            :  * Validate VLAN item.
    2790                 :            :  *
    2791                 :            :  * @param[in] item
    2792                 :            :  *   Item specification.
    2793                 :            :  * @param[in] item_flags
    2794                 :            :  *   Bit-fields that holds the items detected until now.
    2795                 :            :  * @param[in] dev
    2796                 :            :  *   Ethernet device flow is being created on.
    2797                 :            :  * @param[out] error
    2798                 :            :  *   Pointer to error structure.
    2799                 :            :  *
    2800                 :            :  * @return
    2801                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    2802                 :            :  */
    2803                 :            : static int
    2804                 :          0 : flow_dv_validate_item_vlan(const struct rte_flow_item *item,
    2805                 :            :                            uint64_t item_flags,
    2806                 :            :                            struct rte_eth_dev *dev,
    2807                 :            :                            struct rte_flow_error *error)
    2808                 :            : {
    2809                 :          0 :         const struct rte_flow_item_vlan *mask = item->mask;
    2810                 :          0 :         const struct rte_flow_item_vlan nic_mask = {
    2811                 :            :                 .hdr.vlan_tci = RTE_BE16(UINT16_MAX),
    2812                 :            :                 .hdr.eth_proto = RTE_BE16(UINT16_MAX),
    2813                 :            :                 .has_more_vlan = 1,
    2814                 :            :         };
    2815                 :          0 :         const int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL);
    2816                 :            :         int ret;
    2817                 :            :         const uint64_t l34m = tunnel ? (MLX5_FLOW_LAYER_INNER_L3 |
    2818         [ #  # ]:          0 :                                         MLX5_FLOW_LAYER_INNER_L4) :
    2819                 :            :                                        (MLX5_FLOW_LAYER_OUTER_L3 |
    2820                 :            :                                         MLX5_FLOW_LAYER_OUTER_L4);
    2821         [ #  # ]:          0 :         const uint64_t vlanm = tunnel ? MLX5_FLOW_LAYER_INNER_VLAN :
    2822                 :            :                                         MLX5_FLOW_LAYER_OUTER_VLAN;
    2823                 :            : 
    2824         [ #  # ]:          0 :         if (item_flags & vlanm)
    2825                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2826                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2827                 :            :                                           "multiple VLAN layers not supported");
    2828         [ #  # ]:          0 :         else if ((item_flags & l34m) != 0)
    2829                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2830                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2831                 :            :                                           "VLAN cannot follow L3/L4 layer");
    2832         [ #  # ]:          0 :         if (!mask)
    2833                 :            :                 mask = &rte_flow_item_vlan_mask;
    2834                 :          0 :         ret = mlx5_flow_item_acceptable(item, (const uint8_t *)mask,
    2835                 :            :                                         (const uint8_t *)&nic_mask,
    2836                 :            :                                         sizeof(struct rte_flow_item_vlan),
    2837                 :            :                                         MLX5_ITEM_RANGE_NOT_ACCEPTED, error);
    2838         [ #  # ]:          0 :         if (ret)
    2839                 :            :                 return ret;
    2840   [ #  #  #  # ]:          0 :         if (!tunnel && mask->hdr.vlan_tci != RTE_BE16(0x0fff)) {
    2841                 :          0 :                 struct mlx5_priv *priv = dev->data->dev_private;
    2842                 :            : 
    2843         [ #  # ]:          0 :                 if (priv->vmwa_context) {
    2844                 :            :                         /*
    2845                 :            :                          * Non-NULL context means we have a virtual machine
    2846                 :            :                          * and SR-IOV enabled, we have to create VLAN interface
    2847                 :            :                          * to make hypervisor to setup E-Switch vport
    2848                 :            :                          * context correctly. We avoid creating the multiple
    2849                 :            :                          * VLAN interfaces, so we cannot support VLAN tag mask.
    2850                 :            :                          */
    2851                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    2852                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM,
    2853                 :            :                                                   item,
    2854                 :            :                                                   "VLAN tag mask is not"
    2855                 :            :                                                   " supported in virtual"
    2856                 :            :                                                   " environment");
    2857                 :            :                 }
    2858                 :            :         }
    2859                 :            :         return 0;
    2860                 :            : }
    2861                 :            : 
    2862                 :            : /*
    2863                 :            :  * GTP flags are contained in 1 byte of the format:
    2864                 :            :  * -------------------------------------------
    2865                 :            :  * | bit   | 0 - 2   | 3  | 4   | 5 | 6 | 7  |
    2866                 :            :  * |-----------------------------------------|
    2867                 :            :  * | value | Version | PT | Res | E | S | PN |
    2868                 :            :  * -------------------------------------------
    2869                 :            :  *
    2870                 :            :  * Matching is supported only for GTP flags E, S, PN.
    2871                 :            :  */
    2872                 :            : #define MLX5_GTP_FLAGS_MASK     0x07
    2873                 :            : 
    2874                 :            : /**
    2875                 :            :  * Validate GTP item.
    2876                 :            :  *
    2877                 :            :  * @param[in] dev
    2878                 :            :  *   Pointer to the rte_eth_dev structure.
    2879                 :            :  * @param[in] item
    2880                 :            :  *   Item specification.
    2881                 :            :  * @param[in] item_flags
    2882                 :            :  *   Bit-fields that holds the items detected until now.
    2883                 :            :  * @param[out] error
    2884                 :            :  *   Pointer to error structure.
    2885                 :            :  *
    2886                 :            :  * @return
    2887                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    2888                 :            :  */
    2889                 :            : static int
    2890                 :          0 : flow_dv_validate_item_gtp(struct rte_eth_dev *dev,
    2891                 :            :                           const struct rte_flow_item *item,
    2892                 :            :                           uint64_t item_flags,
    2893                 :            :                           struct rte_flow_error *error)
    2894                 :            : {
    2895                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    2896                 :          0 :         const struct rte_flow_item_gtp *spec = item->spec;
    2897                 :          0 :         const struct rte_flow_item_gtp *mask = item->mask;
    2898                 :          0 :         const struct rte_flow_item_gtp nic_mask = {
    2899                 :            :                 .hdr.gtp_hdr_info = MLX5_GTP_FLAGS_MASK,
    2900                 :            :                 .hdr.msg_type = 0xff,
    2901                 :            :                 .hdr.teid = RTE_BE32(0xffffffff),
    2902                 :            :         };
    2903                 :            : 
    2904         [ #  # ]:          0 :         if (!priv->sh->cdev->config.hca_attr.tunnel_stateless_gtp)
    2905                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    2906                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2907                 :            :                                           "GTP support is not enabled");
    2908         [ #  # ]:          0 :         if (item_flags & MLX5_FLOW_LAYER_TUNNEL)
    2909                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    2910                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2911                 :            :                                           "multiple tunnel layers not"
    2912                 :            :                                           " supported");
    2913         [ #  # ]:          0 :         if (!(item_flags & MLX5_FLOW_LAYER_OUTER_L4_UDP))
    2914                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2915                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2916                 :            :                                           "no outer UDP layer found");
    2917         [ #  # ]:          0 :         if (!mask)
    2918                 :            :                 mask = &rte_flow_item_gtp_mask;
    2919   [ #  #  #  # ]:          0 :         if (spec && spec->hdr.gtp_hdr_info & ~MLX5_GTP_FLAGS_MASK)
    2920                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    2921                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2922                 :            :                                           "Match is supported for GTP"
    2923                 :            :                                           " flags only");
    2924                 :          0 :         return mlx5_flow_item_acceptable(item, (const uint8_t *)mask,
    2925                 :            :                                          (const uint8_t *)&nic_mask,
    2926                 :            :                                          sizeof(struct rte_flow_item_gtp),
    2927                 :            :                                          MLX5_ITEM_RANGE_NOT_ACCEPTED, error);
    2928                 :            : }
    2929                 :            : 
    2930                 :            : /**
    2931                 :            :  * Validate GTP PSC item.
    2932                 :            :  *
    2933                 :            :  * @param[in] item
    2934                 :            :  *   Item specification.
    2935                 :            :  * @param[in] last_item
    2936                 :            :  *   Previous validated item in the pattern items.
    2937                 :            :  * @param[in] gtp_item
    2938                 :            :  *   Previous GTP item specification.
    2939                 :            :  * @param root
    2940                 :            :  *   Whether action is on root table.
    2941                 :            :  * @param[out] error
    2942                 :            :  *   Pointer to error structure.
    2943                 :            :  *
    2944                 :            :  * @return
    2945                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    2946                 :            :  */
    2947                 :            : static int
    2948                 :          0 : flow_dv_validate_item_gtp_psc(const struct rte_flow_item *item,
    2949                 :            :                               uint64_t last_item,
    2950                 :            :                               const struct rte_flow_item *gtp_item,
    2951                 :            :                               bool root,
    2952                 :            :                               struct rte_flow_error *error)
    2953                 :            : {
    2954                 :            :         const struct rte_flow_item_gtp *gtp_spec;
    2955                 :            :         const struct rte_flow_item_gtp *gtp_mask;
    2956                 :            :         const struct rte_flow_item_gtp_psc *mask;
    2957                 :          0 :         const struct rte_flow_item_gtp_psc nic_mask = {
    2958                 :            :                 .hdr.type = 0xF,
    2959                 :            :                 .hdr.qfi = 0x3F,
    2960                 :            :         };
    2961                 :            : 
    2962   [ #  #  #  # ]:          0 :         if (!gtp_item || !(last_item & MLX5_FLOW_LAYER_GTP))
    2963                 :          0 :                 return rte_flow_error_set
    2964                 :            :                         (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM, item,
    2965                 :            :                          "GTP PSC item must be preceded with GTP item");
    2966                 :          0 :         gtp_spec = gtp_item->spec;
    2967         [ #  # ]:          0 :         gtp_mask = gtp_item->mask ? gtp_item->mask : &rte_flow_item_gtp_mask;
    2968                 :            :         /* GTP spec and E flag is requested to match zero. */
    2969         [ #  # ]:          0 :         if (gtp_spec &&
    2970                 :          0 :                 (gtp_mask->hdr.gtp_hdr_info &
    2971         [ #  # ]:          0 :                 ~gtp_spec->hdr.gtp_hdr_info & MLX5_GTP_EXT_HEADER_FLAG))
    2972                 :          0 :                 return rte_flow_error_set
    2973                 :            :                         (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM, item,
    2974                 :            :                          "GTP E flag must be 1 to match GTP PSC");
    2975                 :            :         /* Check the flow is not created in group zero. */
    2976         [ #  # ]:          0 :         if (root)
    2977                 :          0 :                 return rte_flow_error_set
    2978                 :            :                         (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    2979                 :            :                          "GTP PSC is not supported for group 0");
    2980                 :            :         /* GTP spec is here and E flag is requested to match zero. */
    2981         [ #  # ]:          0 :         if (!item->spec)
    2982                 :            :                 return 0;
    2983         [ #  # ]:          0 :         mask = item->mask ? item->mask : &rte_flow_item_gtp_psc_mask;
    2984                 :          0 :         return mlx5_flow_item_acceptable(item, (const uint8_t *)mask,
    2985                 :            :                                          (const uint8_t *)&nic_mask,
    2986                 :            :                                          sizeof(struct rte_flow_item_gtp_psc),
    2987                 :            :                                          MLX5_ITEM_RANGE_NOT_ACCEPTED, error);
    2988                 :            : }
    2989                 :            : 
    2990                 :            : /**
    2991                 :            :  * Validate IPV4 item.
    2992                 :            :  * Use existing validation function mlx5_flow_validate_item_ipv4(), and
    2993                 :            :  * add specific validation of fragment_offset field,
    2994                 :            :  *
    2995                 :            :  * @param[in] item
    2996                 :            :  *   Item specification.
    2997                 :            :  * @param[in] item_flags
    2998                 :            :  *   Bit-fields that holds the items detected until now.
    2999                 :            :  * @param[out] error
    3000                 :            :  *   Pointer to error structure.
    3001                 :            :  *
    3002                 :            :  * @return
    3003                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3004                 :            :  */
    3005                 :            : static int
    3006                 :          0 : flow_dv_validate_item_ipv4(struct rte_eth_dev *dev,
    3007                 :            :                            const struct rte_flow_item *item,
    3008                 :            :                            uint64_t item_flags, uint64_t last_item,
    3009                 :            :                            uint16_t ether_type, struct rte_flow_error *error)
    3010                 :            : {
    3011                 :            :         int ret;
    3012                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    3013                 :          0 :         struct mlx5_hca_attr *attr = &priv->sh->cdev->config.hca_attr;
    3014                 :          0 :         const struct rte_flow_item_ipv4 *spec = item->spec;
    3015                 :          0 :         const struct rte_flow_item_ipv4 *last = item->last;
    3016                 :          0 :         const struct rte_flow_item_ipv4 *mask = item->mask;
    3017                 :            :         rte_be16_t fragment_offset_spec = 0;
    3018                 :            :         rte_be16_t fragment_offset_last = 0;
    3019                 :          0 :         struct rte_flow_item_ipv4 nic_ipv4_mask = {
    3020                 :            :                 .hdr = {
    3021                 :            :                         .src_addr = RTE_BE32(0xffffffff),
    3022                 :            :                         .dst_addr = RTE_BE32(0xffffffff),
    3023                 :            :                         .type_of_service = 0xff,
    3024                 :            :                         .fragment_offset = RTE_BE16(0xffff),
    3025                 :            :                         .next_proto_id = 0xff,
    3026                 :            :                         .time_to_live = 0xff,
    3027                 :            :                 },
    3028                 :            :         };
    3029                 :            : 
    3030   [ #  #  #  # ]:          0 :         if (mask && (mask->hdr.version_ihl & RTE_IPV4_HDR_IHL_MASK)) {
    3031                 :          0 :                 int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL);
    3032                 :            :                 bool ihl_cap = !tunnel ?
    3033         [ #  # ]:          0 :                                attr->outer_ipv4_ihl : attr->inner_ipv4_ihl;
    3034         [ #  # ]:          0 :                 if (!ihl_cap)
    3035                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    3036                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM,
    3037                 :            :                                                   item,
    3038                 :            :                                                   "IPV4 ihl offload not supported");
    3039                 :          0 :                 nic_ipv4_mask.hdr.version_ihl = mask->hdr.version_ihl;
    3040                 :            :         }
    3041                 :          0 :         ret = mlx5_flow_validate_item_ipv4(item, item_flags, last_item,
    3042                 :            :                                            ether_type, &nic_ipv4_mask,
    3043                 :            :                                            MLX5_ITEM_RANGE_ACCEPTED, error);
    3044         [ #  # ]:          0 :         if (ret < 0)
    3045                 :            :                 return ret;
    3046         [ #  # ]:          0 :         if (spec && mask)
    3047                 :          0 :                 fragment_offset_spec = spec->hdr.fragment_offset &
    3048                 :          0 :                                        mask->hdr.fragment_offset;
    3049         [ #  # ]:          0 :         if (!fragment_offset_spec)
    3050                 :            :                 return 0;
    3051                 :            :         /*
    3052                 :            :          * spec and mask are valid, enforce using full mask to make sure the
    3053                 :            :          * complete value is used correctly.
    3054                 :            :          */
    3055         [ #  # ]:          0 :         if ((mask->hdr.fragment_offset & RTE_BE16(MLX5_IPV4_FRAG_OFFSET_MASK))
    3056                 :            :                         != RTE_BE16(MLX5_IPV4_FRAG_OFFSET_MASK))
    3057                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3058                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_MASK,
    3059                 :            :                                           item, "must use full mask for"
    3060                 :            :                                           " fragment_offset");
    3061                 :            :         /*
    3062                 :            :          * Match on fragment_offset 0x2000 means MF is 1 and frag-offset is 0,
    3063                 :            :          * indicating this is 1st fragment of fragmented packet.
    3064                 :            :          * This is not yet supported in MLX5, return appropriate error message.
    3065                 :            :          */
    3066         [ #  # ]:          0 :         if (fragment_offset_spec == RTE_BE16(RTE_IPV4_HDR_MF_FLAG))
    3067                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3068                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    3069                 :            :                                           "match on first fragment not "
    3070                 :            :                                           "supported");
    3071         [ #  # ]:          0 :         if (fragment_offset_spec && !last)
    3072                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3073                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    3074                 :            :                                           "specified value not supported");
    3075                 :            :         /* spec and last are valid, validate the specified range. */
    3076                 :          0 :         fragment_offset_last = last->hdr.fragment_offset &
    3077                 :            :                                mask->hdr.fragment_offset;
    3078                 :            :         /*
    3079                 :            :          * Match on fragment_offset spec 0x2001 and last 0x3fff
    3080                 :            :          * means MF is 1 and frag-offset is > 0.
    3081                 :            :          * This packet is fragment 2nd and onward, excluding last.
    3082                 :            :          * This is not yet supported in MLX5, return appropriate
    3083                 :            :          * error message.
    3084                 :            :          */
    3085                 :          0 :         if (fragment_offset_spec == RTE_BE16(RTE_IPV4_HDR_MF_FLAG + 1) &&
    3086         [ #  # ]:          0 :             fragment_offset_last == RTE_BE16(MLX5_IPV4_FRAG_OFFSET_MASK))
    3087                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3088                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_LAST,
    3089                 :            :                                           last, "match on following "
    3090                 :            :                                           "fragments not supported");
    3091                 :            :         /*
    3092                 :            :          * Match on fragment_offset spec 0x0001 and last 0x1fff
    3093                 :            :          * means MF is 0 and frag-offset is > 0.
    3094                 :            :          * This packet is last fragment of fragmented packet.
    3095                 :            :          * This is not yet supported in MLX5, return appropriate
    3096                 :            :          * error message.
    3097                 :            :          */
    3098                 :          0 :         if (fragment_offset_spec == RTE_BE16(1) &&
    3099         [ #  # ]:          0 :             fragment_offset_last == RTE_BE16(RTE_IPV4_HDR_OFFSET_MASK))
    3100                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3101                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_LAST,
    3102                 :            :                                           last, "match on last "
    3103                 :            :                                           "fragment not supported");
    3104                 :            :         /*
    3105                 :            :          * Match on fragment_offset spec 0x0001 and last 0x3fff
    3106                 :            :          * means MF and/or frag-offset is not 0.
    3107                 :            :          * This is a fragmented packet.
    3108                 :            :          * Other range values are invalid and rejected.
    3109                 :            :          */
    3110                 :          0 :         if (!(fragment_offset_spec == RTE_BE16(1) &&
    3111         [ #  # ]:          0 :               fragment_offset_last == RTE_BE16(MLX5_IPV4_FRAG_OFFSET_MASK)))
    3112                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3113                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_LAST, last,
    3114                 :            :                                           "specified range not supported");
    3115                 :            :         return 0;
    3116                 :            : }
    3117                 :            : 
    3118                 :            : /**
    3119                 :            :  * Validate IPV6 fragment extension item.
    3120                 :            :  *
    3121                 :            :  * @param[in] item
    3122                 :            :  *   Item specification.
    3123                 :            :  * @param[in] item_flags
    3124                 :            :  *   Bit-fields that holds the items detected until now.
    3125                 :            :  * @param[out] error
    3126                 :            :  *   Pointer to error structure.
    3127                 :            :  *
    3128                 :            :  * @return
    3129                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3130                 :            :  */
    3131                 :            : static int
    3132                 :          0 : flow_dv_validate_item_ipv6_frag_ext(const struct rte_flow_item *item,
    3133                 :            :                                     uint64_t item_flags,
    3134                 :            :                                     struct rte_flow_error *error)
    3135                 :            : {
    3136                 :          0 :         const struct rte_flow_item_ipv6_frag_ext *spec = item->spec;
    3137                 :          0 :         const struct rte_flow_item_ipv6_frag_ext *last = item->last;
    3138                 :          0 :         const struct rte_flow_item_ipv6_frag_ext *mask = item->mask;
    3139                 :            :         rte_be16_t frag_data_spec = 0;
    3140                 :            :         rte_be16_t frag_data_last = 0;
    3141                 :          0 :         const int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL);
    3142         [ #  # ]:          0 :         const uint64_t l4m = tunnel ? MLX5_FLOW_LAYER_INNER_L4 :
    3143                 :            :                                       MLX5_FLOW_LAYER_OUTER_L4;
    3144                 :            :         int ret = 0;
    3145                 :          0 :         struct rte_flow_item_ipv6_frag_ext nic_mask = {
    3146                 :            :                 .hdr = {
    3147                 :            :                         .next_header = 0xff,
    3148                 :            :                         .frag_data = RTE_BE16(0xffff),
    3149                 :            :                 },
    3150                 :            :         };
    3151                 :            : 
    3152         [ #  # ]:          0 :         if (item_flags & l4m)
    3153                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3154                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    3155                 :            :                                           "ipv6 fragment extension item cannot "
    3156                 :            :                                           "follow L4 item.");
    3157   [ #  #  #  #  :          0 :         if ((tunnel && !(item_flags & MLX5_FLOW_LAYER_INNER_L3_IPV6)) ||
                   #  # ]
    3158         [ #  # ]:          0 :             (!tunnel && !(item_flags & MLX5_FLOW_LAYER_OUTER_L3_IPV6)))
    3159                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3160                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    3161                 :            :                                           "ipv6 fragment extension item must "
    3162                 :            :                                           "follow ipv6 item");
    3163         [ #  # ]:          0 :         if (spec && mask)
    3164                 :          0 :                 frag_data_spec = spec->hdr.frag_data & mask->hdr.frag_data;
    3165         [ #  # ]:          0 :         if (!frag_data_spec)
    3166                 :            :                 return 0;
    3167                 :            :         /*
    3168                 :            :          * spec and mask are valid, enforce using full mask to make sure the
    3169                 :            :          * complete value is used correctly.
    3170                 :            :          */
    3171         [ #  # ]:          0 :         if ((mask->hdr.frag_data & RTE_BE16(RTE_IPV6_FRAG_USED_MASK)) !=
    3172                 :            :                                 RTE_BE16(RTE_IPV6_FRAG_USED_MASK))
    3173                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3174                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_MASK,
    3175                 :            :                                           item, "must use full mask for"
    3176                 :            :                                           " frag_data");
    3177                 :            :         /*
    3178                 :            :          * Match on frag_data 0x00001 means M is 1 and frag-offset is 0.
    3179                 :            :          * This is 1st fragment of fragmented packet.
    3180                 :            :          */
    3181         [ #  # ]:          0 :         if (frag_data_spec == RTE_BE16(RTE_IPV6_EHDR_MF_MASK))
    3182                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3183                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    3184                 :            :                                           "match on first fragment not "
    3185                 :            :                                           "supported");
    3186         [ #  # ]:          0 :         if (frag_data_spec && !last)
    3187                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3188                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    3189                 :            :                                           "specified value not supported");
    3190                 :          0 :         ret = mlx5_flow_item_acceptable
    3191                 :            :                                 (item, (const uint8_t *)mask,
    3192                 :            :                                  (const uint8_t *)&nic_mask,
    3193                 :            :                                  sizeof(struct rte_flow_item_ipv6_frag_ext),
    3194                 :            :                                  MLX5_ITEM_RANGE_ACCEPTED, error);
    3195         [ #  # ]:          0 :         if (ret)
    3196                 :            :                 return ret;
    3197                 :            :         /* spec and last are valid, validate the specified range. */
    3198                 :          0 :         frag_data_last = last->hdr.frag_data & mask->hdr.frag_data;
    3199                 :            :         /*
    3200                 :            :          * Match on frag_data spec 0x0009 and last 0xfff9
    3201                 :            :          * means M is 1 and frag-offset is > 0.
    3202                 :            :          * This packet is fragment 2nd and onward, excluding last.
    3203                 :            :          * This is not yet supported in MLX5, return appropriate
    3204                 :            :          * error message.
    3205                 :            :          */
    3206                 :          0 :         if (frag_data_spec == RTE_BE16(RTE_IPV6_EHDR_FO_ALIGN |
    3207                 :          0 :                                        RTE_IPV6_EHDR_MF_MASK) &&
    3208         [ #  # ]:          0 :             frag_data_last == RTE_BE16(RTE_IPV6_FRAG_USED_MASK))
    3209                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3210                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_LAST,
    3211                 :            :                                           last, "match on following "
    3212                 :            :                                           "fragments not supported");
    3213                 :            :         /*
    3214                 :            :          * Match on frag_data spec 0x0008 and last 0xfff8
    3215                 :            :          * means M is 0 and frag-offset is > 0.
    3216                 :            :          * This packet is last fragment of fragmented packet.
    3217                 :            :          * This is not yet supported in MLX5, return appropriate
    3218                 :            :          * error message.
    3219                 :            :          */
    3220                 :          0 :         if (frag_data_spec == RTE_BE16(RTE_IPV6_EHDR_FO_ALIGN) &&
    3221         [ #  # ]:          0 :             frag_data_last == RTE_BE16(RTE_IPV6_EHDR_FO_MASK))
    3222                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3223                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_LAST,
    3224                 :            :                                           last, "match on last "
    3225                 :            :                                           "fragment not supported");
    3226                 :            :         /* Other range values are invalid and rejected. */
    3227                 :          0 :         return rte_flow_error_set(error, EINVAL,
    3228                 :            :                                   RTE_FLOW_ERROR_TYPE_ITEM_LAST, last,
    3229                 :            :                                   "specified range not supported");
    3230                 :            : }
    3231                 :            : 
    3232                 :            : /*
    3233                 :            :  * Validate ASO CT item.
    3234                 :            :  *
    3235                 :            :  * @param[in] dev
    3236                 :            :  *   Pointer to the rte_eth_dev structure.
    3237                 :            :  * @param[in] item
    3238                 :            :  *   Item specification.
    3239                 :            :  * @param[in] item_flags
    3240                 :            :  *   Pointer to bit-fields that holds the items detected until now.
    3241                 :            :  * @param[out] error
    3242                 :            :  *   Pointer to error structure.
    3243                 :            :  *
    3244                 :            :  * @return
    3245                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3246                 :            :  */
    3247                 :            : static int
    3248                 :          0 : flow_dv_validate_item_aso_ct(struct rte_eth_dev *dev,
    3249                 :            :                              const struct rte_flow_item *item,
    3250                 :            :                              uint64_t *item_flags,
    3251                 :            :                              struct rte_flow_error *error)
    3252                 :            : {
    3253                 :          0 :         const struct rte_flow_item_conntrack *spec = item->spec;
    3254                 :          0 :         const struct rte_flow_item_conntrack *mask = item->mask;
    3255                 :            :         RTE_SET_USED(dev);
    3256                 :            :         uint32_t flags;
    3257                 :            : 
    3258         [ #  # ]:          0 :         if (*item_flags & MLX5_FLOW_LAYER_ASO_CT)
    3259                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3260                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    3261                 :            :                                           "Only one CT is supported");
    3262         [ #  # ]:          0 :         if (!mask)
    3263                 :            :                 mask = &rte_flow_item_conntrack_mask;
    3264                 :          0 :         flags = spec->flags & mask->flags;
    3265         [ #  # ]:          0 :         if ((flags & RTE_FLOW_CONNTRACK_PKT_STATE_VALID) &&
    3266                 :            :             ((flags & RTE_FLOW_CONNTRACK_PKT_STATE_INVALID) ||
    3267         [ #  # ]:          0 :              (flags & RTE_FLOW_CONNTRACK_PKT_STATE_BAD) ||
    3268                 :            :              (flags & RTE_FLOW_CONNTRACK_PKT_STATE_DISABLED)))
    3269                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3270                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    3271                 :            :                                           "Conflict status bits");
    3272                 :            :         /* State change also needs to be considered. */
    3273                 :          0 :         *item_flags |= MLX5_FLOW_LAYER_ASO_CT;
    3274                 :          0 :         return 0;
    3275                 :            : }
    3276                 :            : 
    3277                 :            : /**
    3278                 :            :  * Validate the pop VLAN action.
    3279                 :            :  *
    3280                 :            :  * @param[in] dev
    3281                 :            :  *   Pointer to the rte_eth_dev structure.
    3282                 :            :  * @param[in] action_flags
    3283                 :            :  *   Holds the actions detected until now.
    3284                 :            :  * @param[in] action
    3285                 :            :  *   Pointer to the pop vlan action.
    3286                 :            :  * @param[in] item_flags
    3287                 :            :  *   The items found in this flow rule.
    3288                 :            :  * @param[in] attr
    3289                 :            :  *   Pointer to flow attributes.
    3290                 :            :  * @param[out] error
    3291                 :            :  *   Pointer to error structure.
    3292                 :            :  *
    3293                 :            :  * @return
    3294                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3295                 :            :  */
    3296                 :            : static int
    3297                 :          0 : flow_dv_validate_action_pop_vlan(struct rte_eth_dev *dev,
    3298                 :            :                                  uint64_t action_flags,
    3299                 :            :                                  const struct rte_flow_action *action,
    3300                 :            :                                  uint64_t item_flags,
    3301                 :            :                                  const struct rte_flow_attr *attr,
    3302                 :            :                                  struct rte_flow_error *error)
    3303                 :            : {
    3304                 :          0 :         const struct mlx5_priv *priv = dev->data->dev_private;
    3305                 :            : 
    3306         [ #  # ]:          0 :         if (!priv->sh->pop_vlan_action)
    3307                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3308                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    3309                 :            :                                           NULL,
    3310                 :            :                                           "pop vlan action is not supported");
    3311         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_VLAN_ACTIONS)
    3312                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3313                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3314                 :            :                                           "no support for multiple VLAN "
    3315                 :            :                                           "actions");
    3316                 :            :         /* Pop VLAN with preceding Decap requires inner header with VLAN. */
    3317         [ #  # ]:          0 :         if ((action_flags & MLX5_FLOW_ACTION_DECAP) &&
    3318         [ #  # ]:          0 :             !(item_flags & MLX5_FLOW_LAYER_INNER_VLAN))
    3319                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3320                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    3321                 :            :                                           NULL,
    3322                 :            :                                           "cannot pop vlan after decap without "
    3323                 :            :                                           "match on inner vlan in the flow");
    3324                 :            :         /* Pop VLAN without preceding Decap requires outer header with VLAN. */
    3325         [ #  # ]:          0 :         if (!(action_flags & MLX5_FLOW_ACTION_DECAP) &&
    3326         [ #  # ]:          0 :             !(item_flags & MLX5_FLOW_LAYER_OUTER_VLAN))
    3327                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3328                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    3329                 :            :                                           NULL,
    3330                 :            :                                           "cannot pop vlan without a "
    3331                 :            :                                           "match on (outer) vlan in the flow");
    3332         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_PORT_ID)
    3333                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3334                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3335                 :            :                                           "wrong action order, port_id should "
    3336                 :            :                                           "be after pop VLAN action");
    3337   [ #  #  #  # ]:          0 :         if (!attr->transfer && priv->representor)
    3338                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3339                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    3340                 :            :                                           "pop vlan action for VF representor "
    3341                 :            :                                           "not supported on NIC table");
    3342                 :            :         return 0;
    3343                 :            : }
    3344                 :            : 
    3345                 :            : /**
    3346                 :            :  * Get VLAN default info from vlan match info.
    3347                 :            :  *
    3348                 :            :  * @param[in] items
    3349                 :            :  *   the list of item specifications.
    3350                 :            :  * @param[out] vlan
    3351                 :            :  *   pointer VLAN info to fill to.
    3352                 :            :  *
    3353                 :            :  * @return
    3354                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3355                 :            :  */
    3356                 :            : static void
    3357                 :          0 : flow_dev_get_vlan_info_from_items(const struct rte_flow_item *items,
    3358                 :            :                                   struct rte_vlan_hdr *vlan)
    3359                 :            : {
    3360                 :          0 :         const struct rte_flow_item_vlan nic_mask = {
    3361                 :            :                 .hdr.vlan_tci = RTE_BE16(MLX5DV_FLOW_VLAN_PCP_MASK |
    3362                 :            :                                 MLX5DV_FLOW_VLAN_VID_MASK),
    3363                 :            :                 .hdr.eth_proto = RTE_BE16(0xffff),
    3364                 :            :         };
    3365                 :            : 
    3366         [ #  # ]:          0 :         if (items == NULL)
    3367                 :          0 :                 return;
    3368         [ #  # ]:          0 :         for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {
    3369                 :          0 :                 int type = items->type;
    3370                 :            : 
    3371                 :          0 :                 if (type == RTE_FLOW_ITEM_TYPE_VLAN ||
    3372         [ #  # ]:          0 :                     type == MLX5_RTE_FLOW_ITEM_TYPE_VLAN)
    3373                 :            :                         break;
    3374                 :            :         }
    3375         [ #  # ]:          0 :         if (items->type != RTE_FLOW_ITEM_TYPE_END) {
    3376                 :          0 :                 const struct rte_flow_item_vlan *vlan_m = items->mask;
    3377                 :          0 :                 const struct rte_flow_item_vlan *vlan_v = items->spec;
    3378                 :            : 
    3379                 :            :                 /* If VLAN item in pattern doesn't contain data, return here. */
    3380         [ #  # ]:          0 :                 if (!vlan_v)
    3381                 :            :                         return;
    3382         [ #  # ]:          0 :                 if (!vlan_m)
    3383                 :            :                         vlan_m = &nic_mask;
    3384                 :            :                 /* Only full match values are accepted */
    3385         [ #  # ]:          0 :                 if ((vlan_m->hdr.vlan_tci & MLX5DV_FLOW_VLAN_PCP_MASK_BE) ==
    3386                 :            :                      MLX5DV_FLOW_VLAN_PCP_MASK_BE) {
    3387                 :          0 :                         vlan->vlan_tci &= ~MLX5DV_FLOW_VLAN_PCP_MASK;
    3388                 :          0 :                         vlan->vlan_tci |=
    3389         [ #  # ]:          0 :                                 rte_be_to_cpu_16(vlan_v->hdr.vlan_tci &
    3390                 :            :                                                  MLX5DV_FLOW_VLAN_PCP_MASK_BE);
    3391                 :            :                 }
    3392         [ #  # ]:          0 :                 if ((vlan_m->hdr.vlan_tci & MLX5DV_FLOW_VLAN_VID_MASK_BE) ==
    3393                 :            :                      MLX5DV_FLOW_VLAN_VID_MASK_BE) {
    3394                 :          0 :                         vlan->vlan_tci &= ~MLX5DV_FLOW_VLAN_VID_MASK;
    3395                 :          0 :                         vlan->vlan_tci |=
    3396         [ #  # ]:          0 :                                 rte_be_to_cpu_16(vlan_v->hdr.vlan_tci &
    3397                 :            :                                                  MLX5DV_FLOW_VLAN_VID_MASK_BE);
    3398                 :            :                 }
    3399         [ #  # ]:          0 :                 if (vlan_m->hdr.eth_proto == nic_mask.hdr.eth_proto)
    3400         [ #  # ]:          0 :                         vlan->eth_proto = rte_be_to_cpu_16(vlan_v->hdr.eth_proto &
    3401                 :            :                                                            vlan_m->hdr.eth_proto);
    3402                 :            :         }
    3403                 :            : }
    3404                 :            : 
    3405                 :            : /**
    3406                 :            :  * Validate the push VLAN action.
    3407                 :            :  *
    3408                 :            :  * @param[in] dev
    3409                 :            :  *   Pointer to the rte_eth_dev structure.
    3410                 :            :  * @param[in] action_flags
    3411                 :            :  *   Holds the actions detected until now.
    3412                 :            :  * @param[in] item_flags
    3413                 :            :  *   The items found in this flow rule.
    3414                 :            :  * @param[in] action
    3415                 :            :  *   Pointer to the action structure.
    3416                 :            :  * @param[in] attr
    3417                 :            :  *   Pointer to flow attributes
    3418                 :            :  * @param[out] error
    3419                 :            :  *   Pointer to error structure.
    3420                 :            :  *
    3421                 :            :  * @return
    3422                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3423                 :            :  */
    3424                 :            : static int
    3425                 :          0 : flow_dv_validate_action_push_vlan(struct rte_eth_dev *dev,
    3426                 :            :                                   uint64_t action_flags,
    3427                 :            :                                   const struct rte_flow_item_vlan *vlan_m,
    3428                 :            :                                   const struct rte_flow_action *action,
    3429                 :            :                                   const struct rte_flow_attr *attr,
    3430                 :            :                                   struct rte_flow_error *error)
    3431                 :            : {
    3432                 :          0 :         const struct rte_flow_action_of_push_vlan *push_vlan = action->conf;
    3433                 :          0 :         const struct mlx5_priv *priv = dev->data->dev_private;
    3434                 :            : 
    3435         [ #  # ]:          0 :         if (push_vlan->ethertype != RTE_BE16(RTE_ETHER_TYPE_VLAN) &&
    3436                 :            :             push_vlan->ethertype != RTE_BE16(RTE_ETHER_TYPE_QINQ))
    3437                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3438                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3439                 :            :                                           "invalid vlan ethertype");
    3440         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_PORT_ID)
    3441                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3442                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3443                 :            :                                           "wrong action order, port_id should "
    3444                 :            :                                           "be after push VLAN");
    3445   [ #  #  #  # ]:          0 :         if (!attr->transfer && priv->representor)
    3446                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3447                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    3448                 :            :                                           "push vlan action for VF representor "
    3449                 :            :                                           "not supported on NIC table");
    3450         [ #  # ]:          0 :         if (vlan_m &&
    3451   [ #  #  #  # ]:          0 :             (vlan_m->hdr.vlan_tci & MLX5DV_FLOW_VLAN_PCP_MASK_BE) &&
    3452                 :            :             (vlan_m->hdr.vlan_tci & MLX5DV_FLOW_VLAN_PCP_MASK_BE) !=
    3453                 :          0 :                 MLX5DV_FLOW_VLAN_PCP_MASK_BE &&
    3454   [ #  #  #  # ]:          0 :             !(action_flags & MLX5_FLOW_ACTION_OF_SET_VLAN_PCP) &&
    3455                 :          0 :             !(mlx5_flow_find_action
    3456                 :            :                 (action + 1, RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP)))
    3457                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3458                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3459                 :            :                                           "not full match mask on VLAN PCP and "
    3460                 :            :                                           "there is no of_set_vlan_pcp action, "
    3461                 :            :                                           "push VLAN action cannot figure out "
    3462                 :            :                                           "PCP value");
    3463         [ #  # ]:          0 :         if (vlan_m &&
    3464   [ #  #  #  # ]:          0 :             (vlan_m->hdr.vlan_tci & MLX5DV_FLOW_VLAN_VID_MASK_BE) &&
    3465                 :            :             (vlan_m->hdr.vlan_tci & MLX5DV_FLOW_VLAN_VID_MASK_BE) !=
    3466                 :          0 :                 MLX5DV_FLOW_VLAN_VID_MASK_BE &&
    3467   [ #  #  #  # ]:          0 :             !(action_flags & MLX5_FLOW_ACTION_OF_SET_VLAN_VID) &&
    3468                 :          0 :             !(mlx5_flow_find_action
    3469                 :            :                 (action + 1, RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID)))
    3470                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3471                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3472                 :            :                                           "not full match mask on VLAN VID and "
    3473                 :            :                                           "there is no of_set_vlan_vid action, "
    3474                 :            :                                           "push VLAN action cannot figure out "
    3475                 :            :                                           "VID value");
    3476                 :            :         (void)attr;
    3477                 :            :         return 0;
    3478                 :            : }
    3479                 :            : 
    3480                 :            : /**
    3481                 :            :  * Validate the set VLAN PCP.
    3482                 :            :  *
    3483                 :            :  * @param[in] action_flags
    3484                 :            :  *   Holds the actions detected until now.
    3485                 :            :  * @param[in] actions
    3486                 :            :  *   Pointer to the list of actions remaining in the flow rule.
    3487                 :            :  * @param[out] error
    3488                 :            :  *   Pointer to error structure.
    3489                 :            :  *
    3490                 :            :  * @return
    3491                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3492                 :            :  */
    3493                 :            : static int
    3494                 :          0 : flow_dv_validate_action_set_vlan_pcp(uint64_t action_flags,
    3495                 :            :                                      const struct rte_flow_action actions[],
    3496                 :            :                                      struct rte_flow_error *error)
    3497                 :            : {
    3498                 :            :         const struct rte_flow_action *action = actions;
    3499                 :          0 :         const struct rte_flow_action_of_set_vlan_pcp *conf = action->conf;
    3500                 :            : 
    3501         [ #  # ]:          0 :         if (conf->vlan_pcp > 7)
    3502                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3503                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3504                 :            :                                           "VLAN PCP value is too big");
    3505         [ #  # ]:          0 :         if (!(action_flags & MLX5_FLOW_ACTION_OF_PUSH_VLAN))
    3506                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3507                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3508                 :            :                                           "set VLAN PCP action must follow "
    3509                 :            :                                           "the push VLAN action");
    3510         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_OF_SET_VLAN_PCP)
    3511                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3512                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3513                 :            :                                           "Multiple VLAN PCP modification are "
    3514                 :            :                                           "not supported");
    3515         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_PORT_ID)
    3516                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3517                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3518                 :            :                                           "wrong action order, port_id should "
    3519                 :            :                                           "be after set VLAN PCP");
    3520                 :            :         return 0;
    3521                 :            : }
    3522                 :            : 
    3523                 :            : /**
    3524                 :            :  * Validate the set VLAN VID.
    3525                 :            :  *
    3526                 :            :  * @param[in] item_flags
    3527                 :            :  *   Holds the items detected in this rule.
    3528                 :            :  * @param[in] action_flags
    3529                 :            :  *   Holds the actions detected until now.
    3530                 :            :  * @param[in] actions
    3531                 :            :  *   Pointer to the list of actions remaining in the flow rule.
    3532                 :            :  * @param[out] error
    3533                 :            :  *   Pointer to error structure.
    3534                 :            :  *
    3535                 :            :  * @return
    3536                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3537                 :            :  */
    3538                 :            : static int
    3539                 :          0 : flow_dv_validate_action_set_vlan_vid(uint64_t item_flags,
    3540                 :            :                                      uint64_t action_flags,
    3541                 :            :                                      const struct rte_flow_action actions[],
    3542                 :            :                                      struct rte_flow_error *error)
    3543                 :            : {
    3544                 :            :         const struct rte_flow_action *action = actions;
    3545                 :          0 :         const struct rte_flow_action_of_set_vlan_vid *conf = action->conf;
    3546                 :            : 
    3547   [ #  #  #  # ]:          0 :         if (rte_be_to_cpu_16(conf->vlan_vid) > 0xFFE)
    3548                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3549                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3550                 :            :                                           "VLAN VID value is too big");
    3551         [ #  # ]:          0 :         if (!(action_flags & MLX5_FLOW_ACTION_OF_PUSH_VLAN) &&
    3552         [ #  # ]:          0 :             !(item_flags & MLX5_FLOW_LAYER_OUTER_VLAN))
    3553                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3554                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3555                 :            :                                           "set VLAN VID action must follow push"
    3556                 :            :                                           " VLAN action or match on VLAN item");
    3557         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_OF_SET_VLAN_VID)
    3558                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3559                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3560                 :            :                                           "Multiple VLAN VID modifications are "
    3561                 :            :                                           "not supported");
    3562         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_PORT_ID)
    3563                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3564                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3565                 :            :                                           "wrong action order, port_id should "
    3566                 :            :                                           "be after set VLAN VID");
    3567                 :            :         return 0;
    3568                 :            : }
    3569                 :            : 
    3570                 :            : /*
    3571                 :            :  * Validate the FLAG action.
    3572                 :            :  *
    3573                 :            :  * @param[in] dev
    3574                 :            :  *   Pointer to the rte_eth_dev structure.
    3575                 :            :  * @param[in] action_flags
    3576                 :            :  *   Holds the actions detected until now.
    3577                 :            :  * @param[in] attr
    3578                 :            :  *   Pointer to flow attributes
    3579                 :            :  * @param[out] error
    3580                 :            :  *   Pointer to error structure.
    3581                 :            :  *
    3582                 :            :  * @return
    3583                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3584                 :            :  */
    3585                 :            : static int
    3586                 :          0 : flow_dv_validate_action_flag(struct rte_eth_dev *dev,
    3587                 :            :                              uint64_t action_flags,
    3588                 :            :                              const struct rte_flow_attr *attr,
    3589                 :            :                              struct rte_flow_error *error)
    3590                 :            : {
    3591                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    3592                 :          0 :         struct mlx5_sh_config *config = &priv->sh->config;
    3593                 :            :         int ret;
    3594                 :            : 
    3595                 :            :         /* Fall back if no extended metadata register support. */
    3596         [ #  # ]:          0 :         if (config->dv_xmeta_en == MLX5_XMETA_MODE_LEGACY)
    3597                 :          0 :                 return mlx5_flow_validate_action_flag(action_flags, attr,
    3598                 :            :                                                       error);
    3599                 :            :         /* Extensive metadata mode requires registers. */
    3600         [ #  # ]:          0 :         if (!mlx5_flow_ext_mreg_supported(dev))
    3601                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3602                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    3603                 :            :                                           "no metadata registers "
    3604                 :            :                                           "to support flag action");
    3605         [ #  # ]:          0 :         if (!(priv->sh->dv_mark_mask & MLX5_FLOW_MARK_DEFAULT))
    3606                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3607                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    3608                 :            :                                           "extended metadata register"
    3609                 :            :                                           " isn't available");
    3610                 :          0 :         ret = mlx5_flow_get_reg_id(dev, MLX5_FLOW_MARK, 0, error);
    3611         [ #  # ]:          0 :         if (ret < 0)
    3612                 :            :                 return ret;
    3613                 :            :         MLX5_ASSERT(ret > 0);
    3614         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_MARK)
    3615                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3616                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    3617                 :            :                                           "can't mark and flag in same flow");
    3618         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_FLAG)
    3619                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3620                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    3621                 :            :                                           "can't have 2 flag"
    3622                 :            :                                           " actions in same flow");
    3623                 :            :         return 0;
    3624                 :            : }
    3625                 :            : 
    3626                 :            : /**
    3627                 :            :  * Validate MARK action.
    3628                 :            :  *
    3629                 :            :  * @param[in] dev
    3630                 :            :  *   Pointer to the rte_eth_dev structure.
    3631                 :            :  * @param[in] action
    3632                 :            :  *   Pointer to action.
    3633                 :            :  * @param[in] action_flags
    3634                 :            :  *   Holds the actions detected until now.
    3635                 :            :  * @param[in] attr
    3636                 :            :  *   Pointer to flow attributes
    3637                 :            :  * @param[out] error
    3638                 :            :  *   Pointer to error structure.
    3639                 :            :  *
    3640                 :            :  * @return
    3641                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3642                 :            :  */
    3643                 :            : static int
    3644                 :          0 : flow_dv_validate_action_mark(struct rte_eth_dev *dev,
    3645                 :            :                              const struct rte_flow_action *action,
    3646                 :            :                              uint64_t action_flags,
    3647                 :            :                              const struct rte_flow_attr *attr,
    3648                 :            :                              struct rte_flow_error *error)
    3649                 :            : {
    3650                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    3651                 :          0 :         struct mlx5_sh_config *config = &priv->sh->config;
    3652         [ #  # ]:          0 :         const struct rte_flow_action_mark *mark = action->conf;
    3653                 :            :         int ret;
    3654                 :            : 
    3655         [ #  # ]:          0 :         if (is_tunnel_offload_active(dev))
    3656                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3657                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    3658                 :            :                                           "no mark action "
    3659                 :            :                                           "if tunnel offload active");
    3660                 :            :         /* Fall back if no extended metadata register support. */
    3661         [ #  # ]:          0 :         if (config->dv_xmeta_en == MLX5_XMETA_MODE_LEGACY)
    3662                 :          0 :                 return mlx5_flow_validate_action_mark(action, action_flags,
    3663                 :            :                                                       attr, error);
    3664                 :            :         /* Extensive metadata mode requires registers. */
    3665         [ #  # ]:          0 :         if (!mlx5_flow_ext_mreg_supported(dev))
    3666                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3667                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    3668                 :            :                                           "no metadata registers "
    3669                 :            :                                           "to support mark action");
    3670         [ #  # ]:          0 :         if (!priv->sh->dv_mark_mask)
    3671                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3672                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    3673                 :            :                                           "extended metadata register"
    3674                 :            :                                           " isn't available");
    3675                 :          0 :         ret = mlx5_flow_get_reg_id(dev, MLX5_FLOW_MARK, 0, error);
    3676         [ #  # ]:          0 :         if (ret < 0)
    3677                 :            :                 return ret;
    3678                 :            :         MLX5_ASSERT(ret > 0);
    3679         [ #  # ]:          0 :         if (!mark)
    3680                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3681                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3682                 :            :                                           "configuration cannot be null");
    3683         [ #  # ]:          0 :         if (mark->id >= (MLX5_FLOW_MARK_MAX & priv->sh->dv_mark_mask))
    3684                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3685                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF,
    3686                 :          0 :                                           &mark->id,
    3687                 :            :                                           "mark id exceeds the limit");
    3688         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_FLAG)
    3689                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3690                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    3691                 :            :                                           "can't flag and mark in same flow");
    3692         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_MARK)
    3693                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3694                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    3695                 :            :                                           "can't have 2 mark actions in same"
    3696                 :            :                                           " flow");
    3697                 :            :         return 0;
    3698                 :            : }
    3699                 :            : 
    3700                 :            : /**
    3701                 :            :  * Validate SET_META action.
    3702                 :            :  *
    3703                 :            :  * @param[in] dev
    3704                 :            :  *   Pointer to the rte_eth_dev structure.
    3705                 :            :  * @param[in] action
    3706                 :            :  *   Pointer to the action structure.
    3707                 :            :  * @param[in] action_flags
    3708                 :            :  *   Holds the actions detected until now.
    3709                 :            :  * @param[in] attr
    3710                 :            :  *   Pointer to flow attributes
    3711                 :            :  * @param[out] error
    3712                 :            :  *   Pointer to error structure.
    3713                 :            :  *
    3714                 :            :  * @return
    3715                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3716                 :            :  */
    3717                 :            : static int
    3718                 :          0 : flow_dv_validate_action_set_meta(struct rte_eth_dev *dev,
    3719                 :            :                                  const struct rte_flow_action *action,
    3720                 :            :                                  uint64_t action_flags __rte_unused,
    3721                 :            :                                  const struct rte_flow_attr *attr,
    3722                 :            :                                  struct rte_flow_error *error)
    3723                 :            : {
    3724                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    3725                 :          0 :         struct mlx5_sh_config *config = &priv->sh->config;
    3726                 :            :         const struct rte_flow_action_set_meta *conf;
    3727                 :            :         uint32_t nic_mask = UINT32_MAX;
    3728                 :            :         int reg;
    3729                 :            : 
    3730   [ #  #  #  # ]:          0 :         if (config->dv_xmeta_en != MLX5_XMETA_MODE_LEGACY &&
    3731                 :          0 :             !mlx5_flow_ext_mreg_supported(dev))
    3732                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3733                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3734                 :            :                                           "extended metadata register"
    3735                 :            :                                           " isn't supported");
    3736                 :          0 :         reg = flow_dv_get_metadata_reg(dev, attr, error);
    3737         [ #  # ]:          0 :         if (reg < 0)
    3738                 :            :                 return reg;
    3739         [ #  # ]:          0 :         if (reg == REG_NON)
    3740                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3741                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3742                 :            :                                           "unavailable extended metadata register");
    3743         [ #  # ]:          0 :         if (reg != REG_A && reg != REG_B) {
    3744                 :          0 :                 struct mlx5_priv *priv = dev->data->dev_private;
    3745                 :            : 
    3746                 :          0 :                 nic_mask = priv->sh->dv_meta_mask;
    3747                 :            :         }
    3748         [ #  # ]:          0 :         if (!(action->conf))
    3749                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3750                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3751                 :            :                                           "configuration cannot be null");
    3752                 :            :         conf = (const struct rte_flow_action_set_meta *)action->conf;
    3753         [ #  # ]:          0 :         if (!conf->mask)
    3754                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3755                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3756                 :            :                                           "zero mask doesn't have any effect");
    3757         [ #  # ]:          0 :         if (conf->mask & ~nic_mask)
    3758                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3759                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3760                 :            :                                           "meta data must be within reg C0");
    3761                 :            :         return 0;
    3762                 :            : }
    3763                 :            : 
    3764                 :            : /**
    3765                 :            :  * Validate SET_TAG action.
    3766                 :            :  *
    3767                 :            :  * @param[in] dev
    3768                 :            :  *   Pointer to the rte_eth_dev structure.
    3769                 :            :  * @param[in] action
    3770                 :            :  *   Pointer to the action structure.
    3771                 :            :  * @param[in] action_flags
    3772                 :            :  *   Holds the actions detected until now.
    3773                 :            :  * @param[in] attr
    3774                 :            :  *   Pointer to flow attributes
    3775                 :            :  * @param[out] error
    3776                 :            :  *   Pointer to error structure.
    3777                 :            :  *
    3778                 :            :  * @return
    3779                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3780                 :            :  */
    3781                 :            : static int
    3782                 :          0 : flow_dv_validate_action_set_tag(struct rte_eth_dev *dev,
    3783                 :            :                                 const struct rte_flow_action *action,
    3784                 :            :                                 uint64_t action_flags,
    3785                 :            :                                 const struct rte_flow_attr *attr,
    3786                 :            :                                 struct rte_flow_error *error)
    3787                 :            : {
    3788                 :            :         const struct rte_flow_action_set_tag *conf;
    3789                 :            :         const uint64_t terminal_action_flags =
    3790                 :            :                 MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_QUEUE |
    3791                 :            :                 MLX5_FLOW_ACTION_RSS;
    3792                 :            :         int ret;
    3793                 :            : 
    3794         [ #  # ]:          0 :         if (!mlx5_flow_ext_mreg_supported(dev))
    3795                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3796                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3797                 :            :                                           "extensive metadata register"
    3798                 :            :                                           " isn't supported");
    3799         [ #  # ]:          0 :         if (!(action->conf))
    3800                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3801                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3802                 :            :                                           "configuration cannot be null");
    3803                 :            :         conf = (const struct rte_flow_action_set_tag *)action->conf;
    3804         [ #  # ]:          0 :         if (!conf->mask)
    3805                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3806                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3807                 :            :                                           "zero mask doesn't have any effect");
    3808                 :          0 :         ret = mlx5_flow_get_reg_id(dev, MLX5_APP_TAG, conf->index, error);
    3809         [ #  # ]:          0 :         if (ret < 0)
    3810                 :            :                 return ret;
    3811   [ #  #  #  # ]:          0 :         if (attr->ingress && (action_flags & terminal_action_flags))
    3812                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3813                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3814                 :            :                                           "set_tag has no effect"
    3815                 :            :                                           " with terminal actions");
    3816                 :            :         return 0;
    3817                 :            : }
    3818                 :            : 
    3819                 :            : /**
    3820                 :            :  * Indicates whether ASO aging is supported.
    3821                 :            :  *
    3822                 :            :  * @param[in] priv
    3823                 :            :  *   Pointer to device private context structure.
    3824                 :            :  * @param[in] root
    3825                 :            :  *   Whether action is on root table.
    3826                 :            :  *
    3827                 :            :  * @return
    3828                 :            :  *   True when ASO aging is supported, false otherwise.
    3829                 :            :  */
    3830                 :            : static inline bool
    3831                 :            : flow_hit_aso_supported(const struct mlx5_priv *priv, bool root)
    3832                 :            : {
    3833                 :            :         MLX5_ASSERT(priv);
    3834   [ #  #  #  #  :          0 :         return (priv->sh->flow_hit_aso_en && !root);
          #  #  #  #  #  
                      # ]
    3835                 :            : }
    3836                 :            : 
    3837                 :            : /**
    3838                 :            :  * Validate count action.
    3839                 :            :  *
    3840                 :            :  * @param[in] dev
    3841                 :            :  *   Pointer to rte_eth_dev structure.
    3842                 :            :  * @param[in] shared
    3843                 :            :  *   Indicator if action is shared.
    3844                 :            :  * @param[in] action_flags
    3845                 :            :  *   Holds the actions detected until now.
    3846                 :            :  * @param[in] root
    3847                 :            :  *   Whether action is on root table.
    3848                 :            :  * @param[out] error
    3849                 :            :  *   Pointer to error structure.
    3850                 :            :  *
    3851                 :            :  * @return
    3852                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3853                 :            :  */
    3854                 :            : static int
    3855                 :          0 : flow_dv_validate_action_count(struct rte_eth_dev *dev, bool shared,
    3856                 :            :                               uint64_t action_flags,
    3857                 :            :                               bool root,
    3858                 :            :                               struct rte_flow_error *error)
    3859                 :            : {
    3860                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    3861                 :            : 
    3862         [ #  # ]:          0 :         if (!priv->sh->cdev->config.devx)
    3863                 :          0 :                 goto notsup_err;
    3864         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_COUNT)
    3865                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3866                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    3867                 :            :                                           "duplicate count actions set");
    3868   [ #  #  #  #  :          0 :         if (shared && (action_flags & MLX5_FLOW_ACTION_AGE) &&
                   #  # ]
    3869                 :            :             !flow_hit_aso_supported(priv, root))
    3870                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3871                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    3872                 :            :                                           "old age and indirect count combination is not supported");
    3873                 :            : #ifdef HAVE_IBV_FLOW_DEVX_COUNTERS
    3874                 :            :         return 0;
    3875                 :            : #endif
    3876                 :            : notsup_err:
    3877                 :          0 :         return rte_flow_error_set
    3878                 :            :                       (error, ENOTSUP,
    3879                 :            :                        RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    3880                 :            :                        NULL,
    3881                 :            :                        "count action not supported");
    3882                 :            : }
    3883                 :            : 
    3884                 :            : /**
    3885                 :            :  * Validate the L2 encap action.
    3886                 :            :  *
    3887                 :            :  * @param[in] dev
    3888                 :            :  *   Pointer to the rte_eth_dev structure.
    3889                 :            :  * @param[in] action_flags
    3890                 :            :  *   Holds the actions detected until now.
    3891                 :            :  * @param[in] action
    3892                 :            :  *   Pointer to the action structure.
    3893                 :            :  * @param[in] attr
    3894                 :            :  *   Pointer to flow attributes.
    3895                 :            :  * @param[out] error
    3896                 :            :  *   Pointer to error structure.
    3897                 :            :  *
    3898                 :            :  * @return
    3899                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3900                 :            :  */
    3901                 :            : static int
    3902                 :          0 : flow_dv_validate_action_l2_encap(struct rte_eth_dev *dev,
    3903                 :            :                                  uint64_t action_flags,
    3904                 :            :                                  const struct rte_flow_action *action,
    3905                 :            :                                  const struct rte_flow_attr *attr,
    3906                 :            :                                  struct rte_flow_error *error)
    3907                 :            : {
    3908                 :          0 :         const struct mlx5_priv *priv = dev->data->dev_private;
    3909                 :            : 
    3910         [ #  # ]:          0 :         if (!(action->conf))
    3911                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3912                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3913                 :            :                                           "configuration cannot be null");
    3914         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_ENCAP)
    3915                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3916                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    3917                 :            :                                           "can only have a single encap action "
    3918                 :            :                                           "in a flow");
    3919   [ #  #  #  # ]:          0 :         if (!attr->transfer && priv->representor)
    3920                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3921                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    3922                 :            :                                           "encap action for VF representor "
    3923                 :            :                                           "not supported on NIC table");
    3924                 :            :         return 0;
    3925                 :            : }
    3926                 :            : 
    3927                 :            : /**
    3928                 :            :  * Validate a decap action.
    3929                 :            :  *
    3930                 :            :  * @param[in] dev
    3931                 :            :  *   Pointer to the rte_eth_dev structure.
    3932                 :            :  * @param[in] action_flags
    3933                 :            :  *   Holds the actions detected until now.
    3934                 :            :  * @param[in] action
    3935                 :            :  *   Pointer to the action structure.
    3936                 :            :  * @param[in] item_flags
    3937                 :            :  *   Holds the items detected.
    3938                 :            :  * @param[in] attr
    3939                 :            :  *   Pointer to flow attributes
    3940                 :            :  * @param[out] error
    3941                 :            :  *   Pointer to error structure.
    3942                 :            :  *
    3943                 :            :  * @return
    3944                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3945                 :            :  */
    3946                 :            : static int
    3947                 :          0 : flow_dv_validate_action_decap(struct rte_eth_dev *dev,
    3948                 :            :                               uint64_t action_flags,
    3949                 :            :                               const struct rte_flow_action *action,
    3950                 :            :                               const uint64_t item_flags,
    3951                 :            :                               const struct rte_flow_attr *attr,
    3952                 :            :                               struct rte_flow_error *error)
    3953                 :            : {
    3954                 :          0 :         const struct mlx5_priv *priv = dev->data->dev_private;
    3955                 :            : 
    3956         [ #  # ]:          0 :         if (priv->sh->cdev->config.hca_attr.scatter_fcs_w_decap_disable &&
    3957         [ #  # ]:          0 :             !priv->sh->config.decap_en)
    3958                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3959                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    3960                 :            :                                           "decap is not enabled");
    3961         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_XCAP_ACTIONS)
    3962                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3963                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    3964         [ #  # ]:          0 :                                           action_flags &
    3965                 :            :                                           MLX5_FLOW_ACTION_DECAP ? "can only "
    3966                 :            :                                           "have a single decap action" : "decap "
    3967                 :            :                                           "after encap is not supported");
    3968         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS)
    3969                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3970                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    3971                 :            :                                           "can't have decap action after"
    3972                 :            :                                           " modify action");
    3973         [ #  # ]:          0 :         if (attr->egress)
    3974                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3975                 :            :                                           RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
    3976                 :            :                                           NULL,
    3977                 :            :                                           "decap action not supported for "
    3978                 :            :                                           "egress");
    3979   [ #  #  #  # ]:          0 :         if (!attr->transfer && priv->representor)
    3980                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3981                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    3982                 :            :                                           "decap action for VF representor "
    3983                 :            :                                           "not supported on NIC table");
    3984         [ #  # ]:          0 :         if (action->type == RTE_FLOW_ACTION_TYPE_VXLAN_DECAP &&
    3985         [ #  # ]:          0 :             !(item_flags & MLX5_FLOW_LAYER_VXLAN))
    3986                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3987                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    3988                 :            :                                 "VXLAN item should be present for VXLAN decap");
    3989                 :            :         return 0;
    3990                 :            : }
    3991                 :            : 
    3992                 :            : const struct rte_flow_action_raw_decap empty_decap = {.data = NULL, .size = 0,};
    3993                 :            : 
    3994                 :            : /**
    3995                 :            :  * Validate the raw encap and decap actions.
    3996                 :            :  *
    3997                 :            :  * @param[in] dev
    3998                 :            :  *   Pointer to the rte_eth_dev structure.
    3999                 :            :  * @param[in] decap
    4000                 :            :  *   Pointer to the decap action.
    4001                 :            :  * @param[in] encap
    4002                 :            :  *   Pointer to the encap action.
    4003                 :            :  * @param[in] attr
    4004                 :            :  *   Pointer to flow attributes
    4005                 :            :  * @param[in/out] action_flags
    4006                 :            :  *   Holds the actions detected until now.
    4007                 :            :  * @param[out] actions_n
    4008                 :            :  *   pointer to the number of actions counter.
    4009                 :            :  * @param[in] action
    4010                 :            :  *   Pointer to the action structure.
    4011                 :            :  * @param[in] item_flags
    4012                 :            :  *   Holds the items detected.
    4013                 :            :  * @param[out] error
    4014                 :            :  *   Pointer to error structure.
    4015                 :            :  *
    4016                 :            :  * @return
    4017                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    4018                 :            :  */
    4019                 :            : static int
    4020                 :          0 : flow_dv_validate_action_raw_encap_decap
    4021                 :            :         (struct rte_eth_dev *dev,
    4022                 :            :          const struct rte_flow_action_raw_decap *decap,
    4023                 :            :          const struct rte_flow_action_raw_encap *encap,
    4024                 :            :          const struct rte_flow_attr *attr, uint64_t *action_flags,
    4025                 :            :          int *actions_n, const struct rte_flow_action *action,
    4026                 :            :          uint64_t item_flags, struct rte_flow_error *error)
    4027                 :            : {
    4028                 :          0 :         const struct mlx5_priv *priv = dev->data->dev_private;
    4029                 :            :         int ret;
    4030                 :            : 
    4031   [ #  #  #  #  :          0 :         if (encap && (!encap->size || !encap->data))
                   #  # ]
    4032                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    4033                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    4034                 :            :                                           "raw encap data cannot be empty");
    4035         [ #  # ]:          0 :         if (decap && encap) {
    4036         [ #  # ]:          0 :                 if (decap->size <= MLX5_ENCAPSULATION_DECISION_SIZE &&
    4037         [ #  # ]:          0 :                     encap->size > MLX5_ENCAPSULATION_DECISION_SIZE)
    4038                 :            :                         /* L3 encap. */
    4039                 :            :                         decap = NULL;
    4040         [ #  # ]:          0 :                 else if (encap->size <=
    4041         [ #  # ]:          0 :                            MLX5_ENCAPSULATION_DECISION_SIZE &&
    4042                 :            :                            decap->size >
    4043                 :            :                            MLX5_ENCAPSULATION_DECISION_SIZE)
    4044                 :            :                         /* L3 decap. */
    4045                 :            :                         encap = NULL;
    4046         [ #  # ]:          0 :                 else if (encap->size >
    4047         [ #  # ]:          0 :                            MLX5_ENCAPSULATION_DECISION_SIZE &&
    4048                 :            :                            decap->size >
    4049                 :            :                            MLX5_ENCAPSULATION_DECISION_SIZE)
    4050                 :            :                         /* 2 L2 actions: encap and decap. */
    4051                 :            :                         ;
    4052                 :            :                 else
    4053                 :          0 :                         return rte_flow_error_set(error,
    4054                 :            :                                 ENOTSUP,
    4055                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION,
    4056                 :            :                                 NULL, "unsupported too small "
    4057                 :            :                                 "raw decap and too small raw "
    4058                 :            :                                 "encap combination");
    4059                 :            :         }
    4060         [ #  # ]:          0 :         if (decap) {
    4061                 :          0 :                 ret = flow_dv_validate_action_decap(dev, *action_flags, action,
    4062                 :            :                                                     item_flags, attr, error);
    4063         [ #  # ]:          0 :                 if (ret < 0)
    4064                 :            :                         return ret;
    4065                 :          0 :                 *action_flags |= MLX5_FLOW_ACTION_DECAP;
    4066                 :          0 :                 ++(*actions_n);
    4067                 :            :         }
    4068         [ #  # ]:          0 :         if (encap) {
    4069         [ #  # ]:          0 :                 if (encap->size <= MLX5_ENCAPSULATION_DECISION_SIZE)
    4070                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    4071                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    4072                 :            :                                                   NULL,
    4073                 :            :                                                   "small raw encap size");
    4074         [ #  # ]:          0 :                 if (*action_flags & MLX5_FLOW_ACTION_ENCAP)
    4075                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    4076                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    4077                 :            :                                                   NULL,
    4078                 :            :                                                   "more than one encap action");
    4079   [ #  #  #  # ]:          0 :                 if (!attr->transfer && priv->representor)
    4080                 :          0 :                         return rte_flow_error_set
    4081                 :            :                                         (error, ENOTSUP,
    4082                 :            :                                          RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    4083                 :            :                                          "encap action for VF representor "
    4084                 :            :                                          "not supported on NIC table");
    4085                 :          0 :                 *action_flags |= MLX5_FLOW_ACTION_ENCAP;
    4086                 :          0 :                 ++(*actions_n);
    4087                 :            :         }
    4088                 :            :         return 0;
    4089                 :            : }
    4090                 :            : 
    4091                 :            : /*
    4092                 :            :  * Validate the ASO CT action.
    4093                 :            :  *
    4094                 :            :  * @param[in] dev
    4095                 :            :  *   Pointer to the rte_eth_dev structure.
    4096                 :            :  * @param[in] action_flags
    4097                 :            :  *   Holds the actions detected until now.
    4098                 :            :  * @param[in] item_flags
    4099                 :            :  *   The items found in this flow rule.
    4100                 :            :  * @param root
    4101                 :            :  *   Whether action is on root table.
    4102                 :            :  * @param[out] error
    4103                 :            :  *   Pointer to error structure.
    4104                 :            :  *
    4105                 :            :  * @return
    4106                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    4107                 :            :  */
    4108                 :            : static int
    4109                 :          0 : flow_dv_validate_action_aso_ct(struct rte_eth_dev *dev,
    4110                 :            :                                uint64_t action_flags,
    4111                 :            :                                uint64_t item_flags,
    4112                 :            :                                bool root,
    4113                 :            :                                struct rte_flow_error *error)
    4114                 :            : {
    4115                 :            :         RTE_SET_USED(dev);
    4116                 :            : 
    4117         [ #  # ]:          0 :         if (root)
    4118                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    4119                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    4120                 :            :                                           NULL,
    4121                 :            :                                           "Only support non-root table");
    4122         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_FATE_ACTIONS)
    4123                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    4124                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    4125                 :            :                                           "CT cannot follow a fate action");
    4126         [ #  # ]:          0 :         if ((action_flags & MLX5_FLOW_ACTION_METER) ||
    4127                 :            :             (action_flags & MLX5_FLOW_ACTION_AGE))
    4128                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    4129                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    4130                 :            :                                           "Only one ASO action is supported");
    4131         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_ENCAP)
    4132                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    4133                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    4134                 :            :                                           "Encap cannot exist before CT");
    4135         [ #  # ]:          0 :         if (!(item_flags & MLX5_FLOW_LAYER_OUTER_L4_TCP))
    4136                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    4137                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    4138                 :            :                                           "Not a outer TCP packet");
    4139                 :            :         return 0;
    4140                 :            : }
    4141                 :            : 
    4142                 :            : /**
    4143                 :            :  * Validate METER_COLOR item.
    4144                 :            :  *
    4145                 :            :  * @param[in] dev
    4146                 :            :  *   Pointer to the rte_eth_dev structure.
    4147                 :            :  * @param[in] item
    4148                 :            :  *   Item specification.
    4149                 :            :  * @param[in] attr
    4150                 :            :  *   Attributes of flow that includes this item.
    4151                 :            :  * @param[out] error
    4152                 :            :  *   Pointer to error structure.
    4153                 :            :  *
    4154                 :            :  * @return
    4155                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    4156                 :            :  */
    4157                 :            : static int
    4158                 :          0 : flow_dv_validate_item_meter_color(struct rte_eth_dev *dev,
    4159                 :            :                            const struct rte_flow_item *item,
    4160                 :            :                            const struct rte_flow_attr *attr __rte_unused,
    4161                 :            :                            struct rte_flow_error *error)
    4162                 :            : {
    4163                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    4164                 :          0 :         const struct rte_flow_item_meter_color *spec = item->spec;
    4165                 :          0 :         const struct rte_flow_item_meter_color *mask = item->mask;
    4166                 :          0 :         struct rte_flow_item_meter_color nic_mask = {
    4167                 :            :                 .color = RTE_COLORS
    4168                 :            :         };
    4169                 :            :         int ret;
    4170                 :            : 
    4171         [ #  # ]:          0 :         if (priv->sh->registers.aso_reg == REG_NON)
    4172                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    4173                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    4174                 :            :                                           "meter color register"
    4175                 :            :                                           " isn't available");
    4176                 :          0 :         ret = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR, 0, error);
    4177         [ #  # ]:          0 :         if (ret < 0)
    4178                 :            :                 return ret;
    4179         [ #  # ]:          0 :         if (!spec)
    4180                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    4181                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
    4182                 :          0 :                                           item->spec,
    4183                 :            :                                           "data cannot be empty");
    4184         [ #  # ]:          0 :         if (spec->color > RTE_COLORS)
    4185                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    4186                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF,
    4187                 :          0 :                                           &spec->color,
    4188                 :            :                                           "meter color is invalid");
    4189         [ #  # ]:          0 :         if (!mask)
    4190                 :            :                 mask = &rte_flow_item_meter_color_mask;
    4191         [ #  # ]:          0 :         if (!mask->color)
    4192                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    4193                 :            :                                         RTE_FLOW_ERROR_TYPE_ITEM_SPEC, NULL,
    4194                 :            :                                         "mask cannot be zero");
    4195                 :            : 
    4196                 :          0 :         ret = mlx5_flow_item_acceptable(item, (const uint8_t *)mask,
    4197                 :            :                                 (const uint8_t *)&nic_mask,
    4198                 :            :                                 sizeof(struct rte_flow_item_meter_color),
    4199                 :            :                                 MLX5_ITEM_RANGE_NOT_ACCEPTED, error);
    4200                 :            :         if (ret < 0)
    4201                 :            :                 return ret;
    4202                 :            :         return 0;
    4203                 :            : }
    4204                 :            : 
    4205                 :            : /**
    4206                 :            :  * Validate aggregated affinity item.
    4207                 :            :  *
    4208                 :            :  * @param[in] dev
    4209                 :            :  *   Pointer to the rte_eth_dev structure.
    4210                 :            :  * @param[in] item
    4211                 :            :  *   Item specification.
    4212                 :            :  * @param[in] attr
    4213                 :            :  *   Attributes of flow that includes this item.
    4214                 :            :  * @param[out] error
    4215                 :            :  *   Pointer to error structure.
    4216                 :            :  *
    4217                 :            :  * @return
    4218                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    4219                 :            :  */
    4220                 :            : static int
    4221                 :          0 : flow_dv_validate_item_aggr_affinity(struct rte_eth_dev *dev,
    4222                 :            :                                    const struct rte_flow_item *item,
    4223                 :            :                                    const struct rte_flow_attr *attr,
    4224                 :            :                                    struct rte_flow_error *error)
    4225                 :            : {
    4226                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    4227                 :          0 :         const struct rte_flow_item_aggr_affinity *spec = item->spec;
    4228                 :          0 :         const struct rte_flow_item_aggr_affinity *mask = item->mask;
    4229                 :          0 :         struct rte_flow_item_aggr_affinity nic_mask = {
    4230                 :            :                 .affinity = UINT8_MAX
    4231                 :            :         };
    4232                 :            :         int ret;
    4233                 :            : 
    4234         [ #  # ]:          0 :         if (!priv->sh->lag_rx_port_affinity_en)
    4235                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    4236                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    4237                 :            :                                           "Unsupported aggregated affinity with Older FW");
    4238   [ #  #  #  #  :          0 :         if ((attr->transfer && priv->fdb_def_rule) ||
                   #  # ]
    4239         [ #  # ]:          0 :             attr->egress || attr->group)
    4240                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    4241                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
    4242                 :            :                                           item->spec,
    4243                 :            :                                           "aggregated affinity is not supported with egress or FDB on non root table");
    4244         [ #  # ]:          0 :         if (!spec)
    4245                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    4246                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
    4247                 :            :                                           item->spec,
    4248                 :            :                                           "data cannot be empty");
    4249         [ #  # ]:          0 :         if (spec->affinity == 0)
    4250                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    4251                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
    4252                 :            :                                           item->spec,
    4253                 :            :                                           "zero affinity number not supported");
    4254         [ #  # ]:          0 :         if (spec->affinity > priv->num_lag_ports)
    4255                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    4256                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
    4257                 :            :                                           item->spec,
    4258                 :            :                                           "exceed max affinity number in lag ports");
    4259         [ #  # ]:          0 :         if (!mask)
    4260                 :            :                 mask = &rte_flow_item_aggr_affinity_mask;
    4261         [ #  # ]:          0 :         if (!mask->affinity)
    4262                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    4263                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_SPEC, NULL,
    4264                 :            :                                           "mask cannot be zero");
    4265                 :          0 :         ret = mlx5_flow_item_acceptable(item, (const uint8_t *)mask,
    4266                 :            :                                 (const uint8_t *)&nic_mask,
    4267                 :            :                                 sizeof(struct rte_flow_item_aggr_affinity),
    4268                 :            :                                 MLX5_ITEM_RANGE_NOT_ACCEPTED, error);
    4269                 :            :         if (ret < 0)
    4270                 :            :                 return ret;
    4271                 :            :         return 0;
    4272                 :            : }
    4273                 :            : 
    4274                 :            : int
    4275                 :          0 : flow_dv_encap_decap_match_cb(void *tool_ctx __rte_unused,
    4276                 :            :                              struct mlx5_list_entry *entry, void *cb_ctx)
    4277                 :            : {
    4278                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
    4279                 :          0 :         struct mlx5_flow_dv_encap_decap_resource *ctx_resource = ctx->data;
    4280                 :            :         struct mlx5_flow_dv_encap_decap_resource *resource;
    4281                 :            : 
    4282                 :            :         resource = container_of(entry, struct mlx5_flow_dv_encap_decap_resource,
    4283                 :            :                                 entry);
    4284         [ #  # ]:          0 :         if (resource->reformat_type == ctx_resource->reformat_type &&
    4285                 :          0 :             resource->ft_type == ctx_resource->ft_type &&
    4286         [ #  # ]:          0 :             resource->flags == ctx_resource->flags &&
    4287         [ #  # ]:          0 :             resource->size == ctx_resource->size &&
    4288                 :          0 :             !memcmp((const void *)resource->buf,
    4289         [ #  # ]:          0 :                     (const void *)ctx_resource->buf,
    4290                 :            :                     resource->size))
    4291                 :          0 :                 return 0;
    4292                 :            :         return -1;
    4293                 :            : }
    4294                 :            : 
    4295                 :            : struct mlx5_list_entry *
    4296                 :          0 : flow_dv_encap_decap_create_cb(void *tool_ctx, void *cb_ctx)
    4297                 :            : {
    4298                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
    4299                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
    4300                 :            :         struct mlx5dv_dr_domain *domain;
    4301                 :          0 :         struct mlx5_flow_dv_encap_decap_resource *ctx_resource = ctx->data;
    4302                 :            :         struct mlx5_flow_dv_encap_decap_resource *resource;
    4303                 :            :         uint32_t idx;
    4304                 :            :         int ret;
    4305                 :            : 
    4306         [ #  # ]:          0 :         if (ctx_resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_FDB)
    4307                 :          0 :                 domain = sh->fdb_domain;
    4308         [ #  # ]:          0 :         else if (ctx_resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_NIC_RX)
    4309                 :          0 :                 domain = sh->rx_domain;
    4310                 :            :         else
    4311                 :          0 :                 domain = sh->tx_domain;
    4312                 :            :         /* Register new encap/decap resource. */
    4313                 :          0 :         resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_DECAP_ENCAP], &idx);
    4314         [ #  # ]:          0 :         if (!resource) {
    4315                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
    4316                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    4317                 :            :                                    "cannot allocate resource memory");
    4318                 :          0 :                 return NULL;
    4319                 :            :         }
    4320                 :          0 :         *resource = *ctx_resource;
    4321                 :          0 :         resource->idx = idx;
    4322         [ #  # ]:          0 :         ret = mlx5_flow_os_create_flow_action_packet_reformat(sh->cdev->ctx,
    4323                 :            :                                                               domain, resource,
    4324                 :            :                                                              &resource->action);
    4325                 :            :         if (ret) {
    4326                 :          0 :                 mlx5_ipool_free(sh->ipool[MLX5_IPOOL_DECAP_ENCAP], idx);
    4327                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
    4328                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    4329                 :            :                                    NULL, "cannot create action");
    4330                 :          0 :                 return NULL;
    4331                 :            :         }
    4332                 :            : 
    4333                 :          0 :         return &resource->entry;
    4334                 :            : }
    4335                 :            : 
    4336                 :            : struct mlx5_list_entry *
    4337                 :          0 : flow_dv_encap_decap_clone_cb(void *tool_ctx, struct mlx5_list_entry *oentry,
    4338                 :            :                              void *cb_ctx)
    4339                 :            : {
    4340                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
    4341                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
    4342                 :            :         struct mlx5_flow_dv_encap_decap_resource *cache_resource;
    4343                 :            :         uint32_t idx;
    4344                 :            : 
    4345                 :          0 :         cache_resource = mlx5_ipool_malloc(sh->ipool[MLX5_IPOOL_DECAP_ENCAP],
    4346                 :            :                                            &idx);
    4347         [ #  # ]:          0 :         if (!cache_resource) {
    4348                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
    4349                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    4350                 :            :                                    "cannot allocate resource memory");
    4351                 :          0 :                 return NULL;
    4352                 :            :         }
    4353                 :            :         memcpy(cache_resource, oentry, sizeof(*cache_resource));
    4354                 :          0 :         cache_resource->idx = idx;
    4355                 :          0 :         return &cache_resource->entry;
    4356                 :            : }
    4357                 :            : 
    4358                 :            : void
    4359                 :          0 : flow_dv_encap_decap_clone_free_cb(void *tool_ctx, struct mlx5_list_entry *entry)
    4360                 :            : {
    4361                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
    4362                 :            :         struct mlx5_flow_dv_encap_decap_resource *res =
    4363                 :            :                                        container_of(entry, typeof(*res), entry);
    4364                 :            : 
    4365                 :          0 :         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_DECAP_ENCAP], res->idx);
    4366                 :          0 : }
    4367                 :            : 
    4368                 :            : /**
    4369                 :            :  * Find existing encap/decap resource or create and register a new one.
    4370                 :            :  *
    4371                 :            :  * @param[in, out] dev
    4372                 :            :  *   Pointer to rte_eth_dev structure.
    4373                 :            :  * @param[in, out] resource
    4374                 :            :  *   Pointer to encap/decap resource.
    4375                 :            :  * @parm[in, out] dev_flow
    4376                 :            :  *   Pointer to the dev_flow.
    4377                 :            :  * @param[out] error
    4378                 :            :  *   pointer to error structure.
    4379                 :            :  *
    4380                 :            :  * @return
    4381                 :            :  *   0 on success otherwise -errno and errno is set.
    4382                 :            :  */
    4383                 :            : static int
    4384                 :          0 : flow_dv_encap_decap_resource_register
    4385                 :            :                         (struct rte_eth_dev *dev,
    4386                 :            :                          struct mlx5_flow_dv_encap_decap_resource *resource,
    4387                 :            :                          struct mlx5_flow *dev_flow,
    4388                 :            :                          struct rte_flow_error *error)
    4389                 :            : {
    4390                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    4391                 :          0 :         struct mlx5_dev_ctx_shared *sh = priv->sh;
    4392                 :            :         struct mlx5_list_entry *entry;
    4393                 :            :         union {
    4394                 :            :                 struct {
    4395                 :            :                         uint32_t ft_type:8;
    4396                 :            :                         uint32_t refmt_type:8;
    4397                 :            :                         /*
    4398                 :            :                          * Header reformat actions can be shared between
    4399                 :            :                          * non-root tables. One bit to indicate non-root
    4400                 :            :                          * table or not.
    4401                 :            :                          */
    4402                 :            :                         uint32_t is_root:1;
    4403                 :            :                         uint32_t reserve:15;
    4404                 :            :                 };
    4405                 :            :                 uint32_t v32;
    4406                 :          0 :         } encap_decap_key = {
    4407                 :            :                 {
    4408                 :          0 :                         .ft_type = resource->ft_type,
    4409                 :          0 :                         .refmt_type = resource->reformat_type,
    4410                 :          0 :                         .is_root = !!dev_flow->dv.group,
    4411                 :            :                         .reserve = 0,
    4412                 :            :                 }
    4413                 :            :         };
    4414                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
    4415                 :            :                 .error = error,
    4416                 :            :                 .data = resource,
    4417                 :            :         };
    4418                 :            :         struct mlx5_hlist *encaps_decaps;
    4419                 :            :         uint64_t key64;
    4420                 :            : 
    4421                 :          0 :         encaps_decaps = flow_dv_hlist_prepare(sh, &sh->encaps_decaps,
    4422                 :            :                                 "encaps_decaps",
    4423                 :            :                                 MLX5_FLOW_ENCAP_DECAP_HTABLE_SZ,
    4424                 :            :                                 true, true, sh,
    4425                 :            :                                 flow_dv_encap_decap_create_cb,
    4426                 :            :                                 flow_dv_encap_decap_match_cb,
    4427                 :            :                                 flow_dv_encap_decap_remove_cb,
    4428                 :            :                                 flow_dv_encap_decap_clone_cb,
    4429                 :            :                                 flow_dv_encap_decap_clone_free_cb,
    4430                 :            :                                 error);
    4431         [ #  # ]:          0 :         if (unlikely(!encaps_decaps))
    4432                 :          0 :                 return -rte_errno;
    4433                 :          0 :         resource->flags = dev_flow->dv.group ? 0 : 1;
    4434                 :          0 :         key64 =  __rte_raw_cksum(&encap_decap_key.v32,
    4435                 :            :                                  sizeof(encap_decap_key.v32), 0);
    4436         [ #  # ]:          0 :         if (resource->reformat_type !=
    4437                 :          0 :             MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_TO_L2 &&
    4438         [ #  # ]:          0 :             resource->size)
    4439                 :          0 :                 key64 = __rte_raw_cksum(resource->buf, resource->size, key64);
    4440                 :          0 :         entry = mlx5_hlist_register(encaps_decaps, key64, &ctx);
    4441         [ #  # ]:          0 :         if (!entry)
    4442                 :          0 :                 return -rte_errno;
    4443                 :            :         resource = container_of(entry, typeof(*resource), entry);
    4444                 :          0 :         dev_flow->dv.encap_decap = resource;
    4445                 :          0 :         dev_flow->handle->dvh.rix_encap_decap = resource->idx;
    4446                 :          0 :         return 0;
    4447                 :            : }
    4448                 :            : 
    4449                 :            : /**
    4450                 :            :  * Find existing table jump resource or create and register a new one.
    4451                 :            :  *
    4452                 :            :  * @param[in, out] dev
    4453                 :            :  *   Pointer to rte_eth_dev structure.
    4454                 :            :  * @param[in, out] tbl
    4455                 :            :  *   Pointer to flow table resource.
    4456                 :            :  * @parm[in, out] dev_flow
    4457                 :            :  *   Pointer to the dev_flow.
    4458                 :            :  * @param[out] error
    4459                 :            :  *   pointer to error structure.
    4460                 :            :  *
    4461                 :            :  * @return
    4462                 :            :  *   0 on success otherwise -errno and errno is set.
    4463                 :            :  */
    4464                 :            : static int
    4465                 :            : flow_dv_jump_tbl_resource_register
    4466                 :            :                         (struct rte_eth_dev *dev __rte_unused,
    4467                 :            :                          struct mlx5_flow_tbl_resource *tbl,
    4468                 :            :                          struct mlx5_flow *dev_flow,
    4469                 :            :                          struct rte_flow_error *error __rte_unused)
    4470                 :            : {
    4471                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data =
    4472                 :          0 :                 container_of(tbl, struct mlx5_flow_tbl_data_entry, tbl);
    4473                 :            : 
    4474                 :            :         MLX5_ASSERT(tbl);
    4475                 :            :         MLX5_ASSERT(tbl_data->jump.action);
    4476                 :          0 :         dev_flow->handle->rix_jump = tbl_data->idx;
    4477                 :          0 :         dev_flow->dv.jump = &tbl_data->jump;
    4478                 :            :         return 0;
    4479                 :            : }
    4480                 :            : 
    4481                 :            : int
    4482                 :          0 : flow_dv_port_id_match_cb(void *tool_ctx __rte_unused,
    4483                 :            :                          struct mlx5_list_entry *entry, void *cb_ctx)
    4484                 :            : {
    4485                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
    4486                 :          0 :         struct mlx5_flow_dv_port_id_action_resource *ref = ctx->data;
    4487                 :            :         struct mlx5_flow_dv_port_id_action_resource *res =
    4488                 :            :                                        container_of(entry, typeof(*res), entry);
    4489                 :            : 
    4490                 :          0 :         return ref->port_id != res->port_id;
    4491                 :            : }
    4492                 :            : 
    4493                 :            : struct mlx5_list_entry *
    4494                 :          0 : flow_dv_port_id_create_cb(void *tool_ctx, void *cb_ctx)
    4495                 :            : {
    4496                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
    4497                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
    4498                 :          0 :         struct mlx5_flow_dv_port_id_action_resource *ref = ctx->data;
    4499                 :            :         struct mlx5_flow_dv_port_id_action_resource *resource;
    4500                 :            :         uint32_t idx;
    4501                 :            :         int ret;
    4502                 :            : 
    4503                 :            :         /* Register new port id action resource. */
    4504                 :          0 :         resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_PORT_ID], &idx);
    4505         [ #  # ]:          0 :         if (!resource) {
    4506                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
    4507                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    4508                 :            :                                    "cannot allocate port_id action memory");
    4509                 :          0 :                 return NULL;
    4510                 :            :         }
    4511                 :          0 :         *resource = *ref;
    4512                 :          0 :         ret = mlx5_flow_os_create_flow_action_dest_port(sh->fdb_domain,
    4513                 :            :                                                         ref->port_id,
    4514                 :            :                                                         &resource->action);
    4515                 :            :         if (ret) {
    4516                 :          0 :                 mlx5_ipool_free(sh->ipool[MLX5_IPOOL_PORT_ID], idx);
    4517                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
    4518                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    4519                 :            :                                    "cannot create action");
    4520                 :          0 :                 return NULL;
    4521                 :            :         }
    4522                 :          0 :         resource->idx = idx;
    4523                 :          0 :         return &resource->entry;
    4524                 :            : }
    4525                 :            : 
    4526                 :            : struct mlx5_list_entry *
    4527                 :          0 : flow_dv_port_id_clone_cb(void *tool_ctx,
    4528                 :            :                          struct mlx5_list_entry *entry __rte_unused,
    4529                 :            :                          void *cb_ctx)
    4530                 :            : {
    4531                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
    4532                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
    4533                 :            :         struct mlx5_flow_dv_port_id_action_resource *resource;
    4534                 :            :         uint32_t idx;
    4535                 :            : 
    4536                 :          0 :         resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_PORT_ID], &idx);
    4537         [ #  # ]:          0 :         if (!resource) {
    4538                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
    4539                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    4540                 :            :                                    "cannot allocate port_id action memory");
    4541                 :          0 :                 return NULL;
    4542                 :            :         }
    4543                 :            :         memcpy(resource, entry, sizeof(*resource));
    4544                 :          0 :         resource->idx = idx;
    4545                 :          0 :         return &resource->entry;
    4546                 :            : }
    4547                 :            : 
    4548                 :            : void
    4549                 :          0 : flow_dv_port_id_clone_free_cb(void *tool_ctx, struct mlx5_list_entry *entry)
    4550                 :            : {
    4551                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
    4552                 :            :         struct mlx5_flow_dv_port_id_action_resource *resource =
    4553                 :            :                                   container_of(entry, typeof(*resource), entry);
    4554                 :            : 
    4555                 :          0 :         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_PORT_ID], resource->idx);
    4556                 :          0 : }
    4557                 :            : 
    4558                 :            : /**
    4559                 :            :  * Find existing table port ID resource or create and register a new one.
    4560                 :            :  *
    4561                 :            :  * @param[in, out] dev
    4562                 :            :  *   Pointer to rte_eth_dev structure.
    4563                 :            :  * @param[in, out] ref
    4564                 :            :  *   Pointer to port ID action resource reference.
    4565                 :            :  * @parm[in, out] dev_flow
    4566                 :            :  *   Pointer to the dev_flow.
    4567                 :            :  * @param[out] error
    4568                 :            :  *   pointer to error structure.
    4569                 :            :  *
    4570                 :            :  * @return
    4571                 :            :  *   0 on success otherwise -errno and errno is set.
    4572                 :            :  */
    4573                 :            : static int
    4574                 :          0 : flow_dv_port_id_action_resource_register
    4575                 :            :                         (struct rte_eth_dev *dev,
    4576                 :            :                          struct mlx5_flow_dv_port_id_action_resource *ref,
    4577                 :            :                          struct mlx5_flow *dev_flow,
    4578                 :            :                          struct rte_flow_error *error)
    4579                 :            : {
    4580                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    4581                 :            :         struct mlx5_list_entry *entry;
    4582                 :            :         struct mlx5_flow_dv_port_id_action_resource *resource;
    4583                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
    4584                 :            :                 .error = error,
    4585                 :            :                 .data = ref,
    4586                 :            :         };
    4587                 :            : 
    4588                 :          0 :         entry = mlx5_list_register(priv->sh->port_id_action_list, &ctx);
    4589         [ #  # ]:          0 :         if (!entry)
    4590                 :          0 :                 return -rte_errno;
    4591                 :            :         resource = container_of(entry, typeof(*resource), entry);
    4592                 :          0 :         dev_flow->dv.port_id_action = resource;
    4593                 :          0 :         dev_flow->handle->rix_port_id_action = resource->idx;
    4594                 :          0 :         return 0;
    4595                 :            : }
    4596                 :            : 
    4597                 :            : int
    4598                 :          0 : flow_dv_push_vlan_match_cb(void *tool_ctx __rte_unused,
    4599                 :            :                            struct mlx5_list_entry *entry, void *cb_ctx)
    4600                 :            : {
    4601                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
    4602                 :          0 :         struct mlx5_flow_dv_push_vlan_action_resource *ref = ctx->data;
    4603                 :            :         struct mlx5_flow_dv_push_vlan_action_resource *res =
    4604                 :            :                                        container_of(entry, typeof(*res), entry);
    4605                 :            : 
    4606                 :          0 :         return ref->vlan_tag != res->vlan_tag || ref->ft_type != res->ft_type;
    4607                 :            : }
    4608                 :            : 
    4609                 :            : struct mlx5_list_entry *
    4610                 :          0 : flow_dv_push_vlan_create_cb(void *tool_ctx, void *cb_ctx)
    4611                 :            : {
    4612                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
    4613                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
    4614                 :          0 :         struct mlx5_flow_dv_push_vlan_action_resource *ref = ctx->data;
    4615                 :            :         struct mlx5_flow_dv_push_vlan_action_resource *resource;
    4616                 :            :         struct mlx5dv_dr_domain *domain;
    4617                 :            :         uint32_t idx;
    4618                 :            :         int ret;
    4619                 :            : 
    4620                 :            :         /* Register new port id action resource. */
    4621                 :          0 :         resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_PUSH_VLAN], &idx);
    4622         [ #  # ]:          0 :         if (!resource) {
    4623                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
    4624                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    4625                 :            :                                    "cannot allocate push_vlan action memory");
    4626                 :          0 :                 return NULL;
    4627                 :            :         }
    4628                 :          0 :         *resource = *ref;
    4629         [ #  # ]:          0 :         if (ref->ft_type == MLX5DV_FLOW_TABLE_TYPE_FDB)
    4630                 :          0 :                 domain = sh->fdb_domain;
    4631         [ #  # ]:          0 :         else if (ref->ft_type == MLX5DV_FLOW_TABLE_TYPE_NIC_RX)
    4632                 :          0 :                 domain = sh->rx_domain;
    4633                 :            :         else
    4634                 :          0 :                 domain = sh->tx_domain;
    4635                 :          0 :         ret = mlx5_flow_os_create_flow_action_push_vlan(domain, ref->vlan_tag,
    4636                 :            :                                                         &resource->action);
    4637                 :            :         if (ret) {
    4638                 :          0 :                 mlx5_ipool_free(sh->ipool[MLX5_IPOOL_PUSH_VLAN], idx);
    4639                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
    4640                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    4641                 :            :                                    "cannot create push vlan action");
    4642                 :          0 :                 return NULL;
    4643                 :            :         }
    4644                 :          0 :         resource->idx = idx;
    4645                 :          0 :         return &resource->entry;
    4646                 :            : }
    4647                 :            : 
    4648                 :            : struct mlx5_list_entry *
    4649                 :          0 : flow_dv_push_vlan_clone_cb(void *tool_ctx,
    4650                 :            :                            struct mlx5_list_entry *entry __rte_unused,
    4651                 :            :                            void *cb_ctx)
    4652                 :            : {
    4653                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
    4654                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
    4655                 :            :         struct mlx5_flow_dv_push_vlan_action_resource *resource;
    4656                 :            :         uint32_t idx;
    4657                 :            : 
    4658                 :          0 :         resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_PUSH_VLAN], &idx);
    4659         [ #  # ]:          0 :         if (!resource) {
    4660                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
    4661                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    4662                 :            :                                    "cannot allocate push_vlan action memory");
    4663                 :          0 :                 return NULL;
    4664                 :            :         }
    4665                 :            :         memcpy(resource, entry, sizeof(*resource));
    4666                 :          0 :         resource->idx = idx;
    4667                 :          0 :         return &resource->entry;
    4668                 :            : }
    4669                 :            : 
    4670                 :            : void
    4671                 :          0 : flow_dv_push_vlan_clone_free_cb(void *tool_ctx, struct mlx5_list_entry *entry)
    4672                 :            : {
    4673                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
    4674                 :            :         struct mlx5_flow_dv_push_vlan_action_resource *resource =
    4675                 :            :                                   container_of(entry, typeof(*resource), entry);
    4676                 :            : 
    4677                 :          0 :         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_PUSH_VLAN], resource->idx);
    4678                 :          0 : }
    4679                 :            : 
    4680                 :            : /**
    4681                 :            :  * Find existing push vlan resource or create and register a new one.
    4682                 :            :  *
    4683                 :            :  * @param [in, out] dev
    4684                 :            :  *   Pointer to rte_eth_dev structure.
    4685                 :            :  * @param[in, out] ref
    4686                 :            :  *   Pointer to port ID action resource reference.
    4687                 :            :  * @parm[in, out] dev_flow
    4688                 :            :  *   Pointer to the dev_flow.
    4689                 :            :  * @param[out] error
    4690                 :            :  *   pointer to error structure.
    4691                 :            :  *
    4692                 :            :  * @return
    4693                 :            :  *   0 on success otherwise -errno and errno is set.
    4694                 :            :  */
    4695                 :            : static int
    4696                 :          0 : flow_dv_push_vlan_action_resource_register
    4697                 :            :                        (struct rte_eth_dev *dev,
    4698                 :            :                         struct mlx5_flow_dv_push_vlan_action_resource *ref,
    4699                 :            :                         struct mlx5_flow *dev_flow,
    4700                 :            :                         struct rte_flow_error *error)
    4701                 :            : {
    4702                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    4703                 :            :         struct mlx5_flow_dv_push_vlan_action_resource *resource;
    4704                 :            :         struct mlx5_list_entry *entry;
    4705                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
    4706                 :            :                 .error = error,
    4707                 :            :                 .data = ref,
    4708                 :            :         };
    4709                 :            : 
    4710                 :          0 :         entry = mlx5_list_register(priv->sh->push_vlan_action_list, &ctx);
    4711         [ #  # ]:          0 :         if (!entry)
    4712                 :          0 :                 return -rte_errno;
    4713                 :            :         resource = container_of(entry, typeof(*resource), entry);
    4714                 :            : 
    4715                 :          0 :         dev_flow->handle->dvh.rix_push_vlan = resource->idx;
    4716                 :          0 :         dev_flow->dv.push_vlan_res = resource;
    4717                 :          0 :         return 0;
    4718                 :            : }
    4719                 :            : 
    4720                 :            : /**
    4721                 :            :  * Get the size of specific rte_flow_item_type hdr size
    4722                 :            :  *
    4723                 :            :  * @param[in] item_type
    4724                 :            :  *   Tested rte_flow_item_type.
    4725                 :            :  *
    4726                 :            :  * @return
    4727                 :            :  *   sizeof struct item_type, 0 if void or irrelevant.
    4728                 :            :  */
    4729                 :            : size_t
    4730         [ #  # ]:          0 : flow_dv_get_item_hdr_len(const enum rte_flow_item_type item_type)
    4731                 :            : {
    4732                 :            :         size_t retval;
    4733                 :            : 
    4734                 :            :         switch (item_type) {
    4735                 :            :         case RTE_FLOW_ITEM_TYPE_ETH:
    4736                 :            :                 retval = sizeof(struct rte_ether_hdr);
    4737                 :            :                 break;
    4738                 :            :         case RTE_FLOW_ITEM_TYPE_VLAN:
    4739                 :            :                 retval = sizeof(struct rte_vlan_hdr);
    4740                 :            :                 break;
    4741                 :            :         case RTE_FLOW_ITEM_TYPE_IPV4:
    4742                 :            :                 retval = sizeof(struct rte_ipv4_hdr);
    4743                 :            :                 break;
    4744                 :            :         case RTE_FLOW_ITEM_TYPE_IPV6:
    4745                 :            :                 retval = sizeof(struct rte_ipv6_hdr);
    4746                 :            :                 break;
    4747                 :            :         case RTE_FLOW_ITEM_TYPE_UDP:
    4748                 :            :                 retval = sizeof(struct rte_udp_hdr);
    4749                 :            :                 break;
    4750                 :            :         case RTE_FLOW_ITEM_TYPE_TCP:
    4751                 :            :                 retval = sizeof(struct rte_tcp_hdr);
    4752                 :            :                 break;
    4753                 :            :         case RTE_FLOW_ITEM_TYPE_VXLAN:
    4754                 :            :         case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
    4755                 :            :                 retval = sizeof(struct rte_vxlan_hdr);
    4756                 :            :                 break;
    4757                 :            :         case RTE_FLOW_ITEM_TYPE_GRE:
    4758                 :            :         case RTE_FLOW_ITEM_TYPE_NVGRE:
    4759                 :            :                 retval = sizeof(struct rte_gre_hdr);
    4760                 :            :                 break;
    4761                 :            :         case RTE_FLOW_ITEM_TYPE_MPLS:
    4762                 :            :                 retval = sizeof(struct rte_mpls_hdr);
    4763                 :            :                 break;
    4764                 :            :         case RTE_FLOW_ITEM_TYPE_VOID: /* Fall through. */
    4765                 :            :         default:
    4766                 :            :                 retval = 0;
    4767                 :            :                 break;
    4768                 :            :         }
    4769                 :          0 :         return retval;
    4770                 :            : }
    4771                 :            : 
    4772                 :            : #define MLX5_ENCAP_IPV4_VERSION         0x40
    4773                 :            : #define MLX5_ENCAP_IPV4_IHL_MIN         0x05
    4774                 :            : #define MLX5_ENCAP_IPV4_TTL_DEF         0x40
    4775                 :            : #define MLX5_ENCAP_IPV6_VTC_FLOW        0x60000000
    4776                 :            : #define MLX5_ENCAP_IPV6_HOP_LIMIT       0xff
    4777                 :            : #define MLX5_ENCAP_VXLAN_FLAGS          0x08000000
    4778                 :            : #define MLX5_ENCAP_VXLAN_GPE_FLAGS      0x04
    4779                 :            : 
    4780                 :            : /**
    4781                 :            :  * Convert the encap action data from list of rte_flow_item to raw buffer
    4782                 :            :  *
    4783                 :            :  * @param[in] items
    4784                 :            :  *   Pointer to rte_flow_item objects list.
    4785                 :            :  * @param[out] buf
    4786                 :            :  *   Pointer to the output buffer.
    4787                 :            :  * @param[out] size
    4788                 :            :  *   Pointer to the output buffer size.
    4789                 :            :  * @param[out] error
    4790                 :            :  *   Pointer to the error structure.
    4791                 :            :  *
    4792                 :            :  * @return
    4793                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    4794                 :            :  */
    4795                 :            : int
    4796                 :          0 : flow_dv_convert_encap_data(const struct rte_flow_item *items, uint8_t *buf,
    4797                 :            :                            size_t *size, struct rte_flow_error *error)
    4798                 :            : {
    4799                 :            :         struct rte_ether_hdr *eth = NULL;
    4800                 :            :         struct rte_vlan_hdr *vlan = NULL;
    4801                 :            :         struct rte_ipv4_hdr *ipv4 = NULL;
    4802                 :            :         struct rte_ipv6_hdr *ipv6 = NULL;
    4803                 :            :         struct rte_udp_hdr *udp = NULL;
    4804                 :            :         struct rte_vxlan_hdr *vxlan = NULL;
    4805                 :            :         struct rte_vxlan_gpe_hdr *vxlan_gpe = NULL;
    4806                 :            :         struct rte_gre_hdr *gre = NULL;
    4807                 :            :         size_t len;
    4808                 :            :         size_t temp_size = 0;
    4809                 :            : 
    4810         [ #  # ]:          0 :         if (!items)
    4811                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    4812                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
    4813                 :            :                                           NULL, "invalid empty data");
    4814         [ #  # ]:          0 :         for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {
    4815                 :          0 :                 len = flow_dv_get_item_hdr_len(items->type);
    4816         [ #  # ]:          0 :                 if (len + temp_size > MLX5_ENCAP_MAX_LEN)
    4817                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    4818                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    4819                 :          0 :                                                   (void *)items->type,
    4820                 :            :                                                   "items total size is too big"
    4821                 :            :                                                   " for encap action");
    4822         [ #  # ]:          0 :                 if (items->spec)
    4823         [ #  # ]:          0 :                         rte_memcpy(&buf[temp_size], items->spec, len);
    4824   [ #  #  #  #  :          0 :                 switch (items->type) {
          #  #  #  #  #  
                      # ]
    4825                 :          0 :                 case RTE_FLOW_ITEM_TYPE_ETH:
    4826                 :          0 :                         eth = (struct rte_ether_hdr *)&buf[temp_size];
    4827                 :          0 :                         break;
    4828                 :          0 :                 case RTE_FLOW_ITEM_TYPE_VLAN:
    4829                 :          0 :                         vlan = (struct rte_vlan_hdr *)&buf[temp_size];
    4830         [ #  # ]:          0 :                         if (!eth)
    4831                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    4832                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
    4833                 :            :                                                 (void *)items->type,
    4834                 :            :                                                 "eth header not found");
    4835         [ #  # ]:          0 :                         if (!eth->ether_type)
    4836                 :          0 :                                 eth->ether_type = RTE_BE16(RTE_ETHER_TYPE_VLAN);
    4837                 :            :                         break;
    4838                 :          0 :                 case RTE_FLOW_ITEM_TYPE_IPV4:
    4839                 :          0 :                         ipv4 = (struct rte_ipv4_hdr *)&buf[temp_size];
    4840         [ #  # ]:          0 :                         if (!vlan && !eth)
    4841                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    4842                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
    4843                 :            :                                                 (void *)items->type,
    4844                 :            :                                                 "neither eth nor vlan"
    4845                 :            :                                                 " header found");
    4846   [ #  #  #  # ]:          0 :                         if (vlan && !vlan->eth_proto)
    4847                 :          0 :                                 vlan->eth_proto = RTE_BE16(RTE_ETHER_TYPE_IPV4);
    4848   [ #  #  #  # ]:          0 :                         else if (eth && !eth->ether_type)
    4849                 :          0 :                                 eth->ether_type = RTE_BE16(RTE_ETHER_TYPE_IPV4);
    4850         [ #  # ]:          0 :                         if (!ipv4->version_ihl)
    4851                 :          0 :                                 ipv4->version_ihl = MLX5_ENCAP_IPV4_VERSION |
    4852                 :            :                                                     MLX5_ENCAP_IPV4_IHL_MIN;
    4853         [ #  # ]:          0 :                         if (!ipv4->time_to_live)
    4854                 :          0 :                                 ipv4->time_to_live = MLX5_ENCAP_IPV4_TTL_DEF;
    4855                 :            :                         break;
    4856                 :          0 :                 case RTE_FLOW_ITEM_TYPE_IPV6:
    4857                 :          0 :                         ipv6 = (struct rte_ipv6_hdr *)&buf[temp_size];
    4858         [ #  # ]:          0 :                         if (!vlan && !eth)
    4859                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    4860                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
    4861                 :            :                                                 (void *)items->type,
    4862                 :            :                                                 "neither eth nor vlan"
    4863                 :            :                                                 " header found");
    4864   [ #  #  #  # ]:          0 :                         if (vlan && !vlan->eth_proto)
    4865                 :          0 :                                 vlan->eth_proto = RTE_BE16(RTE_ETHER_TYPE_IPV6);
    4866   [ #  #  #  # ]:          0 :                         else if (eth && !eth->ether_type)
    4867                 :          0 :                                 eth->ether_type = RTE_BE16(RTE_ETHER_TYPE_IPV6);
    4868         [ #  # ]:          0 :                         if (!ipv6->vtc_flow)
    4869                 :          0 :                                 ipv6->vtc_flow =
    4870                 :            :                                         RTE_BE32(MLX5_ENCAP_IPV6_VTC_FLOW);
    4871         [ #  # ]:          0 :                         if (!ipv6->hop_limits)
    4872                 :          0 :                                 ipv6->hop_limits = MLX5_ENCAP_IPV6_HOP_LIMIT;
    4873                 :            :                         break;
    4874                 :          0 :                 case RTE_FLOW_ITEM_TYPE_UDP:
    4875                 :          0 :                         udp = (struct rte_udp_hdr *)&buf[temp_size];
    4876         [ #  # ]:          0 :                         if (!ipv4 && !ipv6)
    4877                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    4878                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
    4879                 :            :                                                 (void *)items->type,
    4880                 :            :                                                 "ip header not found");
    4881   [ #  #  #  # ]:          0 :                         if (ipv4 && !ipv4->next_proto_id)
    4882                 :          0 :                                 ipv4->next_proto_id = IPPROTO_UDP;
    4883   [ #  #  #  # ]:          0 :                         else if (ipv6 && !ipv6->proto)
    4884                 :          0 :                                 ipv6->proto = IPPROTO_UDP;
    4885                 :            :                         break;
    4886                 :          0 :                 case RTE_FLOW_ITEM_TYPE_VXLAN:
    4887                 :          0 :                         vxlan = (struct rte_vxlan_hdr *)&buf[temp_size];
    4888         [ #  # ]:          0 :                         if (!udp)
    4889                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    4890                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
    4891                 :            :                                                 (void *)items->type,
    4892                 :            :                                                 "udp header not found");
    4893         [ #  # ]:          0 :                         if (!udp->dst_port)
    4894                 :          0 :                                 udp->dst_port = RTE_BE16(MLX5_UDP_PORT_VXLAN);
    4895         [ #  # ]:          0 :                         if (!vxlan->vx_flags)
    4896                 :          0 :                                 vxlan->vx_flags =
    4897                 :            :                                         RTE_BE32(MLX5_ENCAP_VXLAN_FLAGS);
    4898                 :            :                         break;
    4899                 :          0 :                 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
    4900                 :          0 :                         vxlan_gpe = (struct rte_vxlan_gpe_hdr *)&buf[temp_size];
    4901         [ #  # ]:          0 :                         if (!udp)
    4902                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    4903                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
    4904                 :            :                                                 (void *)items->type,
    4905                 :            :                                                 "udp header not found");
    4906         [ #  # ]:          0 :                         if (!vxlan_gpe->proto)
    4907                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    4908                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
    4909                 :            :                                                 (void *)items->type,
    4910                 :            :                                                 "next protocol not found");
    4911         [ #  # ]:          0 :                         if (!udp->dst_port)
    4912                 :          0 :                                 udp->dst_port =
    4913                 :            :                                         RTE_BE16(MLX5_UDP_PORT_VXLAN_GPE);
    4914         [ #  # ]:          0 :                         if (!vxlan_gpe->vx_flags)
    4915                 :          0 :                                 vxlan_gpe->vx_flags =
    4916                 :            :                                                 MLX5_ENCAP_VXLAN_GPE_FLAGS;
    4917                 :            :                         break;
    4918                 :          0 :                 case RTE_FLOW_ITEM_TYPE_GRE:
    4919                 :            :                 case RTE_FLOW_ITEM_TYPE_NVGRE:
    4920                 :          0 :                         gre = (struct rte_gre_hdr *)&buf[temp_size];
    4921         [ #  # ]:          0 :                         if (!gre->proto)
    4922                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    4923                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
    4924                 :          0 :                                                 (void *)items->type,
    4925                 :            :                                                 "next protocol not found");
    4926         [ #  # ]:          0 :                         if (!ipv4 && !ipv6)
    4927                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    4928                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
    4929                 :          0 :                                                 (void *)items->type,
    4930                 :            :                                                 "ip header not found");
    4931   [ #  #  #  # ]:          0 :                         if (ipv4 && !ipv4->next_proto_id)
    4932                 :          0 :                                 ipv4->next_proto_id = IPPROTO_GRE;
    4933   [ #  #  #  # ]:          0 :                         else if (ipv6 && !ipv6->proto)
    4934                 :          0 :                                 ipv6->proto = IPPROTO_GRE;
    4935                 :            :                         break;
    4936                 :            :                 case RTE_FLOW_ITEM_TYPE_VOID:
    4937                 :            :                         break;
    4938                 :          0 :                 default:
    4939                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    4940                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    4941                 :          0 :                                                   (void *)items->type,
    4942                 :            :                                                   "unsupported item type");
    4943                 :            :                         break;
    4944                 :            :                 }
    4945                 :            :                 temp_size += len;
    4946                 :            :         }
    4947                 :          0 :         *size = temp_size;
    4948                 :          0 :         return 0;
    4949                 :            : }
    4950                 :            : 
    4951                 :            : static int
    4952                 :          0 : flow_dv_zero_encap_udp_csum(void *data, struct rte_flow_error *error)
    4953                 :            : {
    4954                 :            :         struct rte_ether_hdr *eth = NULL;
    4955                 :            :         struct rte_vlan_hdr *vlan = NULL;
    4956                 :            :         struct rte_ipv4_hdr *ipv4 = NULL;
    4957                 :            :         struct rte_ipv6_hdr *ipv6 = NULL;
    4958                 :            :         struct rte_udp_hdr *udp = NULL;
    4959                 :            :         char *next_hdr;
    4960                 :            :         uint16_t proto;
    4961                 :            : 
    4962                 :            :         eth = (struct rte_ether_hdr *)data;
    4963                 :          0 :         next_hdr = (char *)(eth + 1);
    4964                 :          0 :         proto = RTE_BE16(eth->ether_type);
    4965                 :            : 
    4966                 :            :         /* VLAN skipping */
    4967         [ #  # ]:          0 :         while (proto == RTE_ETHER_TYPE_VLAN || proto == RTE_ETHER_TYPE_QINQ) {
    4968                 :            :                 vlan = (struct rte_vlan_hdr *)next_hdr;
    4969                 :          0 :                 proto = RTE_BE16(vlan->eth_proto);
    4970                 :          0 :                 next_hdr += sizeof(struct rte_vlan_hdr);
    4971                 :            :         }
    4972                 :            : 
    4973                 :            :         /* non IPv4/IPv6 header. not supported */
    4974         [ #  # ]:          0 :         if (proto != RTE_ETHER_TYPE_IPV4 && proto != RTE_ETHER_TYPE_IPV6) {
    4975                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    4976                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
    4977                 :            :                                           NULL, "Cannot offload non IPv4/IPv6");
    4978                 :            :         }
    4979                 :            : 
    4980         [ #  # ]:          0 :         if (proto == RTE_ETHER_TYPE_IPV4) {
    4981                 :            :                 ipv4 = (struct rte_ipv4_hdr *)next_hdr;
    4982                 :            :                 /* ignore non UDP */
    4983         [ #  # ]:          0 :                 if (ipv4->next_proto_id != IPPROTO_UDP)
    4984                 :            :                         return 0;
    4985                 :          0 :                 udp = (struct rte_udp_hdr *)(ipv4 + 1);
    4986                 :            :         } else {
    4987                 :            :                 ipv6 = (struct rte_ipv6_hdr *)next_hdr;
    4988                 :            :                 /* ignore non UDP */
    4989         [ #  # ]:          0 :                 if (ipv6->proto != IPPROTO_UDP)
    4990                 :            :                         return 0;
    4991                 :          0 :                 udp = (struct rte_udp_hdr *)(ipv6 + 1);
    4992                 :            :         }
    4993                 :            : 
    4994                 :          0 :         udp->dgram_cksum = 0;
    4995                 :            : 
    4996                 :          0 :         return 0;
    4997                 :            : }
    4998                 :            : 
    4999                 :            : /**
    5000                 :            :  * Convert L2 encap action to DV specification.
    5001                 :            :  *
    5002                 :            :  * @param[in] dev
    5003                 :            :  *   Pointer to rte_eth_dev structure.
    5004                 :            :  * @param[in] action
    5005                 :            :  *   Pointer to action structure.
    5006                 :            :  * @param[in, out] dev_flow
    5007                 :            :  *   Pointer to the mlx5_flow.
    5008                 :            :  * @param[in] transfer
    5009                 :            :  *   Mark if the flow is E-Switch flow.
    5010                 :            :  * @param[out] error
    5011                 :            :  *   Pointer to the error structure.
    5012                 :            :  *
    5013                 :            :  * @return
    5014                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5015                 :            :  */
    5016                 :            : static int
    5017                 :          0 : flow_dv_create_action_l2_encap(struct rte_eth_dev *dev,
    5018                 :            :                                const struct rte_flow_action *action,
    5019                 :            :                                struct mlx5_flow *dev_flow,
    5020                 :            :                                uint8_t transfer,
    5021                 :            :                                struct rte_flow_error *error)
    5022                 :            : {
    5023                 :            :         const struct rte_flow_item *encap_data;
    5024                 :            :         const struct rte_flow_action_raw_encap *raw_encap_data;
    5025         [ #  # ]:          0 :         struct mlx5_flow_dv_encap_decap_resource res = {
    5026                 :            :                 .reformat_type =
    5027                 :            :                         MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL,
    5028                 :            :                 .ft_type = transfer ? MLX5DV_FLOW_TABLE_TYPE_FDB :
    5029                 :            :                                       MLX5DV_FLOW_TABLE_TYPE_NIC_TX,
    5030                 :            :         };
    5031                 :            : 
    5032         [ #  # ]:          0 :         if (action->type == RTE_FLOW_ACTION_TYPE_RAW_ENCAP) {
    5033                 :          0 :                 raw_encap_data =
    5034                 :            :                         (const struct rte_flow_action_raw_encap *)action->conf;
    5035                 :          0 :                 res.size = raw_encap_data->size;
    5036                 :          0 :                 memcpy(res.buf, raw_encap_data->data, res.size);
    5037                 :            :         } else {
    5038         [ #  # ]:          0 :                 if (action->type == RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP)
    5039                 :          0 :                         encap_data =
    5040                 :            :                                 ((const struct rte_flow_action_vxlan_encap *)
    5041                 :          0 :                                                 action->conf)->definition;
    5042                 :            :                 else
    5043                 :          0 :                         encap_data =
    5044                 :            :                                 ((const struct rte_flow_action_nvgre_encap *)
    5045                 :          0 :                                                 action->conf)->definition;
    5046         [ #  # ]:          0 :                 if (flow_dv_convert_encap_data(encap_data, res.buf,
    5047                 :            :                                                &res.size, error))
    5048                 :          0 :                         return -rte_errno;
    5049                 :            :         }
    5050         [ #  # ]:          0 :         if (flow_dv_zero_encap_udp_csum(res.buf, error))
    5051                 :          0 :                 return -rte_errno;
    5052         [ #  # ]:          0 :         if (flow_dv_encap_decap_resource_register(dev, &res, dev_flow, error))
    5053                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    5054                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
    5055                 :            :                                           NULL, "can't create L2 encap action");
    5056                 :            :         return 0;
    5057                 :            : }
    5058                 :            : 
    5059                 :            : /**
    5060                 :            :  * Convert L2 decap action to DV specification.
    5061                 :            :  *
    5062                 :            :  * @param[in] dev
    5063                 :            :  *   Pointer to rte_eth_dev structure.
    5064                 :            :  * @param[in, out] dev_flow
    5065                 :            :  *   Pointer to the mlx5_flow.
    5066                 :            :  * @param[in] transfer
    5067                 :            :  *   Mark if the flow is E-Switch flow.
    5068                 :            :  * @param[out] error
    5069                 :            :  *   Pointer to the error structure.
    5070                 :            :  *
    5071                 :            :  * @return
    5072                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5073                 :            :  */
    5074                 :            : static int
    5075                 :          0 : flow_dv_create_action_l2_decap(struct rte_eth_dev *dev,
    5076                 :            :                                struct mlx5_flow *dev_flow,
    5077                 :            :                                uint8_t transfer,
    5078                 :            :                                struct rte_flow_error *error)
    5079                 :            : {
    5080         [ #  # ]:          0 :         struct mlx5_flow_dv_encap_decap_resource res = {
    5081                 :            :                 .size = 0,
    5082                 :            :                 .reformat_type =
    5083                 :            :                         MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_TO_L2,
    5084                 :            :                 .ft_type = transfer ? MLX5DV_FLOW_TABLE_TYPE_FDB :
    5085                 :            :                                       MLX5DV_FLOW_TABLE_TYPE_NIC_RX,
    5086                 :            :         };
    5087                 :            : 
    5088         [ #  # ]:          0 :         if (flow_dv_encap_decap_resource_register(dev, &res, dev_flow, error))
    5089                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    5090                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
    5091                 :            :                                           NULL, "can't create L2 decap action");
    5092                 :            :         return 0;
    5093                 :            : }
    5094                 :            : 
    5095                 :            : /**
    5096                 :            :  * Convert raw decap/encap (L3 tunnel) action to DV specification.
    5097                 :            :  *
    5098                 :            :  * @param[in] dev
    5099                 :            :  *   Pointer to rte_eth_dev structure.
    5100                 :            :  * @param[in] action
    5101                 :            :  *   Pointer to action structure.
    5102                 :            :  * @param[in, out] dev_flow
    5103                 :            :  *   Pointer to the mlx5_flow.
    5104                 :            :  * @param[in] attr
    5105                 :            :  *   Pointer to the flow attributes.
    5106                 :            :  * @param[out] error
    5107                 :            :  *   Pointer to the error structure.
    5108                 :            :  *
    5109                 :            :  * @return
    5110                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5111                 :            :  */
    5112                 :            : static int
    5113         [ #  # ]:          0 : flow_dv_create_action_raw_encap(struct rte_eth_dev *dev,
    5114                 :            :                                 const struct rte_flow_action *action,
    5115                 :            :                                 struct mlx5_flow *dev_flow,
    5116                 :            :                                 const struct rte_flow_attr *attr,
    5117                 :            :                                 struct rte_flow_error *error)
    5118                 :            : {
    5119                 :            :         const struct rte_flow_action_raw_encap *encap_data;
    5120                 :            :         struct mlx5_flow_dv_encap_decap_resource res;
    5121                 :            : 
    5122                 :            :         memset(&res, 0, sizeof(res));
    5123                 :          0 :         encap_data = (const struct rte_flow_action_raw_encap *)action->conf;
    5124                 :          0 :         res.size = encap_data->size;
    5125         [ #  # ]:          0 :         memcpy(res.buf, encap_data->data, res.size);
    5126         [ #  # ]:          0 :         res.reformat_type = res.size < MLX5_ENCAPSULATION_DECISION_SIZE ?
    5127                 :            :                 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L3_TUNNEL_TO_L2 :
    5128                 :            :                 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TUNNEL;
    5129         [ #  # ]:          0 :         if (attr->transfer)
    5130                 :          0 :                 res.ft_type = MLX5DV_FLOW_TABLE_TYPE_FDB;
    5131                 :            :         else
    5132                 :          0 :                 res.ft_type = attr->egress ? MLX5DV_FLOW_TABLE_TYPE_NIC_TX :
    5133                 :            :                                              MLX5DV_FLOW_TABLE_TYPE_NIC_RX;
    5134         [ #  # ]:          0 :         if (flow_dv_encap_decap_resource_register(dev, &res, dev_flow, error))
    5135                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    5136                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
    5137                 :            :                                           NULL, "can't create encap action");
    5138                 :            :         return 0;
    5139                 :            : }
    5140                 :            : 
    5141                 :            : /**
    5142                 :            :  * Create action push VLAN.
    5143                 :            :  *
    5144                 :            :  * @param[in] dev
    5145                 :            :  *   Pointer to rte_eth_dev structure.
    5146                 :            :  * @param[in] attr
    5147                 :            :  *   Pointer to the flow attributes.
    5148                 :            :  * @param[in] vlan
    5149                 :            :  *   Pointer to the vlan to push to the Ethernet header.
    5150                 :            :  * @param[in, out] dev_flow
    5151                 :            :  *   Pointer to the mlx5_flow.
    5152                 :            :  * @param[out] error
    5153                 :            :  *   Pointer to the error structure.
    5154                 :            :  *
    5155                 :            :  * @return
    5156                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5157                 :            :  */
    5158                 :            : static int
    5159         [ #  # ]:          0 : flow_dv_create_action_push_vlan(struct rte_eth_dev *dev,
    5160                 :            :                                 const struct rte_flow_attr *attr,
    5161                 :            :                                 const struct rte_vlan_hdr *vlan,
    5162                 :            :                                 struct mlx5_flow *dev_flow,
    5163                 :            :                                 struct rte_flow_error *error)
    5164                 :            : {
    5165                 :            :         struct mlx5_flow_dv_push_vlan_action_resource res;
    5166                 :            : 
    5167                 :            :         memset(&res, 0, sizeof(res));
    5168                 :          0 :         res.vlan_tag =
    5169         [ #  # ]:          0 :                 rte_cpu_to_be_32(((uint32_t)vlan->eth_proto) << 16 |
    5170                 :            :                                  vlan->vlan_tci);
    5171         [ #  # ]:          0 :         if (attr->transfer)
    5172                 :          0 :                 res.ft_type = MLX5DV_FLOW_TABLE_TYPE_FDB;
    5173                 :            :         else
    5174                 :          0 :                 res.ft_type = attr->egress ? MLX5DV_FLOW_TABLE_TYPE_NIC_TX :
    5175                 :            :                                              MLX5DV_FLOW_TABLE_TYPE_NIC_RX;
    5176                 :          0 :         return flow_dv_push_vlan_action_resource_register
    5177                 :            :                                             (dev, &res, dev_flow, error);
    5178                 :            : }
    5179                 :            : 
    5180                 :            : /**
    5181                 :            :  * Validate the modify-header actions.
    5182                 :            :  *
    5183                 :            :  * @param[in] action_flags
    5184                 :            :  *   Holds the actions detected until now.
    5185                 :            :  * @param[in] action
    5186                 :            :  *   Pointer to the modify action.
    5187                 :            :  * @param[out] error
    5188                 :            :  *   Pointer to error structure.
    5189                 :            :  *
    5190                 :            :  * @return
    5191                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5192                 :            :  */
    5193                 :            : static int
    5194                 :          0 : flow_dv_validate_action_modify_hdr(const uint64_t action_flags,
    5195                 :            :                                    const struct rte_flow_action *action,
    5196                 :            :                                    struct rte_flow_error *error)
    5197                 :            : {
    5198   [ #  #  #  # ]:          0 :         if (action->type != RTE_FLOW_ACTION_TYPE_DEC_TTL && !action->conf)
    5199                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    5200                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF,
    5201                 :            :                                           NULL, "action configuration not set");
    5202                 :            : 
    5203         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_ENCAP)
    5204                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    5205                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    5206                 :            :                                           "can't have encap action before"
    5207                 :            :                                           " modify action");
    5208                 :            :         return 0;
    5209                 :            : }
    5210                 :            : 
    5211                 :            : /**
    5212                 :            :  * Validate the modify-header MAC address actions.
    5213                 :            :  *
    5214                 :            :  * @param[in] action_flags
    5215                 :            :  *   Holds the actions detected until now.
    5216                 :            :  * @param[in] action
    5217                 :            :  *   Pointer to the modify action.
    5218                 :            :  * @param[in] item_flags
    5219                 :            :  *   Holds the items detected.
    5220                 :            :  * @param[out] error
    5221                 :            :  *   Pointer to error structure.
    5222                 :            :  *
    5223                 :            :  * @return
    5224                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5225                 :            :  */
    5226                 :            : static int
    5227                 :          0 : flow_dv_validate_action_modify_mac(const uint64_t action_flags,
    5228                 :            :                                    const struct rte_flow_action *action,
    5229                 :            :                                    const uint64_t item_flags,
    5230                 :            :                                    struct rte_flow_error *error)
    5231                 :            : {
    5232                 :            :         int ret = 0;
    5233                 :            : 
    5234                 :          0 :         ret = flow_dv_validate_action_modify_hdr(action_flags, action, error);
    5235         [ #  # ]:          0 :         if (!ret) {
    5236         [ #  # ]:          0 :                 if (!(item_flags & MLX5_FLOW_LAYER_L2))
    5237                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5238                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    5239                 :            :                                                   NULL,
    5240                 :            :                                                   "no L2 item in pattern");
    5241                 :            :         }
    5242                 :            :         return ret;
    5243                 :            : }
    5244                 :            : 
    5245                 :            : /**
    5246                 :            :  * Validate the modify-header IPv4 address actions.
    5247                 :            :  *
    5248                 :            :  * @param[in] action_flags
    5249                 :            :  *   Holds the actions detected until now.
    5250                 :            :  * @param[in] action
    5251                 :            :  *   Pointer to the modify action.
    5252                 :            :  * @param[in] item_flags
    5253                 :            :  *   Holds the items detected.
    5254                 :            :  * @param[out] error
    5255                 :            :  *   Pointer to error structure.
    5256                 :            :  *
    5257                 :            :  * @return
    5258                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5259                 :            :  */
    5260                 :            : static int
    5261                 :          0 : flow_dv_validate_action_modify_ipv4(const uint64_t action_flags,
    5262                 :            :                                     const struct rte_flow_action *action,
    5263                 :            :                                     const uint64_t item_flags,
    5264                 :            :                                     struct rte_flow_error *error)
    5265                 :            : {
    5266                 :            :         int ret = 0;
    5267                 :            :         uint64_t layer;
    5268                 :            : 
    5269                 :          0 :         ret = flow_dv_validate_action_modify_hdr(action_flags, action, error);
    5270         [ #  # ]:          0 :         if (!ret) {
    5271                 :          0 :                 layer = (action_flags & MLX5_FLOW_ACTION_DECAP) ?
    5272         [ #  # ]:          0 :                                  MLX5_FLOW_LAYER_INNER_L3_IPV4 :
    5273                 :            :                                  MLX5_FLOW_LAYER_OUTER_L3_IPV4;
    5274         [ #  # ]:          0 :                 if (!(item_flags & layer))
    5275                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5276                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    5277                 :            :                                                   NULL,
    5278                 :            :                                                   "no ipv4 item in pattern");
    5279                 :            :         }
    5280                 :            :         return ret;
    5281                 :            : }
    5282                 :            : 
    5283                 :            : /**
    5284                 :            :  * Validate the modify-header IPv6 address actions.
    5285                 :            :  *
    5286                 :            :  * @param[in] action_flags
    5287                 :            :  *   Holds the actions detected until now.
    5288                 :            :  * @param[in] action
    5289                 :            :  *   Pointer to the modify action.
    5290                 :            :  * @param[in] item_flags
    5291                 :            :  *   Holds the items detected.
    5292                 :            :  * @param[out] error
    5293                 :            :  *   Pointer to error structure.
    5294                 :            :  *
    5295                 :            :  * @return
    5296                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5297                 :            :  */
    5298                 :            : static int
    5299                 :          0 : flow_dv_validate_action_modify_ipv6(const uint64_t action_flags,
    5300                 :            :                                     const struct rte_flow_action *action,
    5301                 :            :                                     const uint64_t item_flags,
    5302                 :            :                                     struct rte_flow_error *error)
    5303                 :            : {
    5304                 :            :         int ret = 0;
    5305                 :            :         uint64_t layer;
    5306                 :            : 
    5307                 :          0 :         ret = flow_dv_validate_action_modify_hdr(action_flags, action, error);
    5308         [ #  # ]:          0 :         if (!ret) {
    5309                 :          0 :                 layer = (action_flags & MLX5_FLOW_ACTION_DECAP) ?
    5310         [ #  # ]:          0 :                                  MLX5_FLOW_LAYER_INNER_L3_IPV6 :
    5311                 :            :                                  MLX5_FLOW_LAYER_OUTER_L3_IPV6;
    5312         [ #  # ]:          0 :                 if (!(item_flags & layer))
    5313                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5314                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    5315                 :            :                                                   NULL,
    5316                 :            :                                                   "no ipv6 item in pattern");
    5317                 :            :         }
    5318                 :            :         return ret;
    5319                 :            : }
    5320                 :            : 
    5321                 :            : /**
    5322                 :            :  * Validate the modify-header TP actions.
    5323                 :            :  *
    5324                 :            :  * @param[in] action_flags
    5325                 :            :  *   Holds the actions detected until now.
    5326                 :            :  * @param[in] action
    5327                 :            :  *   Pointer to the modify action.
    5328                 :            :  * @param[in] item_flags
    5329                 :            :  *   Holds the items detected.
    5330                 :            :  * @param[out] error
    5331                 :            :  *   Pointer to error structure.
    5332                 :            :  *
    5333                 :            :  * @return
    5334                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5335                 :            :  */
    5336                 :            : static int
    5337                 :          0 : flow_dv_validate_action_modify_tp(const uint64_t action_flags,
    5338                 :            :                                   const struct rte_flow_action *action,
    5339                 :            :                                   const uint64_t item_flags,
    5340                 :            :                                   struct rte_flow_error *error)
    5341                 :            : {
    5342                 :            :         int ret = 0;
    5343                 :            :         uint64_t layer;
    5344                 :            : 
    5345                 :          0 :         ret = flow_dv_validate_action_modify_hdr(action_flags, action, error);
    5346         [ #  # ]:          0 :         if (!ret) {
    5347                 :          0 :                 layer = (action_flags & MLX5_FLOW_ACTION_DECAP) ?
    5348         [ #  # ]:          0 :                                  MLX5_FLOW_LAYER_INNER_L4 :
    5349                 :            :                                  MLX5_FLOW_LAYER_OUTER_L4;
    5350         [ #  # ]:          0 :                 if (!(item_flags & layer))
    5351                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5352                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    5353                 :            :                                                   NULL, "no transport layer "
    5354                 :            :                                                   "in pattern");
    5355                 :            :         }
    5356                 :            :         return ret;
    5357                 :            : }
    5358                 :            : 
    5359                 :            : /**
    5360                 :            :  * Validate the modify-header actions of increment/decrement
    5361                 :            :  * TCP Sequence-number.
    5362                 :            :  *
    5363                 :            :  * @param[in] action_flags
    5364                 :            :  *   Holds the actions detected until now.
    5365                 :            :  * @param[in] action
    5366                 :            :  *   Pointer to the modify action.
    5367                 :            :  * @param[in] item_flags
    5368                 :            :  *   Holds the items detected.
    5369                 :            :  * @param[out] error
    5370                 :            :  *   Pointer to error structure.
    5371                 :            :  *
    5372                 :            :  * @return
    5373                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5374                 :            :  */
    5375                 :            : static int
    5376                 :          0 : flow_dv_validate_action_modify_tcp_seq(const uint64_t action_flags,
    5377                 :            :                                        const struct rte_flow_action *action,
    5378                 :            :                                        const uint64_t item_flags,
    5379                 :            :                                        struct rte_flow_error *error)
    5380                 :            : {
    5381                 :            :         int ret = 0;
    5382                 :            :         uint64_t layer;
    5383                 :            : 
    5384                 :          0 :         ret = flow_dv_validate_action_modify_hdr(action_flags, action, error);
    5385         [ #  # ]:          0 :         if (!ret) {
    5386                 :          0 :                 layer = (action_flags & MLX5_FLOW_ACTION_DECAP) ?
    5387         [ #  # ]:          0 :                                  MLX5_FLOW_LAYER_INNER_L4_TCP :
    5388                 :            :                                  MLX5_FLOW_LAYER_OUTER_L4_TCP;
    5389         [ #  # ]:          0 :                 if (!(item_flags & layer))
    5390                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5391                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    5392                 :            :                                                   NULL, "no TCP item in"
    5393                 :            :                                                   " pattern");
    5394         [ #  # ]:          0 :                 if ((action->type == RTE_FLOW_ACTION_TYPE_INC_TCP_SEQ &&
    5395   [ #  #  #  # ]:          0 :                         (action_flags & MLX5_FLOW_ACTION_DEC_TCP_SEQ)) ||
    5396                 :          0 :                     (action->type == RTE_FLOW_ACTION_TYPE_DEC_TCP_SEQ &&
    5397         [ #  # ]:          0 :                         (action_flags & MLX5_FLOW_ACTION_INC_TCP_SEQ)))
    5398                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5399                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    5400                 :            :                                                   NULL,
    5401                 :            :                                                   "cannot decrease and increase"
    5402                 :            :                                                   " TCP sequence number"
    5403                 :            :                                                   " at the same time");
    5404                 :            :         }
    5405                 :            :         return ret;
    5406                 :            : }
    5407                 :            : 
    5408                 :            : /**
    5409                 :            :  * Validate the modify-header actions of increment/decrement
    5410                 :            :  * TCP Acknowledgment number.
    5411                 :            :  *
    5412                 :            :  * @param[in] action_flags
    5413                 :            :  *   Holds the actions detected until now.
    5414                 :            :  * @param[in] action
    5415                 :            :  *   Pointer to the modify action.
    5416                 :            :  * @param[in] item_flags
    5417                 :            :  *   Holds the items detected.
    5418                 :            :  * @param[out] error
    5419                 :            :  *   Pointer to error structure.
    5420                 :            :  *
    5421                 :            :  * @return
    5422                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5423                 :            :  */
    5424                 :            : static int
    5425                 :          0 : flow_dv_validate_action_modify_tcp_ack(const uint64_t action_flags,
    5426                 :            :                                        const struct rte_flow_action *action,
    5427                 :            :                                        const uint64_t item_flags,
    5428                 :            :                                        struct rte_flow_error *error)
    5429                 :            : {
    5430                 :            :         int ret = 0;
    5431                 :            :         uint64_t layer;
    5432                 :            : 
    5433                 :          0 :         ret = flow_dv_validate_action_modify_hdr(action_flags, action, error);
    5434         [ #  # ]:          0 :         if (!ret) {
    5435                 :          0 :                 layer = (action_flags & MLX5_FLOW_ACTION_DECAP) ?
    5436         [ #  # ]:          0 :                                  MLX5_FLOW_LAYER_INNER_L4_TCP :
    5437                 :            :                                  MLX5_FLOW_LAYER_OUTER_L4_TCP;
    5438         [ #  # ]:          0 :                 if (!(item_flags & layer))
    5439                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5440                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    5441                 :            :                                                   NULL, "no TCP item in"
    5442                 :            :                                                   " pattern");
    5443         [ #  # ]:          0 :                 if ((action->type == RTE_FLOW_ACTION_TYPE_INC_TCP_ACK &&
    5444   [ #  #  #  # ]:          0 :                         (action_flags & MLX5_FLOW_ACTION_DEC_TCP_ACK)) ||
    5445                 :          0 :                     (action->type == RTE_FLOW_ACTION_TYPE_DEC_TCP_ACK &&
    5446         [ #  # ]:          0 :                         (action_flags & MLX5_FLOW_ACTION_INC_TCP_ACK)))
    5447                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5448                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    5449                 :            :                                                   NULL,
    5450                 :            :                                                   "cannot decrease and increase"
    5451                 :            :                                                   " TCP acknowledgment number"
    5452                 :            :                                                   " at the same time");
    5453                 :            :         }
    5454                 :            :         return ret;
    5455                 :            : }
    5456                 :            : 
    5457                 :            : /**
    5458                 :            :  * Validate the modify-header TTL actions.
    5459                 :            :  *
    5460                 :            :  * @param[in] action_flags
    5461                 :            :  *   Holds the actions detected until now.
    5462                 :            :  * @param[in] action
    5463                 :            :  *   Pointer to the modify action.
    5464                 :            :  * @param[in] item_flags
    5465                 :            :  *   Holds the items detected.
    5466                 :            :  * @param[out] error
    5467                 :            :  *   Pointer to error structure.
    5468                 :            :  *
    5469                 :            :  * @return
    5470                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5471                 :            :  */
    5472                 :            : static int
    5473                 :          0 : flow_dv_validate_action_modify_ttl(const uint64_t action_flags,
    5474                 :            :                                    const struct rte_flow_action *action,
    5475                 :            :                                    const uint64_t item_flags,
    5476                 :            :                                    struct rte_flow_error *error)
    5477                 :            : {
    5478                 :            :         int ret = 0;
    5479                 :            :         uint64_t layer;
    5480                 :            : 
    5481                 :          0 :         ret = flow_dv_validate_action_modify_hdr(action_flags, action, error);
    5482         [ #  # ]:          0 :         if (!ret) {
    5483                 :          0 :                 layer = (action_flags & MLX5_FLOW_ACTION_DECAP) ?
    5484         [ #  # ]:          0 :                                  MLX5_FLOW_LAYER_INNER_L3 :
    5485                 :            :                                  MLX5_FLOW_LAYER_OUTER_L3;
    5486         [ #  # ]:          0 :                 if (!(item_flags & layer))
    5487                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5488                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    5489                 :            :                                                   NULL,
    5490                 :            :                                                   "no IP protocol in pattern");
    5491                 :            :         }
    5492                 :            :         return ret;
    5493                 :            : }
    5494                 :            : 
    5495                 :            : /**
    5496                 :            :  * Validate the generic modify field actions.
    5497                 :            :  * @param[in] dev
    5498                 :            :  *   Pointer to the rte_eth_dev structure.
    5499                 :            :  * @param[in] action_flags
    5500                 :            :  *   Holds the actions detected until now.
    5501                 :            :  * @param[in] action
    5502                 :            :  *   Pointer to the modify action.
    5503                 :            :  * @param[in] attr
    5504                 :            :  *   Pointer to the flow attributes.
    5505                 :            :  * @param root
    5506                 :            :  *   Whether action is on root table.
    5507                 :            :  * @param[out] error
    5508                 :            :  *   Pointer to error structure.
    5509                 :            :  *
    5510                 :            :  * @return
    5511                 :            :  *   Number of header fields to modify (0 or more) on success,
    5512                 :            :  *   a negative errno value otherwise and rte_errno is set.
    5513                 :            :  */
    5514                 :            : static int
    5515                 :          0 : flow_dv_validate_action_modify_field(struct rte_eth_dev *dev,
    5516                 :            :                                    const uint64_t action_flags,
    5517                 :            :                                    const struct rte_flow_action *action,
    5518                 :            :                                    const struct rte_flow_attr *attr,
    5519                 :            :                                    bool root,
    5520                 :            :                                    struct rte_flow_error *error)
    5521                 :            : {
    5522                 :            :         int ret = 0;
    5523                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    5524                 :          0 :         struct mlx5_sh_config *config = &priv->sh->config;
    5525                 :          0 :         struct mlx5_hca_attr *hca_attr = &priv->sh->cdev->config.hca_attr;
    5526                 :          0 :         const struct rte_flow_action_modify_field *conf = action->conf;
    5527                 :          0 :         const struct rte_flow_field_data *src_data = &conf->src;
    5528                 :          0 :         const struct rte_flow_field_data *dst_data = &conf->dst;
    5529                 :          0 :         uint32_t dst_width, src_width, width = conf->width;
    5530                 :            : 
    5531                 :          0 :         ret = flow_dv_validate_action_modify_hdr(action_flags, action, error);
    5532         [ #  # ]:          0 :         if (ret)
    5533                 :            :                 return ret;
    5534         [ #  # ]:          0 :         if (src_data->field == RTE_FLOW_FIELD_FLEX_ITEM ||
    5535         [ #  # ]:          0 :             dst_data->field == RTE_FLOW_FIELD_FLEX_ITEM)
    5536                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5537                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    5538                 :            :                                 "flex item fields modification"
    5539                 :            :                                 " is not supported");
    5540                 :          0 :         dst_width = mlx5_flow_item_field_width(dev, dst_data->field,
    5541                 :            :                                                -1, attr, error);
    5542                 :          0 :         src_width = mlx5_flow_item_field_width(dev, src_data->field,
    5543                 :            :                                                dst_width, attr, error);
    5544         [ #  # ]:          0 :         if (width == 0)
    5545                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    5546                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    5547                 :            :                                 "no bits are requested to be modified");
    5548         [ #  # ]:          0 :         else if (width > dst_width || width > src_width)
    5549                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    5550                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    5551                 :            :                                 "cannot modify more bits than"
    5552                 :            :                                 " the width of a field");
    5553         [ #  # ]:          0 :         if (dst_data->field != RTE_FLOW_FIELD_VALUE &&
    5554                 :            :             dst_data->field != RTE_FLOW_FIELD_POINTER) {
    5555         [ #  # ]:          0 :                 if (dst_data->offset + width > dst_width)
    5556                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5557                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, action,
    5558                 :            :                                         "destination offset is too big");
    5559                 :          0 :                 ret = flow_validate_modify_field_level(dst_data, error);
    5560         [ #  # ]:          0 :                 if (ret)
    5561                 :            :                         return ret;
    5562         [ #  # ]:          0 :                 if (dst_data->tag_index &&
    5563         [ #  # ]:          0 :                     !flow_modify_field_support_tag_array(dst_data->field))
    5564                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5565                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, action,
    5566                 :            :                                         "destination tag index is not supported");
    5567         [ #  # ]:          0 :                 if (dst_data->class_id)
    5568                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5569                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, action,
    5570                 :            :                                         "destination class ID is not supported");
    5571                 :            :         }
    5572         [ #  # ]:          0 :         if (src_data->field != RTE_FLOW_FIELD_VALUE &&
    5573                 :            :             src_data->field != RTE_FLOW_FIELD_POINTER) {
    5574         [ #  # ]:          0 :                 if (root)
    5575                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    5576                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, action,
    5577                 :            :                                         "modify field action is not"
    5578                 :            :                                         " supported for group 0");
    5579         [ #  # ]:          0 :                 if (src_data->offset + width > src_width)
    5580                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5581                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, action,
    5582                 :            :                                         "source offset is too big");
    5583                 :          0 :                 ret = flow_validate_modify_field_level(src_data, error);
    5584         [ #  # ]:          0 :                 if (ret)
    5585                 :            :                         return ret;
    5586         [ #  # ]:          0 :                 if (src_data->tag_index &&
    5587         [ #  # ]:          0 :                     !flow_modify_field_support_tag_array(src_data->field))
    5588                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5589                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, action,
    5590                 :            :                                         "source tag index is not supported");
    5591         [ #  # ]:          0 :                 if (src_data->class_id)
    5592                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5593                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, action,
    5594                 :            :                                         "source class ID is not supported");
    5595                 :            :         }
    5596         [ #  # ]:          0 :         if ((dst_data->field == src_data->field) &&
    5597         [ #  # ]:          0 :             (dst_data->level == src_data->level))
    5598                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    5599                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    5600                 :            :                                 "source and destination fields"
    5601                 :            :                                 " cannot be the same");
    5602                 :          0 :         if (dst_data->field == RTE_FLOW_FIELD_VALUE ||
    5603         [ #  # ]:          0 :             dst_data->field == RTE_FLOW_FIELD_POINTER ||
    5604                 :            :             dst_data->field == RTE_FLOW_FIELD_MARK)
    5605                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    5606                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    5607                 :            :                                 "mark, immediate value or a pointer to it"
    5608                 :            :                                 " cannot be used as a destination");
    5609   [ #  #  #  # ]:          0 :         if (dst_data->field == RTE_FLOW_FIELD_START ||
    5610                 :            :             src_data->field == RTE_FLOW_FIELD_START)
    5611                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5612                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    5613                 :            :                                 "modifications of an arbitrary"
    5614                 :            :                                 " place in a packet is not supported");
    5615   [ #  #  #  # ]:          0 :         if (dst_data->field == RTE_FLOW_FIELD_VLAN_TYPE ||
    5616                 :            :             src_data->field == RTE_FLOW_FIELD_VLAN_TYPE)
    5617                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5618                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    5619                 :            :                                 "modifications of the 802.1Q Tag"
    5620                 :            :                                 " Identifier is not supported");
    5621   [ #  #  #  # ]:          0 :         if (dst_data->field == RTE_FLOW_FIELD_VXLAN_VNI ||
    5622                 :            :             src_data->field == RTE_FLOW_FIELD_VXLAN_VNI)
    5623                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5624                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    5625                 :            :                                 "modifications of the VXLAN Network"
    5626                 :            :                                 " Identifier is not supported");
    5627   [ #  #  #  # ]:          0 :         if (dst_data->field == RTE_FLOW_FIELD_GENEVE_VNI ||
    5628                 :            :             src_data->field == RTE_FLOW_FIELD_GENEVE_VNI)
    5629                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5630                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    5631                 :            :                                 "modifications of the GENEVE Network"
    5632                 :            :                                 " Identifier is not supported");
    5633   [ #  #  #  # ]:          0 :         if (dst_data->field == RTE_FLOW_FIELD_GENEVE_OPT_TYPE ||
    5634                 :            :             src_data->field == RTE_FLOW_FIELD_GENEVE_OPT_TYPE)
    5635                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5636                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    5637                 :            :                                 "modifications of the GENEVE option type is not supported");
    5638   [ #  #  #  # ]:          0 :         if (dst_data->field == RTE_FLOW_FIELD_GENEVE_OPT_CLASS ||
    5639                 :            :             src_data->field == RTE_FLOW_FIELD_GENEVE_OPT_CLASS)
    5640                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5641                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    5642                 :            :                                 "modifications of the GENEVE option class is not supported");
    5643   [ #  #  #  # ]:          0 :         if (dst_data->field == RTE_FLOW_FIELD_GENEVE_OPT_DATA ||
    5644                 :            :             src_data->field == RTE_FLOW_FIELD_GENEVE_OPT_DATA)
    5645                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5646                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    5647                 :            :                                 "modifications of the GENEVE option data is not supported");
    5648   [ #  #  #  # ]:          0 :         if (dst_data->field == RTE_FLOW_FIELD_MPLS ||
    5649                 :            :             src_data->field == RTE_FLOW_FIELD_MPLS)
    5650                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5651                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    5652                 :            :                                 "modifications of the MPLS header "
    5653                 :            :                                 "is not supported");
    5654   [ #  #  #  # ]:          0 :         if (dst_data->field == RTE_FLOW_FIELD_RANDOM ||
    5655                 :            :             src_data->field == RTE_FLOW_FIELD_RANDOM)
    5656                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5657                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    5658                 :            :                                 "modifications of random value is not supported");
    5659         [ #  # ]:          0 :         if (dst_data->field == RTE_FLOW_FIELD_MARK ||
    5660                 :            :             src_data->field == RTE_FLOW_FIELD_MARK)
    5661   [ #  #  #  # ]:          0 :                 if (config->dv_xmeta_en == MLX5_XMETA_MODE_LEGACY ||
    5662                 :          0 :                     !mlx5_flow_ext_mreg_supported(dev))
    5663                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    5664                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, action,
    5665                 :            :                                         "cannot modify mark in legacy mode"
    5666                 :            :                                         " or without extensive registers");
    5667         [ #  # ]:          0 :         if (dst_data->field == RTE_FLOW_FIELD_META ||
    5668         [ #  # ]:          0 :             src_data->field == RTE_FLOW_FIELD_META) {
    5669   [ #  #  #  # ]:          0 :                 if (config->dv_xmeta_en != MLX5_XMETA_MODE_LEGACY &&
    5670                 :          0 :                     !mlx5_flow_ext_mreg_supported(dev))
    5671                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    5672                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, action,
    5673                 :            :                                         "cannot modify meta without"
    5674                 :            :                                         " extensive registers support");
    5675                 :          0 :                 ret = flow_dv_get_metadata_reg(dev, attr, error);
    5676         [ #  # ]:          0 :                 if (ret < 0 || ret == REG_NON)
    5677                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    5678                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, action,
    5679                 :            :                                         "cannot modify meta without"
    5680                 :            :                                         " extensive registers available");
    5681                 :            :         }
    5682         [ #  # ]:          0 :         if (conf->operation == RTE_FLOW_MODIFY_SUB)
    5683                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5684                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    5685                 :            :                                 "sub operations are not supported");
    5686         [ #  # ]:          0 :         if (dst_data->field == RTE_FLOW_FIELD_IPV4_ECN ||
    5687   [ #  #  #  # ]:          0 :             src_data->field == RTE_FLOW_FIELD_IPV4_ECN ||
    5688         [ #  # ]:          0 :             dst_data->field == RTE_FLOW_FIELD_IPV6_ECN ||
    5689                 :            :             src_data->field == RTE_FLOW_FIELD_IPV6_ECN)
    5690   [ #  #  #  # ]:          0 :                 if (!hca_attr->modify_outer_ip_ecn && root)
    5691                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    5692                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    5693                 :            :                                 "modifications of the ECN for current firmware is not supported");
    5694                 :          0 :         return (width / 32) + !!(width % 32);
    5695                 :            : }
    5696                 :            : 
    5697                 :            : /**
    5698                 :            :  * Validate jump action.
    5699                 :            :  *
    5700                 :            :  * @param[in] action
    5701                 :            :  *   Pointer to the jump action.
    5702                 :            :  * @param[in] action_flags
    5703                 :            :  *   Holds the actions detected until now.
    5704                 :            :  * @param[in] attributes
    5705                 :            :  *   Pointer to flow attributes
    5706                 :            :  * @param[in] external
    5707                 :            :  *   Action belongs to flow rule created by request external to PMD.
    5708                 :            :  * @param[out] error
    5709                 :            :  *   Pointer to error structure.
    5710                 :            :  *
    5711                 :            :  * @return
    5712                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5713                 :            :  */
    5714                 :            : static int
    5715                 :          0 : flow_dv_validate_action_jump(struct rte_eth_dev *dev,
    5716                 :            :                              const struct mlx5_flow_tunnel *tunnel,
    5717                 :            :                              const struct rte_flow_action *action,
    5718                 :            :                              uint64_t action_flags,
    5719                 :            :                              const struct rte_flow_attr *attributes,
    5720                 :            :                              bool external, struct rte_flow_error *error)
    5721                 :            : {
    5722                 :          0 :         uint32_t target_group, table = 0;
    5723                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    5724                 :            :         int ret = 0;
    5725                 :          0 :         struct flow_grp_info grp_info = {
    5726                 :            :                 .external = !!external,
    5727                 :          0 :                 .transfer = !!attributes->transfer,
    5728                 :          0 :                 .fdb_def_rule = !!priv->fdb_def_rule,
    5729                 :            :                 .std_tbl_fix = 0
    5730                 :            :         };
    5731         [ #  # ]:          0 :         if (action_flags & (MLX5_FLOW_FATE_ACTIONS |
    5732                 :            :                             MLX5_FLOW_FATE_ESWITCH_ACTIONS))
    5733                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    5734                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    5735                 :            :                                           "can't have 2 fate actions in"
    5736                 :            :                                           " same flow");
    5737         [ #  # ]:          0 :         if (!action->conf)
    5738                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    5739                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF,
    5740                 :            :                                           NULL, "action configuration not set");
    5741                 :          0 :         target_group =
    5742                 :            :                 ((const struct rte_flow_action_jump *)action->conf)->group;
    5743                 :          0 :         ret = mlx5_flow_group_to_table(dev, tunnel, target_group, &table,
    5744                 :            :                                        &grp_info, error);
    5745         [ #  # ]:          0 :         if (ret)
    5746                 :            :                 return ret;
    5747         [ #  # ]:          0 :         if (table == 0)
    5748                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    5749                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF,
    5750                 :            :                                           NULL, "root table shouldn't be destination");
    5751                 :            :         return 0;
    5752                 :            : }
    5753                 :            : 
    5754                 :            : /*
    5755                 :            :  * Validate action PORT_ID / REPRESENTED_PORT.
    5756                 :            :  *
    5757                 :            :  * @param[in] dev
    5758                 :            :  *   Pointer to rte_eth_dev structure.
    5759                 :            :  * @param[in] action_flags
    5760                 :            :  *   Bit-fields that holds the actions detected until now.
    5761                 :            :  * @param[in] action
    5762                 :            :  *   PORT_ID / REPRESENTED_PORT action structure.
    5763                 :            :  * @param[in] attr
    5764                 :            :  *   Attributes of flow that includes this action.
    5765                 :            :  * @param[out] error
    5766                 :            :  *   Pointer to error structure.
    5767                 :            :  *
    5768                 :            :  * @return
    5769                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5770                 :            :  */
    5771                 :            : static int
    5772                 :          0 : flow_dv_validate_action_port_id(struct rte_eth_dev *dev,
    5773                 :            :                                 uint64_t action_flags,
    5774                 :            :                                 const struct rte_flow_action *action,
    5775                 :            :                                 const struct rte_flow_attr *attr,
    5776                 :            :                                 struct rte_flow_error *error)
    5777                 :            : {
    5778                 :            :         const struct rte_flow_action_port_id *port_id;
    5779                 :            :         const struct rte_flow_action_ethdev *ethdev;
    5780                 :            :         struct mlx5_priv *act_priv;
    5781                 :            :         struct mlx5_priv *dev_priv;
    5782                 :            :         uint16_t port;
    5783                 :            : 
    5784         [ #  # ]:          0 :         if (!attr->transfer)
    5785                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5786                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    5787                 :            :                                           NULL,
    5788                 :            :                                           "port action is valid in transfer"
    5789                 :            :                                           " mode only");
    5790   [ #  #  #  # ]:          0 :         if (!action || !action->conf)
    5791                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5792                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF,
    5793                 :            :                                           NULL,
    5794                 :            :                                           "port action parameters must be"
    5795                 :            :                                           " specified");
    5796         [ #  # ]:          0 :         if (action_flags & (MLX5_FLOW_FATE_ACTIONS |
    5797                 :            :                             MLX5_FLOW_FATE_ESWITCH_ACTIONS))
    5798                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    5799                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    5800                 :            :                                           "can have only one fate actions in"
    5801                 :            :                                           " a flow");
    5802                 :          0 :         dev_priv = mlx5_dev_to_eswitch_info(dev);
    5803         [ #  # ]:          0 :         if (!dev_priv)
    5804                 :          0 :                 return rte_flow_error_set(error, rte_errno,
    5805                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    5806                 :            :                                           NULL,
    5807                 :            :                                           "failed to obtain E-Switch info");
    5808      [ #  #  # ]:          0 :         switch (action->type) {
    5809                 :          0 :         case RTE_FLOW_ACTION_TYPE_PORT_ID:
    5810                 :          0 :                 port_id = action->conf;
    5811         [ #  # ]:          0 :                 port = port_id->original ? dev->data->port_id : port_id->id;
    5812                 :            :                 break;
    5813                 :          0 :         case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
    5814                 :          0 :                 ethdev = action->conf;
    5815                 :          0 :                 port = ethdev->port_id;
    5816                 :          0 :                 break;
    5817                 :          0 :         default:
    5818                 :            :                 MLX5_ASSERT(false);
    5819                 :          0 :                 return rte_flow_error_set
    5820                 :            :                                 (error, EINVAL,
    5821                 :            :                                  RTE_FLOW_ERROR_TYPE_ACTION, action,
    5822                 :            :                                  "unknown E-Switch action");
    5823                 :            :         }
    5824                 :          0 :         act_priv = mlx5_port_to_eswitch_info(port, false);
    5825         [ #  # ]:          0 :         if (!act_priv)
    5826                 :          0 :                 return rte_flow_error_set
    5827                 :            :                                 (error, rte_errno,
    5828                 :          0 :                                  RTE_FLOW_ERROR_TYPE_ACTION_CONF, action->conf,
    5829                 :            :                                  "failed to obtain E-Switch port id for port");
    5830         [ #  # ]:          0 :         if (act_priv->domain_id != dev_priv->domain_id)
    5831                 :          0 :                 return rte_flow_error_set
    5832                 :            :                                 (error, EINVAL,
    5833                 :            :                                  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    5834                 :            :                                  "port does not belong to"
    5835                 :            :                                  " E-Switch being configured");
    5836                 :            :         return 0;
    5837                 :            : }
    5838                 :            : 
    5839                 :            : /**
    5840                 :            :  * Get the maximum number of modify header actions.
    5841                 :            :  *
    5842                 :            :  * @param dev
    5843                 :            :  *   Pointer to rte_eth_dev structure.
    5844                 :            :  * @param root
    5845                 :            :  *   Whether action is on root table.
    5846                 :            :  *
    5847                 :            :  * @return
    5848                 :            :  *   Max number of modify header actions device can support.
    5849                 :            :  */
    5850                 :            : static inline unsigned int
    5851                 :            : flow_dv_modify_hdr_action_max(struct rte_eth_dev *dev __rte_unused,
    5852                 :            :                               bool root)
    5853                 :            : {
    5854                 :            :         /*
    5855                 :            :          * There's no way to directly query the max capacity from FW.
    5856                 :            :          * The maximal value on root table should be assumed to be supported.
    5857                 :            :          */
    5858         [ #  # ]:          0 :         if (!root)
    5859                 :            :                 return MLX5_MAX_MODIFY_NUM;
    5860                 :            :         else
    5861                 :          0 :                 return MLX5_ROOT_TBL_MODIFY_NUM;
    5862                 :            : }
    5863                 :            : 
    5864                 :            : /**
    5865                 :            :  * Validate the meter action.
    5866                 :            :  *
    5867                 :            :  * @param[in] dev
    5868                 :            :  *   Pointer to rte_eth_dev structure.
    5869                 :            :  * @param[in] action_flags
    5870                 :            :  *   Bit-fields that holds the actions detected until now.
    5871                 :            :  * @param[in] item_flags
    5872                 :            :  *   Holds the items detected.
    5873                 :            :  * @param[in] action
    5874                 :            :  *   Pointer to the meter action.
    5875                 :            :  * @param[in] attr
    5876                 :            :  *   Attributes of flow that includes this action.
    5877                 :            :  * @param[in] port_id_item
    5878                 :            :  *   Pointer to item indicating port id.
    5879                 :            :  * @param[out] error
    5880                 :            :  *   Pointer to error structure.
    5881                 :            :  *
    5882                 :            :  * @return
    5883                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5884                 :            :  */
    5885                 :            : static int
    5886                 :          0 : mlx5_flow_validate_action_meter(struct rte_eth_dev *dev,
    5887                 :            :                                 uint64_t action_flags, uint64_t item_flags,
    5888                 :            :                                 const struct rte_flow_action *action,
    5889                 :            :                                 const struct rte_flow_attr *attr,
    5890                 :            :                                 const struct rte_flow_item *port_id_item,
    5891                 :            :                                 bool *def_policy,
    5892                 :            :                                 struct rte_flow_error *error)
    5893                 :            : {
    5894                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    5895                 :          0 :         const struct rte_flow_action_meter *am = action->conf;
    5896                 :            :         struct mlx5_flow_meter_info *fm;
    5897                 :            :         struct mlx5_flow_meter_policy *mtr_policy;
    5898                 :          0 :         struct mlx5_flow_mtr_mng *mtrmng = priv->sh->mtrmng;
    5899                 :          0 :         uint16_t flow_src_port = priv->representor_id;
    5900                 :          0 :         bool all_ports = false;
    5901                 :            : 
    5902         [ #  # ]:          0 :         if (!am)
    5903                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    5904                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    5905                 :            :                                           "meter action conf is NULL");
    5906                 :            : 
    5907         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_METER)
    5908                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5909                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    5910                 :            :                                           "meter chaining not support");
    5911         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_JUMP)
    5912                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5913                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    5914                 :            :                                           "meter with jump not support");
    5915         [ #  # ]:          0 :         if (!priv->mtr_en)
    5916                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5917                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    5918                 :            :                                           NULL,
    5919                 :            :                                           "meter action not supported");
    5920                 :          0 :         fm = mlx5_flow_meter_find(priv, am->mtr_id, NULL);
    5921         [ #  # ]:          0 :         if (!fm)
    5922                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    5923                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    5924                 :            :                                           "Meter not found");
    5925                 :            :         /* aso meter can always be shared by different domains */
    5926   [ #  #  #  # ]:          0 :         if (fm->ref_cnt && !priv->sh->meter_aso_en &&
    5927         [ #  # ]:          0 :             !(fm->transfer == attr->transfer ||
    5928   [ #  #  #  # ]:          0 :               (!fm->ingress && !attr->ingress && attr->egress) ||
    5929   [ #  #  #  # ]:          0 :               (!fm->egress && !attr->egress && attr->ingress)))
    5930                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    5931                 :            :                         RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    5932                 :            :                         "Flow attributes domain are either invalid "
    5933                 :            :                         "or have a domain conflict with current "
    5934                 :            :                         "meter attributes");
    5935         [ #  # ]:          0 :         if (fm->def_policy) {
    5936         [ #  # ]:          0 :                 if (!((attr->transfer &&
    5937         [ #  # ]:          0 :                         mtrmng->def_policy[MLX5_MTR_DOMAIN_TRANSFER]) ||
    5938         [ #  # ]:          0 :                         (attr->egress &&
    5939         [ #  # ]:          0 :                         mtrmng->def_policy[MLX5_MTR_DOMAIN_EGRESS]) ||
    5940         [ #  # ]:          0 :                         (attr->ingress &&
    5941         [ #  # ]:          0 :                         mtrmng->def_policy[MLX5_MTR_DOMAIN_INGRESS])))
    5942                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5943                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    5944                 :            :                                           "Flow attributes domain "
    5945                 :            :                                           "have a conflict with current "
    5946                 :            :                                           "meter domain attributes");
    5947                 :          0 :                 *def_policy = true;
    5948                 :            :         } else {
    5949                 :          0 :                 mtr_policy = mlx5_flow_meter_policy_find(dev,
    5950                 :            :                                                 fm->policy_id, NULL);
    5951         [ #  # ]:          0 :                 if (!mtr_policy)
    5952                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5953                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    5954                 :            :                                           "Invalid policy id for meter ");
    5955   [ #  #  #  # ]:          0 :                 if (!((attr->transfer && mtr_policy->transfer) ||
    5956   [ #  #  #  # ]:          0 :                         (attr->egress && mtr_policy->egress) ||
    5957   [ #  #  #  # ]:          0 :                         (attr->ingress && mtr_policy->ingress)))
    5958                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5959                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    5960                 :            :                                           "Flow attributes domain "
    5961                 :            :                                           "have a conflict with current "
    5962                 :            :                                           "meter domain attributes");
    5963         [ #  # ]:          0 :                 if (port_id_item) {
    5964         [ #  # ]:          0 :                         if (mlx5_flow_get_item_vport_id(dev, port_id_item, &flow_src_port,
    5965                 :            :                                                         &all_ports, error))
    5966                 :          0 :                                 return -rte_errno;
    5967                 :            :                 }
    5968         [ #  # ]:          0 :                 if (attr->transfer) {
    5969                 :            :                         /* When flow matching all src ports, meter should not have drop count. */
    5970   [ #  #  #  #  :          0 :                         if (all_ports && (fm->drop_cnt || mtr_policy->hierarchy_match_port))
                   #  # ]
    5971                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    5972                 :            :                                                           RTE_FLOW_ERROR_TYPE_ITEM_SPEC, NULL,
    5973                 :            :                                                           "Meter drop count or "
    5974                 :            :                                                           "modify_field/set_tag in meter hierarchy "
    5975                 :            :                                                           "not supported when matching all ports.");
    5976         [ #  # ]:          0 :                 } else if (mtr_policy->is_rss) {
    5977                 :            :                         struct mlx5_flow_meter_policy *fp;
    5978                 :            :                         struct mlx5_meter_policy_action_container *acg;
    5979                 :            :                         struct mlx5_meter_policy_action_container *acy;
    5980                 :            :                         const struct rte_flow_action *rss_act;
    5981                 :            :                         int ret;
    5982                 :            : 
    5983                 :          0 :                         fp = mlx5_flow_meter_hierarchy_get_final_policy(dev,
    5984                 :            :                                                                 mtr_policy);
    5985         [ #  # ]:          0 :                         if (fp == NULL)
    5986                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    5987                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    5988                 :            :                                                   "Unable to get the final "
    5989                 :            :                                                   "policy in the hierarchy");
    5990                 :            :                         acg = &fp->act_cnt[RTE_COLOR_GREEN];
    5991                 :            :                         acy = &fp->act_cnt[RTE_COLOR_YELLOW];
    5992                 :            :                         MLX5_ASSERT(acg->fate_action ==
    5993                 :            :                                     MLX5_FLOW_FATE_SHARED_RSS ||
    5994                 :            :                                     acy->fate_action ==
    5995                 :            :                                     MLX5_FLOW_FATE_SHARED_RSS);
    5996         [ #  # ]:          0 :                         if (acg->fate_action == MLX5_FLOW_FATE_SHARED_RSS)
    5997                 :          0 :                                 rss_act = acg->rss;
    5998                 :            :                         else
    5999                 :          0 :                                 rss_act = acy->rss;
    6000                 :          0 :                         ret = mlx5_flow_validate_action_rss(rss_act,
    6001                 :            :                                         action_flags, dev, attr,
    6002                 :            :                                         item_flags, error);
    6003         [ #  # ]:          0 :                         if (ret)
    6004                 :            :                                 return ret;
    6005                 :            :                 }
    6006                 :          0 :                 *def_policy = false;
    6007                 :            :         }
    6008                 :            :         return 0;
    6009                 :            : }
    6010                 :            : 
    6011                 :            : /**
    6012                 :            :  * Validate the age action.
    6013                 :            :  *
    6014                 :            :  * @param[in] action_flags
    6015                 :            :  *   Holds the actions detected until now.
    6016                 :            :  * @param[in] action
    6017                 :            :  *   Pointer to the age action.
    6018                 :            :  * @param[in] dev
    6019                 :            :  *   Pointer to the Ethernet device structure.
    6020                 :            :  * @param[out] error
    6021                 :            :  *   Pointer to error structure.
    6022                 :            :  *
    6023                 :            :  * @return
    6024                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    6025                 :            :  */
    6026                 :            : static int
    6027                 :          0 : flow_dv_validate_action_age(uint64_t action_flags,
    6028                 :            :                             const struct rte_flow_action *action,
    6029                 :            :                             struct rte_eth_dev *dev,
    6030                 :            :                             struct rte_flow_error *error)
    6031                 :            : {
    6032                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    6033                 :          0 :         const struct rte_flow_action_age *age = action->conf;
    6034                 :            : 
    6035         [ #  # ]:          0 :         if (!priv->sh->cdev->config.devx ||
    6036   [ #  #  #  # ]:          0 :             (priv->sh->sws_cmng.counter_fallback && !priv->sh->aso_age_mng))
    6037                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    6038                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    6039                 :            :                                           NULL,
    6040                 :            :                                           "age action not supported");
    6041         [ #  # ]:          0 :         if (!(action->conf))
    6042                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6043                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    6044                 :            :                                           "configuration cannot be null");
    6045         [ #  # ]:          0 :         if (!(age->timeout))
    6046                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6047                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    6048                 :            :                                           "invalid timeout value 0");
    6049         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_AGE)
    6050                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6051                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    6052                 :            :                                           "duplicate age actions set");
    6053                 :            :         return 0;
    6054                 :            : }
    6055                 :            : 
    6056                 :            : /**
    6057                 :            :  * Validate the modify-header IPv4 DSCP actions.
    6058                 :            :  *
    6059                 :            :  * @param[in] action_flags
    6060                 :            :  *   Holds the actions detected until now.
    6061                 :            :  * @param[in] action
    6062                 :            :  *   Pointer to the modify action.
    6063                 :            :  * @param[in] item_flags
    6064                 :            :  *   Holds the items detected.
    6065                 :            :  * @param[out] error
    6066                 :            :  *   Pointer to error structure.
    6067                 :            :  *
    6068                 :            :  * @return
    6069                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    6070                 :            :  */
    6071                 :            : static int
    6072                 :          0 : flow_dv_validate_action_modify_ipv4_dscp(const uint64_t action_flags,
    6073                 :            :                                          const struct rte_flow_action *action,
    6074                 :            :                                          const uint64_t item_flags,
    6075                 :            :                                          struct rte_flow_error *error)
    6076                 :            : {
    6077                 :            :         int ret = 0;
    6078                 :            : 
    6079                 :          0 :         ret = flow_dv_validate_action_modify_hdr(action_flags, action, error);
    6080         [ #  # ]:          0 :         if (!ret) {
    6081         [ #  # ]:          0 :                 if (!(item_flags & MLX5_FLOW_LAYER_L3_IPV4))
    6082                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    6083                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    6084                 :            :                                                   NULL,
    6085                 :            :                                                   "no ipv4 item in pattern");
    6086                 :            :         }
    6087                 :            :         return ret;
    6088                 :            : }
    6089                 :            : 
    6090                 :            : /**
    6091                 :            :  * Validate the modify-header IPv6 DSCP actions.
    6092                 :            :  *
    6093                 :            :  * @param[in] action_flags
    6094                 :            :  *   Holds the actions detected until now.
    6095                 :            :  * @param[in] action
    6096                 :            :  *   Pointer to the modify action.
    6097                 :            :  * @param[in] item_flags
    6098                 :            :  *   Holds the items detected.
    6099                 :            :  * @param[out] error
    6100                 :            :  *   Pointer to error structure.
    6101                 :            :  *
    6102                 :            :  * @return
    6103                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    6104                 :            :  */
    6105                 :            : static int
    6106                 :          0 : flow_dv_validate_action_modify_ipv6_dscp(const uint64_t action_flags,
    6107                 :            :                                          const struct rte_flow_action *action,
    6108                 :            :                                          const uint64_t item_flags,
    6109                 :            :                                          struct rte_flow_error *error)
    6110                 :            : {
    6111                 :            :         int ret = 0;
    6112                 :            : 
    6113                 :          0 :         ret = flow_dv_validate_action_modify_hdr(action_flags, action, error);
    6114         [ #  # ]:          0 :         if (!ret) {
    6115         [ #  # ]:          0 :                 if (!(item_flags & MLX5_FLOW_LAYER_L3_IPV6))
    6116                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    6117                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    6118                 :            :                                                   NULL,
    6119                 :            :                                                   "no ipv6 item in pattern");
    6120                 :            :         }
    6121                 :            :         return ret;
    6122                 :            : }
    6123                 :            : 
    6124                 :            : int
    6125                 :          0 : flow_dv_modify_match_cb(void *tool_ctx __rte_unused,
    6126                 :            :                         struct mlx5_list_entry *entry, void *cb_ctx)
    6127                 :            : {
    6128                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
    6129                 :          0 :         struct mlx5_flow_dv_modify_hdr_resource *ref = ctx->data;
    6130                 :            :         struct mlx5_flow_dv_modify_hdr_resource *resource =
    6131                 :            :                                   container_of(entry, typeof(*resource), entry);
    6132                 :            :         uint32_t key_len = sizeof(*ref) - offsetof(typeof(*ref), ft_type);
    6133                 :            : 
    6134                 :          0 :         key_len += ref->actions_num * sizeof(ref->actions[0]);
    6135         [ #  # ]:          0 :         return ref->actions_num != resource->actions_num ||
    6136         [ #  # ]:          0 :                memcmp(&ref->ft_type, &resource->ft_type, key_len);
    6137                 :            : }
    6138                 :            : 
    6139                 :            : static struct mlx5_indexed_pool *
    6140                 :          0 : flow_dv_modify_ipool_get(struct mlx5_dev_ctx_shared *sh, uint8_t index)
    6141                 :            : {
    6142                 :          0 :         struct mlx5_indexed_pool *ipool = __atomic_load_n
    6143                 :          0 :                                      (&sh->mdh_ipools[index], __ATOMIC_SEQ_CST);
    6144                 :            : 
    6145         [ #  # ]:          0 :         if (!ipool) {
    6146                 :            :                 struct mlx5_indexed_pool *expected = NULL;
    6147                 :          0 :                 struct mlx5_indexed_pool_config cfg =
    6148                 :            :                     (struct mlx5_indexed_pool_config) {
    6149                 :          0 :                        .size = sizeof(struct mlx5_flow_dv_modify_hdr_resource) +
    6150                 :          0 :                                                                    (index + 1) *
    6151                 :            :                                            sizeof(struct mlx5_modification_cmd),
    6152                 :            :                        .trunk_size = 64,
    6153                 :            :                        .grow_trunk = 3,
    6154                 :            :                        .grow_shift = 2,
    6155                 :            :                        .need_lock = 1,
    6156                 :          0 :                        .release_mem_en = !!sh->config.reclaim_mode,
    6157                 :            :                        .per_core_cache =
    6158         [ #  # ]:          0 :                                        sh->config.reclaim_mode ? 0 : (1 << 16),
    6159                 :            :                        .malloc = mlx5_malloc,
    6160                 :            :                        .free = mlx5_free,
    6161                 :            :                        .type = "mlx5_modify_action_resource",
    6162                 :            :                 };
    6163                 :            : 
    6164                 :          0 :                 cfg.size = RTE_ALIGN(cfg.size, sizeof(ipool));
    6165                 :          0 :                 ipool = mlx5_ipool_create(&cfg);
    6166         [ #  # ]:          0 :                 if (!ipool)
    6167                 :          0 :                         return NULL;
    6168         [ #  # ]:          0 :                 if (!__atomic_compare_exchange_n(&sh->mdh_ipools[index],
    6169                 :            :                                                  &expected, ipool, false,
    6170                 :            :                                                  __ATOMIC_SEQ_CST,
    6171                 :            :                                                  __ATOMIC_SEQ_CST)) {
    6172                 :          0 :                         mlx5_ipool_destroy(ipool);
    6173                 :          0 :                         ipool = __atomic_load_n(&sh->mdh_ipools[index],
    6174                 :            :                                                 __ATOMIC_SEQ_CST);
    6175                 :            :                 }
    6176                 :            :         }
    6177                 :            :         return ipool;
    6178                 :            : }
    6179                 :            : 
    6180                 :            : struct mlx5_list_entry *
    6181                 :          0 : flow_dv_modify_create_cb(void *tool_ctx, void *cb_ctx)
    6182                 :            : {
    6183                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
    6184                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
    6185                 :            :         struct mlx5dv_dr_domain *ns;
    6186                 :            :         struct mlx5_flow_dv_modify_hdr_resource *entry;
    6187                 :          0 :         struct mlx5_flow_dv_modify_hdr_resource *ref = ctx->data;
    6188                 :          0 :         struct mlx5_indexed_pool *ipool = flow_dv_modify_ipool_get(sh,
    6189                 :          0 :                                                           ref->actions_num - 1);
    6190                 :            :         int ret;
    6191                 :          0 :         uint32_t data_len = ref->actions_num * sizeof(ref->actions[0]);
    6192                 :            :         uint32_t key_len = sizeof(*ref) - offsetof(typeof(*ref), ft_type);
    6193                 :            :         uint32_t idx;
    6194                 :            : 
    6195         [ #  # ]:          0 :         if (unlikely(!ipool)) {
    6196                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
    6197                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    6198                 :            :                                    NULL, "cannot allocate modify ipool");
    6199                 :          0 :                 return NULL;
    6200                 :            :         }
    6201                 :          0 :         entry = mlx5_ipool_zmalloc(ipool, &idx);
    6202         [ #  # ]:          0 :         if (!entry) {
    6203                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
    6204                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    6205                 :            :                                    "cannot allocate resource memory");
    6206                 :          0 :                 return NULL;
    6207                 :            :         }
    6208                 :          0 :         rte_memcpy(RTE_PTR_ADD(entry, offsetof(typeof(*entry), ft_type)),
    6209                 :          0 :                    RTE_PTR_ADD(ref, offsetof(typeof(*ref), ft_type)),
    6210         [ #  # ]:          0 :                    key_len + data_len);
    6211         [ #  # ]:          0 :         if (entry->ft_type == MLX5DV_FLOW_TABLE_TYPE_FDB)
    6212                 :          0 :                 ns = sh->fdb_domain;
    6213         [ #  # ]:          0 :         else if (entry->ft_type == MLX5DV_FLOW_TABLE_TYPE_NIC_TX)
    6214                 :          0 :                 ns = sh->tx_domain;
    6215                 :            :         else
    6216                 :          0 :                 ns = sh->rx_domain;
    6217                 :          0 :         ret = mlx5_flow_os_create_flow_action_modify_header
    6218                 :          0 :                                         (sh->cdev->ctx, ns, entry,
    6219                 :            :                                          data_len, &entry->action);
    6220                 :            :         if (ret) {
    6221                 :          0 :                 mlx5_ipool_free(sh->mdh_ipools[ref->actions_num - 1], idx);
    6222                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
    6223                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    6224                 :            :                                    NULL, "cannot create modification action");
    6225                 :          0 :                 return NULL;
    6226                 :            :         }
    6227                 :          0 :         entry->idx = idx;
    6228                 :          0 :         return &entry->entry;
    6229                 :            : }
    6230                 :            : 
    6231                 :            : struct mlx5_list_entry *
    6232                 :          0 : flow_dv_modify_clone_cb(void *tool_ctx, struct mlx5_list_entry *oentry,
    6233                 :            :                         void *cb_ctx)
    6234                 :            : {
    6235                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
    6236                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
    6237                 :            :         struct mlx5_flow_dv_modify_hdr_resource *entry;
    6238                 :          0 :         struct mlx5_flow_dv_modify_hdr_resource *ref = ctx->data;
    6239                 :          0 :         uint32_t data_len = ref->actions_num * sizeof(ref->actions[0]);
    6240                 :            :         uint32_t idx;
    6241                 :            : 
    6242                 :          0 :         entry = mlx5_ipool_malloc(sh->mdh_ipools[ref->actions_num - 1],
    6243                 :            :                                   &idx);
    6244         [ #  # ]:          0 :         if (!entry) {
    6245                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
    6246                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    6247                 :            :                                    "cannot allocate resource memory");
    6248                 :          0 :                 return NULL;
    6249                 :            :         }
    6250                 :          0 :         memcpy(entry, oentry, sizeof(*entry) + data_len);
    6251                 :          0 :         entry->idx = idx;
    6252                 :          0 :         return &entry->entry;
    6253                 :            : }
    6254                 :            : 
    6255                 :            : void
    6256                 :          0 : flow_dv_modify_clone_free_cb(void *tool_ctx, struct mlx5_list_entry *entry)
    6257                 :            : {
    6258                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
    6259                 :            :         struct mlx5_flow_dv_modify_hdr_resource *res =
    6260                 :            :                 container_of(entry, typeof(*res), entry);
    6261                 :            : 
    6262                 :          0 :         mlx5_ipool_free(sh->mdh_ipools[res->actions_num - 1], res->idx);
    6263                 :          0 : }
    6264                 :            : 
    6265                 :            : /**
    6266                 :            :  * Validate the sample action.
    6267                 :            :  *
    6268                 :            :  * @param[in, out] action_flags
    6269                 :            :  *   Holds the actions detected until now.
    6270                 :            :  * @param[in] action
    6271                 :            :  *   Pointer to the sample action.
    6272                 :            :  * @param[in] dev
    6273                 :            :  *   Pointer to the Ethernet device structure.
    6274                 :            :  * @param[in] attr
    6275                 :            :  *   Attributes of flow that includes this action.
    6276                 :            :  * @param[in] item_flags
    6277                 :            :  *   Holds the items detected.
    6278                 :            :  * @param[in] rss
    6279                 :            :  *   Pointer to the RSS action.
    6280                 :            :  * @param[out] sample_rss
    6281                 :            :  *   Pointer to the RSS action in sample action list.
    6282                 :            :  * @param[out] count
    6283                 :            :  *   Pointer to the COUNT action in sample action list.
    6284                 :            :  * @param[out] fdb_mirror
    6285                 :            :  *   Pointer to the FDB mirror flag.
    6286                 :            :  * @param root
    6287                 :            :  *   Whether action is on root table.
    6288                 :            :  * @param[out] error
    6289                 :            :  *   Pointer to error structure.
    6290                 :            :  *
    6291                 :            :  * @return
    6292                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    6293                 :            :  */
    6294                 :            : static int
    6295                 :          0 : flow_dv_validate_action_sample(uint64_t *action_flags,
    6296                 :            :                                uint64_t *sub_action_flags,
    6297                 :            :                                const struct rte_flow_action *action,
    6298                 :            :                                struct rte_eth_dev *dev,
    6299                 :            :                                const struct rte_flow_attr *attr,
    6300                 :            :                                uint64_t item_flags,
    6301                 :            :                                const struct rte_flow_action_rss *rss,
    6302                 :            :                                const struct rte_flow_action_rss **sample_rss,
    6303                 :            :                                const struct rte_flow_action_count **count,
    6304                 :            :                                int *fdb_mirror,
    6305                 :            :                                uint16_t *sample_port_id,
    6306                 :            :                                bool root,
    6307                 :            :                                struct rte_flow_error *error)
    6308                 :            : {
    6309                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    6310                 :          0 :         struct mlx5_sh_config *dev_conf = &priv->sh->config;
    6311                 :          0 :         const struct rte_flow_action_sample *sample = action->conf;
    6312                 :            :         const struct rte_flow_action_port_id *port = NULL;
    6313                 :            :         const struct rte_flow_action *act;
    6314                 :            :         uint16_t queue_index = 0xFFFF;
    6315                 :          0 :         int actions_n = 0;
    6316                 :            :         int ret;
    6317                 :            : 
    6318         [ #  # ]:          0 :         if (!sample)
    6319                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6320                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    6321                 :            :                                           "configuration cannot be NULL");
    6322         [ #  # ]:          0 :         if (sample->ratio == 0)
    6323                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6324                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    6325                 :            :                                           "ratio value starts from 1");
    6326         [ #  # ]:          0 :         if (!priv->sh->cdev->config.devx ||
    6327         [ #  # ]:          0 :             (sample->ratio > 0 && !priv->sampler_en))
    6328                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    6329                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    6330                 :            :                                           NULL,
    6331                 :            :                                           "sample action not supported");
    6332         [ #  # ]:          0 :         if (*action_flags & MLX5_FLOW_ACTION_SAMPLE)
    6333                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6334                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    6335                 :            :                                           "Multiple sample actions not "
    6336                 :            :                                           "supported");
    6337         [ #  # ]:          0 :         if (*action_flags & MLX5_FLOW_ACTION_METER)
    6338                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6339                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    6340                 :            :                                           "wrong action order, meter should "
    6341                 :            :                                           "be after sample action");
    6342         [ #  # ]:          0 :         if (*action_flags & MLX5_FLOW_ACTION_JUMP)
    6343                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6344                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    6345                 :            :                                           "wrong action order, jump should "
    6346                 :            :                                           "be after sample action");
    6347         [ #  # ]:          0 :         if (*action_flags & MLX5_FLOW_ACTION_CT)
    6348                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6349                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    6350                 :            :                                           "Sample after CT not supported");
    6351                 :          0 :         act = sample->actions;
    6352         [ #  # ]:          0 :         for (; act->type != RTE_FLOW_ACTION_TYPE_END; act++) {
    6353         [ #  # ]:          0 :                 if (actions_n == MLX5_DV_MAX_NUMBER_OF_ACTIONS)
    6354                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    6355                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    6356                 :            :                                                   act, "too many actions");
    6357   [ #  #  #  #  :          0 :                 switch (act->type) {
             #  #  #  # ]
    6358                 :          0 :                 case RTE_FLOW_ACTION_TYPE_QUEUE:
    6359                 :          0 :                         ret = mlx5_flow_validate_action_queue(act,
    6360                 :            :                                                               *sub_action_flags,
    6361                 :            :                                                               dev,
    6362                 :            :                                                               attr, error);
    6363         [ #  # ]:          0 :                         if (ret < 0)
    6364                 :          0 :                                 return ret;
    6365                 :          0 :                         queue_index = ((const struct rte_flow_action_queue *)
    6366                 :          0 :                                                         (act->conf))->index;
    6367                 :          0 :                         *sub_action_flags |= MLX5_FLOW_ACTION_QUEUE;
    6368                 :          0 :                         ++actions_n;
    6369                 :          0 :                         break;
    6370                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RSS:
    6371                 :          0 :                         *sample_rss = act->conf;
    6372                 :          0 :                         ret = mlx5_flow_validate_action_rss(act,
    6373                 :            :                                                             *sub_action_flags,
    6374                 :            :                                                             dev, attr,
    6375                 :            :                                                             item_flags,
    6376                 :            :                                                             error);
    6377         [ #  # ]:          0 :                         if (ret < 0)
    6378                 :          0 :                                 return ret;
    6379   [ #  #  #  # ]:          0 :                         if (rss && *sample_rss &&
    6380         [ #  # ]:          0 :                             ((*sample_rss)->level != rss->level ||
    6381         [ #  # ]:          0 :                             (*sample_rss)->types != rss->types))
    6382                 :          0 :                                 return rte_flow_error_set(error, ENOTSUP,
    6383                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION,
    6384                 :            :                                         NULL,
    6385                 :            :                                         "Can't use the different RSS types "
    6386                 :            :                                         "or level in the same flow");
    6387   [ #  #  #  # ]:          0 :                         if (*sample_rss != NULL && (*sample_rss)->queue_num)
    6388                 :          0 :                                 queue_index = (*sample_rss)->queue[0];
    6389                 :          0 :                         *sub_action_flags |= MLX5_FLOW_ACTION_RSS;
    6390                 :          0 :                         ++actions_n;
    6391                 :          0 :                         break;
    6392                 :          0 :                 case RTE_FLOW_ACTION_TYPE_MARK:
    6393                 :          0 :                         ret = flow_dv_validate_action_mark(dev, act,
    6394                 :            :                                                            *sub_action_flags,
    6395                 :            :                                                            attr, error);
    6396         [ #  # ]:          0 :                         if (ret < 0)
    6397                 :          0 :                                 return ret;
    6398         [ #  # ]:          0 :                         if (dev_conf->dv_xmeta_en != MLX5_XMETA_MODE_LEGACY)
    6399                 :          0 :                                 *sub_action_flags |= MLX5_FLOW_ACTION_MARK |
    6400                 :            :                                                 MLX5_FLOW_ACTION_MARK_EXT;
    6401                 :            :                         else
    6402                 :          0 :                                 *sub_action_flags |= MLX5_FLOW_ACTION_MARK;
    6403                 :          0 :                         ++actions_n;
    6404                 :          0 :                         break;
    6405                 :          0 :                 case RTE_FLOW_ACTION_TYPE_COUNT:
    6406                 :          0 :                         ret = flow_dv_validate_action_count
    6407                 :          0 :                                 (dev, false, *action_flags | *sub_action_flags,
    6408                 :            :                                  root, error);
    6409         [ #  # ]:          0 :                         if (ret < 0)
    6410                 :          0 :                                 return ret;
    6411                 :          0 :                         *count = act->conf;
    6412                 :          0 :                         *sub_action_flags |= MLX5_FLOW_ACTION_COUNT;
    6413                 :          0 :                         *action_flags |= MLX5_FLOW_ACTION_COUNT;
    6414                 :          0 :                         ++actions_n;
    6415                 :          0 :                         break;
    6416                 :          0 :                 case RTE_FLOW_ACTION_TYPE_PORT_ID:
    6417                 :            :                 case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
    6418                 :          0 :                         ret = flow_dv_validate_action_port_id(dev,
    6419                 :            :                                                               *sub_action_flags,
    6420                 :            :                                                               act,
    6421                 :            :                                                               attr,
    6422                 :            :                                                               error);
    6423         [ #  # ]:          0 :                         if (ret)
    6424                 :          0 :                                 return ret;
    6425         [ #  # ]:          0 :                         if (act->type == RTE_FLOW_ACTION_TYPE_PORT_ID) {
    6426                 :          0 :                                 port = (const struct rte_flow_action_port_id *)
    6427                 :            :                                         act->conf;
    6428         [ #  # ]:          0 :                                 *sample_port_id = port->original ?
    6429                 :          0 :                                                   dev->data->port_id : port->id;
    6430                 :            :                         } else {
    6431                 :          0 :                                 *sample_port_id = ((const struct rte_flow_action_ethdev *)
    6432                 :          0 :                                                   act->conf)->port_id;
    6433                 :            :                         }
    6434                 :          0 :                         *sub_action_flags |= MLX5_FLOW_ACTION_PORT_ID;
    6435                 :          0 :                         ++actions_n;
    6436                 :          0 :                         break;
    6437                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
    6438                 :          0 :                         ret = flow_dv_validate_action_raw_encap_decap
    6439                 :          0 :                                 (dev, NULL, act->conf, attr, sub_action_flags,
    6440                 :            :                                  &actions_n, action, item_flags, error);
    6441         [ #  # ]:          0 :                         if (ret < 0)
    6442                 :          0 :                                 return ret;
    6443                 :          0 :                         ++actions_n;
    6444                 :          0 :                         break;
    6445                 :          0 :                 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
    6446                 :            :                 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
    6447                 :          0 :                         ret = flow_dv_validate_action_l2_encap(dev,
    6448                 :            :                                                                *sub_action_flags,
    6449                 :            :                                                                act, attr,
    6450                 :            :                                                                error);
    6451         [ #  # ]:          0 :                         if (ret < 0)
    6452                 :          0 :                                 return ret;
    6453                 :          0 :                         *sub_action_flags |= MLX5_FLOW_ACTION_ENCAP;
    6454                 :          0 :                         ++actions_n;
    6455                 :          0 :                         break;
    6456                 :          0 :                 default:
    6457                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    6458                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    6459                 :            :                                                   NULL,
    6460                 :            :                                                   "Doesn't support optional "
    6461                 :            :                                                   "action");
    6462                 :            :                 }
    6463                 :            :         }
    6464         [ #  # ]:          0 :         if (attr->ingress) {
    6465         [ #  # ]:          0 :                 if (!(*sub_action_flags & (MLX5_FLOW_ACTION_QUEUE |
    6466                 :            :                                           MLX5_FLOW_ACTION_RSS)))
    6467                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    6468                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    6469                 :            :                                                   NULL,
    6470                 :            :                                                   "Ingress must has a dest "
    6471                 :            :                                                   "QUEUE for Sample");
    6472         [ #  # ]:          0 :         } else if (attr->egress) {
    6473                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    6474                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
    6475                 :            :                                           NULL,
    6476                 :            :                                           "Sample Only support Ingress "
    6477                 :            :                                           "or E-Switch");
    6478         [ #  # ]:          0 :         } else if (sample->actions->type != RTE_FLOW_ACTION_TYPE_END) {
    6479                 :            :                 MLX5_ASSERT(attr->transfer);
    6480         [ #  # ]:          0 :                 if (sample->ratio > 1)
    6481                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    6482                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    6483                 :            :                                                   NULL,
    6484                 :            :                                                   "E-Switch doesn't support "
    6485                 :            :                                                   "any optional action "
    6486                 :            :                                                   "for sampling");
    6487         [ #  # ]:          0 :                 if (*sub_action_flags & MLX5_FLOW_ACTION_QUEUE)
    6488                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    6489                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    6490                 :            :                                                   NULL,
    6491                 :            :                                                   "unsupported action QUEUE");
    6492         [ #  # ]:          0 :                 if (*sub_action_flags & MLX5_FLOW_ACTION_RSS)
    6493                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    6494                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    6495                 :            :                                                   NULL,
    6496                 :            :                                                   "unsupported action QUEUE");
    6497         [ #  # ]:          0 :                 if (!(*sub_action_flags & MLX5_FLOW_ACTION_PORT_ID))
    6498                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    6499                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    6500                 :            :                                                   NULL,
    6501                 :            :                                                   "E-Switch must has a dest "
    6502                 :            :                                                   "port for mirroring");
    6503                 :          0 :                 *fdb_mirror = 1;
    6504                 :            :         }
    6505                 :            :         /* Continue validation for Xcap actions.*/
    6506   [ #  #  #  # ]:          0 :         if ((*sub_action_flags & MLX5_FLOW_XCAP_ACTIONS) &&
    6507         [ #  # ]:          0 :             (queue_index == 0xFFFF || !mlx5_rxq_is_hairpin(dev, queue_index))) {
    6508         [ #  # ]:          0 :                 if ((*sub_action_flags & MLX5_FLOW_XCAP_ACTIONS) ==
    6509                 :            :                      MLX5_FLOW_XCAP_ACTIONS)
    6510                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    6511                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    6512                 :            :                                                   NULL, "encap and decap "
    6513                 :            :                                                   "combination aren't "
    6514                 :            :                                                   "supported");
    6515   [ #  #  #  # ]:          0 :                 if (attr->ingress && (*sub_action_flags & MLX5_FLOW_ACTION_ENCAP))
    6516                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    6517                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    6518                 :            :                                                   NULL, "encap is not supported"
    6519                 :            :                                                   " for ingress traffic");
    6520                 :            :         }
    6521                 :            :         return 0;
    6522                 :            : }
    6523                 :            : 
    6524                 :            : /**
    6525                 :            :  * Find existing modify-header resource or create and register a new one.
    6526                 :            :  *
    6527                 :            :  * @param dev[in, out]
    6528                 :            :  *   Pointer to rte_eth_dev structure.
    6529                 :            :  * @param[in, out] resource
    6530                 :            :  *   Pointer to modify-header resource.
    6531                 :            :  * @parm[in, out] dev_flow
    6532                 :            :  *   Pointer to the dev_flow.
    6533                 :            :  * @param[out] error
    6534                 :            :  *   pointer to error structure.
    6535                 :            :  *
    6536                 :            :  * @return
    6537                 :            :  *   0 on success otherwise -errno and errno is set.
    6538                 :            :  */
    6539                 :            : static int
    6540                 :          0 : flow_dv_modify_hdr_resource_register
    6541                 :            :                         (struct rte_eth_dev *dev,
    6542                 :            :                          struct mlx5_flow_dv_modify_hdr_resource *resource,
    6543                 :            :                          struct mlx5_flow *dev_flow,
    6544                 :            :                          struct rte_flow_error *error)
    6545                 :            : {
    6546                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    6547                 :          0 :         struct mlx5_dev_ctx_shared *sh = priv->sh;
    6548                 :          0 :         uint32_t key_len = sizeof(*resource) -
    6549                 :            :                            offsetof(typeof(*resource), ft_type) +
    6550                 :          0 :                            resource->actions_num * sizeof(resource->actions[0]);
    6551                 :            :         struct mlx5_list_entry *entry;
    6552                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
    6553                 :            :                 .error = error,
    6554                 :            :                 .data = resource,
    6555                 :            :         };
    6556                 :            :         struct mlx5_hlist *modify_cmds;
    6557                 :            :         uint64_t key64;
    6558                 :            : 
    6559                 :          0 :         modify_cmds = flow_dv_hlist_prepare(sh, &sh->modify_cmds,
    6560                 :            :                                 "hdr_modify",
    6561                 :            :                                 MLX5_FLOW_HDR_MODIFY_HTABLE_SZ,
    6562                 :            :                                 true, false, sh,
    6563                 :            :                                 flow_dv_modify_create_cb,
    6564                 :            :                                 flow_dv_modify_match_cb,
    6565                 :            :                                 flow_dv_modify_remove_cb,
    6566                 :            :                                 flow_dv_modify_clone_cb,
    6567                 :            :                                 flow_dv_modify_clone_free_cb,
    6568                 :            :                                 error);
    6569         [ #  # ]:          0 :         if (unlikely(!modify_cmds))
    6570                 :          0 :                 return -rte_errno;
    6571                 :          0 :         resource->root = !dev_flow->dv.group;
    6572   [ #  #  #  # ]:          0 :         if (resource->actions_num > flow_dv_modify_hdr_action_max(dev,
    6573                 :            :                                                                 resource->root))
    6574                 :          0 :                 return rte_flow_error_set(error, EOVERFLOW,
    6575                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    6576                 :            :                                           "too many modify header items");
    6577                 :          0 :         key64 = __rte_raw_cksum(&resource->ft_type, key_len, 0);
    6578                 :          0 :         entry = mlx5_hlist_register(modify_cmds, key64, &ctx);
    6579         [ #  # ]:          0 :         if (!entry)
    6580                 :          0 :                 return -rte_errno;
    6581                 :            :         resource = container_of(entry, typeof(*resource), entry);
    6582                 :          0 :         dev_flow->handle->dvh.modify_hdr = resource;
    6583                 :          0 :         return 0;
    6584                 :            : }
    6585                 :            : 
    6586                 :            : /**
    6587                 :            :  * Get DV flow counter by index.
    6588                 :            :  *
    6589                 :            :  * @param[in] dev
    6590                 :            :  *   Pointer to the Ethernet device structure.
    6591                 :            :  * @param[in] idx
    6592                 :            :  *   mlx5 flow counter index in the container.
    6593                 :            :  * @param[out] ppool
    6594                 :            :  *   mlx5 flow counter pool in the container.
    6595                 :            :  *
    6596                 :            :  * @return
    6597                 :            :  *   Pointer to the counter, NULL otherwise.
    6598                 :            :  */
    6599                 :            : static struct mlx5_flow_counter *
    6600                 :            : flow_dv_counter_get_by_idx(struct rte_eth_dev *dev,
    6601                 :            :                            uint32_t idx,
    6602                 :            :                            struct mlx5_flow_counter_pool **ppool)
    6603                 :            : {
    6604                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    6605                 :          0 :         struct mlx5_flow_counter_mng *cmng = &priv->sh->sws_cmng;
    6606                 :            :         struct mlx5_flow_counter_pool *pool;
    6607                 :            : 
    6608                 :            :         /* Decrease to original index and clear shared bit. */
    6609                 :          0 :         idx = (idx - 1) & (MLX5_CNT_SHARED_OFFSET - 1);
    6610                 :            :         MLX5_ASSERT(idx / MLX5_COUNTERS_PER_POOL < MLX5_COUNTER_POOLS_MAX_NUM);
    6611                 :          0 :         pool = cmng->pools[idx / MLX5_COUNTERS_PER_POOL];
    6612                 :            :         MLX5_ASSERT(pool);
    6613                 :            :         if (ppool)
    6614                 :            :                 *ppool = pool;
    6615   [ #  #  #  #  :          0 :         return MLX5_POOL_GET_CNT(pool, idx % MLX5_COUNTERS_PER_POOL);
          #  #  #  #  #  
                #  #  # ]
    6616                 :            : }
    6617                 :            : 
    6618                 :            : /**
    6619                 :            :  * Check the devx counter belongs to the pool.
    6620                 :            :  *
    6621                 :            :  * @param[in] pool
    6622                 :            :  *   Pointer to the counter pool.
    6623                 :            :  * @param[in] id
    6624                 :            :  *   The counter devx ID.
    6625                 :            :  *
    6626                 :            :  * @return
    6627                 :            :  *   True if counter belongs to the pool, false otherwise.
    6628                 :            :  */
    6629                 :            : static bool
    6630                 :            : flow_dv_is_counter_in_pool(struct mlx5_flow_counter_pool *pool, int id)
    6631                 :            : {
    6632                 :          0 :         int base = (pool->min_dcs->id / MLX5_COUNTERS_PER_POOL) *
    6633                 :            :                    MLX5_COUNTERS_PER_POOL;
    6634                 :            : 
    6635   [ #  #  #  # ]:          0 :         if (id >= base && id < base + MLX5_COUNTERS_PER_POOL)
    6636                 :            :                 return true;
    6637                 :            :         return false;
    6638                 :            : }
    6639                 :            : 
    6640                 :            : /**
    6641                 :            :  * Get a pool by devx counter ID.
    6642                 :            :  *
    6643                 :            :  * @param[in] cmng
    6644                 :            :  *   Pointer to the counter management.
    6645                 :            :  * @param[in] id
    6646                 :            :  *   The counter devx ID.
    6647                 :            :  *
    6648                 :            :  * @return
    6649                 :            :  *   The counter pool pointer if exists, NULL otherwise,
    6650                 :            :  */
    6651                 :            : static struct mlx5_flow_counter_pool *
    6652                 :          0 : flow_dv_find_pool_by_id(struct mlx5_flow_counter_mng *cmng, int id)
    6653                 :            : {
    6654                 :            :         uint32_t i;
    6655                 :            :         struct mlx5_flow_counter_pool *pool = NULL;
    6656                 :            : 
    6657                 :          0 :         rte_spinlock_lock(&cmng->pool_update_sl);
    6658                 :            :         /* Check last used pool. */
    6659         [ #  # ]:          0 :         if (cmng->last_pool_idx != POOL_IDX_INVALID &&
    6660         [ #  # ]:          0 :             flow_dv_is_counter_in_pool(cmng->pools[cmng->last_pool_idx], id)) {
    6661                 :            :                 pool = cmng->pools[cmng->last_pool_idx];
    6662                 :          0 :                 goto out;
    6663                 :            :         }
    6664                 :            :         /* ID out of range means no suitable pool in the container. */
    6665   [ #  #  #  # ]:          0 :         if (id > cmng->max_id || id < cmng->min_id)
    6666                 :          0 :                 goto out;
    6667                 :            :         /*
    6668                 :            :          * Find the pool from the end of the container, since mostly counter
    6669                 :            :          * ID is sequence increasing, and the last pool should be the needed
    6670                 :            :          * one.
    6671                 :            :          */
    6672                 :          0 :         i = cmng->n_valid;
    6673         [ #  # ]:          0 :         while (i--) {
    6674         [ #  # ]:          0 :                 struct mlx5_flow_counter_pool *pool_tmp = cmng->pools[i];
    6675                 :            : 
    6676                 :            :                 if (flow_dv_is_counter_in_pool(pool_tmp, id)) {
    6677                 :            :                         pool = pool_tmp;
    6678                 :            :                         break;
    6679                 :            :                 }
    6680                 :            :         }
    6681                 :          0 : out:
    6682                 :            :         rte_spinlock_unlock(&cmng->pool_update_sl);
    6683                 :          0 :         return pool;
    6684                 :            : }
    6685                 :            : 
    6686                 :            : /**
    6687                 :            :  * Query a devx flow counter.
    6688                 :            :  *
    6689                 :            :  * @param[in] dev
    6690                 :            :  *   Pointer to the Ethernet device structure.
    6691                 :            :  * @param[in] counter
    6692                 :            :  *   Index to the flow counter.
    6693                 :            :  * @param[out] pkts
    6694                 :            :  *   The statistics value of packets.
    6695                 :            :  * @param[out] bytes
    6696                 :            :  *   The statistics value of bytes.
    6697                 :            :  *
    6698                 :            :  * @return
    6699                 :            :  *   0 on success, otherwise a negative errno value and rte_errno is set.
    6700                 :            :  */
    6701                 :            : static inline int
    6702                 :          0 : _flow_dv_query_count(struct rte_eth_dev *dev, uint32_t counter, uint64_t *pkts,
    6703                 :            :                      uint64_t *bytes)
    6704                 :            : {
    6705         [ #  # ]:          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    6706                 :            :         struct mlx5_flow_counter_pool *pool = NULL;
    6707                 :            :         struct mlx5_flow_counter *cnt;
    6708                 :            :         int offset;
    6709                 :            : 
    6710                 :            :         cnt = flow_dv_counter_get_by_idx(dev, counter, &pool);
    6711                 :            :         MLX5_ASSERT(pool);
    6712         [ #  # ]:          0 :         if (priv->sh->sws_cmng.counter_fallback)
    6713                 :          0 :                 return mlx5_devx_cmd_flow_counter_query(cnt->dcs_when_active, 0,
    6714                 :            :                                         0, pkts, bytes, 0, NULL, NULL, 0);
    6715                 :          0 :         rte_spinlock_lock(&pool->sl);
    6716         [ #  # ]:          0 :         if (!pool->raw) {
    6717                 :          0 :                 *pkts = 0;
    6718                 :          0 :                 *bytes = 0;
    6719                 :            :         } else {
    6720         [ #  # ]:          0 :                 offset = MLX5_CNT_ARRAY_IDX(pool, cnt);
    6721                 :          0 :                 *pkts = rte_be_to_cpu_64(pool->raw->data[offset].hits);
    6722                 :          0 :                 *bytes = rte_be_to_cpu_64(pool->raw->data[offset].bytes);
    6723                 :            :         }
    6724                 :            :         rte_spinlock_unlock(&pool->sl);
    6725                 :          0 :         return 0;
    6726                 :            : }
    6727                 :            : 
    6728                 :            : /**
    6729                 :            :  * Create and initialize a new counter pool.
    6730                 :            :  *
    6731                 :            :  * @param[in] dev
    6732                 :            :  *   Pointer to the Ethernet device structure.
    6733                 :            :  * @param[out] dcs
    6734                 :            :  *   The devX counter handle.
    6735                 :            :  * @param[in] age
    6736                 :            :  *   Whether the pool is for counter that was allocated for aging.
    6737                 :            :  *
    6738                 :            :  * @return
    6739                 :            :  *   The pool container pointer on success, NULL otherwise and rte_errno is set.
    6740                 :            :  */
    6741                 :            : static struct mlx5_flow_counter_pool *
    6742                 :          0 : flow_dv_pool_create(struct rte_eth_dev *dev, struct mlx5_devx_obj *dcs,
    6743                 :            :                     uint32_t age)
    6744                 :            : {
    6745                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    6746                 :            :         struct mlx5_flow_counter_pool *pool;
    6747                 :          0 :         struct mlx5_flow_counter_mng *cmng = &priv->sh->sws_cmng;
    6748                 :          0 :         bool fallback = cmng->counter_fallback;
    6749                 :            :         uint32_t size = sizeof(*pool);
    6750                 :            : 
    6751         [ #  # ]:          0 :         if (cmng->n_valid == MLX5_COUNTER_POOLS_MAX_NUM) {
    6752                 :          0 :                 DRV_LOG(ERR, "All counter is in used, try again later.");
    6753                 :          0 :                 rte_errno = EAGAIN;
    6754                 :          0 :                 return NULL;
    6755                 :            :         }
    6756                 :            :         size += MLX5_COUNTERS_PER_POOL * MLX5_CNT_SIZE;
    6757         [ #  # ]:          0 :         size += (!age ? 0 : MLX5_COUNTERS_PER_POOL * MLX5_AGE_SIZE);
    6758                 :          0 :         pool = mlx5_malloc(MLX5_MEM_ZERO, size, 0, SOCKET_ID_ANY);
    6759         [ #  # ]:          0 :         if (!pool) {
    6760                 :          0 :                 rte_errno = ENOMEM;
    6761                 :          0 :                 return NULL;
    6762                 :            :         }
    6763                 :          0 :         pool->raw = NULL;
    6764                 :          0 :         pool->is_aged = !!age;
    6765                 :          0 :         pool->query_gen = 0;
    6766                 :          0 :         pool->min_dcs = dcs;
    6767                 :            :         rte_spinlock_init(&pool->sl);
    6768                 :            :         rte_spinlock_init(&pool->csl);
    6769                 :          0 :         TAILQ_INIT(&pool->counters[0]);
    6770                 :          0 :         TAILQ_INIT(&pool->counters[1]);
    6771                 :          0 :         pool->time_of_last_age_check = MLX5_CURR_TIME_SEC;
    6772                 :          0 :         rte_spinlock_lock(&cmng->pool_update_sl);
    6773                 :          0 :         pool->index = cmng->n_valid;
    6774                 :          0 :         cmng->pools[pool->index] = pool;
    6775                 :          0 :         cmng->n_valid++;
    6776         [ #  # ]:          0 :         if (unlikely(fallback)) {
    6777                 :          0 :                 int base = RTE_ALIGN_FLOOR(dcs->id, MLX5_COUNTERS_PER_POOL);
    6778                 :            : 
    6779         [ #  # ]:          0 :                 if (base < cmng->min_id)
    6780                 :          0 :                         cmng->min_id = base;
    6781         [ #  # ]:          0 :                 if (base > cmng->max_id)
    6782                 :          0 :                         cmng->max_id = base + MLX5_COUNTERS_PER_POOL - 1;
    6783                 :          0 :                 cmng->last_pool_idx = pool->index;
    6784                 :            :         }
    6785                 :            :         rte_spinlock_unlock(&cmng->pool_update_sl);
    6786                 :          0 :         return pool;
    6787                 :            : }
    6788                 :            : 
    6789                 :            : /**
    6790                 :            :  * Prepare a new counter and/or a new counter pool.
    6791                 :            :  *
    6792                 :            :  * @param[in] dev
    6793                 :            :  *   Pointer to the Ethernet device structure.
    6794                 :            :  * @param[out] cnt_free
    6795                 :            :  *   Where to put the pointer of a new counter.
    6796                 :            :  * @param[in] age
    6797                 :            :  *   Whether the pool is for counter that was allocated for aging.
    6798                 :            :  *
    6799                 :            :  * @return
    6800                 :            :  *   The counter pool pointer and @p cnt_free is set on success,
    6801                 :            :  *   NULL otherwise and rte_errno is set.
    6802                 :            :  */
    6803                 :            : static struct mlx5_flow_counter_pool *
    6804                 :          0 : flow_dv_counter_pool_prepare(struct rte_eth_dev *dev,
    6805                 :            :                              struct mlx5_flow_counter **cnt_free,
    6806                 :            :                              uint32_t age)
    6807                 :            : {
    6808                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    6809                 :          0 :         struct mlx5_flow_counter_mng *cmng = &priv->sh->sws_cmng;
    6810                 :            :         struct mlx5_flow_counter_pool *pool;
    6811                 :            :         struct mlx5_counters tmp_tq;
    6812                 :            :         struct mlx5_devx_obj *dcs = NULL;
    6813                 :            :         struct mlx5_flow_counter *cnt;
    6814                 :          0 :         enum mlx5_counter_type cnt_type =
    6815                 :          0 :                         age ? MLX5_COUNTER_TYPE_AGE : MLX5_COUNTER_TYPE_ORIGIN;
    6816                 :          0 :         bool fallback = priv->sh->sws_cmng.counter_fallback;
    6817                 :            :         uint32_t i;
    6818                 :            : 
    6819         [ #  # ]:          0 :         if (fallback) {
    6820                 :            :                 /* bulk_bitmap must be 0 for single counter allocation. */
    6821                 :          0 :                 dcs = mlx5_devx_cmd_flow_counter_alloc(priv->sh->cdev->ctx, 0);
    6822         [ #  # ]:          0 :                 if (!dcs)
    6823                 :            :                         return NULL;
    6824                 :          0 :                 pool = flow_dv_find_pool_by_id(cmng, dcs->id);
    6825         [ #  # ]:          0 :                 if (!pool) {
    6826                 :          0 :                         pool = flow_dv_pool_create(dev, dcs, age);
    6827         [ #  # ]:          0 :                         if (!pool) {
    6828                 :          0 :                                 mlx5_devx_cmd_destroy(dcs);
    6829                 :          0 :                                 return NULL;
    6830                 :            :                         }
    6831                 :            :                 }
    6832                 :          0 :                 i = dcs->id % MLX5_COUNTERS_PER_POOL;
    6833         [ #  # ]:          0 :                 cnt = MLX5_POOL_GET_CNT(pool, i);
    6834                 :          0 :                 cnt->pool = pool;
    6835                 :          0 :                 cnt->dcs_when_free = dcs;
    6836                 :          0 :                 *cnt_free = cnt;
    6837                 :          0 :                 return pool;
    6838                 :            :         }
    6839                 :          0 :         dcs = mlx5_devx_cmd_flow_counter_alloc(priv->sh->cdev->ctx, 0x4);
    6840         [ #  # ]:          0 :         if (!dcs) {
    6841                 :          0 :                 rte_errno = ENODATA;
    6842                 :          0 :                 return NULL;
    6843                 :            :         }
    6844                 :          0 :         pool = flow_dv_pool_create(dev, dcs, age);
    6845         [ #  # ]:          0 :         if (!pool) {
    6846                 :          0 :                 mlx5_devx_cmd_destroy(dcs);
    6847                 :          0 :                 return NULL;
    6848                 :            :         }
    6849                 :          0 :         TAILQ_INIT(&tmp_tq);
    6850         [ #  # ]:          0 :         for (i = 1; i < MLX5_COUNTERS_PER_POOL; ++i) {
    6851         [ #  # ]:          0 :                 cnt = MLX5_POOL_GET_CNT(pool, i);
    6852                 :          0 :                 cnt->pool = pool;
    6853         [ #  # ]:          0 :                 TAILQ_INSERT_HEAD(&tmp_tq, cnt, next);
    6854                 :            :         }
    6855                 :          0 :         rte_spinlock_lock(&cmng->csl[cnt_type]);
    6856         [ #  # ]:          0 :         TAILQ_CONCAT(&cmng->counters[cnt_type], &tmp_tq, next);
    6857                 :            :         rte_spinlock_unlock(&cmng->csl[cnt_type]);
    6858                 :          0 :         *cnt_free = MLX5_POOL_GET_CNT(pool, 0);
    6859                 :          0 :         (*cnt_free)->pool = pool;
    6860                 :          0 :         return pool;
    6861                 :            : }
    6862                 :            : 
    6863                 :            : /**
    6864                 :            :  * Allocate a flow counter.
    6865                 :            :  *
    6866                 :            :  * @param[in] dev
    6867                 :            :  *   Pointer to the Ethernet device structure.
    6868                 :            :  * @param[in] age
    6869                 :            :  *   Whether the counter was allocated for aging.
    6870                 :            :  *
    6871                 :            :  * @return
    6872                 :            :  *   Index to flow counter on success, 0 otherwise and rte_errno is set.
    6873                 :            :  */
    6874                 :            : static uint32_t
    6875                 :          0 : flow_dv_counter_alloc(struct rte_eth_dev *dev, uint32_t age)
    6876                 :            : {
    6877                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    6878                 :            :         struct mlx5_flow_counter_pool *pool = NULL;
    6879                 :          0 :         struct mlx5_flow_counter *cnt_free = NULL;
    6880                 :          0 :         bool fallback = priv->sh->sws_cmng.counter_fallback;
    6881                 :            :         struct mlx5_flow_counter_mng *cmng = &priv->sh->sws_cmng;
    6882                 :          0 :         enum mlx5_counter_type cnt_type =
    6883                 :          0 :                         age ? MLX5_COUNTER_TYPE_AGE : MLX5_COUNTER_TYPE_ORIGIN;
    6884                 :            :         uint32_t cnt_idx;
    6885                 :            : 
    6886         [ #  # ]:          0 :         if (!priv->sh->cdev->config.devx) {
    6887                 :          0 :                 rte_errno = ENOTSUP;
    6888                 :          0 :                 return 0;
    6889                 :            :         }
    6890                 :            :         /* Get free counters from container. */
    6891                 :          0 :         rte_spinlock_lock(&cmng->csl[cnt_type]);
    6892                 :          0 :         cnt_free = TAILQ_FIRST(&cmng->counters[cnt_type]);
    6893         [ #  # ]:          0 :         if (cnt_free)
    6894         [ #  # ]:          0 :                 TAILQ_REMOVE(&cmng->counters[cnt_type], cnt_free, next);
    6895                 :            :         rte_spinlock_unlock(&cmng->csl[cnt_type]);
    6896   [ #  #  #  # ]:          0 :         if (!cnt_free && !flow_dv_counter_pool_prepare(dev, &cnt_free, age))
    6897                 :          0 :                 goto err;
    6898                 :          0 :         pool = cnt_free->pool;
    6899         [ #  # ]:          0 :         if (fallback)
    6900                 :          0 :                 cnt_free->dcs_when_active = cnt_free->dcs_when_free;
    6901                 :            :         /* Create a DV counter action only in the first time usage. */
    6902         [ #  # ]:          0 :         if (!cnt_free->action) {
    6903                 :            :                 uint16_t offset;
    6904                 :            :                 struct mlx5_devx_obj *dcs;
    6905                 :            :                 int ret;
    6906                 :            : 
    6907         [ #  # ]:          0 :                 if (!fallback) {
    6908         [ #  # ]:          0 :                         offset = MLX5_CNT_ARRAY_IDX(pool, cnt_free);
    6909                 :          0 :                         dcs = pool->min_dcs;
    6910                 :            :                 } else {
    6911                 :            :                         offset = 0;
    6912                 :          0 :                         dcs = cnt_free->dcs_when_free;
    6913                 :            :                 }
    6914                 :          0 :                 ret = mlx5_flow_os_create_flow_action_count(dcs->obj, offset,
    6915                 :            :                                                             &cnt_free->action);
    6916                 :            :                 if (ret) {
    6917                 :          0 :                         rte_errno = errno;
    6918                 :          0 :                         goto err;
    6919                 :            :                 }
    6920                 :            :         }
    6921         [ #  # ]:          0 :         cnt_idx = MLX5_MAKE_CNT_IDX(pool->index,
    6922                 :            :                                 MLX5_CNT_ARRAY_IDX(pool, cnt_free));
    6923                 :            :         /* Update the counter reset values. */
    6924         [ #  # ]:          0 :         if (_flow_dv_query_count(dev, cnt_idx, &cnt_free->hits,
    6925                 :            :                                  &cnt_free->bytes))
    6926                 :          0 :                 goto err;
    6927   [ #  #  #  # ]:          0 :         if (!fallback && !priv->sh->sws_cmng.query_thread_on)
    6928                 :            :                 /* Start the asynchronous batch query by the host thread. */
    6929                 :          0 :                 mlx5_set_query_alarm(priv->sh);
    6930                 :            :         /*
    6931                 :            :          * When the count action isn't shared (by ID), shared_info field is
    6932                 :            :          * used for indirect action API's refcnt.
    6933                 :            :          * When the counter action is not shared neither by ID nor by indirect
    6934                 :            :          * action API, shared info must be 1.
    6935                 :            :          */
    6936                 :          0 :         cnt_free->shared_info.refcnt = 1;
    6937                 :          0 :         return cnt_idx;
    6938                 :          0 : err:
    6939         [ #  # ]:          0 :         if (cnt_free) {
    6940                 :          0 :                 cnt_free->pool = pool;
    6941         [ #  # ]:          0 :                 if (fallback)
    6942                 :          0 :                         cnt_free->dcs_when_free = cnt_free->dcs_when_active;
    6943                 :            :                 rte_spinlock_lock(&cmng->csl[cnt_type]);
    6944                 :          0 :                 TAILQ_INSERT_TAIL(&cmng->counters[cnt_type], cnt_free, next);
    6945                 :            :                 rte_spinlock_unlock(&cmng->csl[cnt_type]);
    6946                 :            :         }
    6947                 :            :         return 0;
    6948                 :            : }
    6949                 :            : 
    6950                 :            : /**
    6951                 :            :  * Get age param from counter index.
    6952                 :            :  *
    6953                 :            :  * @param[in] dev
    6954                 :            :  *   Pointer to the Ethernet device structure.
    6955                 :            :  * @param[in] counter
    6956                 :            :  *   Index to the counter handler.
    6957                 :            :  *
    6958                 :            :  * @return
    6959                 :            :  *   The aging parameter specified for the counter index.
    6960                 :            :  */
    6961                 :            : static struct mlx5_age_param*
    6962                 :            : flow_dv_counter_idx_get_age(struct rte_eth_dev *dev,
    6963                 :            :                                 uint32_t counter)
    6964                 :            : {
    6965                 :            :         struct mlx5_flow_counter *cnt;
    6966                 :            :         struct mlx5_flow_counter_pool *pool = NULL;
    6967                 :            : 
    6968                 :            :         flow_dv_counter_get_by_idx(dev, counter, &pool);
    6969                 :            :         counter = (counter - 1) % MLX5_COUNTERS_PER_POOL;
    6970                 :            :         cnt = MLX5_POOL_GET_CNT(pool, counter);
    6971                 :          0 :         return MLX5_CNT_TO_AGE(cnt);
    6972                 :            : }
    6973                 :            : 
    6974                 :            : /**
    6975                 :            :  * Remove a flow counter from aged counter list.
    6976                 :            :  *
    6977                 :            :  * @param[in] dev
    6978                 :            :  *   Pointer to the Ethernet device structure.
    6979                 :            :  * @param[in] counter
    6980                 :            :  *   Index to the counter handler.
    6981                 :            :  * @param[in] cnt
    6982                 :            :  *   Pointer to the counter handler.
    6983                 :            :  */
    6984                 :            : static void
    6985                 :          0 : flow_dv_counter_remove_from_age(struct rte_eth_dev *dev,
    6986                 :            :                                 uint32_t counter, struct mlx5_flow_counter *cnt)
    6987                 :            : {
    6988                 :            :         struct mlx5_age_info *age_info;
    6989                 :            :         struct mlx5_age_param *age_param;
    6990                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    6991                 :            :         uint16_t expected = AGE_CANDIDATE;
    6992                 :            : 
    6993         [ #  # ]:          0 :         age_info = GET_PORT_AGE_INFO(priv);
    6994                 :            :         age_param = flow_dv_counter_idx_get_age(dev, counter);
    6995         [ #  # ]:          0 :         if (!__atomic_compare_exchange_n(&age_param->state, &expected,
    6996                 :            :                                          AGE_FREE, false, __ATOMIC_RELAXED,
    6997                 :            :                                          __ATOMIC_RELAXED)) {
    6998                 :            :                 /**
    6999                 :            :                  * We need the lock even it is age timeout,
    7000                 :            :                  * since counter may still in process.
    7001                 :            :                  */
    7002                 :          0 :                 rte_spinlock_lock(&age_info->aged_sl);
    7003         [ #  # ]:          0 :                 TAILQ_REMOVE(&age_info->aged_counters, cnt, next);
    7004                 :            :                 rte_spinlock_unlock(&age_info->aged_sl);
    7005                 :          0 :                 __atomic_store_n(&age_param->state, AGE_FREE, __ATOMIC_RELAXED);
    7006                 :            :         }
    7007                 :          0 : }
    7008                 :            : 
    7009                 :            : /**
    7010                 :            :  * Release a flow counter.
    7011                 :            :  *
    7012                 :            :  * @param[in] dev
    7013                 :            :  *   Pointer to the Ethernet device structure.
    7014                 :            :  * @param[in] counter
    7015                 :            :  *   Index to the counter handler.
    7016                 :            :  */
    7017                 :            : static void
    7018                 :          0 : flow_dv_counter_free(struct rte_eth_dev *dev, uint32_t counter)
    7019                 :            : {
    7020                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    7021                 :            :         struct mlx5_flow_counter_pool *pool = NULL;
    7022                 :            :         struct mlx5_flow_counter *cnt;
    7023                 :            :         enum mlx5_counter_type cnt_type;
    7024                 :            : 
    7025         [ #  # ]:          0 :         if (!counter)
    7026                 :            :                 return;
    7027                 :            :         cnt = flow_dv_counter_get_by_idx(dev, counter, &pool);
    7028                 :            :         MLX5_ASSERT(pool);
    7029         [ #  # ]:          0 :         if (pool->is_aged) {
    7030                 :          0 :                 flow_dv_counter_remove_from_age(dev, counter, cnt);
    7031                 :            :         } else {
    7032                 :            :                 /*
    7033                 :            :                  * If the counter action is shared by indirect action API,
    7034                 :            :                  * the atomic function reduces its references counter.
    7035                 :            :                  * If after the reduction the action is still referenced, the
    7036                 :            :                  * function returns here and does not release it.
    7037                 :            :                  * When the counter action is not shared by
    7038                 :            :                  * indirect action API, shared info is 1 before the reduction,
    7039                 :            :                  * so this condition is failed and function doesn't return here.
    7040                 :            :                  */
    7041         [ #  # ]:          0 :                 if (__atomic_fetch_sub(&cnt->shared_info.refcnt, 1,
    7042                 :            :                                        __ATOMIC_RELAXED) - 1)
    7043                 :            :                         return;
    7044                 :            :         }
    7045                 :          0 :         cnt->pool = pool;
    7046                 :            :         /*
    7047                 :            :          * Put the counter back to list to be updated in none fallback mode.
    7048                 :            :          * Currently, we are using two list alternately, while one is in query,
    7049                 :            :          * add the freed counter to the other list based on the pool query_gen
    7050                 :            :          * value. After query finishes, add counter the list to the global
    7051                 :            :          * container counter list. The list changes while query starts. In
    7052                 :            :          * this case, lock will not be needed as query callback and release
    7053                 :            :          * function both operate with the different list.
    7054                 :            :          */
    7055         [ #  # ]:          0 :         if (!priv->sh->sws_cmng.counter_fallback) {
    7056                 :          0 :                 rte_spinlock_lock(&pool->csl);
    7057                 :          0 :                 TAILQ_INSERT_TAIL(&pool->counters[pool->query_gen], cnt, next);
    7058                 :            :                 rte_spinlock_unlock(&pool->csl);
    7059                 :            :         } else {
    7060                 :          0 :                 cnt->dcs_when_free = cnt->dcs_when_active;
    7061                 :          0 :                 cnt_type = pool->is_aged ? MLX5_COUNTER_TYPE_AGE :
    7062                 :            :                                            MLX5_COUNTER_TYPE_ORIGIN;
    7063                 :          0 :                 rte_spinlock_lock(&priv->sh->sws_cmng.csl[cnt_type]);
    7064                 :          0 :                 TAILQ_INSERT_TAIL(&priv->sh->sws_cmng.counters[cnt_type],
    7065                 :            :                                   cnt, next);
    7066                 :          0 :                 rte_spinlock_unlock(&priv->sh->sws_cmng.csl[cnt_type]);
    7067                 :            :         }
    7068                 :            : }
    7069                 :            : 
    7070                 :            : /**
    7071                 :            :  * Resize a meter id container.
    7072                 :            :  *
    7073                 :            :  * @param[in] dev
    7074                 :            :  *   Pointer to the Ethernet device structure.
    7075                 :            :  *
    7076                 :            :  * @return
    7077                 :            :  *   0 on success, otherwise negative errno value and rte_errno is set.
    7078                 :            :  */
    7079                 :            : static int
    7080                 :          0 : flow_dv_mtr_container_resize(struct rte_eth_dev *dev)
    7081                 :            : {
    7082                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    7083                 :            :         struct mlx5_aso_mtr_pools_mng *pools_mng =
    7084                 :          0 :                                 &priv->sh->mtrmng->pools_mng;
    7085                 :          0 :         void *old_pools = pools_mng->pools;
    7086                 :          0 :         uint32_t resize = pools_mng->n + MLX5_MTRS_CONTAINER_RESIZE;
    7087                 :          0 :         uint32_t mem_size = sizeof(struct mlx5_aso_mtr_pool *) * resize;
    7088                 :          0 :         void *pools = mlx5_malloc(MLX5_MEM_ZERO, mem_size, 0, SOCKET_ID_ANY);
    7089                 :            : 
    7090         [ #  # ]:          0 :         if (!pools) {
    7091                 :          0 :                 rte_errno = ENOMEM;
    7092                 :          0 :                 return -ENOMEM;
    7093                 :            :         }
    7094         [ #  # ]:          0 :         if (!pools_mng->n)
    7095         [ #  # ]:          0 :                 if (mlx5_aso_queue_init(priv->sh, ASO_OPC_MOD_POLICER, 1)) {
    7096                 :          0 :                         mlx5_free(pools);
    7097                 :          0 :                         return -ENOMEM;
    7098                 :            :                 }
    7099         [ #  # ]:          0 :         if (old_pools)
    7100                 :          0 :                 memcpy(pools, old_pools, pools_mng->n *
    7101                 :            :                                        sizeof(struct mlx5_aso_mtr_pool *));
    7102                 :          0 :         pools_mng->n = resize;
    7103                 :          0 :         pools_mng->pools = pools;
    7104         [ #  # ]:          0 :         if (old_pools)
    7105                 :          0 :                 mlx5_free(old_pools);
    7106                 :            :         return 0;
    7107                 :            : }
    7108                 :            : 
    7109                 :            : /**
    7110                 :            :  * Prepare a new meter and/or a new meter pool.
    7111                 :            :  *
    7112                 :            :  * @param[in] dev
    7113                 :            :  *   Pointer to the Ethernet device structure.
    7114                 :            :  * @param[out] mtr_free
    7115                 :            :  *   Where to put the pointer of a new meter.g.
    7116                 :            :  *
    7117                 :            :  * @return
    7118                 :            :  *   The meter pool pointer and @mtr_free is set on success,
    7119                 :            :  *   NULL otherwise and rte_errno is set.
    7120                 :            :  */
    7121                 :            : static struct mlx5_aso_mtr_pool *
    7122                 :          0 : flow_dv_mtr_pool_create(struct rte_eth_dev *dev, struct mlx5_aso_mtr **mtr_free)
    7123                 :            : {
    7124                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    7125                 :          0 :         struct mlx5_aso_mtr_pools_mng *pools_mng = &priv->sh->mtrmng->pools_mng;
    7126                 :            :         struct mlx5_aso_mtr_pool *pool = NULL;
    7127                 :            :         struct mlx5_devx_obj *dcs = NULL;
    7128                 :            :         uint32_t i;
    7129                 :            :         uint32_t log_obj_size;
    7130                 :            : 
    7131                 :            :         log_obj_size = rte_log2_u32(MLX5_ASO_MTRS_PER_POOL >> 1);
    7132                 :          0 :         dcs = mlx5_devx_cmd_create_flow_meter_aso_obj(priv->sh->cdev->ctx,
    7133                 :          0 :                                                       priv->sh->cdev->pdn,
    7134                 :            :                                                       log_obj_size);
    7135         [ #  # ]:          0 :         if (!dcs) {
    7136                 :          0 :                 rte_errno = ENODATA;
    7137                 :          0 :                 return NULL;
    7138                 :            :         }
    7139                 :          0 :         pool = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*pool), 0, SOCKET_ID_ANY);
    7140         [ #  # ]:          0 :         if (!pool) {
    7141                 :          0 :                 rte_errno = ENOMEM;
    7142                 :          0 :                 claim_zero(mlx5_devx_cmd_destroy(dcs));
    7143                 :          0 :                 return NULL;
    7144                 :            :         }
    7145                 :          0 :         pool->devx_obj = dcs;
    7146                 :          0 :         rte_rwlock_write_lock(&pools_mng->resize_mtrwl);
    7147                 :          0 :         pool->index = pools_mng->n_valid;
    7148   [ #  #  #  # ]:          0 :         if (pool->index == pools_mng->n && flow_dv_mtr_container_resize(dev)) {
    7149                 :          0 :                 mlx5_free(pool);
    7150                 :          0 :                 claim_zero(mlx5_devx_cmd_destroy(dcs));
    7151                 :            :                 rte_rwlock_write_unlock(&pools_mng->resize_mtrwl);
    7152                 :          0 :                 return NULL;
    7153                 :            :         }
    7154                 :          0 :         pools_mng->pools[pool->index] = pool;
    7155                 :          0 :         pools_mng->n_valid++;
    7156                 :            :         rte_rwlock_write_unlock(&pools_mng->resize_mtrwl);
    7157         [ #  # ]:          0 :         for (i = 1; i < MLX5_ASO_MTRS_PER_POOL; ++i) {
    7158                 :          0 :                 pool->mtrs[i].offset = i;
    7159         [ #  # ]:          0 :                 LIST_INSERT_HEAD(&pools_mng->meters, &pool->mtrs[i], next);
    7160                 :            :         }
    7161                 :          0 :         pool->mtrs[0].offset = 0;
    7162                 :          0 :         *mtr_free = &pool->mtrs[0];
    7163                 :          0 :         return pool;
    7164                 :            : }
    7165                 :            : 
    7166                 :            : /**
    7167                 :            :  * Release a flow meter into pool.
    7168                 :            :  *
    7169                 :            :  * @param[in] dev
    7170                 :            :  *   Pointer to the Ethernet device structure.
    7171                 :            :  * @param[in] mtr_idx
    7172                 :            :  *   Index to aso flow meter.
    7173                 :            :  */
    7174                 :            : static void
    7175                 :          0 : flow_dv_aso_mtr_release_to_pool(struct rte_eth_dev *dev, uint32_t mtr_idx)
    7176                 :            : {
    7177                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    7178                 :            :         struct mlx5_aso_mtr_pools_mng *pools_mng =
    7179                 :          0 :                                 &priv->sh->mtrmng->pools_mng;
    7180                 :          0 :         struct mlx5_aso_mtr *aso_mtr = mlx5_aso_meter_by_idx(priv, mtr_idx);
    7181                 :            : 
    7182                 :            :         MLX5_ASSERT(aso_mtr);
    7183                 :          0 :         rte_spinlock_lock(&pools_mng->mtrsl);
    7184         [ #  # ]:          0 :         memset(&aso_mtr->fm, 0, sizeof(struct mlx5_flow_meter_info));
    7185                 :          0 :         aso_mtr->state = ASO_METER_FREE;
    7186         [ #  # ]:          0 :         LIST_INSERT_HEAD(&pools_mng->meters, aso_mtr, next);
    7187                 :            :         rte_spinlock_unlock(&pools_mng->mtrsl);
    7188                 :          0 : }
    7189                 :            : 
    7190                 :            : /**
    7191                 :            :  * Allocate a aso flow meter.
    7192                 :            :  *
    7193                 :            :  * @param[in] dev
    7194                 :            :  *   Pointer to the Ethernet device structure.
    7195                 :            :  *
    7196                 :            :  * @return
    7197                 :            :  *   Index to aso flow meter on success, 0 otherwise and rte_errno is set.
    7198                 :            :  */
    7199                 :            : static uint32_t
    7200                 :          0 : flow_dv_mtr_alloc(struct rte_eth_dev *dev)
    7201                 :            : {
    7202                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    7203                 :          0 :         struct mlx5_aso_mtr *mtr_free = NULL;
    7204                 :            :         struct mlx5_aso_mtr_pools_mng *pools_mng =
    7205                 :          0 :                                 &priv->sh->mtrmng->pools_mng;
    7206                 :            :         struct mlx5_aso_mtr_pool *pool;
    7207                 :            :         uint32_t mtr_idx = 0;
    7208                 :            : 
    7209         [ #  # ]:          0 :         if (!priv->sh->cdev->config.devx) {
    7210                 :          0 :                 rte_errno = ENOTSUP;
    7211                 :          0 :                 return 0;
    7212                 :            :         }
    7213                 :            :         /* Allocate the flow meter memory. */
    7214                 :            :         /* Get free meters from management. */
    7215                 :          0 :         rte_spinlock_lock(&pools_mng->mtrsl);
    7216                 :          0 :         mtr_free = LIST_FIRST(&pools_mng->meters);
    7217         [ #  # ]:          0 :         if (mtr_free)
    7218         [ #  # ]:          0 :                 LIST_REMOVE(mtr_free, next);
    7219   [ #  #  #  # ]:          0 :         if (!mtr_free && !flow_dv_mtr_pool_create(dev, &mtr_free)) {
    7220                 :            :                 rte_spinlock_unlock(&pools_mng->mtrsl);
    7221                 :          0 :                 return 0;
    7222                 :            :         }
    7223                 :          0 :         mtr_free->state = ASO_METER_WAIT;
    7224                 :            :         rte_spinlock_unlock(&pools_mng->mtrsl);
    7225                 :          0 :         pool = container_of(mtr_free,
    7226                 :            :                         struct mlx5_aso_mtr_pool,
    7227                 :            :                         mtrs[mtr_free->offset]);
    7228                 :          0 :         mtr_idx = MLX5_MAKE_MTR_IDX(pool->index, mtr_free->offset);
    7229         [ #  # ]:          0 :         if (!mtr_free->fm.meter_action_g) {
    7230                 :            : #ifdef HAVE_MLX5_DR_CREATE_ACTION_ASO
    7231                 :            :                 struct rte_flow_error error;
    7232                 :            :                 uint8_t reg_id;
    7233                 :            : 
    7234                 :          0 :                 reg_id = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR, 0, &error);
    7235                 :          0 :                 mtr_free->fm.meter_action_g =
    7236                 :          0 :                         mlx5_glue->dv_create_flow_action_aso
    7237                 :          0 :                                                 (priv->sh->rx_domain,
    7238                 :          0 :                                                  pool->devx_obj->obj,
    7239                 :            :                                                  mtr_free->offset,
    7240                 :            :                                                  (1 << MLX5_FLOW_COLOR_GREEN),
    7241                 :          0 :                                                  reg_id - REG_C_0);
    7242                 :            : #endif /* HAVE_MLX5_DR_CREATE_ACTION_ASO */
    7243         [ #  # ]:          0 :                 if (!mtr_free->fm.meter_action_g) {
    7244                 :          0 :                         flow_dv_aso_mtr_release_to_pool(dev, mtr_idx);
    7245                 :          0 :                         return 0;
    7246                 :            :                 }
    7247                 :            :         }
    7248                 :            :         return mtr_idx;
    7249                 :            : }
    7250                 :            : 
    7251                 :            : /**
    7252                 :            :  * Verify the @p attributes will be correctly understood by the NIC and store
    7253                 :            :  * them in the @p flow if everything is correct.
    7254                 :            :  *
    7255                 :            :  * @param[in] dev
    7256                 :            :  *   Pointer to dev struct.
    7257                 :            :  * @param[in] attributes
    7258                 :            :  *   Pointer to flow attributes
    7259                 :            :  * @param[in] external
    7260                 :            :  *   This flow rule is created by request external to PMD.
    7261                 :            :  * @param[out] error
    7262                 :            :  *   Pointer to error structure.
    7263                 :            :  *
    7264                 :            :  * @return
    7265                 :            :  *   - 0 on success and non root table.
    7266                 :            :  *   - 1 on success and root table.
    7267                 :            :  *   - a negative errno value otherwise and rte_errno is set.
    7268                 :            :  */
    7269                 :            : static int
    7270                 :          0 : flow_dv_validate_attributes(struct rte_eth_dev *dev,
    7271                 :            :                             const struct mlx5_flow_tunnel *tunnel,
    7272                 :            :                             const struct rte_flow_attr *attributes,
    7273                 :            :                             const struct flow_grp_info *grp_info,
    7274                 :            :                             struct rte_flow_error *error)
    7275                 :            : {
    7276                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    7277                 :          0 :         uint32_t lowest_priority = mlx5_get_lowest_priority(dev, attributes);
    7278                 :            :         int ret = 0;
    7279                 :            : 
    7280                 :            : #ifndef HAVE_MLX5DV_DR
    7281                 :            :         RTE_SET_USED(tunnel);
    7282                 :            :         RTE_SET_USED(grp_info);
    7283                 :            :         if (attributes->group)
    7284                 :            :                 return rte_flow_error_set(error, ENOTSUP,
    7285                 :            :                                           RTE_FLOW_ERROR_TYPE_ATTR_GROUP,
    7286                 :            :                                           NULL,
    7287                 :            :                                           "groups are not supported");
    7288                 :            : #else
    7289                 :          0 :         uint32_t table = 0;
    7290                 :            : 
    7291                 :          0 :         ret = mlx5_flow_group_to_table(dev, tunnel, attributes->group, &table,
    7292                 :            :                                        grp_info, error);
    7293         [ #  # ]:          0 :         if (ret)
    7294                 :            :                 return ret;
    7295         [ #  # ]:          0 :         if (!table)
    7296                 :            :                 ret = MLX5DV_DR_ACTION_FLAGS_ROOT_LEVEL;
    7297                 :            : #endif
    7298   [ #  #  #  # ]:          0 :         if (attributes->priority != MLX5_FLOW_LOWEST_PRIO_INDICATOR &&
    7299                 :            :             attributes->priority > lowest_priority)
    7300                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    7301                 :            :                                           RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY,
    7302                 :            :                                           NULL,
    7303                 :            :                                           "priority out of range");
    7304   [ #  #  #  # ]:          0 :         if (attributes->transfer && !priv->sh->config.dv_esw_en)
    7305                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    7306                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    7307                 :            :                                           "E-Switch dr is not supported");
    7308         [ #  # ]:          0 :         if (attributes->ingress + attributes->egress + attributes->transfer != 1) {
    7309                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    7310                 :            :                                           RTE_FLOW_ERROR_TYPE_ATTR, NULL,
    7311                 :            :                                           "must specify exactly one of "
    7312                 :            :                                           "ingress, egress or transfer");
    7313                 :            :         }
    7314                 :            :         return ret;
    7315                 :            : }
    7316                 :            : 
    7317                 :            : static int
    7318                 :          0 : validate_integrity_bits(const struct rte_flow_item_integrity *mask,
    7319                 :            :                         int64_t pattern_flags, uint64_t l3_flags,
    7320                 :            :                         uint64_t l4_flags, uint64_t ip4_flag,
    7321                 :            :                         struct rte_flow_error *error)
    7322                 :            : {
    7323   [ #  #  #  # ]:          0 :         if (mask->l3_ok && !(pattern_flags & l3_flags))
    7324                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    7325                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM,
    7326                 :            :                                           NULL, "missing L3 protocol");
    7327                 :            : 
    7328   [ #  #  #  # ]:          0 :         if (mask->ipv4_csum_ok && !(pattern_flags & ip4_flag))
    7329                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    7330                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM,
    7331                 :            :                                           NULL, "missing IPv4 protocol");
    7332                 :            : 
    7333   [ #  #  #  # ]:          0 :         if ((mask->l4_ok || mask->l4_csum_ok) && !(pattern_flags & l4_flags))
    7334                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    7335                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM,
    7336                 :            :                                           NULL, "missing L4 protocol");
    7337                 :            : 
    7338                 :            :         return 0;
    7339                 :            : }
    7340                 :            : 
    7341                 :            : static int
    7342                 :          0 : flow_dv_validate_item_integrity_post(const struct
    7343                 :            :                                      rte_flow_item *integrity_items[2],
    7344                 :            :                                      int64_t pattern_flags,
    7345                 :            :                                      struct rte_flow_error *error)
    7346                 :            : {
    7347                 :            :         const struct rte_flow_item_integrity *mask;
    7348                 :            :         int ret;
    7349                 :            : 
    7350         [ #  # ]:          0 :         if (pattern_flags & MLX5_FLOW_ITEM_OUTER_INTEGRITY) {
    7351                 :          0 :                 mask = (typeof(mask))integrity_items[0]->mask;
    7352                 :          0 :                 ret = validate_integrity_bits(mask, pattern_flags,
    7353                 :            :                                               MLX5_FLOW_LAYER_OUTER_L3,
    7354                 :            :                                               MLX5_FLOW_LAYER_OUTER_L4,
    7355                 :            :                                               MLX5_FLOW_LAYER_OUTER_L3_IPV4,
    7356                 :            :                                               error);
    7357         [ #  # ]:          0 :                 if (ret)
    7358                 :            :                         return ret;
    7359                 :            :         }
    7360         [ #  # ]:          0 :         if (pattern_flags & MLX5_FLOW_ITEM_INNER_INTEGRITY) {
    7361                 :          0 :                 mask = (typeof(mask))integrity_items[1]->mask;
    7362                 :          0 :                 ret = validate_integrity_bits(mask, pattern_flags,
    7363                 :            :                                               MLX5_FLOW_LAYER_INNER_L3,
    7364                 :            :                                               MLX5_FLOW_LAYER_INNER_L4,
    7365                 :            :                                               MLX5_FLOW_LAYER_INNER_L3_IPV4,
    7366                 :            :                                               error);
    7367         [ #  # ]:          0 :                 if (ret)
    7368                 :          0 :                         return ret;
    7369                 :            :         }
    7370                 :            :         return 0;
    7371                 :            : }
    7372                 :            : 
    7373                 :            : static int
    7374                 :          0 : flow_dv_validate_item_integrity(struct rte_eth_dev *dev,
    7375                 :            :                                 const struct rte_flow_item *integrity_item,
    7376                 :            :                                 uint64_t pattern_flags, uint64_t *last_item,
    7377                 :            :                                 const struct rte_flow_item *integrity_items[2],
    7378                 :            :                                 struct rte_flow_error *error)
    7379                 :            : {
    7380                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    7381                 :          0 :         const struct rte_flow_item_integrity *mask = (typeof(mask))
    7382                 :            :                                                      integrity_item->mask;
    7383                 :          0 :         const struct rte_flow_item_integrity *spec = (typeof(spec))
    7384                 :            :                                                      integrity_item->spec;
    7385                 :            : 
    7386         [ #  # ]:          0 :         if (!priv->sh->cdev->config.hca_attr.pkt_integrity_match)
    7387                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    7388                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM,
    7389                 :            :                                           integrity_item,
    7390                 :            :                                           "packet integrity integrity_item not supported");
    7391         [ #  # ]:          0 :         if (!spec)
    7392                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    7393                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM,
    7394                 :            :                                           integrity_item,
    7395                 :            :                                           "no spec for integrity item");
    7396         [ #  # ]:          0 :         if (!mask)
    7397                 :            :                 mask = &rte_flow_item_integrity_mask;
    7398         [ #  # ]:          0 :         if (!mlx5_validate_integrity_item(mask))
    7399                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    7400                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM,
    7401                 :            :                                           integrity_item,
    7402                 :            :                                           "unsupported integrity filter");
    7403   [ #  #  #  # ]:          0 :         if ((mask->l3_ok & !spec->l3_ok) || (mask->l4_ok & !spec->l4_ok) ||
    7404         [ #  # ]:          0 :                 (mask->ipv4_csum_ok & !spec->ipv4_csum_ok) ||
    7405         [ #  # ]:          0 :                 (mask->l4_csum_ok & !spec->l4_csum_ok))
    7406                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    7407                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM,
    7408                 :            :                                           NULL, "negative integrity flow is not supported");
    7409         [ #  # ]:          0 :         if (spec->level > 1) {
    7410         [ #  # ]:          0 :                 if (pattern_flags & MLX5_FLOW_ITEM_INNER_INTEGRITY)
    7411                 :          0 :                         return rte_flow_error_set
    7412                 :            :                                 (error, ENOTSUP,
    7413                 :            :                                  RTE_FLOW_ERROR_TYPE_ITEM,
    7414                 :            :                                  NULL, "multiple inner integrity items not supported");
    7415                 :          0 :                 integrity_items[1] = integrity_item;
    7416                 :          0 :                 *last_item |= MLX5_FLOW_ITEM_INNER_INTEGRITY;
    7417                 :            :         } else {
    7418         [ #  # ]:          0 :                 if (pattern_flags & MLX5_FLOW_ITEM_OUTER_INTEGRITY)
    7419                 :          0 :                         return rte_flow_error_set
    7420                 :            :                                 (error, ENOTSUP,
    7421                 :            :                                  RTE_FLOW_ERROR_TYPE_ITEM,
    7422                 :            :                                  NULL, "multiple outer integrity items not supported");
    7423                 :          0 :                 integrity_items[0] = integrity_item;
    7424                 :          0 :                 *last_item |= MLX5_FLOW_ITEM_OUTER_INTEGRITY;
    7425                 :            :         }
    7426                 :            :         return 0;
    7427                 :            : }
    7428                 :            : 
    7429                 :            : static int
    7430                 :          0 : flow_dv_validate_item_flex(struct rte_eth_dev *dev,
    7431                 :            :                            const struct rte_flow_item *item,
    7432                 :            :                            uint64_t item_flags,
    7433                 :            :                            uint64_t *last_item,
    7434                 :            :                            bool is_inner,
    7435                 :            :                            struct rte_flow_error *error)
    7436                 :            : {
    7437                 :          0 :         const struct rte_flow_item_flex *flow_spec = item->spec;
    7438                 :          0 :         const struct rte_flow_item_flex *flow_mask = item->mask;
    7439                 :            :         struct mlx5_flex_item *flex;
    7440                 :            : 
    7441         [ #  # ]:          0 :         if (!flow_spec)
    7442                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    7443                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    7444                 :            :                                           "flex flow item spec cannot be NULL");
    7445         [ #  # ]:          0 :         if (!flow_mask)
    7446                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    7447                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    7448                 :            :                                           "flex flow item mask cannot be NULL");
    7449         [ #  # ]:          0 :         if (item->last)
    7450                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    7451                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    7452                 :            :                                           "flex flow item last not supported");
    7453         [ #  # ]:          0 :         if (mlx5_flex_acquire_index(dev, flow_spec->handle, false) < 0)
    7454                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    7455                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    7456                 :            :                                           "invalid flex flow item handle");
    7457                 :          0 :         flex = (struct mlx5_flex_item *)flow_spec->handle;
    7458   [ #  #  #  #  :          0 :         switch (flex->tunnel_mode) {
                   #  # ]
    7459                 :          0 :         case FLEX_TUNNEL_MODE_SINGLE:
    7460         [ #  # ]:          0 :                 if (item_flags &
    7461                 :            :                     (MLX5_FLOW_ITEM_OUTER_FLEX | MLX5_FLOW_ITEM_INNER_FLEX))
    7462                 :          0 :                         rte_flow_error_set(error, EINVAL,
    7463                 :            :                                            RTE_FLOW_ERROR_TYPE_ITEM,
    7464                 :            :                                            NULL, "multiple flex items not supported");
    7465                 :            :                 break;
    7466                 :          0 :         case FLEX_TUNNEL_MODE_OUTER:
    7467         [ #  # ]:          0 :                 if (is_inner)
    7468                 :          0 :                         rte_flow_error_set(error, EINVAL,
    7469                 :            :                                            RTE_FLOW_ERROR_TYPE_ITEM,
    7470                 :            :                                            NULL, "inner flex item was not configured");
    7471         [ #  # ]:          0 :                 if (item_flags & MLX5_FLOW_ITEM_OUTER_FLEX)
    7472                 :          0 :                         rte_flow_error_set(error, ENOTSUP,
    7473                 :            :                                            RTE_FLOW_ERROR_TYPE_ITEM,
    7474                 :            :                                            NULL, "multiple flex items not supported");
    7475                 :            :                 break;
    7476                 :          0 :         case FLEX_TUNNEL_MODE_INNER:
    7477         [ #  # ]:          0 :                 if (!is_inner)
    7478                 :          0 :                         rte_flow_error_set(error, EINVAL,
    7479                 :            :                                            RTE_FLOW_ERROR_TYPE_ITEM,
    7480                 :            :                                            NULL, "outer flex item was not configured");
    7481         [ #  # ]:          0 :                 if (item_flags & MLX5_FLOW_ITEM_INNER_FLEX)
    7482                 :          0 :                         rte_flow_error_set(error, EINVAL,
    7483                 :            :                                            RTE_FLOW_ERROR_TYPE_ITEM,
    7484                 :            :                                            NULL, "multiple flex items not supported");
    7485                 :            :                 break;
    7486                 :          0 :         case FLEX_TUNNEL_MODE_MULTI:
    7487   [ #  #  #  #  :          0 :                 if ((is_inner && (item_flags & MLX5_FLOW_ITEM_INNER_FLEX)) ||
                   #  # ]
    7488         [ #  # ]:          0 :                     (!is_inner && (item_flags & MLX5_FLOW_ITEM_OUTER_FLEX))) {
    7489                 :          0 :                         rte_flow_error_set(error, EINVAL,
    7490                 :            :                                            RTE_FLOW_ERROR_TYPE_ITEM,
    7491                 :            :                                            NULL, "multiple flex items not supported");
    7492                 :            :                 }
    7493                 :            :                 break;
    7494                 :          0 :         case FLEX_TUNNEL_MODE_TUNNEL:
    7495   [ #  #  #  # ]:          0 :                 if (is_inner || (item_flags & MLX5_FLOW_ITEM_FLEX_TUNNEL))
    7496                 :          0 :                         rte_flow_error_set(error, EINVAL,
    7497                 :            :                                            RTE_FLOW_ERROR_TYPE_ITEM,
    7498                 :            :                                            NULL, "multiple flex tunnel items not supported");
    7499                 :            :                 break;
    7500                 :          0 :         default:
    7501                 :          0 :                 rte_flow_error_set(error, EINVAL,
    7502                 :            :                                    RTE_FLOW_ERROR_TYPE_ITEM,
    7503                 :            :                                    NULL, "invalid flex item configuration");
    7504                 :            :         }
    7505                 :          0 :         *last_item = flex->tunnel_mode == FLEX_TUNNEL_MODE_TUNNEL ?
    7506         [ #  # ]:          0 :                      MLX5_FLOW_ITEM_FLEX_TUNNEL : is_inner ?
    7507         [ #  # ]:          0 :                      MLX5_FLOW_ITEM_INNER_FLEX : MLX5_FLOW_ITEM_OUTER_FLEX;
    7508                 :          0 :         return 0;
    7509                 :            : }
    7510                 :            : 
    7511                 :            : static __rte_always_inline uint8_t
    7512                 :            : mlx5_flow_l3_next_protocol(const struct rte_flow_item *l3_item,
    7513                 :            :                            enum MLX5_SET_MATCHER key_type)
    7514                 :            : {
    7515                 :            : #define MLX5_L3_NEXT_PROTOCOL(i, ms)                                            \
    7516                 :            :         ((i)->type == RTE_FLOW_ITEM_TYPE_IPV4 ?                                  \
    7517                 :            :         ((const struct rte_flow_item_ipv4 *)(i)->ms)->hdr.next_proto_id :       \
    7518                 :            :         (i)->type == RTE_FLOW_ITEM_TYPE_IPV6 ?                                  \
    7519                 :            :         ((const struct rte_flow_item_ipv6 *)(i)->ms)->hdr.proto :               \
    7520                 :            :         (i)->type == RTE_FLOW_ITEM_TYPE_IPV6_FRAG_EXT ?                         \
    7521                 :            :         ((const struct rte_flow_item_ipv6_frag_ext *)(i)->ms)->hdr.next_header :\
    7522                 :            :         0xff)
    7523                 :            : 
    7524                 :            :         uint8_t next_protocol;
    7525                 :            : 
    7526   [ #  #  #  #  :          0 :         if (l3_item->mask != NULL && l3_item->spec != NULL) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
    7527   [ #  #  #  #  :          0 :                 next_protocol = MLX5_L3_NEXT_PROTOCOL(l3_item, mask);
          #  #  #  #  #  
                #  #  # ]
    7528   [ #  #  #  #  :          0 :                 if (next_protocol)
          #  #  #  #  #  
                #  #  # ]
    7529   [ #  #  #  #  :          0 :                         next_protocol &= MLX5_L3_NEXT_PROTOCOL(l3_item, spec);
          #  #  #  #  #  
                #  #  # ]
    7530                 :            :                 else
    7531                 :            :                         next_protocol = 0xff;
    7532   [ #  #  #  #  :          0 :         } else if (key_type == MLX5_SET_MATCHER_HS_M && l3_item->mask != NULL) {
          #  #  #  #  #  
                #  #  # ]
    7533   [ #  #  #  #  :          0 :                 next_protocol =  MLX5_L3_NEXT_PROTOCOL(l3_item, mask);
                   #  # ]
    7534   [ #  #  #  #  :          0 :         } else if (key_type == MLX5_SET_MATCHER_HS_V && l3_item->spec != NULL) {
          #  #  #  #  #  
                #  #  # ]
    7535   [ #  #  #  #  :          0 :                 next_protocol =  MLX5_L3_NEXT_PROTOCOL(l3_item, spec);
                   #  # ]
    7536                 :            :         } else {
    7537                 :            :                 /* Reset for inner layer. */
    7538                 :            :                 next_protocol = 0xff;
    7539                 :            :         }
    7540                 :            :         return next_protocol;
    7541                 :            : 
    7542                 :            : #undef MLX5_L3_NEXT_PROTOCOL
    7543                 :            : }
    7544                 :            : 
    7545                 :            : /**
    7546                 :            :  * Validate IB BTH item.
    7547                 :            :  *
    7548                 :            :  * @param[in] dev
    7549                 :            :  *   Pointer to the rte_eth_dev structure.
    7550                 :            :  * @param[in] udp_dport
    7551                 :            :  *   UDP destination port
    7552                 :            :  * @param[in] item
    7553                 :            :  *   Item specification.
    7554                 :            :  * @param root
    7555                 :            :  *   Whether action is on root table.
    7556                 :            :  * @param[out] error
    7557                 :            :  *   Pointer to the error structure.
    7558                 :            :  *
    7559                 :            :  * @return
    7560                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    7561                 :            :  */
    7562                 :            : static int
    7563                 :          0 : mlx5_flow_validate_item_ib_bth(struct rte_eth_dev *dev,
    7564                 :            :                                uint16_t udp_dport,
    7565                 :            :                                const struct rte_flow_item *item,
    7566                 :            :                                bool root,
    7567                 :            :                                struct rte_flow_error *error)
    7568                 :            : {
    7569                 :          0 :         const struct rte_flow_item_ib_bth *mask = item->mask;
    7570                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    7571                 :            :         const struct rte_flow_item_ib_bth *valid_mask;
    7572                 :            :         int ret;
    7573                 :            : 
    7574                 :            :         valid_mask = &rte_flow_item_ib_bth_mask;
    7575         [ #  # ]:          0 :         if (udp_dport && udp_dport != MLX5_UDP_PORT_ROCEv2)
    7576                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    7577                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    7578                 :            :                                           "protocol filtering not compatible"
    7579                 :            :                                           " with UDP layer");
    7580   [ #  #  #  # ]:          0 :         if (mask && (mask->hdr.se || mask->hdr.m || mask->hdr.padcnt ||
    7581   [ #  #  #  # ]:          0 :                 mask->hdr.tver || mask->hdr.pkey || mask->hdr.f || mask->hdr.b ||
    7582         [ #  # ]:          0 :                 mask->hdr.rsvd0 || mask->hdr.a || mask->hdr.rsvd1 ||
    7583   [ #  #  #  #  :          0 :                 mask->hdr.psn[0] || mask->hdr.psn[1] || mask->hdr.psn[2]))
                   #  # ]
    7584                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    7585                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    7586                 :            :                                           "only opcode and dst_qp are supported");
    7587   [ #  #  #  # ]:          0 :         if (root || priv->sh->steering_format_version ==
    7588                 :            :                 MLX5_STEERING_LOGIC_FORMAT_CONNECTX_5)
    7589                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    7590                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM,
    7591                 :            :                                           item,
    7592                 :            :                                           "IB BTH item is not supported");
    7593         [ #  # ]:          0 :         if (!mask)
    7594                 :            :                 mask = &rte_flow_item_ib_bth_mask;
    7595                 :          0 :         ret = mlx5_flow_item_acceptable(item, (const uint8_t *)mask,
    7596                 :            :                                         (const uint8_t *)valid_mask,
    7597                 :            :                                         sizeof(struct rte_flow_item_ib_bth),
    7598                 :            :                                         MLX5_ITEM_RANGE_NOT_ACCEPTED, error);
    7599                 :            :         if (ret < 0)
    7600                 :            :                 return ret;
    7601                 :            :         return 0;
    7602                 :            : }
    7603                 :            : 
    7604                 :            : /**
    7605                 :            :  * Internal validation function. For validating both actions and items.
    7606                 :            :  *
    7607                 :            :  * @param[in] dev
    7608                 :            :  *   Pointer to the rte_eth_dev structure.
    7609                 :            :  * @param[in] attr
    7610                 :            :  *   Pointer to the flow attributes.
    7611                 :            :  * @param[in] items
    7612                 :            :  *   Pointer to the list of items.
    7613                 :            :  * @param[in] actions
    7614                 :            :  *   Pointer to the list of actions.
    7615                 :            :  * @param[in] external
    7616                 :            :  *   This flow rule is created by request external to PMD.
    7617                 :            :  * @param[in] hairpin
    7618                 :            :  *   Number of hairpin TX actions, 0 means classic flow.
    7619                 :            :  * @param[out] error
    7620                 :            :  *   Pointer to the error structure.
    7621                 :            :  *
    7622                 :            :  * @return
    7623                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    7624                 :            :  */
    7625                 :            : static int
    7626                 :          0 : flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
    7627                 :            :                  const struct rte_flow_item items[],
    7628                 :            :                  const struct rte_flow_action actions[],
    7629                 :            :                  bool external, int hairpin, struct rte_flow_error *error)
    7630                 :            : {
    7631                 :            :         int ret;
    7632                 :          0 :         uint64_t aso_mask, action_flags = 0;
    7633                 :          0 :         uint64_t item_flags = 0;
    7634                 :          0 :         uint64_t last_item = 0;
    7635                 :            :         uint8_t next_protocol = 0xff;
    7636                 :            :         uint16_t ether_type = 0;
    7637                 :          0 :         int actions_n = 0;
    7638                 :            :         uint8_t item_ipv6_proto = 0;
    7639                 :          0 :         int fdb_mirror = 0;
    7640                 :            :         int modify_after_mirror = 0;
    7641                 :            :         const struct rte_flow_item *geneve_item = NULL;
    7642                 :            :         const struct rte_flow_item *gre_item = NULL;
    7643                 :            :         const struct rte_flow_item *gtp_item = NULL;
    7644                 :            :         const struct rte_flow_action_raw_decap *decap;
    7645                 :            :         const struct rte_flow_action_raw_encap *encap;
    7646                 :            :         const struct rte_flow_action_rss *rss = NULL;
    7647                 :          0 :         const struct rte_flow_action_rss *sample_rss = NULL;
    7648                 :          0 :         const struct rte_flow_action_count *sample_count = NULL;
    7649                 :          0 :         const struct rte_flow_item_tcp nic_tcp_mask = {
    7650                 :            :                 .hdr = {
    7651                 :            :                         .tcp_flags = 0xFF,
    7652                 :            :                         .src_port = RTE_BE16(UINT16_MAX),
    7653                 :            :                         .dst_port = RTE_BE16(UINT16_MAX),
    7654                 :            :                 }
    7655                 :            :         };
    7656                 :          0 :         const struct rte_flow_item_ipv6 nic_ipv6_mask = {
    7657                 :            :                 .hdr = {
    7658                 :            :                         .src_addr =
    7659                 :            :                         "\xff\xff\xff\xff\xff\xff\xff\xff"
    7660                 :            :                         "\xff\xff\xff\xff\xff\xff\xff\xff",
    7661                 :            :                         .dst_addr =
    7662                 :            :                         "\xff\xff\xff\xff\xff\xff\xff\xff"
    7663                 :            :                         "\xff\xff\xff\xff\xff\xff\xff\xff",
    7664                 :            :                         .vtc_flow = RTE_BE32(0xffffffff),
    7665                 :            :                         .proto = 0xff,
    7666                 :            :                         .hop_limits = 0xff,
    7667                 :            :                 },
    7668                 :            :                 .has_frag_ext = 1,
    7669                 :            :         };
    7670                 :          0 :         const struct rte_flow_item_ecpri nic_ecpri_mask = {
    7671                 :            :                 .hdr = {
    7672                 :            :                         .common = {
    7673                 :            :                                 .u32 =
    7674                 :            :                                 RTE_BE32(((const struct rte_ecpri_common_hdr) {
    7675                 :            :                                         .type = 0xFF,
    7676                 :            :                                         }).u32),
    7677                 :            :                         },
    7678                 :            :                         .dummy[0] = 0xffffffff,
    7679                 :            :                 },
    7680                 :            :         };
    7681                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    7682                 :          0 :         struct mlx5_sh_config *dev_conf = &priv->sh->config;
    7683                 :            :         uint16_t queue_index = 0xFFFF;
    7684                 :            :         const struct rte_flow_item_vlan *vlan_m = NULL;
    7685                 :            :         uint32_t rw_act_num = 0;
    7686                 :            :         uint64_t is_root;
    7687                 :            :         const struct mlx5_flow_tunnel *tunnel;
    7688                 :            :         enum mlx5_tof_rule_type tof_rule_type;
    7689                 :          0 :         struct flow_grp_info grp_info = {
    7690                 :            :                 .external = !!external,
    7691                 :          0 :                 .transfer = !!attr->transfer,
    7692                 :          0 :                 .fdb_def_rule = !!priv->fdb_def_rule,
    7693                 :            :                 .std_tbl_fix = true,
    7694                 :            :         };
    7695                 :            :         const struct rte_eth_hairpin_conf *conf;
    7696                 :          0 :         const struct rte_flow_item *integrity_items[2] = {NULL, NULL};
    7697                 :            :         const struct rte_flow_item *port_id_item = NULL;
    7698                 :          0 :         bool def_policy = false;
    7699                 :            :         bool shared_count = false;
    7700                 :            :         uint16_t udp_dport = 0;
    7701                 :          0 :         uint32_t tag_id = 0, tag_bitmap = 0;
    7702                 :            :         const struct rte_flow_action_age *non_shared_age = NULL;
    7703                 :            :         const struct rte_flow_action_count *count = NULL;
    7704                 :            :         const struct rte_flow_action_port_id *port = NULL;
    7705                 :            :         const struct mlx5_rte_flow_item_tag *mlx5_tag;
    7706                 :          0 :         struct mlx5_priv *act_priv = NULL;
    7707                 :            :         int aso_after_sample = 0;
    7708                 :            :         struct mlx5_priv *port_priv = NULL;
    7709                 :          0 :         uint64_t sub_action_flags = 0;
    7710                 :          0 :         uint16_t sample_port_id = 0;
    7711                 :            :         uint16_t port_id = 0;
    7712                 :            : 
    7713         [ #  # ]:          0 :         if (items == NULL)
    7714                 :            :                 return -1;
    7715                 :            :         tunnel = is_tunnel_offload_active(dev) ?
    7716         [ #  # ]:          0 :                  mlx5_get_tof(items, actions, &tof_rule_type) : NULL;
    7717         [ #  # ]:          0 :         if (tunnel) {
    7718         [ #  # ]:          0 :                 if (!dev_conf->dv_flow_en)
    7719                 :          0 :                         return rte_flow_error_set
    7720                 :            :                                 (error, ENOTSUP,
    7721                 :            :                                  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    7722                 :            :                                  NULL, "tunnel offload requires DV flow interface");
    7723         [ #  # ]:          0 :                 if (priv->representor)
    7724                 :          0 :                         return rte_flow_error_set
    7725                 :            :                                 (error, ENOTSUP,
    7726                 :            :                                  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    7727                 :            :                                  NULL, "decap not supported for VF representor");
    7728         [ #  # ]:          0 :                 if (tof_rule_type == MLX5_TUNNEL_OFFLOAD_SET_RULE)
    7729                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_TUNNEL_SET;
    7730         [ #  # ]:          0 :                 else if (tof_rule_type == MLX5_TUNNEL_OFFLOAD_MATCH_RULE)
    7731                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_TUNNEL_MATCH |
    7732                 :            :                                         MLX5_FLOW_ACTION_DECAP;
    7733                 :          0 :                 grp_info.std_tbl_fix = tunnel_use_standard_attr_group_translate
    7734                 :            :                                         (dev, attr, tunnel, tof_rule_type);
    7735                 :            :         }
    7736                 :          0 :         ret = flow_dv_validate_attributes(dev, tunnel, attr, &grp_info, error);
    7737         [ #  # ]:          0 :         if (ret < 0)
    7738                 :            :                 return ret;
    7739                 :          0 :         is_root = (uint64_t)ret;
    7740         [ #  # ]:          0 :         for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {
    7741                 :            :                 enum mlx5_l3_tunnel_detection l3_tunnel_detection;
    7742                 :            :                 uint64_t l3_tunnel_flag;
    7743                 :          0 :                 int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL);
    7744                 :          0 :                 int type = items->type;
    7745                 :            : 
    7746                 :            :                 if (!mlx5_flow_os_item_supported(type))
    7747                 :            :                         return rte_flow_error_set(error, ENOTSUP,
    7748                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM,
    7749                 :            :                                                   NULL, "item not supported");
    7750   [ #  #  #  #  :          0 :                 switch (type) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    7751                 :            :                 case RTE_FLOW_ITEM_TYPE_VOID:
    7752                 :            :                         break;
    7753                 :          0 :                 case RTE_FLOW_ITEM_TYPE_ESP:
    7754                 :          0 :                         ret = mlx5_flow_os_validate_item_esp(items, item_flags,
    7755                 :            :                                                           next_protocol,
    7756                 :            :                                                           error);
    7757         [ #  # ]:          0 :                         if (ret < 0)
    7758                 :          0 :                                 return ret;
    7759                 :          0 :                         last_item = MLX5_FLOW_ITEM_ESP;
    7760                 :          0 :                         break;
    7761                 :          0 :                 case RTE_FLOW_ITEM_TYPE_PORT_ID:
    7762                 :          0 :                         ret = flow_dv_validate_item_port_id
    7763                 :            :                                         (dev, items, attr, item_flags, &act_priv, error);
    7764         [ #  # ]:          0 :                         if (ret < 0)
    7765                 :          0 :                                 return ret;
    7766                 :          0 :                         last_item = MLX5_FLOW_ITEM_PORT_ID;
    7767                 :            :                         port_id_item = items;
    7768                 :          0 :                         break;
    7769                 :          0 :                 case RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT:
    7770                 :            :                 case RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR:
    7771                 :          0 :                         ret = flow_dv_validate_item_represented_port
    7772                 :            :                                         (dev, items, attr, item_flags, &act_priv, error);
    7773         [ #  # ]:          0 :                         if (ret < 0)
    7774                 :          0 :                                 return ret;
    7775                 :          0 :                         last_item = MLX5_FLOW_ITEM_REPRESENTED_PORT;
    7776                 :            :                         port_id_item = items;
    7777                 :          0 :                         break;
    7778                 :          0 :                 case RTE_FLOW_ITEM_TYPE_ETH:
    7779                 :          0 :                         ret = mlx5_flow_validate_item_eth(items, item_flags,
    7780                 :            :                                                           true, error);
    7781         [ #  # ]:          0 :                         if (ret < 0)
    7782                 :          0 :                                 return ret;
    7783         [ #  # ]:          0 :                         last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L2 :
    7784                 :            :                                              MLX5_FLOW_LAYER_OUTER_L2;
    7785   [ #  #  #  # ]:          0 :                         if (items->mask != NULL && items->spec != NULL) {
    7786                 :          0 :                                 ether_type =
    7787                 :            :                                         ((const struct rte_flow_item_eth *)
    7788                 :            :                                          items->spec)->hdr.ether_type;
    7789                 :          0 :                                 ether_type &=
    7790                 :            :                                         ((const struct rte_flow_item_eth *)
    7791                 :          0 :                                          items->mask)->hdr.ether_type;
    7792         [ #  # ]:          0 :                                 ether_type = rte_be_to_cpu_16(ether_type);
    7793                 :            :                         } else {
    7794                 :            :                                 ether_type = 0;
    7795                 :            :                         }
    7796                 :            :                         break;
    7797                 :          0 :                 case RTE_FLOW_ITEM_TYPE_VLAN:
    7798                 :          0 :                         ret = flow_dv_validate_item_vlan(items, item_flags,
    7799                 :            :                                                          dev, error);
    7800         [ #  # ]:          0 :                         if (ret < 0)
    7801                 :          0 :                                 return ret;
    7802         [ #  # ]:          0 :                         last_item = tunnel ? MLX5_FLOW_LAYER_INNER_VLAN :
    7803                 :            :                                              MLX5_FLOW_LAYER_OUTER_VLAN;
    7804   [ #  #  #  # ]:          0 :                         if (items->mask != NULL && items->spec != NULL) {
    7805                 :          0 :                                 ether_type =
    7806                 :            :                                         ((const struct rte_flow_item_vlan *)
    7807                 :            :                                          items->spec)->hdr.eth_proto;
    7808                 :          0 :                                 ether_type &=
    7809                 :            :                                         ((const struct rte_flow_item_vlan *)
    7810                 :          0 :                                          items->mask)->hdr.eth_proto;
    7811         [ #  # ]:          0 :                                 ether_type = rte_be_to_cpu_16(ether_type);
    7812                 :            :                         } else {
    7813                 :            :                                 ether_type = 0;
    7814                 :            :                         }
    7815                 :            :                         /* Store outer VLAN mask for of_push_vlan action. */
    7816         [ #  # ]:          0 :                         if (!tunnel)
    7817                 :            :                                 vlan_m = items->mask;
    7818                 :            :                         break;
    7819                 :            :                 case RTE_FLOW_ITEM_TYPE_IPV4:
    7820                 :            :                         next_protocol = mlx5_flow_l3_next_protocol
    7821                 :            :                                 (items, (enum MLX5_SET_MATCHER)-1);
    7822                 :            :                         l3_tunnel_detection =
    7823                 :            :                                 mlx5_flow_tunnel_ip_check(items, next_protocol,
    7824                 :            :                                                           item_flags,
    7825                 :            :                                                           &l3_tunnel_flag);
    7826                 :            :                         if (l3_tunnel_detection == l3_tunnel_inner) {
    7827                 :          0 :                                 item_flags |= l3_tunnel_flag;
    7828                 :            :                                 tunnel = 1;
    7829                 :            :                         }
    7830                 :          0 :                         ret = flow_dv_validate_item_ipv4(dev, items, item_flags,
    7831                 :            :                                                          last_item, ether_type,
    7832                 :            :                                                          error);
    7833         [ #  # ]:          0 :                         if (ret < 0)
    7834                 :          0 :                                 return ret;
    7835         [ #  # ]:          0 :                         last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV4 :
    7836                 :            :                                              MLX5_FLOW_LAYER_OUTER_L3_IPV4;
    7837         [ #  # ]:          0 :                         if (l3_tunnel_detection == l3_tunnel_outer)
    7838                 :          0 :                                 item_flags |= l3_tunnel_flag;
    7839                 :            :                         break;
    7840                 :            :                 case RTE_FLOW_ITEM_TYPE_IPV6:
    7841                 :            :                         next_protocol = mlx5_flow_l3_next_protocol
    7842                 :            :                                 (items, (enum MLX5_SET_MATCHER)-1);
    7843                 :            :                         l3_tunnel_detection =
    7844                 :            :                                 mlx5_flow_tunnel_ip_check(items, next_protocol,
    7845                 :            :                                                           item_flags,
    7846                 :            :                                                           &l3_tunnel_flag);
    7847                 :            :                         if (l3_tunnel_detection == l3_tunnel_inner) {
    7848                 :          0 :                                 item_flags |= l3_tunnel_flag;
    7849                 :            :                                 tunnel = 1;
    7850                 :            :                         }
    7851                 :          0 :                         ret = mlx5_flow_validate_item_ipv6(items, item_flags,
    7852                 :            :                                                            last_item,
    7853                 :            :                                                            ether_type,
    7854                 :            :                                                            &nic_ipv6_mask,
    7855                 :            :                                                            error);
    7856         [ #  # ]:          0 :                         if (ret < 0)
    7857                 :          0 :                                 return ret;
    7858         [ #  # ]:          0 :                         last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV6 :
    7859                 :            :                                              MLX5_FLOW_LAYER_OUTER_L3_IPV6;
    7860         [ #  # ]:          0 :                         if (l3_tunnel_detection == l3_tunnel_outer)
    7861                 :          0 :                                 item_flags |= l3_tunnel_flag;
    7862                 :            :                         break;
    7863                 :          0 :                 case RTE_FLOW_ITEM_TYPE_IPV6_FRAG_EXT:
    7864                 :          0 :                         ret = flow_dv_validate_item_ipv6_frag_ext(items,
    7865                 :            :                                                                   item_flags,
    7866                 :            :                                                                   error);
    7867         [ #  # ]:          0 :                         if (ret < 0)
    7868                 :          0 :                                 return ret;
    7869         [ #  # ]:          0 :                         last_item = tunnel ?
    7870         [ #  # ]:          0 :                                         MLX5_FLOW_LAYER_INNER_L3_IPV6_FRAG_EXT :
    7871                 :            :                                         MLX5_FLOW_LAYER_OUTER_L3_IPV6_FRAG_EXT;
    7872                 :            :                         next_protocol = mlx5_flow_l3_next_protocol
    7873                 :            :                                 (items, (enum MLX5_SET_MATCHER)-1);
    7874                 :            :                         break;
    7875                 :          0 :                 case RTE_FLOW_ITEM_TYPE_TCP:
    7876                 :          0 :                         ret = mlx5_flow_validate_item_tcp
    7877                 :            :                                                 (items, item_flags,
    7878                 :            :                                                  next_protocol,
    7879                 :            :                                                  &nic_tcp_mask,
    7880                 :            :                                                  error);
    7881         [ #  # ]:          0 :                         if (ret < 0)
    7882                 :          0 :                                 return ret;
    7883         [ #  # ]:          0 :                         last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L4_TCP :
    7884                 :            :                                              MLX5_FLOW_LAYER_OUTER_L4_TCP;
    7885                 :          0 :                         break;
    7886                 :          0 :                 case RTE_FLOW_ITEM_TYPE_UDP:
    7887                 :          0 :                         ret = mlx5_flow_validate_item_udp(items, item_flags,
    7888                 :            :                                                           next_protocol,
    7889                 :            :                                                           error);
    7890                 :          0 :                         const struct rte_flow_item_udp *spec = items->spec;
    7891                 :          0 :                         const struct rte_flow_item_udp *mask = items->mask;
    7892         [ #  # ]:          0 :                         if (!mask)
    7893                 :            :                                 mask = &rte_flow_item_udp_mask;
    7894         [ #  # ]:          0 :                         if (spec != NULL)
    7895         [ #  # ]:          0 :                                 udp_dport = rte_be_to_cpu_16
    7896                 :            :                                                 (spec->hdr.dst_port &
    7897                 :            :                                                  mask->hdr.dst_port);
    7898         [ #  # ]:          0 :                         if (ret < 0)
    7899                 :          0 :                                 return ret;
    7900         [ #  # ]:          0 :                         last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L4_UDP :
    7901                 :            :                                              MLX5_FLOW_LAYER_OUTER_L4_UDP;
    7902                 :          0 :                         break;
    7903                 :          0 :                 case RTE_FLOW_ITEM_TYPE_GRE:
    7904                 :          0 :                         ret = mlx5_flow_validate_item_gre(items, item_flags,
    7905                 :            :                                                           next_protocol, error);
    7906         [ #  # ]:          0 :                         if (ret < 0)
    7907                 :          0 :                                 return ret;
    7908                 :            :                         gre_item = items;
    7909                 :          0 :                         last_item = MLX5_FLOW_LAYER_GRE;
    7910                 :          0 :                         break;
    7911                 :          0 :                 case RTE_FLOW_ITEM_TYPE_GRE_OPTION:
    7912                 :          0 :                         ret = mlx5_flow_validate_item_gre_option(dev, items, item_flags,
    7913                 :            :                                                           attr, gre_item, error);
    7914         [ #  # ]:          0 :                         if (ret < 0)
    7915                 :          0 :                                 return ret;
    7916                 :          0 :                         last_item = MLX5_FLOW_LAYER_GRE;
    7917                 :          0 :                         break;
    7918                 :          0 :                 case RTE_FLOW_ITEM_TYPE_NVGRE:
    7919                 :          0 :                         ret = mlx5_flow_validate_item_nvgre(items, item_flags,
    7920                 :            :                                                             next_protocol,
    7921                 :            :                                                             error);
    7922         [ #  # ]:          0 :                         if (ret < 0)
    7923                 :          0 :                                 return ret;
    7924                 :          0 :                         last_item = MLX5_FLOW_LAYER_NVGRE;
    7925                 :          0 :                         break;
    7926                 :          0 :                 case RTE_FLOW_ITEM_TYPE_GRE_KEY:
    7927                 :          0 :                         ret = mlx5_flow_validate_item_gre_key
    7928                 :            :                                 (items, item_flags, gre_item, error);
    7929         [ #  # ]:          0 :                         if (ret < 0)
    7930                 :          0 :                                 return ret;
    7931                 :          0 :                         last_item = MLX5_FLOW_LAYER_GRE_KEY;
    7932                 :          0 :                         break;
    7933                 :          0 :                 case RTE_FLOW_ITEM_TYPE_VXLAN:
    7934                 :          0 :                         ret = mlx5_flow_validate_item_vxlan(dev, udp_dport,
    7935                 :            :                                                             items, item_flags,
    7936                 :            :                                                             is_root, error);
    7937         [ #  # ]:          0 :                         if (ret < 0)
    7938                 :          0 :                                 return ret;
    7939                 :          0 :                         last_item = MLX5_FLOW_LAYER_VXLAN;
    7940                 :          0 :                         break;
    7941                 :          0 :                 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
    7942                 :          0 :                         ret = mlx5_flow_validate_item_vxlan_gpe(items,
    7943                 :            :                                                                 item_flags, dev,
    7944                 :            :                                                                 error);
    7945         [ #  # ]:          0 :                         if (ret < 0)
    7946                 :          0 :                                 return ret;
    7947                 :          0 :                         last_item = MLX5_FLOW_LAYER_VXLAN_GPE;
    7948                 :          0 :                         break;
    7949                 :          0 :                 case RTE_FLOW_ITEM_TYPE_GENEVE:
    7950                 :          0 :                         ret = mlx5_flow_validate_item_geneve(items,
    7951                 :            :                                                              item_flags, dev,
    7952                 :            :                                                              error);
    7953         [ #  # ]:          0 :                         if (ret < 0)
    7954                 :          0 :                                 return ret;
    7955                 :            :                         geneve_item = items;
    7956                 :          0 :                         last_item = MLX5_FLOW_LAYER_GENEVE;
    7957                 :          0 :                         break;
    7958                 :          0 :                 case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
    7959                 :          0 :                         ret = mlx5_flow_validate_item_geneve_opt(items,
    7960                 :            :                                                                  last_item,
    7961                 :            :                                                                  geneve_item,
    7962                 :            :                                                                  dev,
    7963                 :            :                                                                  error);
    7964         [ #  # ]:          0 :                         if (ret < 0)
    7965                 :          0 :                                 return ret;
    7966                 :          0 :                         last_item = MLX5_FLOW_LAYER_GENEVE_OPT;
    7967                 :          0 :                         break;
    7968                 :          0 :                 case RTE_FLOW_ITEM_TYPE_MPLS:
    7969                 :          0 :                         ret = mlx5_flow_validate_item_mpls(dev, items,
    7970                 :            :                                                            item_flags,
    7971                 :            :                                                            last_item, error);
    7972         [ #  # ]:          0 :                         if (ret < 0)
    7973                 :          0 :                                 return ret;
    7974                 :          0 :                         last_item = MLX5_FLOW_LAYER_MPLS;
    7975                 :          0 :                         break;
    7976                 :            : 
    7977                 :          0 :                 case RTE_FLOW_ITEM_TYPE_MARK:
    7978                 :          0 :                         ret = flow_dv_validate_item_mark(dev, items, attr,
    7979                 :            :                                                          error);
    7980         [ #  # ]:          0 :                         if (ret < 0)
    7981                 :          0 :                                 return ret;
    7982                 :          0 :                         last_item = MLX5_FLOW_ITEM_MARK;
    7983                 :          0 :                         break;
    7984                 :          0 :                 case RTE_FLOW_ITEM_TYPE_META:
    7985                 :          0 :                         ret = flow_dv_validate_item_meta(dev, items, attr,
    7986                 :            :                                                          error);
    7987         [ #  # ]:          0 :                         if (ret < 0)
    7988                 :          0 :                                 return ret;
    7989                 :          0 :                         last_item = MLX5_FLOW_ITEM_METADATA;
    7990                 :          0 :                         break;
    7991                 :          0 :                 case RTE_FLOW_ITEM_TYPE_ICMP:
    7992                 :          0 :                         ret = mlx5_flow_validate_item_icmp(items, item_flags,
    7993                 :            :                                                            next_protocol,
    7994                 :            :                                                            error);
    7995         [ #  # ]:          0 :                         if (ret < 0)
    7996                 :          0 :                                 return ret;
    7997                 :          0 :                         last_item = MLX5_FLOW_LAYER_ICMP;
    7998                 :          0 :                         break;
    7999                 :          0 :                 case RTE_FLOW_ITEM_TYPE_ICMP6:
    8000                 :          0 :                         ret = mlx5_flow_validate_item_icmp6(items, item_flags,
    8001                 :            :                                                             next_protocol,
    8002                 :            :                                                             error);
    8003         [ #  # ]:          0 :                         if (ret < 0)
    8004                 :          0 :                                 return ret;
    8005                 :            :                         item_ipv6_proto = IPPROTO_ICMPV6;
    8006                 :          0 :                         last_item = MLX5_FLOW_LAYER_ICMP6;
    8007                 :          0 :                         break;
    8008                 :          0 :                 case RTE_FLOW_ITEM_TYPE_ICMP6_ECHO_REQUEST:
    8009                 :            :                 case RTE_FLOW_ITEM_TYPE_ICMP6_ECHO_REPLY:
    8010                 :          0 :                         ret = mlx5_flow_validate_item_icmp6_echo(items,
    8011                 :            :                                                                  item_flags,
    8012                 :            :                                                                  next_protocol,
    8013                 :            :                                                                  error);
    8014         [ #  # ]:          0 :                         if (ret < 0)
    8015                 :          0 :                                 return ret;
    8016                 :            :                         item_ipv6_proto = IPPROTO_ICMPV6;
    8017                 :          0 :                         last_item = MLX5_FLOW_LAYER_ICMP6;
    8018                 :          0 :                         break;
    8019                 :          0 :                 case RTE_FLOW_ITEM_TYPE_TAG:
    8020                 :          0 :                         ret = flow_dv_validate_item_tag(dev, items, &tag_bitmap,
    8021                 :            :                                                         attr, error);
    8022         [ #  # ]:          0 :                         if (ret < 0)
    8023                 :          0 :                                 return ret;
    8024                 :          0 :                         last_item = MLX5_FLOW_ITEM_TAG;
    8025                 :          0 :                         break;
    8026                 :          0 :                 case MLX5_RTE_FLOW_ITEM_TYPE_SQ:
    8027                 :          0 :                         last_item = MLX5_FLOW_ITEM_SQ;
    8028                 :          0 :                         break;
    8029                 :          0 :                 case MLX5_RTE_FLOW_ITEM_TYPE_TAG:
    8030                 :          0 :                         mlx5_tag = (const struct mlx5_rte_flow_item_tag *)items->spec;
    8031         [ #  # ]:          0 :                         if (tag_bitmap & (1 << mlx5_tag->id))
    8032                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    8033                 :            :                                                           RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
    8034                 :            :                                                           items->spec,
    8035                 :            :                                                           "Duplicated tag index");
    8036                 :          0 :                         tag_bitmap |= 1 << mlx5_tag->id;
    8037                 :          0 :                         break;
    8038                 :          0 :                 case RTE_FLOW_ITEM_TYPE_GTP:
    8039                 :          0 :                         ret = flow_dv_validate_item_gtp(dev, items, item_flags,
    8040                 :            :                                                         error);
    8041         [ #  # ]:          0 :                         if (ret < 0)
    8042                 :          0 :                                 return ret;
    8043                 :            :                         gtp_item = items;
    8044                 :          0 :                         last_item = MLX5_FLOW_LAYER_GTP;
    8045                 :          0 :                         break;
    8046                 :          0 :                 case RTE_FLOW_ITEM_TYPE_GTP_PSC:
    8047                 :          0 :                         ret = flow_dv_validate_item_gtp_psc(items, last_item,
    8048                 :            :                                                             gtp_item, is_root,
    8049                 :            :                                                             error);
    8050         [ #  # ]:          0 :                         if (ret < 0)
    8051                 :          0 :                                 return ret;
    8052                 :          0 :                         last_item = MLX5_FLOW_LAYER_GTP_PSC;
    8053                 :          0 :                         break;
    8054                 :          0 :                 case RTE_FLOW_ITEM_TYPE_ECPRI:
    8055                 :            :                         /* Capacity will be checked in the translate stage. */
    8056                 :          0 :                         ret = mlx5_flow_validate_item_ecpri(items, item_flags,
    8057                 :            :                                                             last_item,
    8058                 :            :                                                             ether_type,
    8059                 :            :                                                             &nic_ecpri_mask,
    8060                 :            :                                                             error);
    8061         [ #  # ]:          0 :                         if (ret < 0)
    8062                 :          0 :                                 return ret;
    8063                 :          0 :                         last_item = MLX5_FLOW_LAYER_ECPRI;
    8064                 :          0 :                         break;
    8065                 :          0 :                 case RTE_FLOW_ITEM_TYPE_INTEGRITY:
    8066                 :          0 :                         ret = flow_dv_validate_item_integrity(dev, items,
    8067                 :            :                                                               item_flags,
    8068                 :            :                                                               &last_item,
    8069                 :            :                                                               integrity_items,
    8070                 :            :                                                               error);
    8071         [ #  # ]:          0 :                         if (ret < 0)
    8072                 :          0 :                                 return ret;
    8073                 :            :                         break;
    8074                 :          0 :                 case RTE_FLOW_ITEM_TYPE_CONNTRACK:
    8075                 :          0 :                         ret = flow_dv_validate_item_aso_ct(dev, items,
    8076                 :            :                                                            &item_flags, error);
    8077         [ #  # ]:          0 :                         if (ret < 0)
    8078                 :          0 :                                 return ret;
    8079                 :            :                         break;
    8080                 :            :                 case MLX5_RTE_FLOW_ITEM_TYPE_TUNNEL:
    8081                 :            :                         /* tunnel offload item was processed before
    8082                 :            :                          * list it here as a supported type
    8083                 :            :                          */
    8084                 :            :                         break;
    8085                 :          0 :                 case RTE_FLOW_ITEM_TYPE_FLEX:
    8086                 :          0 :                         ret = flow_dv_validate_item_flex(dev, items, item_flags,
    8087                 :            :                                                          &last_item,
    8088                 :            :                                                          tunnel != 0, error);
    8089         [ #  # ]:          0 :                         if (ret < 0)
    8090                 :          0 :                                 return ret;
    8091                 :            :                         break;
    8092                 :          0 :                 case RTE_FLOW_ITEM_TYPE_METER_COLOR:
    8093                 :          0 :                         ret = flow_dv_validate_item_meter_color(dev, items,
    8094                 :            :                                                                 attr, error);
    8095         [ #  # ]:          0 :                         if (ret < 0)
    8096                 :          0 :                                 return ret;
    8097                 :          0 :                         last_item = MLX5_FLOW_ITEM_METER_COLOR;
    8098                 :          0 :                         break;
    8099                 :          0 :                 case RTE_FLOW_ITEM_TYPE_AGGR_AFFINITY:
    8100                 :          0 :                         ret = flow_dv_validate_item_aggr_affinity(dev, items,
    8101                 :            :                                                                   attr, error);
    8102         [ #  # ]:          0 :                         if (ret < 0)
    8103                 :          0 :                                 return ret;
    8104                 :          0 :                         last_item = MLX5_FLOW_ITEM_AGGR_AFFINITY;
    8105                 :          0 :                         break;
    8106                 :          0 :                 case RTE_FLOW_ITEM_TYPE_IB_BTH:
    8107                 :          0 :                         ret = mlx5_flow_validate_item_ib_bth(dev, udp_dport,
    8108                 :            :                                                             items, is_root, error);
    8109         [ #  # ]:          0 :                         if (ret < 0)
    8110                 :          0 :                                 return ret;
    8111                 :            : 
    8112                 :          0 :                         last_item = MLX5_FLOW_ITEM_IB_BTH;
    8113                 :          0 :                         break;
    8114                 :          0 :                 case RTE_FLOW_ITEM_TYPE_NSH:
    8115                 :          0 :                         ret = mlx5_flow_validate_item_nsh(dev, items, error);
    8116         [ #  # ]:          0 :                         if (ret < 0)
    8117                 :          0 :                                 return ret;
    8118                 :          0 :                         last_item = MLX5_FLOW_ITEM_NSH;
    8119                 :          0 :                         break;
    8120                 :          0 :                 default:
    8121                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    8122                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM,
    8123                 :            :                                                   NULL, "item not supported");
    8124                 :            :                 }
    8125                 :          0 :                 item_flags |= last_item;
    8126                 :            :         }
    8127         [ #  # ]:          0 :         if (item_flags & MLX5_FLOW_ITEM_INTEGRITY) {
    8128                 :          0 :                 ret = flow_dv_validate_item_integrity_post(integrity_items,
    8129                 :            :                                                            item_flags, error);
    8130         [ #  # ]:          0 :                 if (ret)
    8131                 :            :                         return ret;
    8132                 :            :         }
    8133         [ #  # ]:          0 :         for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
    8134                 :          0 :                 int type = actions->type;
    8135                 :            : 
    8136                 :            :                 if (!mlx5_flow_os_action_supported(type))
    8137                 :            :                         return rte_flow_error_set(error, ENOTSUP,
    8138                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    8139                 :            :                                                   actions,
    8140                 :            :                                                   "action not supported");
    8141         [ #  # ]:          0 :                 if (actions_n == MLX5_DV_MAX_NUMBER_OF_ACTIONS)
    8142                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    8143                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    8144                 :            :                                                   actions, "too many actions");
    8145         [ #  # ]:          0 :                 if (action_flags &
    8146                 :            :                         MLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY)
    8147                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    8148                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION,
    8149                 :            :                                 NULL, "meter action with policy "
    8150                 :            :                                 "must be the last action");
    8151   [ #  #  #  #  :          0 :                 switch (type) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
    8152                 :            :                 case RTE_FLOW_ACTION_TYPE_VOID:
    8153                 :            :                         break;
    8154                 :          0 :                 case RTE_FLOW_ACTION_TYPE_PORT_ID:
    8155                 :            :                 case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
    8156                 :          0 :                         ret = flow_dv_validate_action_port_id(dev,
    8157                 :            :                                                               action_flags,
    8158                 :            :                                                               actions,
    8159                 :            :                                                               attr,
    8160                 :            :                                                               error);
    8161         [ #  # ]:          0 :                         if (ret)
    8162                 :          0 :                                 return ret;
    8163         [ #  # ]:          0 :                         if (type == RTE_FLOW_ACTION_TYPE_PORT_ID) {
    8164                 :          0 :                                 port = (const struct rte_flow_action_port_id *)
    8165                 :            :                                         actions->conf;
    8166         [ #  # ]:          0 :                                 port_id = port->original ? dev->data->port_id : port->id;
    8167                 :            :                         } else {
    8168                 :          0 :                                 port_id = ((const struct rte_flow_action_ethdev *)
    8169                 :          0 :                                         actions->conf)->port_id;
    8170                 :            :                         }
    8171                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_PORT_ID;
    8172                 :          0 :                         ++actions_n;
    8173                 :          0 :                         break;
    8174                 :          0 :                 case RTE_FLOW_ACTION_TYPE_FLAG:
    8175                 :          0 :                         ret = flow_dv_validate_action_flag(dev, action_flags,
    8176                 :            :                                                            attr, error);
    8177         [ #  # ]:          0 :                         if (ret < 0)
    8178                 :          0 :                                 return ret;
    8179         [ #  # ]:          0 :                         if (dev_conf->dv_xmeta_en != MLX5_XMETA_MODE_LEGACY) {
    8180                 :            :                                 /* Count all modify-header actions as one. */
    8181         [ #  # ]:          0 :                                 if (!(action_flags &
    8182                 :            :                                       MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8183                 :          0 :                                         ++actions_n;
    8184                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_FLAG |
    8185                 :            :                                                 MLX5_FLOW_ACTION_MARK_EXT;
    8186         [ #  # ]:          0 :                                 if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8187                 :            :                                         modify_after_mirror = 1;
    8188                 :            : 
    8189                 :            :                         } else {
    8190                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_FLAG;
    8191                 :          0 :                                 ++actions_n;
    8192                 :            :                         }
    8193                 :          0 :                         rw_act_num += MLX5_ACT_NUM_SET_MARK;
    8194                 :          0 :                         break;
    8195                 :          0 :                 case RTE_FLOW_ACTION_TYPE_MARK:
    8196                 :          0 :                         ret = flow_dv_validate_action_mark(dev, actions,
    8197                 :            :                                                            action_flags,
    8198                 :            :                                                            attr, error);
    8199         [ #  # ]:          0 :                         if (ret < 0)
    8200                 :          0 :                                 return ret;
    8201         [ #  # ]:          0 :                         if (dev_conf->dv_xmeta_en != MLX5_XMETA_MODE_LEGACY) {
    8202                 :            :                                 /* Count all modify-header actions as one. */
    8203         [ #  # ]:          0 :                                 if (!(action_flags &
    8204                 :            :                                       MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8205                 :          0 :                                         ++actions_n;
    8206                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_MARK |
    8207                 :            :                                                 MLX5_FLOW_ACTION_MARK_EXT;
    8208         [ #  # ]:          0 :                                 if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8209                 :            :                                         modify_after_mirror = 1;
    8210                 :            :                         } else {
    8211                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_MARK;
    8212                 :          0 :                                 ++actions_n;
    8213                 :            :                         }
    8214                 :          0 :                         rw_act_num += MLX5_ACT_NUM_SET_MARK;
    8215                 :          0 :                         break;
    8216                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_META:
    8217                 :          0 :                         ret = flow_dv_validate_action_set_meta(dev, actions,
    8218                 :            :                                                                action_flags,
    8219                 :            :                                                                attr, error);
    8220         [ #  # ]:          0 :                         if (ret < 0)
    8221                 :          0 :                                 return ret;
    8222                 :            :                         /* Count all modify-header actions as one action. */
    8223         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8224                 :          0 :                                 ++actions_n;
    8225         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8226                 :            :                                 modify_after_mirror = 1;
    8227                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SET_META;
    8228                 :          0 :                         rw_act_num += MLX5_ACT_NUM_SET_META;
    8229                 :          0 :                         break;
    8230                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_TAG:
    8231                 :          0 :                         ret = flow_dv_validate_action_set_tag(dev, actions,
    8232                 :            :                                                               action_flags,
    8233                 :            :                                                               attr, error);
    8234         [ #  # ]:          0 :                         if (ret < 0)
    8235                 :          0 :                                 return ret;
    8236                 :            :                         /* Count all modify-header actions as one action. */
    8237         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8238                 :          0 :                                 ++actions_n;
    8239         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8240                 :            :                                 modify_after_mirror = 1;
    8241                 :          0 :                         tag_id = ((const struct rte_flow_action_set_tag *)
    8242                 :          0 :                                   actions->conf)->index;
    8243                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SET_TAG;
    8244                 :          0 :                         rw_act_num += MLX5_ACT_NUM_SET_TAG;
    8245                 :          0 :                         break;
    8246                 :          0 :                 case RTE_FLOW_ACTION_TYPE_DROP:
    8247                 :          0 :                         ret = mlx5_flow_validate_action_drop(dev, is_root,
    8248                 :            :                                                              attr, error);
    8249         [ #  # ]:          0 :                         if (ret < 0)
    8250                 :          0 :                                 return ret;
    8251                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_DROP;
    8252                 :          0 :                         ++actions_n;
    8253                 :          0 :                         break;
    8254                 :          0 :                 case RTE_FLOW_ACTION_TYPE_QUEUE:
    8255                 :          0 :                         ret = mlx5_flow_validate_action_queue(actions,
    8256                 :            :                                                               action_flags, dev,
    8257                 :            :                                                               attr, error);
    8258         [ #  # ]:          0 :                         if (ret < 0)
    8259                 :          0 :                                 return ret;
    8260                 :          0 :                         queue_index = ((const struct rte_flow_action_queue *)
    8261                 :          0 :                                                         (actions->conf))->index;
    8262                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_QUEUE;
    8263                 :          0 :                         ++actions_n;
    8264                 :          0 :                         break;
    8265                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RSS:
    8266                 :          0 :                         rss = actions->conf;
    8267                 :          0 :                         ret = mlx5_flow_validate_action_rss(actions,
    8268                 :            :                                                             action_flags, dev,
    8269                 :            :                                                             attr, item_flags,
    8270                 :            :                                                             error);
    8271         [ #  # ]:          0 :                         if (ret < 0)
    8272                 :          0 :                                 return ret;
    8273         [ #  # ]:          0 :                         if (rss && sample_rss &&
    8274         [ #  # ]:          0 :                             (sample_rss->level != rss->level ||
    8275         [ #  # ]:          0 :                             sample_rss->types != rss->types))
    8276                 :          0 :                                 return rte_flow_error_set(error, ENOTSUP,
    8277                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION,
    8278                 :            :                                         NULL,
    8279                 :            :                                         "Can't use the different RSS types "
    8280                 :            :                                         "or level in the same flow");
    8281   [ #  #  #  # ]:          0 :                         if (rss != NULL && rss->queue_num)
    8282                 :          0 :                                 queue_index = rss->queue[0];
    8283                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_RSS;
    8284                 :          0 :                         ++actions_n;
    8285                 :          0 :                         break;
    8286                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_DEFAULT_MISS:
    8287                 :            :                         ret =
    8288                 :          0 :                         mlx5_flow_validate_action_default_miss(action_flags,
    8289                 :            :                                         attr, error);
    8290         [ #  # ]:          0 :                         if (ret < 0)
    8291                 :          0 :                                 return ret;
    8292                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_DEFAULT_MISS;
    8293                 :          0 :                         ++actions_n;
    8294                 :          0 :                         break;
    8295                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_COUNT:
    8296                 :            :                         shared_count = true;
    8297                 :            :                         /* fall-through. */
    8298                 :          0 :                 case RTE_FLOW_ACTION_TYPE_COUNT:
    8299                 :          0 :                         ret = flow_dv_validate_action_count(dev, shared_count,
    8300                 :            :                                                             action_flags,
    8301                 :            :                                                             is_root, error);
    8302         [ #  # ]:          0 :                         if (ret < 0)
    8303                 :          0 :                                 return ret;
    8304                 :          0 :                         count = actions->conf;
    8305                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_COUNT;
    8306                 :          0 :                         ++actions_n;
    8307                 :          0 :                         break;
    8308                 :          0 :                 case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:
    8309         [ #  # ]:          0 :                         if (flow_dv_validate_action_pop_vlan(dev,
    8310                 :            :                                                              action_flags,
    8311                 :            :                                                              actions,
    8312                 :            :                                                              item_flags, attr,
    8313                 :            :                                                              error))
    8314                 :          0 :                                 return -rte_errno;
    8315         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8316                 :            :                                 modify_after_mirror = 1;
    8317                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_OF_POP_VLAN;
    8318                 :          0 :                         ++actions_n;
    8319                 :          0 :                         break;
    8320                 :          0 :                 case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
    8321                 :          0 :                         ret = flow_dv_validate_action_push_vlan(dev,
    8322                 :            :                                                                 action_flags,
    8323                 :            :                                                                 vlan_m,
    8324                 :            :                                                                 actions, attr,
    8325                 :            :                                                                 error);
    8326         [ #  # ]:          0 :                         if (ret < 0)
    8327                 :          0 :                                 return ret;
    8328         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8329                 :            :                                 modify_after_mirror = 1;
    8330                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_OF_PUSH_VLAN;
    8331                 :          0 :                         ++actions_n;
    8332                 :          0 :                         break;
    8333                 :          0 :                 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:
    8334                 :          0 :                         ret = flow_dv_validate_action_set_vlan_pcp
    8335                 :            :                                                 (action_flags, actions, error);
    8336         [ #  # ]:          0 :                         if (ret < 0)
    8337                 :          0 :                                 return ret;
    8338         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8339                 :            :                                 modify_after_mirror = 1;
    8340                 :            :                         /* Count PCP with push_vlan command. */
    8341                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_OF_SET_VLAN_PCP;
    8342                 :          0 :                         break;
    8343                 :          0 :                 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
    8344                 :          0 :                         ret = flow_dv_validate_action_set_vlan_vid
    8345                 :            :                                                 (item_flags, action_flags,
    8346                 :            :                                                  actions, error);
    8347         [ #  # ]:          0 :                         if (ret < 0)
    8348                 :          0 :                                 return ret;
    8349         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8350                 :            :                                 modify_after_mirror = 1;
    8351                 :            :                         /* Count VID with push_vlan command. */
    8352                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_OF_SET_VLAN_VID;
    8353                 :          0 :                         rw_act_num += MLX5_ACT_NUM_MDF_VID;
    8354                 :          0 :                         break;
    8355                 :          0 :                 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
    8356                 :            :                 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
    8357                 :          0 :                         ret = flow_dv_validate_action_l2_encap(dev,
    8358                 :            :                                                                action_flags,
    8359                 :            :                                                                actions, attr,
    8360                 :            :                                                                error);
    8361         [ #  # ]:          0 :                         if (ret < 0)
    8362                 :          0 :                                 return ret;
    8363                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_ENCAP;
    8364                 :          0 :                         ++actions_n;
    8365                 :          0 :                         break;
    8366                 :          0 :                 case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
    8367                 :            :                 case RTE_FLOW_ACTION_TYPE_NVGRE_DECAP:
    8368                 :          0 :                         ret = flow_dv_validate_action_decap(dev, action_flags,
    8369                 :            :                                                             actions, item_flags,
    8370                 :            :                                                             attr, error);
    8371         [ #  # ]:          0 :                         if (ret < 0)
    8372                 :          0 :                                 return ret;
    8373         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8374                 :            :                                 modify_after_mirror = 1;
    8375                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_DECAP;
    8376                 :          0 :                         ++actions_n;
    8377                 :          0 :                         break;
    8378                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
    8379                 :          0 :                         ret = flow_dv_validate_action_raw_encap_decap
    8380                 :          0 :                                 (dev, NULL, actions->conf, attr, &action_flags,
    8381                 :            :                                  &actions_n, actions, item_flags, error);
    8382         [ #  # ]:          0 :                         if (ret < 0)
    8383                 :          0 :                                 return ret;
    8384                 :            :                         break;
    8385                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
    8386                 :          0 :                         decap = actions->conf;
    8387         [ #  # ]:          0 :                         while ((++actions)->type == RTE_FLOW_ACTION_TYPE_VOID)
    8388                 :            :                                 ;
    8389         [ #  # ]:          0 :                         if (actions->type != RTE_FLOW_ACTION_TYPE_RAW_ENCAP) {
    8390                 :            :                                 encap = NULL;
    8391                 :            :                                 actions--;
    8392                 :            :                         } else {
    8393                 :          0 :                                 encap = actions->conf;
    8394                 :            :                         }
    8395         [ #  # ]:          0 :                         ret = flow_dv_validate_action_raw_encap_decap
    8396                 :            :                                            (dev,
    8397                 :            :                                             decap ? decap : &empty_decap, encap,
    8398                 :            :                                             attr, &action_flags, &actions_n,
    8399                 :            :                                             actions, item_flags, error);
    8400         [ #  # ]:          0 :                         if (ret < 0)
    8401                 :          0 :                                 return ret;
    8402         [ #  # ]:          0 :                         if ((action_flags & MLX5_FLOW_ACTION_SAMPLE) &&
    8403                 :            :                             (action_flags & MLX5_FLOW_ACTION_DECAP))
    8404                 :            :                                 modify_after_mirror = 1;
    8405                 :            :                         break;
    8406                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_MAC_SRC:
    8407                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_MAC_DST:
    8408                 :          0 :                         ret = flow_dv_validate_action_modify_mac(action_flags,
    8409                 :            :                                                                  actions,
    8410                 :            :                                                                  item_flags,
    8411                 :            :                                                                  error);
    8412         [ #  # ]:          0 :                         if (ret < 0)
    8413                 :          0 :                                 return ret;
    8414                 :            :                         /* Count all modify-header actions as one action. */
    8415         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8416                 :          0 :                                 ++actions_n;
    8417                 :          0 :                         action_flags |= actions->type ==
    8418                 :            :                                         RTE_FLOW_ACTION_TYPE_SET_MAC_SRC ?
    8419         [ #  # ]:          0 :                                                 MLX5_FLOW_ACTION_SET_MAC_SRC :
    8420                 :            :                                                 MLX5_FLOW_ACTION_SET_MAC_DST;
    8421         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8422                 :            :                                 modify_after_mirror = 1;
    8423                 :            :                         /*
    8424                 :            :                          * Even if the source and destination MAC addresses have
    8425                 :            :                          * overlap in the header with 4B alignment, the convert
    8426                 :            :                          * function will handle them separately and 4 SW actions
    8427                 :            :                          * will be created. And 2 actions will be added each
    8428                 :            :                          * time no matter how many bytes of address will be set.
    8429                 :            :                          */
    8430                 :          0 :                         rw_act_num += MLX5_ACT_NUM_MDF_MAC;
    8431                 :          0 :                         break;
    8432                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:
    8433                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:
    8434                 :          0 :                         ret = flow_dv_validate_action_modify_ipv4(action_flags,
    8435                 :            :                                                                   actions,
    8436                 :            :                                                                   item_flags,
    8437                 :            :                                                                   error);
    8438         [ #  # ]:          0 :                         if (ret < 0)
    8439                 :          0 :                                 return ret;
    8440                 :            :                         /* Count all modify-header actions as one action. */
    8441         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8442                 :          0 :                                 ++actions_n;
    8443         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8444                 :            :                                 modify_after_mirror = 1;
    8445                 :          0 :                         action_flags |= actions->type ==
    8446                 :            :                                         RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC ?
    8447         [ #  # ]:          0 :                                                 MLX5_FLOW_ACTION_SET_IPV4_SRC :
    8448                 :            :                                                 MLX5_FLOW_ACTION_SET_IPV4_DST;
    8449                 :          0 :                         rw_act_num += MLX5_ACT_NUM_MDF_IPV4;
    8450                 :          0 :                         break;
    8451                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC:
    8452                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_IPV6_DST:
    8453                 :          0 :                         ret = flow_dv_validate_action_modify_ipv6(action_flags,
    8454                 :            :                                                                   actions,
    8455                 :            :                                                                   item_flags,
    8456                 :            :                                                                   error);
    8457         [ #  # ]:          0 :                         if (ret < 0)
    8458                 :          0 :                                 return ret;
    8459         [ #  # ]:          0 :                         if (item_ipv6_proto == IPPROTO_ICMPV6)
    8460                 :          0 :                                 return rte_flow_error_set(error, ENOTSUP,
    8461                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION,
    8462                 :            :                                         actions,
    8463                 :            :                                         "Can't change header "
    8464                 :            :                                         "with ICMPv6 proto");
    8465                 :            :                         /* Count all modify-header actions as one action. */
    8466         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8467                 :          0 :                                 ++actions_n;
    8468         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8469                 :            :                                 modify_after_mirror = 1;
    8470                 :          0 :                         action_flags |= actions->type ==
    8471                 :            :                                         RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC ?
    8472         [ #  # ]:          0 :                                                 MLX5_FLOW_ACTION_SET_IPV6_SRC :
    8473                 :            :                                                 MLX5_FLOW_ACTION_SET_IPV6_DST;
    8474                 :          0 :                         rw_act_num += MLX5_ACT_NUM_MDF_IPV6;
    8475                 :          0 :                         break;
    8476                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_TP_SRC:
    8477                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_TP_DST:
    8478                 :          0 :                         ret = flow_dv_validate_action_modify_tp(action_flags,
    8479                 :            :                                                                 actions,
    8480                 :            :                                                                 item_flags,
    8481                 :            :                                                                 error);
    8482         [ #  # ]:          0 :                         if (ret < 0)
    8483                 :          0 :                                 return ret;
    8484                 :            :                         /* Count all modify-header actions as one action. */
    8485         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8486                 :          0 :                                 ++actions_n;
    8487         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8488                 :            :                                 modify_after_mirror = 1;
    8489                 :          0 :                         action_flags |= actions->type ==
    8490                 :            :                                         RTE_FLOW_ACTION_TYPE_SET_TP_SRC ?
    8491         [ #  # ]:          0 :                                                 MLX5_FLOW_ACTION_SET_TP_SRC :
    8492                 :            :                                                 MLX5_FLOW_ACTION_SET_TP_DST;
    8493                 :          0 :                         rw_act_num += MLX5_ACT_NUM_MDF_PORT;
    8494                 :          0 :                         break;
    8495                 :          0 :                 case RTE_FLOW_ACTION_TYPE_DEC_TTL:
    8496                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_TTL:
    8497                 :          0 :                         ret = flow_dv_validate_action_modify_ttl(action_flags,
    8498                 :            :                                                                  actions,
    8499                 :            :                                                                  item_flags,
    8500                 :            :                                                                  error);
    8501         [ #  # ]:          0 :                         if (ret < 0)
    8502                 :          0 :                                 return ret;
    8503                 :            :                         /* Count all modify-header actions as one action. */
    8504         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8505                 :          0 :                                 ++actions_n;
    8506         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8507                 :            :                                 modify_after_mirror = 1;
    8508                 :          0 :                         action_flags |= actions->type ==
    8509                 :            :                                         RTE_FLOW_ACTION_TYPE_SET_TTL ?
    8510         [ #  # ]:          0 :                                                 MLX5_FLOW_ACTION_SET_TTL :
    8511                 :            :                                                 MLX5_FLOW_ACTION_DEC_TTL;
    8512                 :          0 :                         rw_act_num += MLX5_ACT_NUM_MDF_TTL;
    8513                 :          0 :                         break;
    8514                 :          0 :                 case RTE_FLOW_ACTION_TYPE_JUMP:
    8515                 :          0 :                         ret = flow_dv_validate_action_jump(dev, tunnel, actions,
    8516                 :            :                                                            action_flags,
    8517                 :            :                                                            attr, external,
    8518                 :            :                                                            error);
    8519         [ #  # ]:          0 :                         if (ret)
    8520                 :          0 :                                 return ret;
    8521                 :          0 :                         ++actions_n;
    8522                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_JUMP;
    8523                 :          0 :                         break;
    8524                 :          0 :                 case RTE_FLOW_ACTION_TYPE_INC_TCP_SEQ:
    8525                 :            :                 case RTE_FLOW_ACTION_TYPE_DEC_TCP_SEQ:
    8526                 :          0 :                         ret = flow_dv_validate_action_modify_tcp_seq
    8527                 :            :                                                                 (action_flags,
    8528                 :            :                                                                  actions,
    8529                 :            :                                                                  item_flags,
    8530                 :            :                                                                  error);
    8531         [ #  # ]:          0 :                         if (ret < 0)
    8532                 :          0 :                                 return ret;
    8533                 :            :                         /* Count all modify-header actions as one action. */
    8534         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8535                 :          0 :                                 ++actions_n;
    8536         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8537                 :            :                                 modify_after_mirror = 1;
    8538                 :          0 :                         action_flags |= actions->type ==
    8539                 :            :                                         RTE_FLOW_ACTION_TYPE_INC_TCP_SEQ ?
    8540         [ #  # ]:          0 :                                                 MLX5_FLOW_ACTION_INC_TCP_SEQ :
    8541                 :            :                                                 MLX5_FLOW_ACTION_DEC_TCP_SEQ;
    8542                 :          0 :                         rw_act_num += MLX5_ACT_NUM_MDF_TCPSEQ;
    8543                 :          0 :                         break;
    8544                 :          0 :                 case RTE_FLOW_ACTION_TYPE_INC_TCP_ACK:
    8545                 :            :                 case RTE_FLOW_ACTION_TYPE_DEC_TCP_ACK:
    8546                 :          0 :                         ret = flow_dv_validate_action_modify_tcp_ack
    8547                 :            :                                                                 (action_flags,
    8548                 :            :                                                                  actions,
    8549                 :            :                                                                  item_flags,
    8550                 :            :                                                                  error);
    8551         [ #  # ]:          0 :                         if (ret < 0)
    8552                 :          0 :                                 return ret;
    8553                 :            :                         /* Count all modify-header actions as one action. */
    8554         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8555                 :          0 :                                 ++actions_n;
    8556         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8557                 :            :                                 modify_after_mirror = 1;
    8558                 :          0 :                         action_flags |= actions->type ==
    8559                 :            :                                         RTE_FLOW_ACTION_TYPE_INC_TCP_ACK ?
    8560         [ #  # ]:          0 :                                                 MLX5_FLOW_ACTION_INC_TCP_ACK :
    8561                 :            :                                                 MLX5_FLOW_ACTION_DEC_TCP_ACK;
    8562                 :          0 :                         rw_act_num += MLX5_ACT_NUM_MDF_TCPACK;
    8563                 :          0 :                         break;
    8564                 :            :                 case MLX5_RTE_FLOW_ACTION_TYPE_MARK:
    8565                 :            :                         break;
    8566                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_TAG:
    8567                 :            :                 case MLX5_RTE_FLOW_ACTION_TYPE_COPY_MREG:
    8568                 :          0 :                         rw_act_num += MLX5_ACT_NUM_SET_TAG;
    8569                 :          0 :                         break;
    8570                 :          0 :                 case RTE_FLOW_ACTION_TYPE_METER:
    8571                 :          0 :                         ret = mlx5_flow_validate_action_meter(dev,
    8572                 :            :                                                               action_flags,
    8573                 :            :                                                               item_flags,
    8574                 :            :                                                               actions, attr,
    8575                 :            :                                                               port_id_item,
    8576                 :            :                                                               &def_policy,
    8577                 :            :                                                               error);
    8578         [ #  # ]:          0 :                         if (ret < 0)
    8579                 :          0 :                                 return ret;
    8580                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_METER;
    8581         [ #  # ]:          0 :                         if (!def_policy)
    8582                 :          0 :                                 action_flags |=
    8583                 :            :                                 MLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY;
    8584                 :          0 :                         ++actions_n;
    8585                 :            :                         /* Meter action will add one more TAG action. */
    8586                 :          0 :                         rw_act_num += MLX5_ACT_NUM_SET_TAG;
    8587                 :          0 :                         break;
    8588                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_AGE:
    8589         [ #  # ]:          0 :                         if (is_root)
    8590                 :          0 :                                 return rte_flow_error_set(error, ENOTSUP,
    8591                 :            :                                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    8592                 :            :                                                                            NULL,
    8593                 :            :                           "Shared ASO age action is not supported for group 0");
    8594         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_AGE)
    8595                 :          0 :                                 return rte_flow_error_set
    8596                 :            :                                                   (error, EINVAL,
    8597                 :            :                                                    RTE_FLOW_ERROR_TYPE_ACTION,
    8598                 :            :                                                    NULL,
    8599                 :            :                                                    "duplicate age actions set");
    8600         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8601                 :            :                                 aso_after_sample = 1;
    8602                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_AGE;
    8603                 :          0 :                         ++actions_n;
    8604                 :          0 :                         break;
    8605                 :          0 :                 case RTE_FLOW_ACTION_TYPE_AGE:
    8606                 :          0 :                         non_shared_age = actions->conf;
    8607                 :          0 :                         ret = flow_dv_validate_action_age(action_flags,
    8608                 :            :                                                           actions, dev,
    8609                 :            :                                                           error);
    8610         [ #  # ]:          0 :                         if (ret < 0)
    8611                 :          0 :                                 return ret;
    8612                 :            :                         /*
    8613                 :            :                          * Validate the regular AGE action (using counter)
    8614                 :            :                          * mutual exclusion with indirect counter actions.
    8615                 :            :                          */
    8616         [ #  # ]:          0 :                         if (!flow_hit_aso_supported(priv, is_root)) {
    8617         [ #  # ]:          0 :                                 if (shared_count)
    8618                 :          0 :                                         return rte_flow_error_set
    8619                 :            :                                                 (error, EINVAL,
    8620                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
    8621                 :            :                                                 NULL,
    8622                 :            :                                                 "old age and indirect count combination is not supported");
    8623         [ #  # ]:          0 :                                 if (sample_count)
    8624                 :          0 :                                         return rte_flow_error_set
    8625                 :            :                                                 (error, EINVAL,
    8626                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
    8627                 :            :                                                 NULL,
    8628                 :            :                                                 "old age action and count must be in the same sub flow");
    8629                 :            :                         } else {
    8630         [ #  # ]:          0 :                                 if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8631                 :            :                                         aso_after_sample = 1;
    8632                 :            :                         }
    8633                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_AGE;
    8634                 :          0 :                         ++actions_n;
    8635                 :          0 :                         break;
    8636                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_IPV4_DSCP:
    8637                 :          0 :                         ret = flow_dv_validate_action_modify_ipv4_dscp
    8638                 :            :                                                          (action_flags,
    8639                 :            :                                                           actions,
    8640                 :            :                                                           item_flags,
    8641                 :            :                                                           error);
    8642         [ #  # ]:          0 :                         if (ret < 0)
    8643                 :          0 :                                 return ret;
    8644                 :            :                         /* Count all modify-header actions as one action. */
    8645         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8646                 :          0 :                                 ++actions_n;
    8647         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8648                 :            :                                 modify_after_mirror = 1;
    8649                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SET_IPV4_DSCP;
    8650                 :          0 :                         rw_act_num += MLX5_ACT_NUM_SET_DSCP;
    8651                 :          0 :                         break;
    8652                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_IPV6_DSCP:
    8653                 :          0 :                         ret = flow_dv_validate_action_modify_ipv6_dscp
    8654                 :            :                                                                 (action_flags,
    8655                 :            :                                                                  actions,
    8656                 :            :                                                                  item_flags,
    8657                 :            :                                                                  error);
    8658         [ #  # ]:          0 :                         if (ret < 0)
    8659                 :          0 :                                 return ret;
    8660                 :            :                         /* Count all modify-header actions as one action. */
    8661         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8662                 :          0 :                                 ++actions_n;
    8663         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8664                 :            :                                 modify_after_mirror = 1;
    8665                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SET_IPV6_DSCP;
    8666                 :          0 :                         rw_act_num += MLX5_ACT_NUM_SET_DSCP;
    8667                 :          0 :                         break;
    8668                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SAMPLE:
    8669                 :          0 :                         ret = flow_dv_validate_action_sample(&action_flags,
    8670                 :            :                                                              &sub_action_flags,
    8671                 :            :                                                              actions, dev,
    8672                 :            :                                                              attr, item_flags,
    8673                 :            :                                                              rss, &sample_rss,
    8674                 :            :                                                              &sample_count,
    8675                 :            :                                                              &fdb_mirror,
    8676                 :            :                                                              &sample_port_id,
    8677                 :            :                                                              is_root,
    8678                 :            :                                                              error);
    8679         [ #  # ]:          0 :                         if (ret < 0)
    8680                 :          0 :                                 return ret;
    8681   [ #  #  #  # ]:          0 :                         if ((action_flags & MLX5_FLOW_ACTION_SET_TAG) &&
    8682                 :          0 :                             tag_id == 0 &&
    8683         [ #  # ]:          0 :                             priv->sh->registers.aso_reg == REG_NON)
    8684                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    8685                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    8686                 :            :                                         "sample after tag action causes metadata tag index 0 corruption");
    8687                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SAMPLE;
    8688                 :          0 :                         ++actions_n;
    8689                 :          0 :                         break;
    8690                 :          0 :                 case RTE_FLOW_ACTION_TYPE_MODIFY_FIELD:
    8691                 :          0 :                         ret = flow_dv_validate_action_modify_field(dev,
    8692                 :            :                                                                    action_flags,
    8693                 :            :                                                                    actions,
    8694                 :            :                                                                    attr,
    8695                 :            :                                                                    is_root,
    8696                 :            :                                                                    error);
    8697         [ #  # ]:          0 :                         if (ret < 0)
    8698                 :          0 :                                 return ret;
    8699         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8700                 :            :                                 modify_after_mirror = 1;
    8701                 :            :                         /* Count all modify-header actions as one action. */
    8702         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8703                 :          0 :                                 ++actions_n;
    8704                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_MODIFY_FIELD;
    8705                 :          0 :                         rw_act_num += ret;
    8706                 :          0 :                         break;
    8707                 :          0 :                 case RTE_FLOW_ACTION_TYPE_CONNTRACK:
    8708                 :          0 :                         ret = flow_dv_validate_action_aso_ct(dev, action_flags,
    8709                 :            :                                                              item_flags,
    8710                 :            :                                                              is_root, error);
    8711         [ #  # ]:          0 :                         if (ret < 0)
    8712                 :          0 :                                 return ret;
    8713         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8714                 :            :                                 aso_after_sample = 1;
    8715                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_CT;
    8716                 :          0 :                         break;
    8717                 :            :                 case MLX5_RTE_FLOW_ACTION_TYPE_TUNNEL_SET:
    8718                 :            :                         /* tunnel offload action was processed before
    8719                 :            :                          * list it here as a supported type
    8720                 :            :                          */
    8721                 :            :                         break;
    8722                 :            : #ifdef HAVE_MLX5DV_DR_ACTION_CREATE_DEST_ROOT_TABLE
    8723                 :            :                 case RTE_FLOW_ACTION_TYPE_SEND_TO_KERNEL:
    8724                 :            :                         action_flags |= MLX5_FLOW_ACTION_SEND_TO_KERNEL;
    8725                 :            :                         ++actions_n;
    8726                 :            :                         break;
    8727                 :            : #endif
    8728                 :          0 :                 default:
    8729                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    8730                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    8731                 :            :                                                   actions,
    8732                 :            :                                                   "action not supported");
    8733                 :            :                 }
    8734                 :            :         }
    8735                 :            :         /*
    8736                 :            :          * Validate actions in flow rules
    8737                 :            :          * - Explicit decap action is prohibited by the tunnel offload API.
    8738                 :            :          * - Drop action in tunnel steer rule is prohibited by the API.
    8739                 :            :          * - Application cannot use MARK action because it's value can mask
    8740                 :            :          *   tunnel default miss notification.
    8741                 :            :          * - JUMP in tunnel match rule has no support in current PMD
    8742                 :            :          *   implementation.
    8743                 :            :          * - TAG & META are reserved for future uses.
    8744                 :            :          */
    8745         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_TUNNEL_SET) {
    8746                 :            :                 uint64_t bad_actions_mask = MLX5_FLOW_ACTION_DECAP    |
    8747                 :            :                                             MLX5_FLOW_ACTION_MARK     |
    8748                 :            :                                             MLX5_FLOW_ACTION_SET_TAG  |
    8749                 :            :                                             MLX5_FLOW_ACTION_SET_META |
    8750                 :            :                                             MLX5_FLOW_ACTION_DROP;
    8751                 :            : 
    8752         [ #  # ]:          0 :                 if (action_flags & bad_actions_mask)
    8753                 :          0 :                         return rte_flow_error_set
    8754                 :            :                                         (error, EINVAL,
    8755                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    8756                 :            :                                         "Invalid RTE action in tunnel "
    8757                 :            :                                         "set decap rule");
    8758         [ #  # ]:          0 :                 if (!(action_flags & MLX5_FLOW_ACTION_JUMP))
    8759                 :          0 :                         return rte_flow_error_set
    8760                 :            :                                         (error, EINVAL,
    8761                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    8762                 :            :                                         "tunnel set decap rule must terminate "
    8763                 :            :                                         "with JUMP");
    8764         [ #  # ]:          0 :                 if (attr->egress)
    8765                 :          0 :                         return rte_flow_error_set
    8766                 :            :                                         (error, EINVAL,
    8767                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    8768                 :            :                                         "tunnel flows for ingress and transfer traffic only");
    8769                 :            :         }
    8770         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_TUNNEL_MATCH) {
    8771                 :            :                 uint64_t bad_actions_mask = MLX5_FLOW_ACTION_JUMP    |
    8772                 :            :                                             MLX5_FLOW_ACTION_MARK    |
    8773                 :            :                                             MLX5_FLOW_ACTION_SET_TAG |
    8774                 :            :                                             MLX5_FLOW_ACTION_SET_META;
    8775                 :            : 
    8776         [ #  # ]:          0 :                 if (action_flags & bad_actions_mask)
    8777                 :          0 :                         return rte_flow_error_set
    8778                 :            :                                         (error, EINVAL,
    8779                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    8780                 :            :                                         "Invalid RTE action in tunnel "
    8781                 :            :                                         "set match rule");
    8782                 :            :         }
    8783                 :            :         /*
    8784                 :            :          * Validate the drop action mutual exclusion with other actions.
    8785                 :            :          * Drop action is mutually-exclusive with any other action, except for
    8786                 :            :          * Count/Sample/Age actions.
    8787                 :            :          * Drop action compatibility with tunnel offload was already validated.
    8788                 :            :          */
    8789         [ #  # ]:          0 :         if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_MATCH |
    8790                 :            :                             MLX5_FLOW_ACTION_TUNNEL_MATCH));
    8791         [ #  # ]:          0 :         else if ((action_flags & MLX5_FLOW_ACTION_DROP) &&
    8792         [ #  # ]:          0 :             (action_flags & ~(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_DROP_INCLUSIVE_ACTIONS)))
    8793                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    8794                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    8795                 :            :                                           "Drop action is mutually-exclusive "
    8796                 :            :                                           "with any other action, except for "
    8797                 :            :                                           "Count/Sample/Age action");
    8798                 :            :         /* Eswitch has few restrictions on using items and actions */
    8799         [ #  # ]:          0 :         if (attr->transfer) {
    8800         [ #  # ]:          0 :                 if (!mlx5_flow_ext_mreg_supported(dev) &&
    8801         [ #  # ]:          0 :                     action_flags & MLX5_FLOW_ACTION_FLAG)
    8802                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    8803                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    8804                 :            :                                                   NULL,
    8805                 :            :                                                   "unsupported action FLAG");
    8806         [ #  # ]:          0 :                 if (!mlx5_flow_ext_mreg_supported(dev) &&
    8807         [ #  # ]:          0 :                     action_flags & MLX5_FLOW_ACTION_MARK)
    8808                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    8809                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    8810                 :            :                                                   NULL,
    8811                 :            :                                                   "unsupported action MARK");
    8812         [ #  # ]:          0 :                 if (action_flags & MLX5_FLOW_ACTION_QUEUE)
    8813                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    8814                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    8815                 :            :                                                   NULL,
    8816                 :            :                                                   "unsupported action QUEUE");
    8817         [ #  # ]:          0 :                 if (action_flags & MLX5_FLOW_ACTION_RSS)
    8818                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    8819                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    8820                 :            :                                                   NULL,
    8821                 :            :                                                   "unsupported action RSS");
    8822         [ #  # ]:          0 :                 if (!(action_flags & MLX5_FLOW_FATE_ESWITCH_ACTIONS))
    8823                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    8824                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    8825                 :            :                                                   actions,
    8826                 :            :                                                   "no fate action is found");
    8827                 :            :         } else {
    8828   [ #  #  #  # ]:          0 :                 if (!(action_flags & MLX5_FLOW_FATE_ACTIONS) && attr->ingress)
    8829                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    8830                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    8831                 :            :                                                   actions,
    8832                 :            :                                                   "no fate action is found");
    8833                 :            :         }
    8834                 :            :         /*
    8835                 :            :          * Continue validation for Xcap and VLAN actions.
    8836                 :            :          * If hairpin is working in explicit TX rule mode, there is no actions
    8837                 :            :          * splitting and the validation of hairpin ingress flow should be the
    8838                 :            :          * same as other standard flows.
    8839                 :            :          */
    8840         [ #  # ]:          0 :         if ((action_flags & (MLX5_FLOW_XCAP_ACTIONS |
    8841         [ #  # ]:          0 :                              MLX5_FLOW_VLAN_ACTIONS)) &&
    8842   [ #  #  #  # ]:          0 :             (queue_index == 0xFFFF || !mlx5_rxq_is_hairpin(dev, queue_index) ||
    8843                 :          0 :              ((conf = mlx5_rxq_get_hairpin_conf(dev, queue_index)) != NULL &&
    8844         [ #  # ]:          0 :              conf->tx_explicit != 0))) {
    8845         [ #  # ]:          0 :                 if ((action_flags & MLX5_FLOW_XCAP_ACTIONS) ==
    8846                 :            :                     MLX5_FLOW_XCAP_ACTIONS)
    8847                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    8848                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    8849                 :            :                                                   NULL, "encap and decap "
    8850                 :            :                                                   "combination aren't supported");
    8851                 :            :                 /* Push VLAN is not supported in ingress except for NICs newer than CX5. */
    8852         [ #  # ]:          0 :                 if (action_flags & MLX5_FLOW_ACTION_OF_PUSH_VLAN) {
    8853                 :          0 :                         struct mlx5_dev_ctx_shared *sh = priv->sh;
    8854                 :            :                         bool direction_error = false;
    8855                 :            : 
    8856         [ #  # ]:          0 :                         if (attr->transfer) {
    8857         [ #  # ]:          0 :                                 bool fdb_tx = flow_source_vport_representor(priv, act_priv);
    8858                 :          0 :                                 bool is_cx5 = sh->steering_format_version ==
    8859                 :            :                                     MLX5_STEERING_LOGIC_FORMAT_CONNECTX_5;
    8860                 :            : 
    8861         [ #  # ]:          0 :                                 if (!fdb_tx && is_cx5)
    8862                 :            :                                         direction_error = true;
    8863         [ #  # ]:          0 :                         } else if (attr->ingress) {
    8864                 :            :                                 direction_error = true;
    8865                 :            :                         }
    8866                 :            :                         if (direction_error)
    8867                 :          0 :                                 return rte_flow_error_set(error, ENOTSUP,
    8868                 :            :                                                           RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
    8869                 :            :                                                           NULL,
    8870                 :            :                                                           "push VLAN action not supported "
    8871                 :            :                                                           "for ingress");
    8872                 :            :                 }
    8873         [ #  # ]:          0 :                 if (attr->ingress) {
    8874         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_ENCAP)
    8875                 :          0 :                                 return rte_flow_error_set
    8876                 :            :                                                 (error, ENOTSUP,
    8877                 :            :                                                  RTE_FLOW_ERROR_TYPE_ACTION,
    8878                 :            :                                                  NULL, "encap is not supported"
    8879                 :            :                                                  " for ingress traffic");
    8880         [ #  # ]:          0 :                         else if ((action_flags & MLX5_FLOW_VLAN_ACTIONS) ==
    8881                 :            :                                         MLX5_FLOW_VLAN_ACTIONS)
    8882                 :          0 :                                 return rte_flow_error_set
    8883                 :            :                                                 (error, ENOTSUP,
    8884                 :            :                                                  RTE_FLOW_ERROR_TYPE_ACTION,
    8885                 :            :                                                  NULL, "no support for "
    8886                 :            :                                                  "multiple VLAN actions");
    8887                 :            :                 }
    8888                 :            :         }
    8889                 :            :         /* Pop VLAN is not supported in egress except for NICs newer than CX5. */
    8890         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_OF_POP_VLAN) {
    8891                 :          0 :                 struct mlx5_dev_ctx_shared *sh = priv->sh;
    8892                 :            :                 bool direction_error = false;
    8893                 :            : 
    8894         [ #  # ]:          0 :                 if (attr->transfer) {
    8895         [ #  # ]:          0 :                         bool fdb_tx = flow_source_vport_representor(priv, act_priv);
    8896                 :          0 :                         bool is_cx5 = sh->steering_format_version ==
    8897                 :            :                                         MLX5_STEERING_LOGIC_FORMAT_CONNECTX_5;
    8898                 :            : 
    8899         [ #  # ]:          0 :                         if (fdb_tx && is_cx5)
    8900                 :            :                                 direction_error = true;
    8901         [ #  # ]:          0 :                 } else if (attr->egress) {
    8902                 :            :                         direction_error = true;
    8903                 :            :                 }
    8904                 :            :                 if (direction_error)
    8905                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    8906                 :            :                                                 RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
    8907                 :            :                                                 NULL,
    8908                 :            :                                                 "pop vlan action not supported for egress");
    8909                 :            :         }
    8910         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY) {
    8911         [ #  # ]:          0 :                 if ((action_flags & (MLX5_FLOW_FATE_ACTIONS &
    8912         [ #  # ]:          0 :                         ~MLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY)) &&
    8913                 :            :                         attr->ingress)
    8914                 :          0 :                         return rte_flow_error_set
    8915                 :            :                                 (error, ENOTSUP,
    8916                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION,
    8917                 :            :                                 NULL, "fate action not supported for "
    8918                 :            :                                 "meter with policy");
    8919         [ #  # ]:          0 :                 if (attr->egress) {
    8920         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS)
    8921                 :          0 :                                 return rte_flow_error_set
    8922                 :            :                                         (error, ENOTSUP,
    8923                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION,
    8924                 :            :                                         NULL, "modify header action in egress "
    8925                 :            :                                         "cannot be done before meter action");
    8926         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_ENCAP)
    8927                 :          0 :                                 return rte_flow_error_set
    8928                 :            :                                         (error, ENOTSUP,
    8929                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION,
    8930                 :            :                                         NULL, "encap action in egress "
    8931                 :            :                                         "cannot be done before meter action");
    8932         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_OF_PUSH_VLAN)
    8933                 :          0 :                                 return rte_flow_error_set
    8934                 :            :                                         (error, ENOTSUP,
    8935                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION,
    8936                 :            :                                         NULL, "push vlan action in egress "
    8937                 :            :                                         "cannot be done before meter action");
    8938                 :            :                 }
    8939                 :            :         }
    8940                 :            :         /*
    8941                 :            :          * Only support one ASO action in a single flow rule.
    8942                 :            :          * non-shared AGE + counter will fallback to use HW counter, no ASO hit object.
    8943                 :            :          * Group 0 uses HW counter for AGE too even if no counter action.
    8944                 :            :          */
    8945   [ #  #  #  # ]:          0 :         aso_mask = (action_flags & MLX5_FLOW_ACTION_METER && priv->sh->meter_aso_en) << 2 |
    8946   [ #  #  #  # ]:          0 :                    (action_flags & MLX5_FLOW_ACTION_CT && priv->sh->ct_aso_en) << 1 |
    8947                 :          0 :                    (action_flags & MLX5_FLOW_ACTION_AGE &&
    8948         [ #  # ]:          0 :                     !(non_shared_age && count) &&
    8949   [ #  #  #  #  :          0 :                     (attr->group || (attr->transfer && priv->fdb_def_rule)) &&
             #  #  #  # ]
    8950         [ #  # ]:          0 :                     priv->sh->flow_hit_aso_en);
    8951         [ #  # ]:          0 :         if (__builtin_popcountl(aso_mask) > 1)
    8952                 :          0 :                 return rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION,
    8953                 :            :                                           NULL, "unsupported combining AGE, METER, CT ASO actions in a single rule");
    8954                 :            :         /*
    8955                 :            :          * Hairpin flow will add one more TAG action in TX implicit mode.
    8956                 :            :          * In TX explicit mode, there will be no hairpin flow ID.
    8957                 :            :          */
    8958         [ #  # ]:          0 :         if (hairpin > 0)
    8959                 :          0 :                 rw_act_num += MLX5_ACT_NUM_SET_TAG;
    8960                 :            :         /* extra metadata enabled: one more TAG action will be add. */
    8961         [ #  # ]:          0 :         if (dev_conf->dv_flow_en &&
    8962   [ #  #  #  # ]:          0 :             dev_conf->dv_xmeta_en != MLX5_XMETA_MODE_LEGACY &&
    8963                 :          0 :             mlx5_flow_ext_mreg_supported(dev))
    8964                 :          0 :                 rw_act_num += MLX5_ACT_NUM_SET_TAG;
    8965         [ #  # ]:          0 :         if (rw_act_num >
    8966                 :            :                         flow_dv_modify_hdr_action_max(dev, is_root)) {
    8967                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    8968                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
    8969                 :            :                                           NULL, "too many header modify"
    8970                 :            :                                           " actions to support");
    8971                 :            :         }
    8972         [ #  # ]:          0 :         if (fdb_mirror) {
    8973   [ #  #  #  # ]:          0 :                 if (!priv->sh->cdev->config.hca_attr.reg_c_preserve &&
    8974         [ #  # ]:          0 :                     flow_source_vport_representor(priv, act_priv)) {
    8975                 :            :                         /* Eswitch egress mirror and modify flow has limitation on CX5 */
    8976         [ #  # ]:          0 :                         if (modify_after_mirror)
    8977                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    8978                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    8979                 :            :                                                 "sample before modify action is not supported");
    8980         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_JUMP)
    8981                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    8982                 :            :                                                         RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    8983                 :            :                                                         "sample and jump action combination is not supported");
    8984                 :            :                 }
    8985         [ #  # ]:          0 :                 if (aso_mask > 0 && aso_after_sample && fdb_mirror)
    8986                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    8987                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    8988                 :            :                                                   "sample before ASO action is not supported");
    8989         [ #  # ]:          0 :                 if (sub_action_flags & MLX5_FLOW_ACTION_PORT_ID) {
    8990                 :          0 :                         port_priv = mlx5_port_to_eswitch_info(sample_port_id, false);
    8991         [ #  # ]:          0 :                         if (flow_source_vport_representor(priv, port_priv)) {
    8992         [ #  # ]:          0 :                                 if (sub_action_flags & MLX5_FLOW_ACTION_ENCAP)
    8993                 :          0 :                                         return rte_flow_error_set(error, ENOTSUP,
    8994                 :            :                                                                 RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    8995                 :            :                                                                 "mirror to rep port with encap is not supported");
    8996                 :            :                         } else {
    8997         [ #  # ]:          0 :                                 if (!(sub_action_flags & MLX5_FLOW_ACTION_ENCAP) &&
    8998         [ #  # ]:          0 :                                     (action_flags & MLX5_FLOW_ACTION_JUMP))
    8999                 :          0 :                                         return rte_flow_error_set(error, ENOTSUP,
    9000                 :            :                                                                 RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    9001                 :            :                                                                 "mirror to wire port without encap is not supported");
    9002                 :            :                         }
    9003                 :            :                 }
    9004         [ #  # ]:          0 :                 if ((action_flags & MLX5_FLOW_ACTION_PORT_ID) &&
    9005                 :            :                     (action_flags & MLX5_FLOW_ACTION_ENCAP)) {
    9006                 :          0 :                         port_priv = mlx5_port_to_eswitch_info(port_id, false);
    9007         [ #  # ]:          0 :                         if (flow_source_vport_representor(priv, port_priv))
    9008                 :          0 :                                 return rte_flow_error_set(error, ENOTSUP,
    9009                 :            :                                                         RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    9010                 :            :                                                         "mirror to rep port with encap is not supported");
    9011                 :            :                 }
    9012                 :            :         }
    9013                 :            :         /*
    9014                 :            :          * Validation the NIC Egress flow on representor, except implicit
    9015                 :            :          * hairpin default egress flow with TX_QUEUE item, other flows not
    9016                 :            :          * work due to metadata regC0 mismatch.
    9017                 :            :          */
    9018   [ #  #  #  #  :          0 :         if (attr->egress && priv->representor && !(item_flags & MLX5_FLOW_ITEM_SQ))
                   #  # ]
    9019                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    9020                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM,
    9021                 :            :                                           NULL,
    9022                 :            :                                           "NIC egress rules on representors"
    9023                 :            :                                           " is not supported");
    9024                 :            :         return 0;
    9025                 :            : }
    9026                 :            : 
    9027                 :            : /**
    9028                 :            :  * Internal preparation function. Allocates the DV flow size,
    9029                 :            :  * this size is constant.
    9030                 :            :  *
    9031                 :            :  * @param[in] dev
    9032                 :            :  *   Pointer to the rte_eth_dev structure.
    9033                 :            :  * @param[in] attr
    9034                 :            :  *   Pointer to the flow attributes.
    9035                 :            :  * @param[in] items
    9036                 :            :  *   Pointer to the list of items.
    9037                 :            :  * @param[in] actions
    9038                 :            :  *   Pointer to the list of actions.
    9039                 :            :  * @param[out] error
    9040                 :            :  *   Pointer to the error structure.
    9041                 :            :  *
    9042                 :            :  * @return
    9043                 :            :  *   Pointer to mlx5_flow object on success,
    9044                 :            :  *   otherwise NULL and rte_errno is set.
    9045                 :            :  */
    9046                 :            : static struct mlx5_flow *
    9047                 :          0 : flow_dv_prepare(struct rte_eth_dev *dev,
    9048                 :            :                 const struct rte_flow_attr *attr __rte_unused,
    9049                 :            :                 const struct rte_flow_item items[] __rte_unused,
    9050                 :            :                 const struct rte_flow_action actions[] __rte_unused,
    9051                 :            :                 struct rte_flow_error *error)
    9052                 :            : {
    9053                 :          0 :         uint32_t handle_idx = 0;
    9054                 :            :         struct mlx5_flow *dev_flow;
    9055                 :            :         struct mlx5_flow_handle *dev_handle;
    9056                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    9057                 :          0 :         struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace();
    9058                 :            : 
    9059                 :            :         MLX5_ASSERT(wks);
    9060                 :          0 :         wks->skip_matcher_reg = 0;
    9061                 :          0 :         wks->policy = NULL;
    9062                 :          0 :         wks->final_policy = NULL;
    9063                 :          0 :         wks->vport_meta_tag = 0;
    9064                 :            :         /* In case of corrupting the memory. */
    9065         [ #  # ]:          0 :         if (wks->flow_idx >= MLX5_NUM_MAX_DEV_FLOWS) {
    9066                 :          0 :                 rte_flow_error_set(error, ENOSPC,
    9067                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    9068                 :            :                                    "not free temporary device flow");
    9069                 :          0 :                 return NULL;
    9070                 :            :         }
    9071                 :          0 :         dev_handle = mlx5_ipool_zmalloc(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW],
    9072                 :            :                                    &handle_idx);
    9073         [ #  # ]:          0 :         if (!dev_handle) {
    9074                 :          0 :                 rte_flow_error_set(error, ENOMEM,
    9075                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    9076                 :            :                                    "not enough memory to create flow handle");
    9077                 :          0 :                 return NULL;
    9078                 :            :         }
    9079                 :            :         MLX5_ASSERT(wks->flow_idx < RTE_DIM(wks->flows));
    9080                 :          0 :         dev_flow = &wks->flows[wks->flow_idx++];
    9081                 :            :         memset(dev_flow, 0, sizeof(*dev_flow));
    9082                 :          0 :         dev_flow->handle = dev_handle;
    9083                 :          0 :         dev_flow->handle_idx = handle_idx;
    9084                 :          0 :         dev_flow->dv.value.size = MLX5_ST_SZ_BYTES(fte_match_param);
    9085                 :          0 :         dev_flow->ingress = attr->ingress;
    9086                 :          0 :         dev_flow->dv.transfer = attr->transfer;
    9087                 :          0 :         return dev_flow;
    9088                 :            : }
    9089                 :            : 
    9090                 :            : #ifdef RTE_LIBRTE_MLX5_DEBUG
    9091                 :            : /**
    9092                 :            :  * Sanity check for match mask and value. Similar to check_valid_spec() in
    9093                 :            :  * kernel driver. If unmasked bit is present in value, it returns failure.
    9094                 :            :  *
    9095                 :            :  * @param match_mask
    9096                 :            :  *   pointer to match mask buffer.
    9097                 :            :  * @param match_value
    9098                 :            :  *   pointer to match value buffer.
    9099                 :            :  *
    9100                 :            :  * @return
    9101                 :            :  *   0 if valid, -EINVAL otherwise.
    9102                 :            :  */
    9103                 :            : static int
    9104                 :            : flow_dv_check_valid_spec(void *match_mask, void *match_value)
    9105                 :            : {
    9106                 :            :         uint8_t *m = match_mask;
    9107                 :            :         uint8_t *v = match_value;
    9108                 :            :         unsigned int i;
    9109                 :            : 
    9110                 :            :         for (i = 0; i < MLX5_ST_SZ_BYTES(fte_match_param); ++i) {
    9111                 :            :                 if (v[i] & ~m[i]) {
    9112                 :            :                         DRV_LOG(ERR,
    9113                 :            :                                 "match_value differs from match_criteria"
    9114                 :            :                                 " %p[%u] != %p[%u]",
    9115                 :            :                                 match_value, i, match_mask, i);
    9116                 :            :                         return -EINVAL;
    9117                 :            :                 }
    9118                 :            :         }
    9119                 :            :         return 0;
    9120                 :            : }
    9121                 :            : #endif
    9122                 :            : 
    9123                 :            : /**
    9124                 :            :  * Add match of ip_version.
    9125                 :            :  *
    9126                 :            :  * @param[in] group
    9127                 :            :  *   Flow group.
    9128                 :            :  * @param[in] headers_v
    9129                 :            :  *   Values header pointer.
    9130                 :            :  * @param[in] headers_m
    9131                 :            :  *   Masks header pointer.
    9132                 :            :  * @param[in] ip_version
    9133                 :            :  *   The IP version to set.
    9134                 :            :  */
    9135                 :            : static inline void
    9136                 :          0 : flow_dv_set_match_ip_version(uint32_t group,
    9137                 :            :                              void *headers_v,
    9138                 :            :                              uint32_t key_type,
    9139                 :            :                              uint8_t ip_version)
    9140                 :            : {
    9141   [ #  #  #  # ]:          0 :         if (group == 0 && (key_type & MLX5_SET_MATCHER_M))
    9142         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_version, 0xf);
    9143                 :            :         else
    9144         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_version,
    9145                 :            :                          ip_version);
    9146         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, ethertype, 0);
    9147                 :          0 : }
    9148                 :            : 
    9149                 :            : /**
    9150                 :            :  * Add Ethernet item to the value.
    9151                 :            :  *
    9152                 :            :  * @param[in, out] key
    9153                 :            :  *   Flow matcher value.
    9154                 :            :  * @param[in] item
    9155                 :            :  *   Flow pattern to translate.
    9156                 :            :  * @param[in] inner
    9157                 :            :  *   Item is inner pattern.
    9158                 :            :  * @param[in] grpup
    9159                 :            :  *   Flow matcher group.
    9160                 :            :  * @param[in] key_type
    9161                 :            :  *   Set flow matcher mask or value.
    9162                 :            :  */
    9163                 :            : static void
    9164                 :          0 : flow_dv_translate_item_eth(void *key, const struct rte_flow_item *item,
    9165                 :            :                            int inner, uint32_t group, uint32_t key_type)
    9166                 :            : {
    9167                 :          0 :         const struct rte_flow_item_eth *eth_vv = item->spec;
    9168                 :            :         const struct rte_flow_item_eth *eth_m;
    9169                 :            :         const struct rte_flow_item_eth *eth_v;
    9170                 :          0 :         const struct rte_flow_item_eth nic_mask = {
    9171                 :            :                 .hdr.dst_addr.addr_bytes = "\xff\xff\xff\xff\xff\xff",
    9172                 :            :                 .hdr.src_addr.addr_bytes = "\xff\xff\xff\xff\xff\xff",
    9173                 :            :                 .hdr.ether_type = RTE_BE16(0xffff),
    9174                 :            :                 .has_vlan = 0,
    9175                 :            :         };
    9176                 :            :         void *hdrs_v;
    9177                 :            :         char *l24_v;
    9178                 :            :         unsigned int i;
    9179                 :            : 
    9180   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
    9181                 :          0 :                 return;
    9182   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, eth_v, eth_m, &nic_mask);
             #  #  #  # ]
    9183         [ #  # ]:          0 :         if (!eth_vv)
    9184                 :            :                 eth_vv = eth_v;
    9185         [ #  # ]:          0 :         if (inner)
    9186                 :          0 :                 hdrs_v = MLX5_ADDR_OF(fte_match_param, key, inner_headers);
    9187                 :            :         else
    9188                 :            :                 hdrs_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
    9189                 :            :         /* The value must be in the range of the mask. */
    9190                 :            :         l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, hdrs_v, dmac_47_16);
    9191         [ #  # ]:          0 :         for (i = 0; i < sizeof(eth_m->hdr.dst_addr); ++i)
    9192                 :          0 :                 l24_v[i] = eth_m->hdr.dst_addr.addr_bytes[i] & eth_v->hdr.dst_addr.addr_bytes[i];
    9193                 :            :         l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, hdrs_v, smac_47_16);
    9194                 :            :         /* The value must be in the range of the mask. */
    9195         [ #  # ]:          0 :         for (i = 0; i < sizeof(eth_m->hdr.dst_addr); ++i)
    9196                 :          0 :                 l24_v[i] = eth_m->hdr.src_addr.addr_bytes[i] & eth_v->hdr.src_addr.addr_bytes[i];
    9197                 :            :         /*
    9198                 :            :          * HW supports match on one Ethertype, the Ethertype following the last
    9199                 :            :          * VLAN tag of the packet (see PRM).
    9200                 :            :          * Set match on ethertype only if ETH header is not followed by VLAN.
    9201                 :            :          * HW is optimized for IPv4/IPv6. In such cases, avoid setting
    9202                 :            :          * ethertype, and use ip_version field instead.
    9203                 :            :          * eCPRI over Ether layer will use type value 0xAEFE.
    9204                 :            :          */
    9205         [ #  # ]:          0 :         if (eth_m->hdr.ether_type == 0xFFFF) {
    9206                 :          0 :                 rte_be16_t type = eth_v->hdr.ether_type;
    9207                 :            : 
    9208                 :            :                 /*
    9209                 :            :                  * When set the matcher mask, refer to the original spec
    9210                 :            :                  * value.
    9211                 :            :                  */
    9212         [ #  # ]:          0 :                 if (key_type == MLX5_SET_MATCHER_SW_M) {
    9213         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, cvlan_tag, 1);
    9214                 :          0 :                         type = eth_vv->hdr.ether_type;
    9215                 :            :                 }
    9216                 :            :                 /* Set cvlan_tag mask for any single\multi\un-tagged case. */
    9217   [ #  #  #  #  :          0 :                 switch (type) {
                      # ]
    9218                 :          0 :                 case RTE_BE16(RTE_ETHER_TYPE_VLAN):
    9219         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, cvlan_tag, 1);
    9220                 :          0 :                         return;
    9221                 :          0 :                 case RTE_BE16(RTE_ETHER_TYPE_QINQ):
    9222         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, svlan_tag, 1);
    9223                 :          0 :                         return;
    9224                 :          0 :                 case RTE_BE16(RTE_ETHER_TYPE_IPV4):
    9225                 :          0 :                         flow_dv_set_match_ip_version(group, hdrs_v, key_type,
    9226                 :            :                                                      4);
    9227                 :          0 :                         return;
    9228                 :          0 :                 case RTE_BE16(RTE_ETHER_TYPE_IPV6):
    9229                 :          0 :                         flow_dv_set_match_ip_version(group, hdrs_v, key_type,
    9230                 :            :                                                      6);
    9231                 :          0 :                         return;
    9232                 :            :                 default:
    9233                 :            :                         break;
    9234                 :            :                 }
    9235                 :            :         }
    9236                 :            :         /*
    9237                 :            :          * Only SW steering value should refer to the mask value.
    9238                 :            :          * Other cases are using the fake masks, just ignore the mask.
    9239                 :            :          */
    9240   [ #  #  #  # ]:          0 :         if (eth_v->has_vlan && eth_m->has_vlan) {
    9241                 :            :                 /*
    9242                 :            :                  * Here, when also has_more_vlan field in VLAN item is
    9243                 :            :                  * not set, only single-tagged packets will be matched.
    9244                 :            :                  */
    9245         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, cvlan_tag, 1);
    9246   [ #  #  #  # ]:          0 :                 if (key_type != MLX5_SET_MATCHER_HS_M && eth_vv->has_vlan)
    9247                 :            :                         return;
    9248                 :            :         }
    9249                 :            :         l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, hdrs_v, ethertype);
    9250                 :          0 :         *(uint16_t *)(l24_v) = eth_m->hdr.ether_type & eth_v->hdr.ether_type;
    9251                 :            : }
    9252                 :            : 
    9253                 :            : /**
    9254                 :            :  * Add VLAN item to the value.
    9255                 :            :  *
    9256                 :            :  * @param[in, out] key
    9257                 :            :  *   Flow matcher value.
    9258                 :            :  * @param[in] item
    9259                 :            :  *   Flow pattern to translate.
    9260                 :            :  * @param[in] inner
    9261                 :            :  *   Item is inner pattern.
    9262                 :            :  * @param[in] wks
    9263                 :            :  *   Item workspace.
    9264                 :            :  * @param[in] key_type
    9265                 :            :  *   Set flow matcher mask or value.
    9266                 :            :  */
    9267                 :            : static void
    9268                 :          0 : flow_dv_translate_item_vlan(void *key, const struct rte_flow_item *item,
    9269                 :            :                             int inner, struct mlx5_dv_matcher_workspace *wks,
    9270                 :            :                             uint32_t key_type)
    9271                 :            : {
    9272                 :            :         const struct rte_flow_item_vlan *vlan_m;
    9273                 :            :         const struct rte_flow_item_vlan *vlan_v;
    9274                 :          0 :         const struct rte_flow_item_vlan *vlan_vv = item->spec;
    9275                 :            :         void *hdrs_v;
    9276                 :            :         uint16_t tci_v;
    9277                 :            : 
    9278         [ #  # ]:          0 :         if (inner) {
    9279                 :          0 :                 hdrs_v = MLX5_ADDR_OF(fte_match_param, key, inner_headers);
    9280                 :            :         } else {
    9281                 :            :                 hdrs_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
    9282                 :            :                 /*
    9283                 :            :                  * This is workaround, masks are not supported,
    9284                 :            :                  * and pre-validated.
    9285                 :            :                  */
    9286         [ #  # ]:          0 :                 if (vlan_vv)
    9287         [ #  # ]:          0 :                         wks->vlan_tag = rte_be_to_cpu_16(vlan_vv->hdr.vlan_tci) & 0x0fff;
    9288                 :            :         }
    9289                 :            :         /*
    9290                 :            :          * When VLAN item exists in flow, mark packet as tagged,
    9291                 :            :          * even if TCI is not specified.
    9292                 :            :          */
    9293   [ #  #  #  # ]:          0 :         if (!MLX5_GET(fte_match_set_lyr_2_4, hdrs_v, svlan_tag))
    9294         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, cvlan_tag, 1);
    9295   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
    9296                 :            :                 return;
    9297   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, vlan_v, vlan_m,
             #  #  #  # ]
    9298                 :            :                          &rte_flow_item_vlan_mask);
    9299         [ #  # ]:          0 :         tci_v = rte_be_to_cpu_16(vlan_m->hdr.vlan_tci & vlan_v->hdr.vlan_tci);
    9300         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, first_vid, tci_v);
    9301         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, first_cfi, tci_v >> 12);
    9302         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, first_prio, tci_v >> 13);
    9303                 :            :         /*
    9304                 :            :          * HW is optimized for IPv4/IPv6. In such cases, avoid setting
    9305                 :            :          * ethertype, and use ip_version field instead.
    9306                 :            :          */
    9307         [ #  # ]:          0 :         if (vlan_m->hdr.eth_proto == 0xFFFF) {
    9308                 :          0 :                 rte_be16_t inner_type = vlan_v->hdr.eth_proto;
    9309                 :            : 
    9310                 :            :                 /*
    9311                 :            :                  * When set the matcher mask, refer to the original spec
    9312                 :            :                  * value.
    9313                 :            :                  */
    9314         [ #  # ]:          0 :                 if (key_type == MLX5_SET_MATCHER_SW_M)
    9315                 :          0 :                         inner_type = vlan_vv->hdr.eth_proto;
    9316   [ #  #  #  # ]:          0 :                 switch (inner_type) {
    9317                 :          0 :                 case RTE_BE16(RTE_ETHER_TYPE_VLAN):
    9318         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, svlan_tag, 1);
    9319         [ #  # ]:          0 :                         if (key_type & MLX5_SET_MATCHER_V)
    9320         [ #  # ]:          0 :                                 MLX5_SET(fte_match_set_lyr_2_4, hdrs_v,
    9321                 :            :                                          cvlan_tag, 0);
    9322                 :          0 :                         return;
    9323                 :          0 :                 case RTE_BE16(RTE_ETHER_TYPE_IPV4):
    9324                 :          0 :                         flow_dv_set_match_ip_version
    9325                 :            :                                 (wks->group, hdrs_v, key_type, 4);
    9326                 :          0 :                         return;
    9327                 :          0 :                 case RTE_BE16(RTE_ETHER_TYPE_IPV6):
    9328                 :          0 :                         flow_dv_set_match_ip_version
    9329                 :            :                                 (wks->group, hdrs_v, key_type, 6);
    9330                 :          0 :                         return;
    9331                 :            :                 default:
    9332                 :            :                         break;
    9333                 :            :                 }
    9334                 :            :         }
    9335   [ #  #  #  # ]:          0 :         if (vlan_m->has_more_vlan && vlan_v->has_more_vlan) {
    9336         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, svlan_tag, 1);
    9337                 :            :                 /* Only one vlan_tag bit can be set. */
    9338         [ #  # ]:          0 :                 if (key_type & MLX5_SET_MATCHER_V)
    9339         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, cvlan_tag, 0);
    9340                 :          0 :                 return;
    9341                 :            :         }
    9342   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, ethertype,
    9343                 :            :                  rte_be_to_cpu_16(vlan_m->hdr.eth_proto & vlan_v->hdr.eth_proto));
    9344                 :            : }
    9345                 :            : 
    9346                 :            : /**
    9347                 :            :  * Add IPV4 item to the value.
    9348                 :            :  *
    9349                 :            :  * @param[in, out] key
    9350                 :            :  *   Flow matcher value.
    9351                 :            :  * @param[in] item
    9352                 :            :  *   Flow pattern to translate.
    9353                 :            :  * @param[in] inner
    9354                 :            :  *   Item is inner pattern.
    9355                 :            :  * @param[in] group
    9356                 :            :  *   The group to insert the rule.
    9357                 :            :  * @param[in] key_type
    9358                 :            :  *   Set flow matcher mask or value.
    9359                 :            :  */
    9360                 :            : static void
    9361                 :          0 : flow_dv_translate_item_ipv4(void *key, const struct rte_flow_item *item,
    9362                 :            :                             int inner, uint32_t group, uint32_t key_type)
    9363                 :            : {
    9364                 :            :         const struct rte_flow_item_ipv4 *ipv4_m;
    9365                 :            :         const struct rte_flow_item_ipv4 *ipv4_v;
    9366                 :          0 :         const struct rte_flow_item_ipv4 nic_mask = {
    9367                 :            :                 .hdr = {
    9368                 :            :                         .src_addr = RTE_BE32(0xffffffff),
    9369                 :            :                         .dst_addr = RTE_BE32(0xffffffff),
    9370                 :            :                         .type_of_service = 0xff,
    9371                 :            :                         .next_proto_id = 0xff,
    9372                 :            :                         .time_to_live = 0xff,
    9373                 :            :                 },
    9374                 :            :         };
    9375                 :            :         void *headers_v;
    9376                 :            :         char *l24_v;
    9377                 :            :         uint8_t tos;
    9378                 :            : 
    9379         [ #  # ]:          0 :         headers_v = inner ? MLX5_ADDR_OF(fte_match_param, key, inner_headers) :
    9380                 :            :                             MLX5_ADDR_OF(fte_match_param, key, outer_headers);
    9381                 :          0 :         flow_dv_set_match_ip_version(group, headers_v, key_type, 4);
    9382   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
    9383                 :          0 :                 return;
    9384   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, ipv4_v, ipv4_m, &nic_mask);
             #  #  #  # ]
    9385                 :            :         l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
    9386                 :            :                              dst_ipv4_dst_ipv6.ipv4_layout.ipv4);
    9387                 :          0 :         *(uint32_t *)l24_v = ipv4_m->hdr.dst_addr & ipv4_v->hdr.dst_addr;
    9388                 :            :         l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
    9389                 :            :                           src_ipv4_src_ipv6.ipv4_layout.ipv4);
    9390                 :          0 :         *(uint32_t *)l24_v = ipv4_m->hdr.src_addr & ipv4_v->hdr.src_addr;
    9391                 :          0 :         tos = ipv4_m->hdr.type_of_service & ipv4_v->hdr.type_of_service;
    9392         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, ipv4_ihl,
    9393                 :            :                  ipv4_v->hdr.ihl & ipv4_m->hdr.ihl);
    9394         [ #  # ]:          0 :         if (key_type == MLX5_SET_MATCHER_SW_M)
    9395         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_ecn,
    9396                 :            :                          ipv4_v->hdr.type_of_service);
    9397         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_ecn, tos);
    9398         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_dscp, tos >> 2);
    9399         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol,
    9400                 :            :                  ipv4_v->hdr.next_proto_id & ipv4_m->hdr.next_proto_id);
    9401         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_ttl_hoplimit,
    9402                 :            :                  ipv4_v->hdr.time_to_live & ipv4_m->hdr.time_to_live);
    9403         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, frag,
    9404                 :            :                  !!(ipv4_v->hdr.fragment_offset & ipv4_m->hdr.fragment_offset));
    9405                 :            : }
    9406                 :            : 
    9407                 :            : /**
    9408                 :            :  * Add IPV6 item to the value.
    9409                 :            :  *
    9410                 :            :  * @param[in, out] key
    9411                 :            :  *   Flow matcher value.
    9412                 :            :  * @param[in] item
    9413                 :            :  *   Flow pattern to translate.
    9414                 :            :  * @param[in] inner
    9415                 :            :  *   Item is inner pattern.
    9416                 :            :  * @param[in] group
    9417                 :            :  *   The group to insert the rule.
    9418                 :            :  * @param[in] key_type
    9419                 :            :  *   Set flow matcher mask or value.
    9420                 :            :  */
    9421                 :            : static void
    9422                 :          0 : flow_dv_translate_item_ipv6(void *key, const struct rte_flow_item *item,
    9423                 :            :                             int inner, uint32_t group, uint32_t key_type)
    9424                 :            : {
    9425                 :            :         const struct rte_flow_item_ipv6 *ipv6_m;
    9426                 :            :         const struct rte_flow_item_ipv6 *ipv6_v;
    9427                 :          0 :         const struct rte_flow_item_ipv6 nic_mask = {
    9428                 :            :                 .hdr = {
    9429                 :            :                         .src_addr =
    9430                 :            :                                 "\xff\xff\xff\xff\xff\xff\xff\xff"
    9431                 :            :                                 "\xff\xff\xff\xff\xff\xff\xff\xff",
    9432                 :            :                         .dst_addr =
    9433                 :            :                                 "\xff\xff\xff\xff\xff\xff\xff\xff"
    9434                 :            :                                 "\xff\xff\xff\xff\xff\xff\xff\xff",
    9435                 :            :                         .vtc_flow = RTE_BE32(0xffffffff),
    9436                 :            :                         .proto = 0xff,
    9437                 :            :                         .hop_limits = 0xff,
    9438                 :            :                 },
    9439                 :            :         };
    9440                 :            :         void *headers_v;
    9441                 :            :         void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
    9442                 :            :         char *l24_v;
    9443                 :            :         uint32_t vtc_v;
    9444                 :            :         int i;
    9445                 :            :         int size;
    9446                 :            : 
    9447         [ #  # ]:          0 :         headers_v = inner ? MLX5_ADDR_OF(fte_match_param, key, inner_headers) :
    9448                 :            :                             MLX5_ADDR_OF(fte_match_param, key, outer_headers);
    9449                 :          0 :         flow_dv_set_match_ip_version(group, headers_v, key_type, 6);
    9450   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
    9451                 :          0 :                 return;
    9452   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, ipv6_v, ipv6_m, &nic_mask);
             #  #  #  # ]
    9453                 :            :         size = sizeof(ipv6_m->hdr.dst_addr);
    9454                 :            :         l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
    9455                 :            :                              dst_ipv4_dst_ipv6.ipv6_layout.ipv6);
    9456         [ #  # ]:          0 :         for (i = 0; i < size; ++i)
    9457                 :          0 :                 l24_v[i] = ipv6_m->hdr.dst_addr[i] & ipv6_v->hdr.dst_addr[i];
    9458                 :            :         l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
    9459                 :            :                              src_ipv4_src_ipv6.ipv6_layout.ipv6);
    9460         [ #  # ]:          0 :         for (i = 0; i < size; ++i)
    9461                 :          0 :                 l24_v[i] = ipv6_m->hdr.src_addr[i] & ipv6_v->hdr.src_addr[i];
    9462                 :            :         /* TOS. */
    9463         [ #  # ]:          0 :         vtc_v = rte_be_to_cpu_32(ipv6_m->hdr.vtc_flow & ipv6_v->hdr.vtc_flow);
    9464         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_ecn, vtc_v >> 20);
    9465         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_dscp, vtc_v >> 22);
    9466                 :            :         /* Label. */
    9467         [ #  # ]:          0 :         if (inner)
    9468         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc, misc_v, inner_ipv6_flow_label,
    9469                 :            :                          vtc_v);
    9470                 :            :         else
    9471         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc, misc_v, outer_ipv6_flow_label,
    9472                 :            :                          vtc_v);
    9473                 :            :         /* Protocol. */
    9474         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol,
    9475                 :            :                  ipv6_v->hdr.proto & ipv6_m->hdr.proto);
    9476                 :            :         /* Hop limit. */
    9477         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_ttl_hoplimit,
    9478                 :            :                  ipv6_v->hdr.hop_limits & ipv6_m->hdr.hop_limits);
    9479         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, frag,
    9480                 :            :                  !!(ipv6_v->has_frag_ext & ipv6_m->has_frag_ext));
    9481                 :            : }
    9482                 :            : 
    9483                 :            : /**
    9484                 :            :  * Add IPV6 fragment extension item to the value.
    9485                 :            :  *
    9486                 :            :  * @param[in, out] key
    9487                 :            :  *   Flow matcher value.
    9488                 :            :  * @param[in] item
    9489                 :            :  *   Flow pattern to translate.
    9490                 :            :  * @param[in] inner
    9491                 :            :  *   Item is inner pattern.
    9492                 :            :  * @param[in] key_type
    9493                 :            :  *   Set flow matcher mask or value.
    9494                 :            :  */
    9495                 :            : static void
    9496                 :          0 : flow_dv_translate_item_ipv6_frag_ext(void *key,
    9497                 :            :                                      const struct rte_flow_item *item,
    9498                 :            :                                      int inner, uint32_t key_type)
    9499                 :            : {
    9500                 :            :         const struct rte_flow_item_ipv6_frag_ext *ipv6_frag_ext_m;
    9501                 :            :         const struct rte_flow_item_ipv6_frag_ext *ipv6_frag_ext_v;
    9502                 :          0 :         const struct rte_flow_item_ipv6_frag_ext nic_mask = {
    9503                 :            :                 .hdr = {
    9504                 :            :                         .next_header = 0xff,
    9505                 :            :                         .frag_data = RTE_BE16(0xffff),
    9506                 :            :                 },
    9507                 :            :         };
    9508                 :            :         void *headers_v;
    9509                 :            : 
    9510         [ #  # ]:          0 :         headers_v = inner ? MLX5_ADDR_OF(fte_match_param, key, inner_headers) :
    9511                 :            :                             MLX5_ADDR_OF(fte_match_param, key, outer_headers);
    9512                 :            :         /* IPv6 fragment extension item exists, so packet is IP fragment. */
    9513         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, frag, 1);
    9514   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
    9515                 :          0 :                 return;
    9516   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, ipv6_frag_ext_v,
             #  #  #  # ]
    9517                 :            :                          ipv6_frag_ext_m, &nic_mask);
    9518         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol,
    9519                 :            :                  ipv6_frag_ext_v->hdr.next_header &
    9520                 :            :                  ipv6_frag_ext_m->hdr.next_header);
    9521                 :            : }
    9522                 :            : 
    9523                 :            : /**
    9524                 :            :  * Add TCP item to the value.
    9525                 :            :  *
    9526                 :            :  * @param[in, out] key
    9527                 :            :  *   Flow matcher value.
    9528                 :            :  * @param[in] item
    9529                 :            :  *   Flow pattern to translate.
    9530                 :            :  * @param[in] inner
    9531                 :            :  *   Item is inner pattern.
    9532                 :            :  * @param[in] key_type
    9533                 :            :  *   Set flow matcher mask or value.
    9534                 :            :  */
    9535                 :            : static void
    9536                 :          0 : flow_dv_translate_item_tcp(void *key, const struct rte_flow_item *item,
    9537                 :            :                            int inner, uint32_t key_type)
    9538                 :            : {
    9539                 :            :         const struct rte_flow_item_tcp *tcp_m;
    9540                 :            :         const struct rte_flow_item_tcp *tcp_v;
    9541                 :            :         void *headers_v;
    9542                 :            : 
    9543         [ #  # ]:          0 :         headers_v = inner ? MLX5_ADDR_OF(fte_match_param, key, inner_headers) :
    9544                 :            :                 MLX5_ADDR_OF(fte_match_param, key, outer_headers);
    9545         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M)
    9546         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
    9547                 :            :                          ip_protocol, 0xff);
    9548                 :            :         else
    9549         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
    9550                 :            :                          ip_protocol, IPPROTO_TCP);
    9551   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
    9552                 :            :                 return;
    9553   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, tcp_v, tcp_m,
             #  #  #  # ]
    9554                 :            :                          &rte_flow_item_tcp_mask);
    9555   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, tcp_sport,
    9556                 :            :                  rte_be_to_cpu_16(tcp_v->hdr.src_port & tcp_m->hdr.src_port));
    9557   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, tcp_dport,
    9558                 :            :                  rte_be_to_cpu_16(tcp_v->hdr.dst_port & tcp_m->hdr.dst_port));
    9559         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, tcp_flags,
    9560                 :            :                  tcp_v->hdr.tcp_flags & tcp_m->hdr.tcp_flags);
    9561                 :            : }
    9562                 :            : 
    9563                 :            : /**
    9564                 :            :  * Add ESP item to the value.
    9565                 :            :  *
    9566                 :            :  * @param[in, out] key
    9567                 :            :  *   Flow matcher value.
    9568                 :            :  * @param[in] item
    9569                 :            :  *   Flow pattern to translate.
    9570                 :            :  * @param[in] inner
    9571                 :            :  *   Item is inner pattern.
    9572                 :            :  * @param[in] key_type
    9573                 :            :  *   Set flow matcher mask or value.
    9574                 :            :  */
    9575                 :            : static void
    9576                 :          0 : flow_dv_translate_item_esp(void *key, const struct rte_flow_item *item,
    9577                 :            :                            int inner, uint32_t key_type)
    9578                 :            : {
    9579                 :            :         const struct rte_flow_item_esp *esp_m;
    9580                 :            :         const struct rte_flow_item_esp *esp_v;
    9581                 :            :         void *headers_v;
    9582                 :            :         char *spi_v;
    9583                 :            : 
    9584         [ #  # ]:          0 :         headers_v = inner ? MLX5_ADDR_OF(fte_match_param, key, inner_headers) :
    9585                 :            :                 MLX5_ADDR_OF(fte_match_param, key, outer_headers);
    9586         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M)
    9587         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
    9588                 :            :                          ip_protocol, 0xff);
    9589                 :            :         else
    9590         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
    9591                 :            :                          ip_protocol, IPPROTO_ESP);
    9592   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
    9593                 :            :                 return;
    9594   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, esp_v, esp_m,
             #  #  #  # ]
    9595                 :            :                          &rte_flow_item_esp_mask);
    9596                 :            :         headers_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
    9597                 :            :         spi_v = inner ? MLX5_ADDR_OF(fte_match_set_misc, headers_v,
    9598         [ #  # ]:          0 :                                 inner_esp_spi) : MLX5_ADDR_OF(fte_match_set_misc
    9599                 :            :                                 , headers_v, outer_esp_spi);
    9600                 :          0 :         *(uint32_t *)spi_v = esp_m->hdr.spi & esp_v->hdr.spi;
    9601                 :            : }
    9602                 :            : 
    9603                 :            : /**
    9604                 :            :  * Add UDP item to the value.
    9605                 :            :  *
    9606                 :            :  * @param[in, out] key
    9607                 :            :  *   Flow matcher value.
    9608                 :            :  * @param[in] item
    9609                 :            :  *   Flow pattern to translate.
    9610                 :            :  * @param[in] inner
    9611                 :            :  *   Item is inner pattern.
    9612                 :            :  * @param[in] key_type
    9613                 :            :  *   Set flow matcher mask or value.
    9614                 :            :  */
    9615                 :            : static void
    9616                 :          0 : flow_dv_translate_item_udp(void *key, const struct rte_flow_item *item,
    9617                 :            :                            int inner, struct mlx5_dv_matcher_workspace *wks,
    9618                 :            :                            uint32_t key_type)
    9619                 :            : {
    9620                 :            :         const struct rte_flow_item_udp *udp_m;
    9621                 :            :         const struct rte_flow_item_udp *udp_v;
    9622                 :            :         void *headers_v;
    9623                 :            : 
    9624         [ #  # ]:          0 :         headers_v = inner ? MLX5_ADDR_OF(fte_match_param, key, inner_headers) :
    9625                 :            :                 MLX5_ADDR_OF(fte_match_param, key, outer_headers);
    9626         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M)
    9627         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
    9628                 :            :                          ip_protocol, 0xff);
    9629                 :            :         else
    9630         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
    9631                 :            :                          ip_protocol, IPPROTO_UDP);
    9632   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
    9633                 :            :                 return;
    9634   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, udp_v, udp_m,
             #  #  #  # ]
    9635                 :            :                          &rte_flow_item_udp_mask);
    9636   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_sport,
    9637                 :            :                  rte_be_to_cpu_16(udp_v->hdr.src_port & udp_m->hdr.src_port));
    9638   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_dport,
    9639                 :            :                  rte_be_to_cpu_16(udp_v->hdr.dst_port & udp_m->hdr.dst_port));
    9640                 :            :         /* Force get UDP dport in case to be used in VXLAN translate. */
    9641         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_SW) {
    9642                 :          0 :                 udp_v = item->spec;
    9643         [ #  # ]:          0 :                 wks->udp_dport = rte_be_to_cpu_16(udp_v->hdr.dst_port &
    9644                 :            :                                                   udp_m->hdr.dst_port);
    9645                 :            :         }
    9646                 :            : }
    9647                 :            : 
    9648                 :            : /**
    9649                 :            :  * Add GRE optional Key item to the value.
    9650                 :            :  *
    9651                 :            :  * @param[in, out] key
    9652                 :            :  *   Flow matcher value.
    9653                 :            :  * @param[in] item
    9654                 :            :  *   Flow pattern to translate.
    9655                 :            :  * @param[in] inner
    9656                 :            :  *   Item is inner pattern.
    9657                 :            :  */
    9658                 :            : static void
    9659                 :          0 : flow_dv_translate_item_gre_key(void *key, const struct rte_flow_item *item,
    9660                 :            :                                uint32_t key_type)
    9661                 :            : {
    9662                 :            :         const rte_be32_t *key_m;
    9663                 :            :         const rte_be32_t *key_v;
    9664                 :            :         void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
    9665                 :          0 :         rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX);
    9666                 :            : 
    9667                 :            :         /* GRE K bit must be on and should already be validated */
    9668         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, gre_k_present, 1);
    9669   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
    9670                 :          0 :                 return;
    9671   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, key_v, key_m,
             #  #  #  # ]
    9672                 :            :                          &gre_key_default_mask);
    9673   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, gre_key_h,
    9674                 :            :                  rte_be_to_cpu_32((*key_v) & (*key_m)) >> 8);
    9675   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, gre_key_l,
    9676                 :            :                  rte_be_to_cpu_32((*key_v) & (*key_m)) & 0xFF);
    9677                 :            : }
    9678                 :            : 
    9679                 :            : /**
    9680                 :            :  * Add GRE 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] pattern_flags
    9687                 :            :  *   Accumulated pattern flags.
    9688                 :            :  * @param[in] key_type
    9689                 :            :  *   Set flow matcher mask or value.
    9690                 :            :  */
    9691                 :            : static void
    9692                 :          0 : flow_dv_translate_item_gre(void *key, const struct rte_flow_item *item,
    9693                 :            :                            uint64_t pattern_flags, uint32_t key_type)
    9694                 :            : {
    9695                 :            :         static const struct rte_flow_item_gre empty_gre = {0,};
    9696                 :          0 :         const struct rte_flow_item_gre *gre_m = item->mask;
    9697                 :          0 :         const struct rte_flow_item_gre *gre_v = item->spec;
    9698                 :            :         void *headers_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
    9699                 :            :         void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
    9700                 :            :         struct {
    9701                 :            :                 union {
    9702                 :            :                         __extension__
    9703                 :            :                         struct {
    9704                 :            :                                 uint16_t version:3;
    9705                 :            :                                 uint16_t rsvd0:9;
    9706                 :            :                                 uint16_t s_present:1;
    9707                 :            :                                 uint16_t k_present:1;
    9708                 :            :                                 uint16_t rsvd_bit1:1;
    9709                 :            :                                 uint16_t c_present:1;
    9710                 :            :                         };
    9711                 :            :                         uint16_t value;
    9712                 :            :                 };
    9713                 :            :         } gre_crks_rsvd0_ver_m, gre_crks_rsvd0_ver_v;
    9714                 :            :         uint16_t protocol_m, protocol_v;
    9715                 :            : 
    9716         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M)
    9717         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol, 0xff);
    9718                 :            :         else
    9719         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol,
    9720                 :            :                          IPPROTO_GRE);
    9721         [ #  # ]:          0 :         if (!gre_v) {
    9722                 :            :                 gre_v = &empty_gre;
    9723                 :            :                 gre_m = &empty_gre;
    9724                 :            :         } else {
    9725         [ #  # ]:          0 :                 if (!gre_m)
    9726                 :            :                         gre_m = &rte_flow_item_gre_mask;
    9727                 :            :         }
    9728         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M)
    9729                 :            :                 gre_v = gre_m;
    9730         [ #  # ]:          0 :         else if (key_type == MLX5_SET_MATCHER_HS_V)
    9731                 :            :                 gre_m = gre_v;
    9732         [ #  # ]:          0 :         gre_crks_rsvd0_ver_m.value = rte_be_to_cpu_16(gre_m->c_rsvd0_ver);
    9733         [ #  # ]:          0 :         gre_crks_rsvd0_ver_v.value = rte_be_to_cpu_16(gre_v->c_rsvd0_ver);
    9734         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, gre_c_present,
    9735                 :            :                  gre_crks_rsvd0_ver_v.c_present &
    9736                 :            :                  gre_crks_rsvd0_ver_m.c_present);
    9737         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, gre_k_present,
    9738                 :            :                  gre_crks_rsvd0_ver_v.k_present &
    9739                 :            :                  gre_crks_rsvd0_ver_m.k_present);
    9740         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, gre_s_present,
    9741                 :            :                  gre_crks_rsvd0_ver_v.s_present &
    9742                 :            :                  gre_crks_rsvd0_ver_m.s_present);
    9743         [ #  # ]:          0 :         protocol_m = rte_be_to_cpu_16(gre_m->protocol);
    9744         [ #  # ]:          0 :         protocol_v = rte_be_to_cpu_16(gre_v->protocol);
    9745         [ #  # ]:          0 :         if (!protocol_m) {
    9746                 :            :                 /* Force next protocol to prevent matchers duplication */
    9747                 :            :                 protocol_v = mlx5_translate_tunnel_etypes(pattern_flags);
    9748                 :            :                 if (protocol_v)
    9749                 :            :                         protocol_m = 0xFFFF;
    9750                 :            :                 /* Restore the value to mask in mask case. */
    9751         [ #  # ]:          0 :                 if (key_type & MLX5_SET_MATCHER_M)
    9752                 :            :                         protocol_v = protocol_m;
    9753                 :            :         }
    9754         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, gre_protocol,
    9755                 :            :                  protocol_m & protocol_v);
    9756                 :          0 : }
    9757                 :            : 
    9758                 :            : /**
    9759                 :            :  * Add GRE optional items to the value.
    9760                 :            :  *
    9761                 :            :  * @param[in, out] key
    9762                 :            :  *   Flow matcher value.
    9763                 :            :  * @param[in] item
    9764                 :            :  *   Flow pattern to translate.
    9765                 :            :  * @param[in] gre_item
    9766                 :            :  *   Pointer to gre_item.
    9767                 :            :  * @param[in] pattern_flags
    9768                 :            :  *   Accumulated pattern flags.
    9769                 :            :  * @param[in] key_type
    9770                 :            :  *   Set flow matcher mask or value.
    9771                 :            :  */
    9772                 :            : static void
    9773                 :          0 : flow_dv_translate_item_gre_option(void *key,
    9774                 :            :                                   const struct rte_flow_item *item,
    9775                 :            :                                   const struct rte_flow_item *gre_item,
    9776                 :            :                                   uint64_t pattern_flags, uint32_t key_type)
    9777                 :            : {
    9778                 :            :         void *misc5_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_5);
    9779                 :          0 :         const struct rte_flow_item_gre_opt *option_m = item->mask;
    9780                 :          0 :         const struct rte_flow_item_gre_opt *option_v = item->spec;
    9781                 :          0 :         const struct rte_flow_item_gre *gre_m = gre_item->mask;
    9782                 :          0 :         const struct rte_flow_item_gre *gre_v = gre_item->spec;
    9783                 :            :         static const struct rte_flow_item_gre empty_gre = {0};
    9784                 :            :         struct rte_flow_item gre_key_item;
    9785                 :            :         uint16_t c_rsvd0_ver_m, c_rsvd0_ver_v;
    9786                 :            :         uint16_t protocol_m, protocol_v;
    9787                 :            : 
    9788                 :            :         /*
    9789                 :            :          * If only match key field, keep using misc for matching.
    9790                 :            :          * If need to match checksum or sequence, using misc5 and do
    9791                 :            :          * not need using misc.
    9792                 :            :          */
    9793         [ #  # ]:          0 :         if (!(option_m->sequence.sequence ||
    9794         [ #  # ]:          0 :               option_m->checksum_rsvd.checksum)) {
    9795                 :          0 :                 flow_dv_translate_item_gre(key, gre_item, pattern_flags, key_type);
    9796                 :          0 :                 gre_key_item.spec = &option_v->key.key;
    9797                 :          0 :                 gre_key_item.mask = &option_m->key.key;
    9798                 :          0 :                 flow_dv_translate_item_gre_key(key, &gre_key_item, key_type);
    9799                 :          0 :                 return;
    9800                 :            :         }
    9801         [ #  # ]:          0 :         if (!gre_v) {
    9802                 :            :                 gre_v = &empty_gre;
    9803                 :            :                 gre_m = &empty_gre;
    9804                 :            :         } else {
    9805         [ #  # ]:          0 :                 if (!gre_m)
    9806                 :            :                         gre_m = &rte_flow_item_gre_mask;
    9807                 :            :         }
    9808                 :          0 :         protocol_v = gre_v->protocol;
    9809                 :          0 :         protocol_m = gre_m->protocol;
    9810         [ #  # ]:          0 :         if (!protocol_m) {
    9811                 :            :                 /* Force next protocol to prevent matchers duplication */
    9812                 :            :                 uint16_t ether_type =
    9813                 :            :                         mlx5_translate_tunnel_etypes(pattern_flags);
    9814                 :            :                 if (ether_type) {
    9815         [ #  # ]:          0 :                         protocol_v = rte_be_to_cpu_16(ether_type);
    9816                 :            :                         protocol_m = UINT16_MAX;
    9817                 :            :                 }
    9818                 :            :         }
    9819                 :          0 :         c_rsvd0_ver_v = gre_v->c_rsvd0_ver;
    9820                 :          0 :         c_rsvd0_ver_m = gre_m->c_rsvd0_ver;
    9821         [ #  # ]:          0 :         if (option_m->sequence.sequence) {
    9822                 :          0 :                 c_rsvd0_ver_v |= RTE_BE16(0x1000);
    9823                 :          0 :                 c_rsvd0_ver_m |= RTE_BE16(0x1000);
    9824                 :            :         }
    9825         [ #  # ]:          0 :         if (option_m->key.key) {
    9826                 :          0 :                 c_rsvd0_ver_v |= RTE_BE16(0x2000);
    9827                 :          0 :                 c_rsvd0_ver_m |= RTE_BE16(0x2000);
    9828                 :            :         }
    9829         [ #  # ]:          0 :         if (option_m->checksum_rsvd.checksum) {
    9830                 :          0 :                 c_rsvd0_ver_v |= RTE_BE16(0x8000);
    9831                 :          0 :                 c_rsvd0_ver_m |= RTE_BE16(0x8000);
    9832                 :            :         }
    9833         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M) {
    9834                 :            :                 c_rsvd0_ver_v = c_rsvd0_ver_m;
    9835                 :            :                 protocol_v = protocol_m;
    9836                 :            :                 option_v = option_m;
    9837                 :            :         }
    9838                 :            :         /*
    9839                 :            :          * Hardware parses GRE optional field into the fixed location,
    9840                 :            :          * do not need to adjust the tunnel dword indices.
    9841                 :            :          */
    9842   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_misc5, misc5_v, tunnel_header_0,
    9843                 :            :                  rte_be_to_cpu_32((c_rsvd0_ver_v | protocol_v << 16) &
    9844                 :            :                                   (c_rsvd0_ver_m | protocol_m << 16)));
    9845   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_misc5, misc5_v, tunnel_header_1,
    9846                 :            :                  rte_be_to_cpu_32(option_v->checksum_rsvd.checksum &
    9847                 :            :                                   option_m->checksum_rsvd.checksum));
    9848   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_misc5, misc5_v, tunnel_header_2,
    9849                 :            :                  rte_be_to_cpu_32(option_v->key.key & option_m->key.key));
    9850   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_misc5, misc5_v, tunnel_header_3,
    9851                 :            :                  rte_be_to_cpu_32(option_v->sequence.sequence &
    9852                 :            :                                   option_m->sequence.sequence));
    9853                 :            : }
    9854                 :            : 
    9855                 :            : /**
    9856                 :            :  * Add NVGRE item to matcher and to the value.
    9857                 :            :  *
    9858                 :            :  * @param[in, out] key
    9859                 :            :  *   Flow matcher value.
    9860                 :            :  * @param[in] item
    9861                 :            :  *   Flow pattern to translate.
    9862                 :            :  * @param[in] pattern_flags
    9863                 :            :  *   Accumulated pattern flags.
    9864                 :            :  * @param[in] key_type
    9865                 :            :  *   Set flow matcher mask or value.
    9866                 :            :  */
    9867                 :            : static void
    9868                 :          0 : flow_dv_translate_item_nvgre(void *key, const struct rte_flow_item *item,
    9869                 :            :                              unsigned long pattern_flags, uint32_t key_type)
    9870                 :            : {
    9871                 :            :         const struct rte_flow_item_nvgre *nvgre_m;
    9872                 :            :         const struct rte_flow_item_nvgre *nvgre_v;
    9873                 :            :         void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
    9874                 :            :         const char *tni_flow_id_m;
    9875                 :            :         const char *tni_flow_id_v;
    9876                 :            :         char *gre_key_v;
    9877                 :            :         int size;
    9878                 :            :         int i;
    9879                 :            : 
    9880                 :            :         /* For NVGRE, GRE header fields must be set with defined values. */
    9881                 :          0 :         const struct rte_flow_item_gre gre_spec = {
    9882                 :            :                 .c_rsvd0_ver = RTE_BE16(0x2000),
    9883                 :            :                 .protocol = RTE_BE16(RTE_ETHER_TYPE_TEB)
    9884                 :            :         };
    9885                 :          0 :         const struct rte_flow_item_gre gre_mask = {
    9886                 :            :                 .c_rsvd0_ver = RTE_BE16(0xB000),
    9887                 :            :                 .protocol = RTE_BE16(UINT16_MAX),
    9888                 :            :         };
    9889                 :          0 :         const struct rte_flow_item gre_item = {
    9890                 :            :                 .spec = &gre_spec,
    9891                 :            :                 .mask = &gre_mask,
    9892                 :            :                 .last = NULL,
    9893                 :            :         };
    9894                 :          0 :         flow_dv_translate_item_gre(key, &gre_item, pattern_flags, key_type);
    9895   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
    9896                 :          0 :                 return;
    9897   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, nvgre_v, nvgre_m,
             #  #  #  # ]
    9898                 :            :                     &rte_flow_item_nvgre_mask);
    9899                 :          0 :         tni_flow_id_m = (const char *)nvgre_m->tni;
    9900                 :          0 :         tni_flow_id_v = (const char *)nvgre_v->tni;
    9901                 :            :         size = sizeof(nvgre_m->tni) + sizeof(nvgre_m->flow_id);
    9902                 :          0 :         gre_key_v = MLX5_ADDR_OF(fte_match_set_misc, misc_v, gre_key_h);
    9903         [ #  # ]:          0 :         for (i = 0; i < size; ++i)
    9904                 :          0 :                 gre_key_v[i] = tni_flow_id_m[i] & tni_flow_id_v[i];
    9905                 :            : }
    9906                 :            : 
    9907                 :            : /**
    9908                 :            :  * Add VXLAN item to the value.
    9909                 :            :  *
    9910                 :            :  * @param[in] dev
    9911                 :            :  *   Pointer to the Ethernet device structure.
    9912                 :            :  * @param[in] attr
    9913                 :            :  *   Flow rule attributes.
    9914                 :            :  * @param[in, out] key
    9915                 :            :  *   Flow matcher value.
    9916                 :            :  * @param[in] item
    9917                 :            :  *   Flow pattern to translate.
    9918                 :            :  * @param[in] inner
    9919                 :            :  *   Item is inner pattern.
    9920                 :            :  * @param[in] wks
    9921                 :            :  *   Matcher workspace.
    9922                 :            :  * @param[in] key_type
    9923                 :            :  *   Set flow matcher mask or value.
    9924                 :            :  */
    9925                 :            : static void
    9926                 :          0 : flow_dv_translate_item_vxlan(struct rte_eth_dev *dev,
    9927                 :            :                              const struct rte_flow_attr *attr,
    9928                 :            :                              void *key, const struct rte_flow_item *item,
    9929                 :            :                              int inner, struct mlx5_dv_matcher_workspace *wks,
    9930                 :            :                              uint32_t key_type)
    9931                 :            : {
    9932                 :            :         const struct rte_flow_item_vxlan *vxlan_m;
    9933                 :            :         const struct rte_flow_item_vxlan *vxlan_v;
    9934                 :            :         void *headers_v;
    9935                 :            :         void *misc_v;
    9936                 :            :         void *misc5_v;
    9937                 :            :         uint32_t tunnel_v;
    9938                 :            :         char *vni_v;
    9939                 :            :         uint16_t dport;
    9940                 :            :         int size;
    9941                 :            :         int i;
    9942                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    9943                 :          0 :         const struct rte_flow_item_vxlan nic_mask = {
    9944                 :            :                 .hdr.vni = "\xff\xff\xff",
    9945                 :            :                 .hdr.rsvd1 = 0xff,
    9946                 :            :         };
    9947                 :            : 
    9948                 :            :         misc5_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_5);
    9949         [ #  # ]:          0 :         headers_v = inner ? MLX5_ADDR_OF(fte_match_param, key, inner_headers) :
    9950                 :            :                 MLX5_ADDR_OF(fte_match_param, key, outer_headers);
    9951         [ #  # ]:          0 :         dport = item->type == RTE_FLOW_ITEM_TYPE_VXLAN ?
    9952                 :            :                 MLX5_UDP_PORT_VXLAN : MLX5_UDP_PORT_VXLAN_GPE;
    9953   [ #  #  #  # ]:          0 :         if (!MLX5_GET16(fte_match_set_lyr_2_4, headers_v, udp_dport)) {
    9954         [ #  # ]:          0 :                 if (key_type & MLX5_SET_MATCHER_M)
    9955         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, headers_v,
    9956                 :            :                                  udp_dport, 0xFFFF);
    9957                 :            :                 else
    9958         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, headers_v,
    9959                 :            :                                  udp_dport, dport);
    9960                 :            :         }
    9961                 :            :         /*
    9962                 :            :          * Read the UDP dport to check if the value satisfies the VXLAN
    9963                 :            :          * matching with MISC5 for CX5.
    9964                 :            :          */
    9965         [ #  # ]:          0 :         if (wks->udp_dport)
    9966                 :            :                 dport = wks->udp_dport;
    9967   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
    9968                 :          0 :                 return;
    9969   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, vxlan_v, vxlan_m, &nic_mask);
             #  #  #  # ]
    9970                 :            :         if ((item->mask == &nic_mask) &&
    9971                 :            :             ((!attr->group && !(attr->transfer && priv->fdb_def_rule) &&
    9972                 :            :             !priv->sh->tunnel_header_0_1) ||
    9973                 :            :             ((attr->group || (attr->transfer && priv->fdb_def_rule)) &&
    9974                 :            :             !priv->sh->misc5_cap)))
    9975                 :            :                 vxlan_m = &rte_flow_item_vxlan_mask;
    9976         [ #  # ]:          0 :         if ((priv->sh->steering_format_version ==
    9977         [ #  # ]:          0 :              MLX5_STEERING_LOGIC_FORMAT_CONNECTX_5 &&
    9978                 :          0 :              dport != MLX5_UDP_PORT_VXLAN) ||
    9979   [ #  #  #  #  :          0 :             (!attr->group && !(attr->transfer && priv->fdb_def_rule)) ||
             #  #  #  # ]
    9980   [ #  #  #  # ]:          0 :             ((attr->group || (attr->transfer && priv->fdb_def_rule)) &&
    9981         [ #  # ]:          0 :             !priv->sh->misc5_cap)) {
    9982                 :            :                 misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
    9983                 :            :                 size = sizeof(vxlan_m->hdr.vni);
    9984                 :          0 :                 vni_v = MLX5_ADDR_OF(fte_match_set_misc, misc_v, vxlan_vni);
    9985         [ #  # ]:          0 :                 for (i = 0; i < size; ++i)
    9986                 :          0 :                         vni_v[i] = vxlan_m->hdr.vni[i] & vxlan_v->hdr.vni[i];
    9987                 :            :                 return;
    9988                 :            :         }
    9989                 :          0 :         tunnel_v = (vxlan_v->hdr.vni[0] & vxlan_m->hdr.vni[0]) |
    9990                 :          0 :                    (vxlan_v->hdr.vni[1] & vxlan_m->hdr.vni[1]) << 8 |
    9991                 :          0 :                    (vxlan_v->hdr.vni[2] & vxlan_m->hdr.vni[2]) << 16;
    9992                 :          0 :         tunnel_v |= (vxlan_v->hdr.rsvd1 & vxlan_m->hdr.rsvd1) << 24;
    9993         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc5, misc5_v, tunnel_header_1, RTE_BE32(tunnel_v));
    9994                 :            : }
    9995                 :            : 
    9996                 :            : /**
    9997                 :            :  * Add VXLAN-GPE item to the value.
    9998                 :            :  *
    9999                 :            :  * @param[in, out] key
   10000                 :            :  *   Flow matcher value.
   10001                 :            :  * @param[in] item
   10002                 :            :  *   Flow pattern to translate.
   10003                 :            :  * @param[in] pattern_flags
   10004                 :            :  *   Item pattern flags.
   10005                 :            :  * @param[in] key_type
   10006                 :            :  *   Set flow matcher mask or value.
   10007                 :            :  */
   10008                 :            : 
   10009                 :            : static void
   10010                 :          0 : flow_dv_translate_item_vxlan_gpe(void *key, const struct rte_flow_item *item,
   10011                 :            :                                  const uint64_t pattern_flags,
   10012                 :            :                                  uint32_t key_type)
   10013                 :            : {
   10014                 :            :         static const struct rte_flow_item_vxlan_gpe dummy_vxlan_gpe_hdr = {{{0}}};
   10015                 :          0 :         const struct rte_flow_item_vxlan_gpe *vxlan_m = item->mask;
   10016                 :          0 :         const struct rte_flow_item_vxlan_gpe *vxlan_v = item->spec;
   10017                 :            :         /* The item was validated to be on the outer side */
   10018                 :            :         void *headers_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
   10019                 :            :         void *misc_v =
   10020                 :            :                 MLX5_ADDR_OF(fte_match_param, key, misc_parameters_3);
   10021                 :          0 :         char *vni_v =
   10022                 :            :                 MLX5_ADDR_OF(fte_match_set_misc3, misc_v, outer_vxlan_gpe_vni);
   10023                 :            :         int i, size = sizeof(vxlan_m->hdr.vni);
   10024                 :            :         uint8_t flags_m = 0xff;
   10025                 :            :         uint8_t flags_v = 0xc;
   10026                 :            :         uint8_t m_protocol, v_protocol;
   10027                 :            : 
   10028   [ #  #  #  # ]:          0 :         if (!MLX5_GET16(fte_match_set_lyr_2_4, headers_v, udp_dport)) {
   10029         [ #  # ]:          0 :                 if (key_type & MLX5_SET_MATCHER_M)
   10030         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_dport,
   10031                 :            :                                  0xFFFF);
   10032                 :            :                 else
   10033         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_dport,
   10034                 :            :                                  MLX5_UDP_PORT_VXLAN_GPE);
   10035                 :            :         }
   10036         [ #  # ]:          0 :         if (!vxlan_v) {
   10037                 :            :                 vxlan_v = &dummy_vxlan_gpe_hdr;
   10038                 :            :                 vxlan_m = &dummy_vxlan_gpe_hdr;
   10039                 :            :         } else {
   10040         [ #  # ]:          0 :                 if (!vxlan_m)
   10041                 :            :                         vxlan_m = &rte_flow_item_vxlan_gpe_mask;
   10042                 :            :         }
   10043         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M)
   10044                 :            :                 vxlan_v = vxlan_m;
   10045         [ #  # ]:          0 :         else if (key_type == MLX5_SET_MATCHER_HS_V)
   10046                 :            :                 vxlan_m = vxlan_v;
   10047         [ #  # ]:          0 :         if (vxlan_m->hdr.flags) {
   10048                 :            :                 flags_m = vxlan_m->hdr.flags;
   10049                 :          0 :                 flags_v = vxlan_v->hdr.flags;
   10050                 :            :         }
   10051                 :          0 :         m_protocol = vxlan_m->hdr.protocol;
   10052                 :          0 :         v_protocol = vxlan_v->hdr.protocol;
   10053         [ #  # ]:          0 :         if (!m_protocol) {
   10054                 :            :                 /* Force next protocol to ensure next headers parsing. */
   10055         [ #  # ]:          0 :                 if (pattern_flags & MLX5_FLOW_ITEM_NSH)
   10056                 :            :                         v_protocol = RTE_VXLAN_GPE_TYPE_NSH;
   10057         [ #  # ]:          0 :                 else if (pattern_flags & MLX5_FLOW_LAYER_INNER_L2)
   10058                 :            :                         v_protocol = RTE_VXLAN_GPE_TYPE_ETH;
   10059         [ #  # ]:          0 :                 else if (pattern_flags & MLX5_FLOW_LAYER_INNER_L3_IPV4)
   10060                 :            :                         v_protocol = RTE_VXLAN_GPE_TYPE_IPV4;
   10061         [ #  # ]:          0 :                 else if (pattern_flags & MLX5_FLOW_LAYER_INNER_L3_IPV6)
   10062                 :            :                         v_protocol = RTE_VXLAN_GPE_TYPE_IPV6;
   10063         [ #  # ]:          0 :                 if (v_protocol)
   10064                 :            :                         m_protocol = 0xFF;
   10065                 :            :                 /* Restore the value to mask in mask case. */
   10066         [ #  # ]:          0 :                 if (key_type & MLX5_SET_MATCHER_M)
   10067                 :            :                         v_protocol = m_protocol;
   10068                 :            :         }
   10069                 :            :         /*
   10070                 :            :          * If only match flags/protocol/vni field, keep using misc3 for matching.
   10071                 :            :          * If need to match rsvd0 or rsvd1, using misc5 and do not need using misc3.
   10072                 :            :          */
   10073   [ #  #  #  #  :          0 :         if (!(vxlan_m->hdr.rsvd0[0] || vxlan_m->hdr.rsvd0[1] || vxlan_m->hdr.rsvd1)) {
                   #  # ]
   10074         [ #  # ]:          0 :                 for (i = 0; i < size; ++i)
   10075                 :          0 :                         vni_v[i] = vxlan_m->hdr.vni[i] & vxlan_v->hdr.vni[i];
   10076         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc3, misc_v, outer_vxlan_gpe_flags,
   10077                 :            :                          flags_m & flags_v);
   10078         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc3, misc_v,
   10079                 :            :                          outer_vxlan_gpe_next_protocol, m_protocol & v_protocol);
   10080                 :            :         } else {
   10081                 :            :                 uint32_t tunnel_v;
   10082                 :            :                 void *misc5_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_5);
   10083                 :            : 
   10084                 :          0 :                 tunnel_v = (flags_m & flags_v) << 24 |
   10085                 :          0 :                            (vxlan_v->hdr.rsvd0[0] & vxlan_m->hdr.rsvd0[0]) << 16 |
   10086                 :          0 :                            (vxlan_v->hdr.rsvd0[1] & vxlan_m->hdr.rsvd0[1]) << 8 |
   10087                 :          0 :                            (m_protocol & v_protocol);
   10088         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc5, misc5_v, tunnel_header_0, tunnel_v);
   10089                 :          0 :                 tunnel_v = (vxlan_v->hdr.vni[0] & vxlan_m->hdr.vni[0]) << 24 |
   10090                 :          0 :                            (vxlan_v->hdr.vni[1] & vxlan_m->hdr.vni[1]) << 16 |
   10091                 :          0 :                            (vxlan_v->hdr.vni[2] & vxlan_m->hdr.vni[2]) << 8 |
   10092                 :          0 :                            (vxlan_v->hdr.rsvd1 & vxlan_m->hdr.rsvd1);
   10093         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc5, misc5_v, tunnel_header_1, tunnel_v);
   10094                 :            :         }
   10095                 :          0 : }
   10096                 :            : 
   10097                 :            : /**
   10098                 :            :  * Add Geneve item to the value.
   10099                 :            :  *
   10100                 :            :  * @param[in, out] key
   10101                 :            :  *   Flow matcher value.
   10102                 :            :  * @param[in] item
   10103                 :            :  *   Flow pattern to translate.
   10104                 :            :  * @param[in] pattern_flags
   10105                 :            :  *   Item pattern flags.
   10106                 :            :  * @param[in] key_type
   10107                 :            :  *   Set flow matcher mask or value.
   10108                 :            :  */
   10109                 :            : 
   10110                 :            : static void
   10111                 :          0 : flow_dv_translate_item_geneve(void *key, const struct rte_flow_item *item,
   10112                 :            :                               uint64_t pattern_flags, uint32_t key_type)
   10113                 :            : {
   10114                 :            :         static const struct rte_flow_item_geneve empty_geneve = {0,};
   10115                 :          0 :         const struct rte_flow_item_geneve *geneve_m = item->mask;
   10116                 :          0 :         const struct rte_flow_item_geneve *geneve_v = item->spec;
   10117                 :            :         /* GENEVE flow item validation allows single tunnel item */
   10118                 :            :         void *headers_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
   10119                 :            :         void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
   10120                 :            :         uint16_t gbhdr_m;
   10121                 :            :         uint16_t gbhdr_v;
   10122                 :          0 :         char *vni_v = MLX5_ADDR_OF(fte_match_set_misc, misc_v, geneve_vni);
   10123                 :            :         size_t size = sizeof(geneve_m->vni), i;
   10124                 :            :         uint16_t protocol_m, protocol_v;
   10125                 :            : 
   10126   [ #  #  #  # ]:          0 :         if (!MLX5_GET16(fte_match_set_lyr_2_4, headers_v, udp_dport)) {
   10127         [ #  # ]:          0 :                 if (key_type & MLX5_SET_MATCHER_M)
   10128         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_dport,
   10129                 :            :                                  0xFFFF);
   10130                 :            :                 else
   10131         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_dport,
   10132                 :            :                                  MLX5_UDP_PORT_GENEVE);
   10133                 :            :         }
   10134         [ #  # ]:          0 :         if (!geneve_v) {
   10135                 :            :                 geneve_v = &empty_geneve;
   10136                 :            :                 geneve_m = &empty_geneve;
   10137                 :            :         } else {
   10138         [ #  # ]:          0 :                 if (!geneve_m)
   10139                 :            :                         geneve_m = &rte_flow_item_geneve_mask;
   10140                 :            :         }
   10141         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M)
   10142                 :            :                 geneve_v = geneve_m;
   10143         [ #  # ]:          0 :         else if (key_type == MLX5_SET_MATCHER_HS_V)
   10144                 :            :                 geneve_m = geneve_v;
   10145         [ #  # ]:          0 :         for (i = 0; i < size; ++i)
   10146                 :          0 :                 vni_v[i] = geneve_m->vni[i] & geneve_v->vni[i];
   10147         [ #  # ]:          0 :         gbhdr_m = rte_be_to_cpu_16(geneve_m->ver_opt_len_o_c_rsvd0);
   10148         [ #  # ]:          0 :         gbhdr_v = rte_be_to_cpu_16(geneve_v->ver_opt_len_o_c_rsvd0);
   10149         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, geneve_oam,
   10150                 :            :                  MLX5_GENEVE_OAMF_VAL(gbhdr_v) & MLX5_GENEVE_OAMF_VAL(gbhdr_m));
   10151         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, geneve_opt_len,
   10152                 :            :                  MLX5_GENEVE_OPTLEN_VAL(gbhdr_v) &
   10153                 :            :                  MLX5_GENEVE_OPTLEN_VAL(gbhdr_m));
   10154         [ #  # ]:          0 :         protocol_m = rte_be_to_cpu_16(geneve_m->protocol);
   10155         [ #  # ]:          0 :         protocol_v = rte_be_to_cpu_16(geneve_v->protocol);
   10156         [ #  # ]:          0 :         if (!protocol_m) {
   10157                 :            :                 /* Force next protocol to prevent matchers duplication */
   10158                 :            :                 protocol_v = mlx5_translate_tunnel_etypes(pattern_flags);
   10159                 :            :                 if (protocol_v)
   10160                 :            :                         protocol_m = 0xFFFF;
   10161                 :            :                 /* Restore the value to mask in mask case. */
   10162         [ #  # ]:          0 :                 if (key_type & MLX5_SET_MATCHER_M)
   10163                 :            :                         protocol_v = protocol_m;
   10164                 :            :         }
   10165         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, geneve_protocol_type,
   10166                 :            :                  protocol_m & protocol_v);
   10167                 :          0 : }
   10168                 :            : 
   10169                 :            : /**
   10170                 :            :  * Create Geneve TLV option resource.
   10171                 :            :  *
   10172                 :            :  * @param[in, out] dev
   10173                 :            :  *   Pointer to rte_eth_dev structure.
   10174                 :            :  * @param[in] item
   10175                 :            :  *   Flow pattern to translate.
   10176                 :            :  * @param[out] error
   10177                 :            :  *   pointer to error structure.
   10178                 :            :  *
   10179                 :            :  * @return
   10180                 :            :  *   0 on success otherwise -errno and errno is set.
   10181                 :            :  */
   10182                 :            : static int
   10183                 :          0 : flow_dev_geneve_tlv_option_resource_register(struct rte_eth_dev *dev,
   10184                 :            :                                              const struct rte_flow_item *item,
   10185                 :            :                                              struct rte_flow_error *error)
   10186                 :            : {
   10187                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   10188                 :          0 :         struct mlx5_dev_ctx_shared *sh = priv->sh;
   10189                 :          0 :         struct mlx5_geneve_tlv_option_resource *geneve_opt_resource =
   10190                 :            :                         sh->geneve_tlv_option_resource;
   10191                 :            :         struct mlx5_devx_obj *obj;
   10192                 :          0 :         const struct rte_flow_item_geneve_opt *geneve_opt_v = item->spec;
   10193                 :            :         int ret = 0;
   10194                 :            : 
   10195                 :            :         MLX5_ASSERT(sh->config.dv_flow_en == 1);
   10196         [ #  # ]:          0 :         if (!geneve_opt_v)
   10197                 :            :                 return -1;
   10198                 :          0 :         rte_spinlock_lock(&sh->geneve_tlv_opt_sl);
   10199         [ #  # ]:          0 :         if (geneve_opt_resource != NULL) {
   10200                 :          0 :                 if (geneve_opt_resource->option_class ==
   10201                 :            :                         geneve_opt_v->option_class &&
   10202                 :            :                         geneve_opt_resource->option_type ==
   10203         [ #  # ]:          0 :                         geneve_opt_v->option_type &&
   10204                 :            :                         geneve_opt_resource->length ==
   10205                 :            :                         geneve_opt_v->option_len) {
   10206                 :          0 :                         __atomic_fetch_add(&geneve_opt_resource->refcnt, 1,
   10207                 :            :                                            __ATOMIC_RELAXED);
   10208                 :            :                 } else {
   10209                 :          0 :                         ret = rte_flow_error_set(error, ENOMEM,
   10210                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   10211                 :            :                                 "Only one GENEVE TLV option supported");
   10212                 :          0 :                         goto exit;
   10213                 :            :                 }
   10214                 :            :         } else {
   10215                 :          0 :                 struct mlx5_devx_geneve_tlv_option_attr attr = {
   10216                 :          0 :                         .option_class = geneve_opt_v->option_class,
   10217                 :          0 :                         .option_type = geneve_opt_v->option_type,
   10218                 :          0 :                         .option_data_len = geneve_opt_v->option_len,
   10219                 :            :                 };
   10220                 :            : 
   10221                 :            :                 /* Create a GENEVE TLV object and resource. */
   10222                 :          0 :                 obj = mlx5_devx_cmd_create_geneve_tlv_option(sh->cdev->ctx,
   10223                 :            :                                                              &attr);
   10224         [ #  # ]:          0 :                 if (!obj) {
   10225                 :          0 :                         ret = rte_flow_error_set(error, ENODATA,
   10226                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   10227                 :            :                                 "Failed to create GENEVE TLV Devx object");
   10228                 :          0 :                         goto exit;
   10229                 :            :                 }
   10230                 :          0 :                 sh->geneve_tlv_option_resource =
   10231                 :          0 :                                 mlx5_malloc(MLX5_MEM_ZERO,
   10232                 :            :                                                 sizeof(*geneve_opt_resource),
   10233                 :            :                                                 0, SOCKET_ID_ANY);
   10234         [ #  # ]:          0 :                 if (!sh->geneve_tlv_option_resource) {
   10235                 :          0 :                         claim_zero(mlx5_devx_cmd_destroy(obj));
   10236                 :          0 :                         ret = rte_flow_error_set(error, ENOMEM,
   10237                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   10238                 :            :                                 "GENEVE TLV object memory allocation failed");
   10239                 :          0 :                         goto exit;
   10240                 :            :                 }
   10241                 :            :                 geneve_opt_resource = sh->geneve_tlv_option_resource;
   10242                 :          0 :                 geneve_opt_resource->obj = obj;
   10243                 :          0 :                 geneve_opt_resource->option_class = geneve_opt_v->option_class;
   10244                 :          0 :                 geneve_opt_resource->option_type = geneve_opt_v->option_type;
   10245                 :          0 :                 geneve_opt_resource->length = geneve_opt_v->option_len;
   10246                 :          0 :                 __atomic_store_n(&geneve_opt_resource->refcnt, 1,
   10247                 :            :                                 __ATOMIC_RELAXED);
   10248                 :            :         }
   10249                 :          0 : exit:
   10250                 :            :         rte_spinlock_unlock(&sh->geneve_tlv_opt_sl);
   10251                 :          0 :         return ret;
   10252                 :            : }
   10253                 :            : 
   10254                 :            : /**
   10255                 :            :  * Add Geneve TLV option item to value.
   10256                 :            :  *
   10257                 :            :  * @param[in, out] dev
   10258                 :            :  *   Pointer to rte_eth_dev structure.
   10259                 :            :  * @param[in, out] key
   10260                 :            :  *   Flow matcher value.
   10261                 :            :  * @param[in] item
   10262                 :            :  *   Flow pattern to translate.
   10263                 :            :  * @param[in] key_type
   10264                 :            :  *   Set flow matcher mask or value.
   10265                 :            :  * @param[out] error
   10266                 :            :  *   Pointer to error structure.
   10267                 :            :  */
   10268                 :            : static int
   10269                 :          0 : flow_dv_translate_item_geneve_opt(struct rte_eth_dev *dev, void *key,
   10270                 :            :                                   const struct rte_flow_item *item,
   10271                 :            :                                   uint32_t key_type,
   10272                 :            :                                   struct rte_flow_error *error)
   10273                 :            : {
   10274                 :            :         const struct rte_flow_item_geneve_opt *geneve_opt_m;
   10275                 :            :         const struct rte_flow_item_geneve_opt *geneve_opt_v;
   10276                 :          0 :         const struct rte_flow_item_geneve_opt *orig_spec = item->spec;
   10277                 :            :         void *misc3_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_3);
   10278                 :          0 :         rte_be32_t opt_data_key = 0, opt_data_mask = 0;
   10279                 :            :         size_t option_byte_len;
   10280                 :            :         int ret = 0;
   10281                 :            : 
   10282   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type) || !orig_spec)
          #  #  #  #  #  
                #  #  # ]
   10283                 :            :                 return -1;
   10284   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, geneve_opt_v, geneve_opt_m,
             #  #  #  # ]
   10285                 :            :                          &rte_flow_item_geneve_opt_mask);
   10286                 :            :         /*
   10287                 :            :          * Register resource requires item spec for SW steering,
   10288                 :            :          * for HW steering resources is registered explicitly by user.
   10289                 :            :          */
   10290         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_SW_V) {
   10291                 :          0 :                 ret = flow_dev_geneve_tlv_option_resource_register(dev, item,
   10292                 :            :                                                                    error);
   10293         [ #  # ]:          0 :                 if (ret) {
   10294                 :          0 :                         DRV_LOG(ERR, "Failed to create geneve_tlv_obj");
   10295                 :          0 :                         return ret;
   10296                 :            :                 }
   10297                 :            :         }
   10298                 :            :         /* Convert the option length from DW to bytes for using memcpy. */
   10299                 :          0 :         option_byte_len = RTE_MIN((size_t)(orig_spec->option_len * 4),
   10300                 :            :                                   sizeof(rte_be32_t));
   10301         [ #  # ]:          0 :         if (geneve_opt_v->data) {
   10302                 :            :                 memcpy(&opt_data_key, geneve_opt_v->data, option_byte_len);
   10303                 :          0 :                 memcpy(&opt_data_mask, geneve_opt_m->data, option_byte_len);
   10304   [ #  #  #  # ]:          0 :                 MLX5_SET(fte_match_set_misc3, misc3_v,
   10305                 :            :                          geneve_tlv_option_0_data,
   10306                 :            :                          rte_be_to_cpu_32(opt_data_key & opt_data_mask));
   10307                 :            :         }
   10308                 :            :         return ret;
   10309                 :            : }
   10310                 :            : 
   10311                 :            : /**
   10312                 :            :  * Add MPLS item to the value.
   10313                 :            :  *
   10314                 :            :  * @param[in, out] key
   10315                 :            :  *   Flow matcher value.
   10316                 :            :  * @param[in] item
   10317                 :            :  *   Flow pattern to translate.
   10318                 :            :  * @param[in] prev_layer
   10319                 :            :  *   The protocol layer indicated in previous item.
   10320                 :            :  * @param[in] inner
   10321                 :            :  *   Item is inner pattern.
   10322                 :            :  * @param[in] key_type
   10323                 :            :  *   Set flow matcher mask or value.
   10324                 :            :  */
   10325                 :            : static void
   10326                 :          0 : flow_dv_translate_item_mpls(void *key, const struct rte_flow_item *item,
   10327                 :            :                             uint64_t prev_layer, int inner,
   10328                 :            :                             uint32_t key_type)
   10329                 :            : {
   10330                 :            :         const uint32_t *in_mpls_m;
   10331                 :            :         const uint32_t *in_mpls_v;
   10332                 :            :         uint32_t *out_mpls_v = 0;
   10333                 :            :         void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
   10334                 :          0 :         void *misc2_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_2);
   10335                 :            :         void *headers_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
   10336                 :            : 
   10337      [ #  #  # ]:          0 :         switch (prev_layer) {
   10338                 :          0 :         case MLX5_FLOW_LAYER_OUTER_L4_UDP:
   10339   [ #  #  #  # ]:          0 :                 if (!MLX5_GET16(fte_match_set_lyr_2_4, headers_v, udp_dport)) {
   10340         [ #  # ]:          0 :                         if (key_type & MLX5_SET_MATCHER_M)
   10341         [ #  # ]:          0 :                                 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
   10342                 :            :                                          udp_dport, 0xffff);
   10343                 :            :                         else
   10344         [ #  # ]:          0 :                                 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
   10345                 :            :                                          udp_dport, MLX5_UDP_PORT_MPLS);
   10346                 :            :                 }
   10347                 :            :                 break;
   10348                 :          0 :         case MLX5_FLOW_LAYER_GRE:
   10349                 :            :                 /* Fall-through. */
   10350                 :            :         case MLX5_FLOW_LAYER_GRE_KEY:
   10351   [ #  #  #  # ]:          0 :                 if (!MLX5_GET16(fte_match_set_misc, misc_v, gre_protocol)) {
   10352         [ #  # ]:          0 :                         if (key_type & MLX5_SET_MATCHER_M)
   10353         [ #  # ]:          0 :                                 MLX5_SET(fte_match_set_misc, misc_v,
   10354                 :            :                                          gre_protocol, 0xffff);
   10355                 :            :                         else
   10356         [ #  # ]:          0 :                                 MLX5_SET(fte_match_set_misc, misc_v,
   10357                 :            :                                          gre_protocol, RTE_ETHER_TYPE_MPLS);
   10358                 :            :                 }
   10359                 :            :                 break;
   10360                 :            :         default:
   10361                 :            :                 break;
   10362                 :            :         }
   10363   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
   10364                 :            :                 return;
   10365   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, in_mpls_v, in_mpls_m,
             #  #  #  # ]
   10366                 :            :                          &rte_flow_item_mpls_mask);
   10367      [ #  #  # ]:          0 :         switch (prev_layer) {
   10368                 :          0 :         case MLX5_FLOW_LAYER_OUTER_L4_UDP:
   10369                 :          0 :                 out_mpls_v =
   10370                 :            :                         (uint32_t *)MLX5_ADDR_OF(fte_match_set_misc2, misc2_v,
   10371                 :            :                                                  outer_first_mpls_over_udp);
   10372                 :          0 :                 break;
   10373                 :          0 :         case MLX5_FLOW_LAYER_GRE:
   10374                 :          0 :                 out_mpls_v =
   10375                 :            :                         (uint32_t *)MLX5_ADDR_OF(fte_match_set_misc2, misc2_v,
   10376                 :            :                                                  outer_first_mpls_over_gre);
   10377                 :          0 :                 break;
   10378                 :          0 :         default:
   10379                 :            :                 /* Inner MPLS not over GRE is not supported. */
   10380         [ #  # ]:          0 :                 if (!inner)
   10381                 :            :                         out_mpls_v =
   10382                 :            :                                 (uint32_t *)MLX5_ADDR_OF(fte_match_set_misc2,
   10383                 :            :                                                          misc2_v,
   10384                 :            :                                                          outer_first_mpls);
   10385                 :            :                 break;
   10386                 :            :         }
   10387                 :            :         if (out_mpls_v)
   10388                 :          0 :                 *out_mpls_v = *in_mpls_v & *in_mpls_m;
   10389                 :            : }
   10390                 :            : 
   10391                 :            : /**
   10392                 :            :  * Add metadata register item to matcher
   10393                 :            :  *
   10394                 :            :  * @param[in, out] key
   10395                 :            :  *   Flow matcher value.
   10396                 :            :  * @param[in] reg_type
   10397                 :            :  *   Type of device metadata register
   10398                 :            :  * @param[in] data
   10399                 :            :  *   Register data
   10400                 :            :  * @param[in] mask
   10401                 :            :  *   Register mask
   10402                 :            :  */
   10403                 :            : static void
   10404                 :          0 : flow_dv_match_meta_reg(void *key, enum modify_reg reg_type,
   10405                 :            :                        uint32_t data, uint32_t mask)
   10406                 :            : {
   10407                 :            :         void *misc2_v =
   10408                 :            :                 MLX5_ADDR_OF(fte_match_param, key, misc_parameters_2);
   10409                 :            :         uint32_t temp;
   10410                 :            : 
   10411                 :          0 :         data &= mask;
   10412   [ #  #  #  #  :          0 :         switch (reg_type) {
          #  #  #  #  #  
                   #  # ]
   10413                 :          0 :         case REG_A:
   10414         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_a, data);
   10415                 :          0 :                 break;
   10416                 :          0 :         case REG_B:
   10417         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_b, data);
   10418                 :          0 :                 break;
   10419                 :          0 :         case REG_C_0:
   10420                 :            :                 /*
   10421                 :            :                  * The metadata register C0 field might be divided into
   10422                 :            :                  * source vport index and META item value, we should set
   10423                 :            :                  * this field according to specified mask, not as whole one.
   10424                 :            :                  */
   10425         [ #  # ]:          0 :                 temp = MLX5_GET(fte_match_set_misc2, misc2_v, metadata_reg_c_0);
   10426   [ #  #  #  # ]:          0 :                 if (mask)
   10427                 :          0 :                         temp &= ~mask;
   10428                 :          0 :                 temp |= data;
   10429   [ #  #  #  # ]:          0 :                 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_0, temp);
   10430                 :          0 :                 break;
   10431                 :          0 :         case REG_C_1:
   10432         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_1, data);
   10433                 :          0 :                 break;
   10434                 :          0 :         case REG_C_2:
   10435         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_2, data);
   10436                 :          0 :                 break;
   10437                 :          0 :         case REG_C_3:
   10438         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_3, data);
   10439                 :          0 :                 break;
   10440                 :          0 :         case REG_C_4:
   10441         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_4, data);
   10442                 :          0 :                 break;
   10443                 :          0 :         case REG_C_5:
   10444         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_5, data);
   10445                 :          0 :                 break;
   10446                 :          0 :         case REG_C_6:
   10447         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_6, data);
   10448                 :          0 :                 break;
   10449                 :          0 :         case REG_C_7:
   10450         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_7, data);
   10451                 :          0 :                 break;
   10452                 :            :         default:
   10453                 :            :                 MLX5_ASSERT(false);
   10454                 :            :                 break;
   10455                 :            :         }
   10456                 :          0 : }
   10457                 :            : 
   10458                 :            : /**
   10459                 :            :  * Add metadata register item to matcher
   10460                 :            :  *
   10461                 :            :  * @param[in, out] matcher
   10462                 :            :  *   Flow matcher.
   10463                 :            :  * @param[in, out] key
   10464                 :            :  *   Flow matcher value.
   10465                 :            :  * @param[in] reg_type
   10466                 :            :  *   Type of device metadata register
   10467                 :            :  * @param[in] value
   10468                 :            :  *   Register value
   10469                 :            :  * @param[in] mask
   10470                 :            :  *   Register mask
   10471                 :            :  */
   10472                 :            : static void
   10473                 :            : flow_dv_match_meta_reg_all(void *matcher, void *key, enum modify_reg reg_type,
   10474                 :            :                            uint32_t data, uint32_t mask)
   10475                 :            : {
   10476                 :          0 :         flow_dv_match_meta_reg(key, reg_type, data, mask);
   10477                 :          0 :         flow_dv_match_meta_reg(matcher, reg_type, mask, mask);
   10478                 :            : }
   10479                 :            : 
   10480                 :            : /**
   10481                 :            :  * Add MARK item to matcher
   10482                 :            :  *
   10483                 :            :  * @param[in] dev
   10484                 :            :  *   The device to configure through.
   10485                 :            :  * @param[in, out] key
   10486                 :            :  *   Flow matcher value.
   10487                 :            :  * @param[in] item
   10488                 :            :  *   Flow pattern to translate.
   10489                 :            :  * @param[in] key_type
   10490                 :            :  *   Set flow matcher mask or value.
   10491                 :            :  */
   10492                 :            : static void
   10493                 :          0 : flow_dv_translate_item_mark(struct rte_eth_dev *dev, void *key,
   10494                 :            :                             const struct rte_flow_item *item,
   10495                 :            :                             uint32_t key_type)
   10496                 :            : {
   10497                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   10498                 :            :         const struct rte_flow_item_mark *mark;
   10499                 :            :         uint32_t value;
   10500                 :            :         uint32_t mask = 0;
   10501                 :            : 
   10502         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_SW) {
   10503         [ #  # ]:          0 :                 mark = item->mask ? (const void *)item->mask :
   10504                 :            :                                     &rte_flow_item_mark_mask;
   10505                 :          0 :                 mask = mark->id;
   10506         [ #  # ]:          0 :                 if (key_type == MLX5_SET_MATCHER_SW_M) {
   10507                 :            :                         value = mask;
   10508                 :            :                 } else {
   10509                 :          0 :                         mark = (const void *)item->spec;
   10510                 :            :                         MLX5_ASSERT(mark);
   10511                 :          0 :                         value = mark->id;
   10512                 :            :                 }
   10513                 :            :         } else {
   10514         [ #  # ]:          0 :                 mark = (key_type == MLX5_SET_MATCHER_HS_V) ?
   10515                 :            :                         (const void *)item->spec : (const void *)item->mask;
   10516                 :            :                 MLX5_ASSERT(mark);
   10517                 :          0 :                 value = mark->id;
   10518         [ #  # ]:          0 :                 if (key_type == MLX5_SET_MATCHER_HS_M)
   10519                 :            :                         mask = value;
   10520                 :            :         }
   10521                 :          0 :         mask &= priv->sh->dv_mark_mask;
   10522                 :          0 :         value &= mask;
   10523         [ #  # ]:          0 :         if (mask) {
   10524                 :            :                 enum modify_reg reg;
   10525                 :            : 
   10526                 :            :                 /* Get the metadata register index for the mark. */
   10527                 :          0 :                 reg = mlx5_flow_get_reg_id(dev, MLX5_FLOW_MARK, 0, NULL);
   10528                 :            :                 MLX5_ASSERT(reg > 0);
   10529         [ #  # ]:          0 :                 if (reg == REG_C_0) {
   10530                 :          0 :                         struct mlx5_priv *priv = dev->data->dev_private;
   10531                 :          0 :                         uint32_t msk_c0 = priv->sh->dv_regc0_mask;
   10532                 :            :                         uint32_t shl_c0 = rte_bsf32(msk_c0);
   10533                 :            : 
   10534                 :          0 :                         mask &= msk_c0;
   10535                 :          0 :                         mask <<= shl_c0;
   10536                 :          0 :                         value <<= shl_c0;
   10537                 :            :                 }
   10538                 :          0 :                 flow_dv_match_meta_reg(key, reg, value, mask);
   10539                 :            :         }
   10540                 :          0 : }
   10541                 :            : 
   10542                 :            : /**
   10543                 :            :  * Add META item to matcher
   10544                 :            :  *
   10545                 :            :  * @param[in] dev
   10546                 :            :  *   The devich to configure through.
   10547                 :            :  * @param[in, out] key
   10548                 :            :  *   Flow matcher value.
   10549                 :            :  * @param[in] attr
   10550                 :            :  *   Attributes of flow that includes this item.
   10551                 :            :  * @param[in] item
   10552                 :            :  *   Flow pattern to translate.
   10553                 :            :  * @param[in] key_type
   10554                 :            :  *   Set flow matcher mask or value.
   10555                 :            :  */
   10556                 :            : static void
   10557                 :          0 : flow_dv_translate_item_meta(struct rte_eth_dev *dev,
   10558                 :            :                             void *key,
   10559                 :            :                             const struct rte_flow_attr *attr,
   10560                 :            :                             const struct rte_flow_item *item,
   10561                 :            :                             uint32_t key_type)
   10562                 :            : {
   10563                 :            :         const struct rte_flow_item_meta *meta_m;
   10564                 :            :         const struct rte_flow_item_meta *meta_v;
   10565                 :            :         uint32_t value;
   10566                 :            :         uint32_t mask = 0;
   10567                 :            :         int reg;
   10568                 :            : 
   10569   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
   10570                 :            :                 return;
   10571   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, meta_v, meta_m,
             #  #  #  # ]
   10572                 :            :                          &rte_flow_item_meta_mask);
   10573                 :          0 :         value = meta_v->data;
   10574                 :          0 :         mask = meta_m->data;
   10575         [ #  # ]:          0 :         if (key_type == MLX5_SET_MATCHER_HS_M)
   10576                 :            :                 mask = value;
   10577                 :            :         /*
   10578                 :            :          * In the current implementation, REG_B cannot be used to match.
   10579                 :            :          * Force to use REG_C_1 in HWS root table as other tables.
   10580                 :            :          * This map may change.
   10581                 :            :          * NIC: modify - REG_B to be present in SW
   10582                 :            :          *      match - REG_C_1 when copied from FDB, different from SWS
   10583                 :            :          * FDB: modify - REG_C_1 in Xmeta mode, REG_NON in legacy mode
   10584                 :            :          *      match - REG_C_1 in FDB
   10585                 :            :          */
   10586         [ #  # ]:          0 :         if (!!(key_type & MLX5_SET_MATCHER_SW))
   10587                 :          0 :                 reg = flow_dv_get_metadata_reg(dev, attr, NULL);
   10588                 :            :         else
   10589                 :            :                 reg = flow_hw_get_reg_id(dev, RTE_FLOW_ITEM_TYPE_META, 0);
   10590         [ #  # ]:          0 :         if (reg < 0)
   10591                 :            :                 return;
   10592                 :            :         MLX5_ASSERT(reg != REG_NON);
   10593         [ #  # ]:          0 :         if (reg == REG_C_0) {
   10594                 :          0 :                 struct mlx5_priv *priv = dev->data->dev_private;
   10595                 :          0 :                 uint32_t msk_c0 = priv->sh->dv_regc0_mask;
   10596                 :            :                 uint32_t shl_c0 = rte_bsf32(msk_c0);
   10597                 :            : 
   10598                 :          0 :                 mask &= msk_c0;
   10599                 :          0 :                 mask <<= shl_c0;
   10600                 :          0 :                 value <<= shl_c0;
   10601                 :            :         }
   10602                 :          0 :         flow_dv_match_meta_reg(key, reg, value, mask);
   10603                 :            : }
   10604                 :            : 
   10605                 :            : /**
   10606                 :            :  * Add vport metadata Reg C0 item to matcher
   10607                 :            :  *
   10608                 :            :  * @param[in, out] key
   10609                 :            :  *   Flow matcher value.
   10610                 :            :  * @param[in] value
   10611                 :            :  *   Register value
   10612                 :            :  * @param[in] mask
   10613                 :            :  *   Register mask
   10614                 :            :  */
   10615                 :            : static void
   10616         [ #  # ]:          0 : flow_dv_translate_item_meta_vport(void *key, uint32_t value, uint32_t mask)
   10617                 :            : {
   10618                 :            :         flow_dv_match_meta_reg(key, REG_C_0, value, mask);
   10619                 :          0 : }
   10620                 :            : 
   10621                 :            : /**
   10622                 :            :  * Add tag item to matcher
   10623                 :            :  *
   10624                 :            :  * @param[in] dev
   10625                 :            :  *   The devich to configure through.
   10626                 :            :  * @param[in, out] key
   10627                 :            :  *   Flow matcher value.
   10628                 :            :  * @param[in] item
   10629                 :            :  *   Flow pattern to translate.
   10630                 :            :  * @param[in] key_type
   10631                 :            :  *   Set flow matcher mask or value.
   10632                 :            :  */
   10633                 :            : static void
   10634                 :          0 : flow_dv_translate_mlx5_item_tag(struct rte_eth_dev *dev, void *key,
   10635                 :            :                                 const struct rte_flow_item *item,
   10636                 :            :                                 uint32_t key_type)
   10637                 :            : {
   10638                 :          0 :         const struct mlx5_rte_flow_item_tag *tag_v = item->spec;
   10639                 :          0 :         const struct mlx5_rte_flow_item_tag *tag_m = item->mask;
   10640                 :            :         uint32_t mask, value;
   10641                 :            : 
   10642                 :            :         MLX5_ASSERT(tag_v);
   10643                 :          0 :         value = tag_v->data;
   10644         [ #  # ]:          0 :         mask = tag_m ? tag_m->data : UINT32_MAX;
   10645         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M)
   10646                 :            :                 value = mask;
   10647         [ #  # ]:          0 :         if (tag_v->id == REG_C_0) {
   10648                 :          0 :                 struct mlx5_priv *priv = dev->data->dev_private;
   10649                 :          0 :                 uint32_t msk_c0 = priv->sh->dv_regc0_mask;
   10650                 :            :                 uint32_t shl_c0 = rte_bsf32(msk_c0);
   10651                 :            : 
   10652                 :          0 :                 mask &= msk_c0;
   10653                 :          0 :                 mask <<= shl_c0;
   10654                 :          0 :                 value <<= shl_c0;
   10655                 :            :         }
   10656                 :          0 :         flow_dv_match_meta_reg(key, tag_v->id, value, mask);
   10657                 :          0 : }
   10658                 :            : 
   10659                 :            : /**
   10660                 :            :  * Add TAG item to matcher
   10661                 :            :  *
   10662                 :            :  * @param[in] dev
   10663                 :            :  *   The devich to configure through.
   10664                 :            :  * @param[in, out] key
   10665                 :            :  *   Flow matcher value.
   10666                 :            :  * @param[in] item
   10667                 :            :  *   Flow pattern to translate.
   10668                 :            :  * @param[in] key_type
   10669                 :            :  *   Set flow matcher mask or value.
   10670                 :            :  */
   10671                 :            : static void
   10672                 :          0 : flow_dv_translate_item_tag(struct rte_eth_dev *dev, void *key,
   10673                 :            :                            const struct rte_flow_item *item,
   10674                 :            :                            uint32_t key_type)
   10675                 :            : {
   10676                 :          0 :         const struct rte_flow_item_tag *tag_vv = item->spec;
   10677                 :            :         const struct rte_flow_item_tag *tag_v;
   10678                 :            :         const struct rte_flow_item_tag *tag_m;
   10679                 :            :         int reg;
   10680                 :            :         uint32_t index;
   10681                 :            : 
   10682   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
   10683                 :            :                 return;
   10684   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, tag_v, tag_m,
             #  #  #  # ]
   10685                 :            :                 &rte_flow_item_tag_mask);
   10686                 :            :         /* When set mask, the index should be from spec. */
   10687         [ #  # ]:          0 :         index = tag_vv ? tag_vv->index : tag_v->index;
   10688                 :            :         /* Get the metadata register index for the tag. */
   10689         [ #  # ]:          0 :         if (!!(key_type & MLX5_SET_MATCHER_SW))
   10690                 :          0 :                 reg = mlx5_flow_get_reg_id(dev, MLX5_APP_TAG, index, NULL);
   10691                 :            :         else
   10692                 :            :                 reg = flow_hw_get_reg_id(dev, RTE_FLOW_ITEM_TYPE_TAG, index);
   10693                 :            :         MLX5_ASSERT(reg > 0);
   10694                 :          0 :         flow_dv_match_meta_reg(key, (enum modify_reg)reg, tag_v->data, tag_m->data);
   10695                 :            : }
   10696                 :            : 
   10697                 :            : /**
   10698                 :            :  * Add source vport match to the specified matcher.
   10699                 :            :  *
   10700                 :            :  * @param[in, out] key
   10701                 :            :  *   Flow matcher value.
   10702                 :            :  * @param[in] port
   10703                 :            :  *   Source vport value to match
   10704                 :            :  */
   10705                 :            : static void
   10706                 :            : flow_dv_translate_item_source_vport(void *key,
   10707                 :            :                                     int16_t port)
   10708                 :            : {
   10709                 :            :         void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
   10710                 :            : 
   10711   [ #  #  #  #  :          0 :         MLX5_SET(fte_match_set_misc, misc_v, source_port, port);
                   #  # ]
   10712                 :          0 : }
   10713                 :            : 
   10714                 :            : /**
   10715                 :            :  * Translate port-id item to eswitch match on  port-id.
   10716                 :            :  *
   10717                 :            :  * @param[in] dev
   10718                 :            :  *   The devich to configure through.
   10719                 :            :  * @param[in, out] key
   10720                 :            :  *   Flow matcher value.
   10721                 :            :  * @param[in] item
   10722                 :            :  *   Flow pattern to translate.
   10723                 :            :  * @param[in] attr
   10724                 :            :  *   Flow attributes.
   10725                 :            :  * @param[in] key_type
   10726                 :            :  *   Set flow matcher mask or value.
   10727                 :            :  *
   10728                 :            :  * @return
   10729                 :            :  *   0 on success, a negative errno value otherwise.
   10730                 :            :  */
   10731                 :            : static int
   10732                 :          0 : flow_dv_translate_item_port_id(struct rte_eth_dev *dev, void *key,
   10733                 :            :                                const struct rte_flow_item *item,
   10734                 :            :                                const struct rte_flow_attr *attr,
   10735                 :            :                                uint32_t key_type)
   10736                 :            : {
   10737         [ #  # ]:          0 :         const struct rte_flow_item_port_id *pid_m = item ? item->mask : NULL;
   10738         [ #  # ]:          0 :         const struct rte_flow_item_port_id *pid_v = item ? item->spec : NULL;
   10739                 :          0 :         struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace();
   10740                 :            :         struct mlx5_priv *priv;
   10741                 :            :         uint16_t mask, id;
   10742                 :            :         uint32_t vport_meta;
   10743                 :            : 
   10744                 :            :         MLX5_ASSERT(wks);
   10745   [ #  #  #  # ]:          0 :         if (pid_v && pid_v->id == MLX5_PORT_ESW_MGR) {
   10746                 :          0 :                 flow_dv_translate_item_source_vport(key,
   10747         [ #  # ]:          0 :                                 key_type & MLX5_SET_MATCHER_V ?
   10748                 :          0 :                                 mlx5_flow_get_esw_manager_vport_id(dev) : 0xffff);
   10749                 :          0 :                 return 0;
   10750                 :            :         }
   10751         [ #  # ]:          0 :         mask = pid_m ? pid_m->id : 0xffff;
   10752         [ #  # ]:          0 :         id = pid_v ? pid_v->id : dev->data->port_id;
   10753                 :          0 :         priv = mlx5_port_to_eswitch_info(id, item == NULL);
   10754         [ #  # ]:          0 :         if (!priv)
   10755                 :          0 :                 return -rte_errno;
   10756         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M) {
   10757                 :            :                 id = mask;
   10758                 :          0 :                 vport_meta = priv->vport_meta_mask;
   10759                 :            :         } else {
   10760                 :          0 :                 id = priv->vport_id;
   10761                 :          0 :                 vport_meta = priv->vport_meta_tag;
   10762                 :          0 :                 wks->vport_meta_tag = vport_meta;
   10763                 :            :         }
   10764                 :            :         /*
   10765                 :            :          * Translate to vport field or to metadata, depending on mode.
   10766                 :            :          * Kernel can use either misc.source_port or half of C0 metadata
   10767                 :            :          * register.
   10768                 :            :          */
   10769         [ #  # ]:          0 :         if (priv->vport_meta_mask) {
   10770                 :            :                 /*
   10771                 :            :                  * Provide the hint for SW steering library
   10772                 :            :                  * to insert the flow into ingress domain and
   10773                 :            :                  * save the extra vport match.
   10774                 :            :                  */
   10775   [ #  #  #  # ]:          0 :                 if (mask == 0xffff && priv->vport_id == 0xffff &&
   10776   [ #  #  #  # ]:          0 :                     priv->pf_bond < 0 && attr->transfer)
   10777         [ #  # ]:          0 :                         flow_dv_translate_item_source_vport(key, id);
   10778                 :            :                 /*
   10779                 :            :                  * We should always set the vport metadata register,
   10780                 :            :                  * otherwise the SW steering library can drop
   10781                 :            :                  * the rule if wire vport metadata value is not zero,
   10782                 :            :                  * it depends on kernel configuration.
   10783                 :            :                  */
   10784                 :          0 :                 flow_dv_translate_item_meta_vport
   10785                 :            :                                 (key, vport_meta, priv->vport_meta_mask);
   10786                 :            :         } else {
   10787         [ #  # ]:          0 :                 flow_dv_translate_item_source_vport(key, id);
   10788                 :            :         }
   10789                 :            :         return 0;
   10790                 :            : }
   10791                 :            : 
   10792                 :            : /**
   10793                 :            :  * Translate port representor item to eswitch match on port id.
   10794                 :            :  *
   10795                 :            :  * @param[in] dev
   10796                 :            :  *   The devich to configure through.
   10797                 :            :  * @param[in, out] key
   10798                 :            :  *   Flow matcher value.
   10799                 :            :  * @param[in] key_type
   10800                 :            :  *   Set flow matcher mask or value.
   10801                 :            :  *
   10802                 :            :  * @return
   10803                 :            :  *   0 on success, a negative errno value otherwise.
   10804                 :            :  */
   10805                 :            : static int
   10806                 :          0 : flow_dv_translate_item_port_representor(struct rte_eth_dev *dev, void *key,
   10807                 :            :                                         uint32_t key_type)
   10808                 :            : {
   10809                 :          0 :         flow_dv_translate_item_source_vport(key,
   10810         [ #  # ]:          0 :                         key_type & MLX5_SET_MATCHER_V ?
   10811                 :          0 :                         mlx5_flow_get_esw_manager_vport_id(dev) : 0xffff);
   10812                 :          0 :         return 0;
   10813                 :            : }
   10814                 :            : 
   10815                 :            : /**
   10816                 :            :  * Translate represented port item to eswitch match on port id.
   10817                 :            :  *
   10818                 :            :  * @param[in] dev
   10819                 :            :  *   The devich to configure through.
   10820                 :            :  * @param[in, out] key
   10821                 :            :  *   Flow matcher value.
   10822                 :            :  * @param[in] item
   10823                 :            :  *   Flow pattern to translate.
   10824                 :            :  * @param[in]
   10825                 :            :  *   Flow attributes.
   10826                 :            :  *
   10827                 :            :  * @return
   10828                 :            :  *   0 on success, a negative errno value otherwise.
   10829                 :            :  */
   10830                 :            : static int
   10831                 :          0 : flow_dv_translate_item_represented_port(struct rte_eth_dev *dev, void *key,
   10832                 :            :                                         const struct rte_flow_item *item,
   10833                 :            :                                         const struct rte_flow_attr *attr,
   10834                 :            :                                         uint32_t key_type)
   10835                 :            : {
   10836         [ #  # ]:          0 :         const struct rte_flow_item_ethdev *pid_m = item ? item->mask : NULL;
   10837         [ #  # ]:          0 :         const struct rte_flow_item_ethdev *pid_v = item ? item->spec : NULL;
   10838                 :          0 :         struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace();
   10839                 :            :         struct mlx5_priv *priv;
   10840                 :            :         uint16_t mask, id;
   10841                 :            :         uint32_t vport_meta;
   10842                 :            : 
   10843                 :            :         MLX5_ASSERT(wks);
   10844         [ #  # ]:          0 :         if (!pid_m && !pid_v)
   10845                 :            :                 return 0;
   10846   [ #  #  #  # ]:          0 :         if (pid_v && pid_v->port_id == UINT16_MAX) {
   10847                 :          0 :                 flow_dv_translate_item_source_vport(key,
   10848         [ #  # ]:          0 :                         key_type & MLX5_SET_MATCHER_V ?
   10849                 :          0 :                         mlx5_flow_get_esw_manager_vport_id(dev) : 0xffff);
   10850                 :          0 :                 return 0;
   10851                 :            :         }
   10852         [ #  # ]:          0 :         mask = pid_m ? pid_m->port_id : UINT16_MAX;
   10853         [ #  # ]:          0 :         id = pid_v ? pid_v->port_id : dev->data->port_id;
   10854                 :          0 :         priv = mlx5_port_to_eswitch_info(id, item == NULL);
   10855         [ #  # ]:          0 :         if (!priv)
   10856                 :          0 :                 return -rte_errno;
   10857         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M) {
   10858                 :            :                 id = mask;
   10859                 :          0 :                 vport_meta = priv->vport_meta_mask;
   10860                 :            :         } else {
   10861                 :          0 :                 id = priv->vport_id;
   10862                 :          0 :                 vport_meta = priv->vport_meta_tag;
   10863                 :          0 :                 wks->vport_meta_tag = vport_meta;
   10864                 :            :         }
   10865                 :            :         /*
   10866                 :            :          * Translate to vport field or to metadata, depending on mode.
   10867                 :            :          * Kernel can use either misc.source_port or half of C0 metadata
   10868                 :            :          * register.
   10869                 :            :          */
   10870         [ #  # ]:          0 :         if (priv->vport_meta_mask) {
   10871                 :            :                 /*
   10872                 :            :                  * Provide the hint for SW steering library
   10873                 :            :                  * to insert the flow into ingress domain and
   10874                 :            :                  * save the extra vport match.
   10875                 :            :                  */
   10876   [ #  #  #  # ]:          0 :                 if (mask == UINT16_MAX && priv->vport_id == UINT16_MAX &&
   10877   [ #  #  #  # ]:          0 :                     priv->pf_bond < 0 && attr->transfer &&
   10878         [ #  # ]:          0 :                     priv->sh->config.dv_flow_en != 2)
   10879         [ #  # ]:          0 :                         flow_dv_translate_item_source_vport(key, id);
   10880                 :            :                 /*
   10881                 :            :                  * We should always set the vport metadata register,
   10882                 :            :                  * otherwise the SW steering library can drop
   10883                 :            :                  * the rule if wire vport metadata value is not zero,
   10884                 :            :                  * it depends on kernel configuration.
   10885                 :            :                  */
   10886                 :          0 :                 flow_dv_translate_item_meta_vport(key, vport_meta,
   10887                 :            :                                                   priv->vport_meta_mask);
   10888                 :            :         } else {
   10889         [ #  # ]:          0 :                 flow_dv_translate_item_source_vport(key, id);
   10890                 :            :         }
   10891                 :            :         return 0;
   10892                 :            : }
   10893                 :            : 
   10894                 :            : /**
   10895                 :            :  * Translate port-id item to eswitch match on  port-id.
   10896                 :            :  *
   10897                 :            :  * @param[in] dev
   10898                 :            :  *   The devich to configure through.
   10899                 :            :  * @param[in, out] matcher
   10900                 :            :  *   Flow matcher.
   10901                 :            :  * @param[in, out] key
   10902                 :            :  *   Flow matcher value.
   10903                 :            :  * @param[in] item
   10904                 :            :  *   Flow pattern to translate.
   10905                 :            :  * @param[in] attr
   10906                 :            :  *   Flow attributes.
   10907                 :            :  *
   10908                 :            :  * @return
   10909                 :            :  *   0 on success, a negative errno value otherwise.
   10910                 :            :  */
   10911                 :            : static int
   10912                 :          0 : flow_dv_translate_item_port_id_all(struct rte_eth_dev *dev,
   10913                 :            :                                void *matcher, void *key,
   10914                 :            :                                const struct rte_flow_item *item,
   10915                 :            :                                const struct rte_flow_attr *attr)
   10916                 :            : {
   10917                 :            :         int ret;
   10918                 :            : 
   10919                 :          0 :         ret = flow_dv_translate_item_port_id
   10920                 :            :                         (dev, matcher, item, attr, MLX5_SET_MATCHER_SW_M);
   10921         [ #  # ]:          0 :         if (ret)
   10922                 :            :                 return ret;
   10923                 :          0 :         ret = flow_dv_translate_item_port_id
   10924                 :            :                         (dev, key, item, attr, MLX5_SET_MATCHER_SW_V);
   10925                 :          0 :         return ret;
   10926                 :            : }
   10927                 :            : 
   10928                 :            : 
   10929                 :            : /**
   10930                 :            :  * Add ICMP6 item to the value.
   10931                 :            :  *
   10932                 :            :  * @param[in, out] key
   10933                 :            :  *   Flow matcher value.
   10934                 :            :  * @param[in] item
   10935                 :            :  *   Flow pattern to translate.
   10936                 :            :  * @param[in] inner
   10937                 :            :  *   Item is inner pattern.
   10938                 :            :  * @param[in] key_type
   10939                 :            :  *   Set flow matcher mask or value.
   10940                 :            :  */
   10941                 :            : static void
   10942                 :          0 : flow_dv_translate_item_icmp6(void *key, const struct rte_flow_item *item,
   10943                 :            :                              int inner, uint32_t key_type)
   10944                 :            : {
   10945                 :            :         const struct rte_flow_item_icmp6 *icmp6_m;
   10946                 :            :         const struct rte_flow_item_icmp6 *icmp6_v;
   10947                 :            :         void *headers_v;
   10948                 :            :         void *misc3_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_3);
   10949                 :            : 
   10950         [ #  # ]:          0 :         headers_v = inner ? MLX5_ADDR_OF(fte_match_param, key, inner_headers) :
   10951                 :            :                 MLX5_ADDR_OF(fte_match_param, key, outer_headers);
   10952         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M)
   10953         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol, 0xFF);
   10954                 :            :         else
   10955         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol,
   10956                 :            :                          IPPROTO_ICMPV6);
   10957   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
   10958                 :            :                 return;
   10959   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, icmp6_v, icmp6_m,
             #  #  #  # ]
   10960                 :            :                 &rte_flow_item_icmp6_mask);
   10961         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc3, misc3_v, icmpv6_type,
   10962                 :            :                  icmp6_v->type & icmp6_m->type);
   10963         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc3, misc3_v, icmpv6_code,
   10964                 :            :                  icmp6_v->code & icmp6_m->code);
   10965                 :            : }
   10966                 :            : 
   10967                 :            : /**
   10968                 :            :  * Add ICMP6 echo request/reply item to the value.
   10969                 :            :  *
   10970                 :            :  * @param[in, out] key
   10971                 :            :  *   Flow matcher value.
   10972                 :            :  * @param[in] item
   10973                 :            :  *   Flow pattern to translate.
   10974                 :            :  * @param[in] inner
   10975                 :            :  *   Item is inner pattern.
   10976                 :            :  * @param[in] key_type
   10977                 :            :  *   Set flow matcher mask or value.
   10978                 :            :  */
   10979                 :            : static void
   10980         [ #  # ]:          0 : flow_dv_translate_item_icmp6_echo(void *key, const struct rte_flow_item *item,
   10981                 :            :                                   int inner, uint32_t key_type)
   10982                 :            : {
   10983                 :            :         const struct rte_flow_item_icmp6_echo *icmp6_m;
   10984                 :            :         const struct rte_flow_item_icmp6_echo *icmp6_v;
   10985                 :            :         uint32_t icmp6_header_data_m = 0;
   10986                 :            :         uint32_t icmp6_header_data_v = 0;
   10987                 :            :         void *headers_v;
   10988                 :            :         void *misc3_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_3);
   10989                 :            :         uint8_t icmp6_type = 0;
   10990                 :            :         struct rte_flow_item_icmp6_echo zero_mask;
   10991                 :            : 
   10992                 :            :         memset(&zero_mask, 0, sizeof(zero_mask));
   10993         [ #  # ]:          0 :         headers_v = inner ? MLX5_ADDR_OF(fte_match_param, key, inner_headers) :
   10994                 :            :                 MLX5_ADDR_OF(fte_match_param, key, outer_headers);
   10995         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M)
   10996         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol, 0xFF);
   10997                 :            :         else
   10998         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol,
   10999                 :            :                          IPPROTO_ICMPV6);
   11000   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, icmp6_v, icmp6_m, &zero_mask);
             #  #  #  # ]
   11001                 :            :         /* Set fixed type and code for icmpv6 echo request or reply */
   11002         [ #  # ]:          0 :         icmp6_type = (item->type == RTE_FLOW_ITEM_TYPE_ICMP6_ECHO_REQUEST ?
   11003                 :            :                       RTE_ICMP6_ECHO_REQUEST : RTE_ICMP6_ECHO_REPLY);
   11004         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M) {
   11005         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc3, misc3_v, icmpv6_type, 0xFF);
   11006         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc3, misc3_v, icmpv6_code, 0xFF);
   11007                 :            :         } else {
   11008         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc3, misc3_v, icmpv6_type, icmp6_type);
   11009         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc3, misc3_v, icmpv6_code, 0);
   11010                 :            :         }
   11011         [ #  # ]:          0 :         if (icmp6_v == NULL)
   11012                 :          0 :                 return;
   11013                 :            :         /* Set icmp6 header data (identifier & sequence) accordingly */
   11014                 :          0 :         icmp6_header_data_m =
   11015         [ #  # ]:          0 :                 (rte_be_to_cpu_16(icmp6_m->hdr.identifier) << 16) |
   11016         [ #  # ]:          0 :                 rte_be_to_cpu_16(icmp6_m->hdr.sequence);
   11017         [ #  # ]:          0 :         if (icmp6_header_data_m) {
   11018                 :          0 :                 icmp6_header_data_v =
   11019         [ #  # ]:          0 :                         (rte_be_to_cpu_16(icmp6_v->hdr.identifier) << 16) |
   11020         [ #  # ]:          0 :                         rte_be_to_cpu_16(icmp6_v->hdr.sequence);
   11021         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc3, misc3_v, icmpv6_header_data,
   11022                 :            :                          icmp6_header_data_v & icmp6_header_data_m);
   11023                 :            :         }
   11024                 :            : }
   11025                 :            : 
   11026                 :            : /**
   11027                 :            :  * Add ICMP item to the value.
   11028                 :            :  *
   11029                 :            :  * @param[in, out] key
   11030                 :            :  *   Flow matcher value.
   11031                 :            :  * @param[in] item
   11032                 :            :  *   Flow pattern to translate.
   11033                 :            :  * @param[in] inner
   11034                 :            :  *   Item is inner pattern.
   11035                 :            :  * @param[in] key_type
   11036                 :            :  *   Set flow matcher mask or value.
   11037                 :            :  */
   11038                 :            : static void
   11039                 :          0 : flow_dv_translate_item_icmp(void *key, const struct rte_flow_item *item,
   11040                 :            :                             int inner, uint32_t key_type)
   11041                 :            : {
   11042                 :            :         const struct rte_flow_item_icmp *icmp_m;
   11043                 :            :         const struct rte_flow_item_icmp *icmp_v;
   11044                 :            :         uint32_t icmp_header_data_m = 0;
   11045                 :            :         uint32_t icmp_header_data_v = 0;
   11046                 :            :         void *headers_v;
   11047                 :            :         void *misc3_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_3);
   11048                 :            : 
   11049         [ #  # ]:          0 :         headers_v = inner ? MLX5_ADDR_OF(fte_match_param, key, inner_headers) :
   11050                 :            :                         MLX5_ADDR_OF(fte_match_param, key, outer_headers);
   11051         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M)
   11052         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
   11053                 :            :                          ip_protocol, 0xFF);
   11054                 :            :         else
   11055         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
   11056                 :            :                          ip_protocol, IPPROTO_ICMP);
   11057   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
   11058                 :            :                 return;
   11059   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, icmp_v, icmp_m,
             #  #  #  # ]
   11060                 :            :                 &rte_flow_item_icmp_mask);
   11061         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc3, misc3_v, icmp_type,
   11062                 :            :                  icmp_v->hdr.icmp_type & icmp_m->hdr.icmp_type);
   11063         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc3, misc3_v, icmp_code,
   11064                 :            :                  icmp_v->hdr.icmp_code & icmp_m->hdr.icmp_code);
   11065         [ #  # ]:          0 :         icmp_header_data_m = rte_be_to_cpu_16(icmp_m->hdr.icmp_seq_nb);
   11066         [ #  # ]:          0 :         icmp_header_data_m |= rte_be_to_cpu_16(icmp_m->hdr.icmp_ident) << 16;
   11067         [ #  # ]:          0 :         if (icmp_header_data_m) {
   11068         [ #  # ]:          0 :                 icmp_header_data_v = rte_be_to_cpu_16(icmp_v->hdr.icmp_seq_nb);
   11069                 :          0 :                 icmp_header_data_v |=
   11070         [ #  # ]:          0 :                          rte_be_to_cpu_16(icmp_v->hdr.icmp_ident) << 16;
   11071         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc3, misc3_v, icmp_header_data,
   11072                 :            :                          icmp_header_data_v & icmp_header_data_m);
   11073                 :            :         }
   11074                 :            : }
   11075                 :            : 
   11076                 :            : /**
   11077                 :            :  * Add GTP item to the value.
   11078                 :            :  *
   11079                 :            :  * @param[in, out] key
   11080                 :            :  *   Flow matcher value.
   11081                 :            :  * @param[in] item
   11082                 :            :  *   Flow pattern to translate.
   11083                 :            :  * @param[in] inner
   11084                 :            :  *   Item is inner pattern.
   11085                 :            :  * @param[in] key_type
   11086                 :            :  *   Set flow matcher mask or value.
   11087                 :            :  */
   11088                 :            : static void
   11089                 :          0 : flow_dv_translate_item_gtp(void *key, const struct rte_flow_item *item,
   11090                 :            :                            int inner, uint32_t key_type)
   11091                 :            : {
   11092                 :            :         const struct rte_flow_item_gtp *gtp_m;
   11093                 :            :         const struct rte_flow_item_gtp *gtp_v;
   11094                 :            :         void *headers_v;
   11095                 :            :         void *misc3_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_3);
   11096                 :            :         uint16_t dport = RTE_GTPU_UDP_PORT;
   11097                 :            : 
   11098         [ #  # ]:          0 :         headers_v = inner ? MLX5_ADDR_OF(fte_match_param, key, inner_headers) :
   11099                 :            :                         MLX5_ADDR_OF(fte_match_param, key, outer_headers);
   11100   [ #  #  #  # ]:          0 :         if (!MLX5_GET16(fte_match_set_lyr_2_4, headers_v, udp_dport)) {
   11101         [ #  # ]:          0 :                 if (key_type & MLX5_SET_MATCHER_M)
   11102         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, headers_v,
   11103                 :            :                                  udp_dport, 0xFFFF);
   11104                 :            :                 else
   11105         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, headers_v,
   11106                 :            :                                  udp_dport, dport);
   11107                 :            :         }
   11108   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
   11109                 :            :                 return;
   11110   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, gtp_v, gtp_m,
             #  #  #  # ]
   11111                 :            :                 &rte_flow_item_gtp_mask);
   11112         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc3, misc3_v, gtpu_msg_flags,
   11113                 :            :                  gtp_v->hdr.gtp_hdr_info & gtp_m->hdr.gtp_hdr_info);
   11114         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc3, misc3_v, gtpu_msg_type,
   11115                 :            :                  gtp_v->hdr.msg_type & gtp_m->hdr.msg_type);
   11116   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_misc3, misc3_v, gtpu_teid,
   11117                 :            :                  rte_be_to_cpu_32(gtp_v->hdr.teid & gtp_m->hdr.teid));
   11118                 :            : }
   11119                 :            : 
   11120                 :            : /**
   11121                 :            :  * Add GTP PSC item to matcher.
   11122                 :            :  *
   11123                 :            :  * @param[in, out] key
   11124                 :            :  *   Flow matcher value.
   11125                 :            :  * @param[in] item
   11126                 :            :  *   Flow pattern to translate.
   11127                 :            :  * @param[in] key_type
   11128                 :            :  *   Set flow matcher mask or value.
   11129                 :            :  */
   11130                 :            : static int
   11131                 :          0 : flow_dv_translate_item_gtp_psc(void *key, const struct rte_flow_item *item,
   11132                 :            :                                uint32_t key_type)
   11133                 :            : {
   11134                 :            :         const struct rte_flow_item_gtp_psc *gtp_psc_m;
   11135                 :            :         const struct rte_flow_item_gtp_psc *gtp_psc_v;
   11136                 :            :         void *misc3_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_3);
   11137                 :            :         union {
   11138                 :            :                 uint32_t w32;
   11139                 :            :                 struct {
   11140                 :            :                         uint16_t seq_num;
   11141                 :            :                         uint8_t npdu_num;
   11142                 :            :                         uint8_t next_ext_header_type;
   11143                 :            :                 };
   11144                 :            :         } dw_2;
   11145                 :            :         union {
   11146                 :            :                 uint32_t w32;
   11147                 :            :                 struct {
   11148                 :            :                         uint8_t len;
   11149                 :            :                         uint8_t type_flags;
   11150                 :            :                         uint8_t qfi;
   11151                 :            :                         uint8_t reserved;
   11152                 :            :                 };
   11153                 :            :         } dw_0;
   11154                 :            :         uint8_t gtp_flags;
   11155                 :            : 
   11156                 :            :         /* Always set E-flag match on one, regardless of GTP item settings. */
   11157         [ #  # ]:          0 :         gtp_flags = MLX5_GET(fte_match_set_misc3, misc3_v, gtpu_msg_flags);
   11158                 :          0 :         gtp_flags |= MLX5_GTP_EXT_HEADER_FLAG;
   11159         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc3, misc3_v, gtpu_msg_flags, gtp_flags);
   11160                 :            :         /*Set next extension header type. */
   11161                 :          0 :         dw_2.seq_num = 0;
   11162                 :          0 :         dw_2.npdu_num = 0;
   11163         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M)
   11164                 :          0 :                 dw_2.next_ext_header_type = 0xff;
   11165                 :            :         else
   11166                 :          0 :                 dw_2.next_ext_header_type = 0x85;
   11167   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_misc3, misc3_v, gtpu_dw_2,
   11168                 :            :                  rte_cpu_to_be_32(dw_2.w32));
   11169   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
   11170                 :            :                 return 0;
   11171   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, gtp_psc_v,
             #  #  #  # ]
   11172                 :            :                 gtp_psc_m, &rte_flow_item_gtp_psc_mask);
   11173                 :          0 :         dw_0.w32 = 0;
   11174                 :          0 :         dw_0.type_flags = MLX5_GTP_PDU_TYPE_SHIFT(gtp_psc_v->hdr.type &
   11175                 :            :                                                   gtp_psc_m->hdr.type);
   11176                 :          0 :         dw_0.qfi = gtp_psc_v->hdr.qfi & gtp_psc_m->hdr.qfi;
   11177   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_misc3, misc3_v, gtpu_first_ext_dw_0,
   11178                 :            :                  rte_cpu_to_be_32(dw_0.w32));
   11179                 :          0 :         return 0;
   11180                 :            : }
   11181                 :            : 
   11182                 :            : /**
   11183                 :            :  * Add eCPRI item to matcher and to the value.
   11184                 :            :  *
   11185                 :            :  * @param[in] dev
   11186                 :            :  *   The devich to configure through.
   11187                 :            :  * @param[in, out] key
   11188                 :            :  *   Flow matcher value.
   11189                 :            :  * @param[in] item
   11190                 :            :  *   Flow pattern to translate.
   11191                 :            :  * @param[in] last_item
   11192                 :            :  *   Last item flags.
   11193                 :            :  * @param[in] key_type
   11194                 :            :  *   Set flow matcher mask or value.
   11195                 :            :  */
   11196                 :            : static void
   11197                 :          0 : flow_dv_translate_item_ecpri(struct rte_eth_dev *dev, void *key,
   11198                 :            :                              const struct rte_flow_item *item,
   11199                 :            :                              uint64_t last_item, uint32_t key_type)
   11200                 :            : {
   11201                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   11202                 :            :         const struct rte_flow_item_ecpri *ecpri_m;
   11203                 :            :         const struct rte_flow_item_ecpri *ecpri_v;
   11204                 :          0 :         const struct rte_flow_item_ecpri *ecpri_vv = item->spec;
   11205                 :            :         struct rte_ecpri_common_hdr common;
   11206                 :            :         void *misc4_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_4);
   11207                 :            :         uint32_t *samples;
   11208                 :            :         void *dw_v;
   11209                 :            : 
   11210                 :            :         /*
   11211                 :            :          * In case of eCPRI over Ethernet, if EtherType is not specified,
   11212                 :            :          * match on eCPRI EtherType implicitly.
   11213                 :            :          */
   11214         [ #  # ]:          0 :         if (last_item & MLX5_FLOW_LAYER_OUTER_L2) {
   11215                 :            :                 void *hdrs_v, *l2v;
   11216                 :            : 
   11217                 :            :                 hdrs_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
   11218                 :            :                 l2v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, hdrs_v, ethertype);
   11219         [ #  # ]:          0 :                 if (*(uint16_t *)l2v == 0) {
   11220         [ #  # ]:          0 :                         if (key_type & MLX5_SET_MATCHER_M)
   11221                 :          0 :                                 *(uint16_t *)l2v = UINT16_MAX;
   11222                 :            :                         else
   11223                 :          0 :                                 *(uint16_t *)l2v =
   11224                 :            :                                         RTE_BE16(RTE_ETHER_TYPE_ECPRI);
   11225                 :            :                 }
   11226                 :            :         }
   11227   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
   11228                 :          0 :                 return;
   11229   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, ecpri_v, ecpri_m,
             #  #  #  # ]
   11230                 :            :                 &rte_flow_item_ecpri_mask);
   11231                 :            :         /*
   11232                 :            :          * Maximal four DW samples are supported in a single matching now.
   11233                 :            :          * Two are used now for a eCPRI matching:
   11234                 :            :          * 1. Type: one byte, mask should be 0x00ff0000 in network order
   11235                 :            :          * 2. ID of a message: one or two bytes, mask 0xffff0000 or 0xff000000
   11236                 :            :          *    if any.
   11237                 :            :          */
   11238         [ #  # ]:          0 :         if (!ecpri_m->hdr.common.u32)
   11239                 :            :                 return;
   11240                 :          0 :         samples = priv->sh->ecpri_parser.ids;
   11241                 :            :         /* Need to take the whole DW as the mask to fill the entry. */
   11242                 :            :         dw_v = MLX5_ADDR_OF(fte_match_set_misc4, misc4_v,
   11243                 :            :                             prog_sample_field_value_0);
   11244                 :            :         /* Already big endian (network order) in the header. */
   11245                 :          0 :         *(uint32_t *)dw_v = ecpri_v->hdr.common.u32 & ecpri_m->hdr.common.u32;
   11246                 :            :         /* Sample#0, used for matching type, offset 0. */
   11247                 :            :         /* It makes no sense to set the sample ID in the mask field. */
   11248         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc4, misc4_v,
   11249                 :            :                  prog_sample_field_id_0, samples[0]);
   11250                 :            :         /*
   11251                 :            :          * Checking if message body part needs to be matched.
   11252                 :            :          * Some wildcard rules only matching type field should be supported.
   11253                 :            :          */
   11254         [ #  # ]:          0 :         if (ecpri_m->hdr.dummy[0]) {
   11255         [ #  # ]:          0 :                 if (key_type == MLX5_SET_MATCHER_SW_M)
   11256         [ #  # ]:          0 :                         common.u32 = rte_be_to_cpu_32(ecpri_vv->hdr.common.u32);
   11257                 :            :                 else
   11258         [ #  # ]:          0 :                         common.u32 = rte_be_to_cpu_32(ecpri_v->hdr.common.u32);
   11259         [ #  # ]:          0 :                 switch (common.type) {
   11260                 :          0 :                 case RTE_ECPRI_MSG_TYPE_IQ_DATA:
   11261                 :            :                 case RTE_ECPRI_MSG_TYPE_RTC_CTRL:
   11262                 :            :                 case RTE_ECPRI_MSG_TYPE_DLY_MSR:
   11263                 :            :                         dw_v = MLX5_ADDR_OF(fte_match_set_misc4, misc4_v,
   11264                 :            :                                             prog_sample_field_value_1);
   11265                 :          0 :                         *(uint32_t *)dw_v = ecpri_v->hdr.dummy[0] &
   11266                 :            :                                             ecpri_m->hdr.dummy[0];
   11267                 :            :                         /* Sample#1, to match message body, offset 4. */
   11268         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_misc4, misc4_v,
   11269                 :            :                                  prog_sample_field_id_1, samples[1]);
   11270                 :          0 :                         break;
   11271                 :            :                 default:
   11272                 :            :                         /* Others, do not match any sample ID. */
   11273                 :            :                         break;
   11274                 :            :                 }
   11275                 :            :         }
   11276                 :            : }
   11277                 :            : 
   11278                 :            : /*
   11279                 :            :  * Add connection tracking status item to matcher
   11280                 :            :  *
   11281                 :            :  * @param[in] dev
   11282                 :            :  *   The devich to configure through.
   11283                 :            :  * @param[in, out] matcher
   11284                 :            :  *   Flow matcher.
   11285                 :            :  * @param[in, out] key
   11286                 :            :  *   Flow matcher value.
   11287                 :            :  * @param[in] item
   11288                 :            :  *   Flow pattern to translate.
   11289                 :            :  */
   11290                 :            : static void
   11291                 :          0 : flow_dv_translate_item_aso_ct(struct rte_eth_dev *dev,
   11292                 :            :                               void *matcher, void *key,
   11293                 :            :                               const struct rte_flow_item *item)
   11294                 :            : {
   11295                 :            :         uint32_t reg_value = 0;
   11296                 :            :         int reg_id;
   11297                 :            :         /* 8LSB 0b 11/0000/11, middle 4 bits are reserved. */
   11298                 :            :         uint32_t reg_mask = 0;
   11299                 :          0 :         const struct rte_flow_item_conntrack *spec = item->spec;
   11300                 :          0 :         const struct rte_flow_item_conntrack *mask = item->mask;
   11301                 :            :         uint32_t flags;
   11302                 :            :         struct rte_flow_error error;
   11303                 :            : 
   11304         [ #  # ]:          0 :         if (!mask)
   11305                 :            :                 mask = &rte_flow_item_conntrack_mask;
   11306   [ #  #  #  # ]:          0 :         if (!spec || !mask->flags)
   11307                 :          0 :                 return;
   11308                 :          0 :         flags = spec->flags & mask->flags;
   11309                 :            :         /* The conflict should be checked in the validation. */
   11310                 :            :         if (flags & RTE_FLOW_CONNTRACK_PKT_STATE_VALID)
   11311                 :            :                 reg_value |= MLX5_CT_SYNDROME_VALID;
   11312         [ #  # ]:          0 :         if (flags & RTE_FLOW_CONNTRACK_PKT_STATE_CHANGED)
   11313                 :            :                 reg_value |= MLX5_CT_SYNDROME_STATE_CHANGE;
   11314         [ #  # ]:          0 :         if (flags & RTE_FLOW_CONNTRACK_PKT_STATE_INVALID)
   11315                 :          0 :                 reg_value |= MLX5_CT_SYNDROME_INVALID;
   11316         [ #  # ]:          0 :         if (flags & RTE_FLOW_CONNTRACK_PKT_STATE_DISABLED)
   11317                 :          0 :                 reg_value |= MLX5_CT_SYNDROME_TRAP;
   11318         [ #  # ]:          0 :         if (flags & RTE_FLOW_CONNTRACK_PKT_STATE_BAD)
   11319                 :          0 :                 reg_value |= MLX5_CT_SYNDROME_BAD_PACKET;
   11320         [ #  # ]:          0 :         if (mask->flags & (RTE_FLOW_CONNTRACK_PKT_STATE_VALID |
   11321                 :            :                            RTE_FLOW_CONNTRACK_PKT_STATE_INVALID |
   11322                 :            :                            RTE_FLOW_CONNTRACK_PKT_STATE_DISABLED))
   11323                 :            :                 reg_mask |= 0xc0;
   11324         [ #  # ]:          0 :         if (mask->flags & RTE_FLOW_CONNTRACK_PKT_STATE_CHANGED)
   11325                 :          0 :                 reg_mask |= MLX5_CT_SYNDROME_STATE_CHANGE;
   11326         [ #  # ]:          0 :         if (mask->flags & RTE_FLOW_CONNTRACK_PKT_STATE_BAD)
   11327                 :          0 :                 reg_mask |= MLX5_CT_SYNDROME_BAD_PACKET;
   11328                 :            :         /* The REG_C_x value could be saved during startup. */
   11329                 :          0 :         reg_id = mlx5_flow_get_reg_id(dev, MLX5_ASO_CONNTRACK, 0, &error);
   11330         [ #  # ]:          0 :         if (reg_id == REG_NON)
   11331                 :            :                 return;
   11332                 :          0 :         flow_dv_match_meta_reg_all(matcher, key, (enum modify_reg)reg_id,
   11333                 :            :                                reg_value, reg_mask);
   11334                 :            : }
   11335                 :            : 
   11336                 :            : static void
   11337                 :          0 : flow_dv_translate_item_flex(struct rte_eth_dev *dev, void *matcher, void *key,
   11338                 :            :                             const struct rte_flow_item *item,
   11339                 :            :                             struct mlx5_flow *dev_flow, bool is_inner)
   11340                 :            : {
   11341                 :          0 :         const struct rte_flow_item_flex *spec =
   11342                 :            :                 (const struct rte_flow_item_flex *)item->spec;
   11343                 :          0 :         int index = mlx5_flex_acquire_index(dev, spec->handle, false);
   11344                 :            : 
   11345                 :            :         MLX5_ASSERT(index >= 0 && index < (int)(sizeof(uint32_t) * CHAR_BIT));
   11346         [ #  # ]:          0 :         if (index < 0)
   11347                 :            :                 return;
   11348         [ #  # ]:          0 :         if (!(dev_flow->handle->flex_item & RTE_BIT32(index))) {
   11349                 :            :                 /* Don't count both inner and outer flex items in one rule. */
   11350                 :          0 :                 if (mlx5_flex_acquire_index(dev, spec->handle, true) != index)
   11351                 :            :                         MLX5_ASSERT(false);
   11352                 :          0 :                 dev_flow->handle->flex_item |= (uint8_t)RTE_BIT32(index);
   11353                 :            :         }
   11354                 :          0 :         mlx5_flex_flow_translate_item(dev, matcher, key, item, is_inner);
   11355                 :            : }
   11356                 :            : 
   11357                 :            : /**
   11358                 :            :  * Add METER_COLOR item to matcher
   11359                 :            :  *
   11360                 :            :  * @param[in] dev
   11361                 :            :  *   The device to configure through.
   11362                 :            :  * @param[in, out] key
   11363                 :            :  *   Flow matcher value.
   11364                 :            :  * @param[in] item
   11365                 :            :  *   Flow pattern to translate.
   11366                 :            :  * @param[in] key_type
   11367                 :            :  *   Set flow matcher mask or value.
   11368                 :            :  */
   11369                 :            : static void
   11370                 :          0 : flow_dv_translate_item_meter_color(struct rte_eth_dev *dev, void *key,
   11371                 :            :                             const struct rte_flow_item *item,
   11372                 :            :                             uint32_t key_type)
   11373                 :            : {
   11374                 :          0 :         const struct rte_flow_item_meter_color *color_m = item->mask;
   11375                 :          0 :         const struct rte_flow_item_meter_color *color_v = item->spec;
   11376                 :            :         uint32_t value, mask;
   11377                 :            :         int reg = REG_NON;
   11378                 :            : 
   11379                 :            :         MLX5_ASSERT(color_v);
   11380   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
   11381                 :            :                 return;
   11382   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, color_v, color_m,
             #  #  #  # ]
   11383                 :            :                 &rte_flow_item_meter_color_mask);
   11384         [ #  # ]:          0 :         value = rte_col_2_mlx5_col(color_v->color);
   11385                 :            :         mask = color_m ?
   11386         [ #  # ]:          0 :                 color_m->color : (UINT32_C(1) << MLX5_MTR_COLOR_BITS) - 1;
   11387         [ #  # ]:          0 :         if (!!(key_type & MLX5_SET_MATCHER_SW))
   11388                 :          0 :                 reg = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR, 0, NULL);
   11389                 :            :         else
   11390                 :            :                 reg = flow_hw_get_reg_id(dev,
   11391                 :            :                                          RTE_FLOW_ITEM_TYPE_METER_COLOR, 0);
   11392         [ #  # ]:          0 :         if (reg == REG_NON)
   11393                 :            :                 return;
   11394                 :          0 :         flow_dv_match_meta_reg(key, (enum modify_reg)reg, value, mask);
   11395                 :            : }
   11396                 :            : 
   11397                 :            : static void
   11398                 :          0 : flow_dv_translate_item_aggr_affinity(void *key,
   11399                 :            :                                     const struct rte_flow_item *item,
   11400                 :            :                                     uint32_t key_type)
   11401                 :            : {
   11402                 :            :         const struct rte_flow_item_aggr_affinity *affinity_v;
   11403                 :            :         const struct rte_flow_item_aggr_affinity *affinity_m;
   11404                 :            :         void *misc_v;
   11405                 :            : 
   11406   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, affinity_v, affinity_m,
             #  #  #  # ]
   11407                 :            :                          &rte_flow_item_aggr_affinity_mask);
   11408                 :            :         misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
   11409         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, lag_rx_port_affinity,
   11410                 :            :                  affinity_v->affinity & affinity_m->affinity);
   11411                 :          0 : }
   11412                 :            : 
   11413                 :            : static void
   11414                 :          0 : flow_dv_translate_item_ib_bth(void *key,
   11415                 :            :                               const struct rte_flow_item *item,
   11416                 :            :                               int inner, uint32_t key_type)
   11417                 :            : {
   11418                 :            :         const struct rte_flow_item_ib_bth *bth_m;
   11419                 :            :         const struct rte_flow_item_ib_bth *bth_v;
   11420                 :            :         void *headers_v, *misc_v;
   11421                 :            :         uint16_t udp_dport;
   11422                 :            :         char *qpn_v;
   11423                 :            :         int i, size;
   11424                 :            : 
   11425         [ #  # ]:          0 :         headers_v = inner ? MLX5_ADDR_OF(fte_match_param, key, inner_headers) :
   11426                 :            :                 MLX5_ADDR_OF(fte_match_param, key, outer_headers);
   11427   [ #  #  #  # ]:          0 :         if (!MLX5_GET16(fte_match_set_lyr_2_4, headers_v, udp_dport)) {
   11428         [ #  # ]:          0 :                 udp_dport = key_type & MLX5_SET_MATCHER_M ?
   11429                 :            :                         0xFFFF : MLX5_UDP_PORT_ROCEv2;
   11430         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_dport, udp_dport);
   11431                 :            :         }
   11432   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
   11433                 :            :                 return;
   11434   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, bth_v, bth_m, &rte_flow_item_ib_bth_mask);
             #  #  #  # ]
   11435                 :            :         misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
   11436         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, bth_opcode,
   11437                 :            :                  bth_v->hdr.opcode & bth_m->hdr.opcode);
   11438                 :          0 :         qpn_v = MLX5_ADDR_OF(fte_match_set_misc, misc_v, bth_dst_qp);
   11439                 :            :         size = sizeof(bth_m->hdr.dst_qp);
   11440         [ #  # ]:          0 :         for (i = 0; i < size; ++i)
   11441                 :          0 :                 qpn_v[i] = bth_m->hdr.dst_qp[i] & bth_v->hdr.dst_qp[i];
   11442                 :            : }
   11443                 :            : 
   11444                 :            : static uint32_t matcher_zero[MLX5_ST_SZ_DW(fte_match_param)] = { 0 };
   11445                 :            : 
   11446                 :            : #define HEADER_IS_ZERO(match_criteria, headers)                              \
   11447                 :            :         !(memcmp(MLX5_ADDR_OF(fte_match_param, match_criteria, headers),     \
   11448                 :            :                  matcher_zero, MLX5_FLD_SZ_BYTES(fte_match_param, headers))) \
   11449                 :            : 
   11450                 :            : /**
   11451                 :            :  * Calculate flow matcher enable bitmap.
   11452                 :            :  *
   11453                 :            :  * @param match_criteria
   11454                 :            :  *   Pointer to flow matcher criteria.
   11455                 :            :  *
   11456                 :            :  * @return
   11457                 :            :  *   Bitmap of enabled fields.
   11458                 :            :  */
   11459                 :            : static uint8_t
   11460                 :          0 : flow_dv_matcher_enable(uint32_t *match_criteria)
   11461                 :            : {
   11462                 :            :         uint8_t match_criteria_enable;
   11463                 :            : 
   11464                 :            :         match_criteria_enable =
   11465                 :          0 :                 (!HEADER_IS_ZERO(match_criteria, outer_headers)) <<
   11466                 :            :                 MLX5_MATCH_CRITERIA_ENABLE_OUTER_BIT;
   11467                 :          0 :         match_criteria_enable |=
   11468         [ #  # ]:          0 :                 (!HEADER_IS_ZERO(match_criteria, misc_parameters)) <<
   11469                 :            :                 MLX5_MATCH_CRITERIA_ENABLE_MISC_BIT;
   11470                 :          0 :         match_criteria_enable |=
   11471         [ #  # ]:          0 :                 (!HEADER_IS_ZERO(match_criteria, inner_headers)) <<
   11472                 :            :                 MLX5_MATCH_CRITERIA_ENABLE_INNER_BIT;
   11473                 :          0 :         match_criteria_enable |=
   11474         [ #  # ]:          0 :                 (!HEADER_IS_ZERO(match_criteria, misc_parameters_2)) <<
   11475                 :            :                 MLX5_MATCH_CRITERIA_ENABLE_MISC2_BIT;
   11476                 :          0 :         match_criteria_enable |=
   11477         [ #  # ]:          0 :                 (!HEADER_IS_ZERO(match_criteria, misc_parameters_3)) <<
   11478                 :            :                 MLX5_MATCH_CRITERIA_ENABLE_MISC3_BIT;
   11479                 :          0 :         match_criteria_enable |=
   11480         [ #  # ]:          0 :                 (!HEADER_IS_ZERO(match_criteria, misc_parameters_4)) <<
   11481                 :            :                 MLX5_MATCH_CRITERIA_ENABLE_MISC4_BIT;
   11482                 :          0 :         match_criteria_enable |=
   11483         [ #  # ]:          0 :                 (!HEADER_IS_ZERO(match_criteria, misc_parameters_5)) <<
   11484                 :            :                 MLX5_MATCH_CRITERIA_ENABLE_MISC5_BIT;
   11485                 :          0 :         return match_criteria_enable;
   11486                 :            : }
   11487                 :            : 
   11488                 :            : static void
   11489                 :            : __flow_dv_adjust_buf_size(size_t *size, uint8_t match_criteria)
   11490                 :            : {
   11491                 :            :         /*
   11492                 :            :          * Check flow matching criteria first, subtract misc5/4 length if flow
   11493                 :            :          * doesn't own misc5/4 parameters. In some old rdma-core releases,
   11494                 :            :          * misc5/4 are not supported, and matcher creation failure is expected
   11495                 :            :          * w/o subtraction. If misc5 is provided, misc4 must be counted in since
   11496                 :            :          * misc5 is right after misc4.
   11497                 :            :          */
   11498                 :          0 :         if (!(match_criteria & (1 << MLX5_MATCH_CRITERIA_ENABLE_MISC5_BIT))) {
   11499                 :          0 :                 *size = MLX5_ST_SZ_BYTES(fte_match_param) -
   11500                 :            :                         MLX5_ST_SZ_BYTES(fte_match_set_misc5);
   11501   [ #  #  #  #  :          0 :                 if (!(match_criteria & (1 <<
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
   11502                 :            :                         MLX5_MATCH_CRITERIA_ENABLE_MISC4_BIT))) {
   11503                 :          0 :                         *size -= MLX5_ST_SZ_BYTES(fte_match_set_misc4);
   11504                 :            :                 }
   11505                 :            :         }
   11506                 :            : }
   11507                 :            : 
   11508                 :            : static struct mlx5_list_entry *
   11509                 :          0 : flow_dv_matcher_clone_cb(void *tool_ctx __rte_unused,
   11510                 :            :                          struct mlx5_list_entry *entry, void *cb_ctx)
   11511                 :            : {
   11512                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   11513                 :          0 :         struct mlx5_flow_dv_matcher *ref = ctx->data;
   11514                 :          0 :         struct mlx5_flow_tbl_data_entry *tbl = container_of(ref->tbl,
   11515                 :            :                                                             typeof(*tbl), tbl);
   11516                 :          0 :         struct mlx5_flow_dv_matcher *resource = mlx5_malloc(MLX5_MEM_ANY,
   11517                 :            :                                                             sizeof(*resource),
   11518                 :            :                                                             0, SOCKET_ID_ANY);
   11519                 :            : 
   11520         [ #  # ]:          0 :         if (!resource) {
   11521                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
   11522                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   11523                 :            :                                    "cannot create matcher");
   11524                 :          0 :                 return NULL;
   11525                 :            :         }
   11526                 :            :         memcpy(resource, entry, sizeof(*resource));
   11527                 :          0 :         resource->tbl = &tbl->tbl;
   11528                 :          0 :         return &resource->entry;
   11529                 :            : }
   11530                 :            : 
   11531                 :            : static void
   11532                 :          0 : flow_dv_matcher_clone_free_cb(void *tool_ctx __rte_unused,
   11533                 :            :                              struct mlx5_list_entry *entry)
   11534                 :            : {
   11535                 :          0 :         mlx5_free(entry);
   11536                 :          0 : }
   11537                 :            : 
   11538                 :            : struct mlx5_list_entry *
   11539                 :          0 : flow_dv_tbl_create_cb(void *tool_ctx, void *cb_ctx)
   11540                 :          0 : {
   11541                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   11542                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   11543                 :          0 :         struct rte_eth_dev *dev = ctx->dev;
   11544                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data;
   11545                 :          0 :         struct mlx5_flow_tbl_tunnel_prm *tt_prm = ctx->data2;
   11546                 :          0 :         struct rte_flow_error *error = ctx->error;
   11547                 :          0 :         union mlx5_flow_tbl_key key = { .v64 = *(uint64_t *)(ctx->data) };
   11548                 :            :         struct mlx5_flow_tbl_resource *tbl;
   11549                 :            :         void *domain;
   11550                 :          0 :         uint32_t idx = 0;
   11551                 :            :         int ret;
   11552                 :            : 
   11553                 :          0 :         tbl_data = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_JUMP], &idx);
   11554         [ #  # ]:          0 :         if (!tbl_data) {
   11555                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   11556                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   11557                 :            :                                    NULL,
   11558                 :            :                                    "cannot allocate flow table data entry");
   11559                 :          0 :                 return NULL;
   11560                 :            :         }
   11561                 :          0 :         tbl_data->idx = idx;
   11562                 :          0 :         tbl_data->tunnel = tt_prm->tunnel;
   11563                 :          0 :         tbl_data->group_id = tt_prm->group_id;
   11564         [ #  # ]:          0 :         tbl_data->external = !!tt_prm->external;
   11565                 :          0 :         tbl_data->tunnel_offload = is_tunnel_offload_active(dev);
   11566                 :          0 :         tbl_data->is_egress = !!key.is_egress;
   11567                 :          0 :         tbl_data->is_transfer = !!key.is_fdb;
   11568                 :          0 :         tbl_data->dummy = !!key.dummy;
   11569                 :          0 :         tbl_data->level = key.level;
   11570                 :          0 :         tbl_data->id = key.id;
   11571                 :            :         tbl = &tbl_data->tbl;
   11572         [ #  # ]:          0 :         if (key.dummy)
   11573                 :          0 :                 return &tbl_data->entry;
   11574         [ #  # ]:          0 :         if (key.is_fdb)
   11575                 :          0 :                 domain = sh->fdb_domain;
   11576         [ #  # ]:          0 :         else if (key.is_egress)
   11577                 :          0 :                 domain = sh->tx_domain;
   11578                 :            :         else
   11579                 :          0 :                 domain = sh->rx_domain;
   11580                 :            :         ret = mlx5_flow_os_create_flow_tbl(domain, key.level, &tbl->obj);
   11581                 :            :         if (ret) {
   11582                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   11583                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   11584                 :            :                                    NULL, "cannot create flow table object");
   11585                 :          0 :                 mlx5_ipool_free(sh->ipool[MLX5_IPOOL_JUMP], idx);
   11586                 :          0 :                 return NULL;
   11587                 :            :         }
   11588         [ #  # ]:          0 :         if (key.level != 0) {
   11589                 :            :                 ret = mlx5_flow_os_create_flow_action_dest_flow_tbl
   11590                 :            :                                         (tbl->obj, &tbl_data->jump.action);
   11591                 :            :                 if (ret) {
   11592                 :          0 :                         rte_flow_error_set(error, ENOMEM,
   11593                 :            :                                            RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   11594                 :            :                                            NULL,
   11595                 :            :                                            "cannot create flow jump action");
   11596                 :          0 :                         mlx5_flow_os_destroy_flow_tbl(tbl->obj);
   11597                 :          0 :                         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_JUMP], idx);
   11598                 :          0 :                         return NULL;
   11599                 :            :                 }
   11600                 :            :         }
   11601   [ #  #  #  # ]:          0 :         MKSTR(matcher_name, "%s_%s_%u_%u_matcher_list",
   11602                 :            :               key.is_fdb ? "FDB" : "NIC", key.is_egress ? "egress" : "ingress",
   11603                 :            :               key.level, key.id);
   11604                 :          0 :         tbl_data->matchers = mlx5_list_create(matcher_name, sh, true,
   11605                 :            :                                               flow_dv_matcher_create_cb,
   11606                 :            :                                               flow_dv_matcher_match_cb,
   11607                 :            :                                               flow_dv_matcher_remove_cb,
   11608                 :            :                                               flow_dv_matcher_clone_cb,
   11609                 :            :                                               flow_dv_matcher_clone_free_cb);
   11610         [ #  # ]:          0 :         if (!tbl_data->matchers) {
   11611                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   11612                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   11613                 :            :                                    NULL,
   11614                 :            :                                    "cannot create tbl matcher list");
   11615                 :          0 :                 mlx5_flow_os_destroy_flow_action(tbl_data->jump.action);
   11616                 :          0 :                 mlx5_flow_os_destroy_flow_tbl(tbl->obj);
   11617                 :          0 :                 mlx5_ipool_free(sh->ipool[MLX5_IPOOL_JUMP], idx);
   11618                 :          0 :                 return NULL;
   11619                 :            :         }
   11620                 :          0 :         return &tbl_data->entry;
   11621                 :            : }
   11622                 :            : 
   11623                 :            : int
   11624                 :          0 : flow_dv_tbl_match_cb(void *tool_ctx __rte_unused, struct mlx5_list_entry *entry,
   11625                 :            :                      void *cb_ctx)
   11626                 :            : {
   11627                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   11628                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data =
   11629                 :            :                 container_of(entry, struct mlx5_flow_tbl_data_entry, entry);
   11630                 :          0 :         union mlx5_flow_tbl_key key = { .v64 =  *(uint64_t *)(ctx->data) };
   11631                 :            : 
   11632                 :          0 :         return tbl_data->level != key.level ||
   11633         [ #  # ]:          0 :                tbl_data->id != key.id ||
   11634         [ #  # ]:          0 :                tbl_data->dummy != key.dummy ||
   11635   [ #  #  #  # ]:          0 :                tbl_data->is_transfer != !!key.is_fdb ||
   11636         [ #  # ]:          0 :                tbl_data->is_egress != !!key.is_egress;
   11637                 :            : }
   11638                 :            : 
   11639                 :            : struct mlx5_list_entry *
   11640                 :          0 : flow_dv_tbl_clone_cb(void *tool_ctx, struct mlx5_list_entry *oentry,
   11641                 :            :                       void *cb_ctx)
   11642                 :            : {
   11643                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   11644                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   11645                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data;
   11646                 :          0 :         struct rte_flow_error *error = ctx->error;
   11647                 :          0 :         uint32_t idx = 0;
   11648                 :            : 
   11649                 :          0 :         tbl_data = mlx5_ipool_malloc(sh->ipool[MLX5_IPOOL_JUMP], &idx);
   11650         [ #  # ]:          0 :         if (!tbl_data) {
   11651                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   11652                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   11653                 :            :                                    NULL,
   11654                 :            :                                    "cannot allocate flow table data entry");
   11655                 :          0 :                 return NULL;
   11656                 :            :         }
   11657                 :            :         memcpy(tbl_data, oentry, sizeof(*tbl_data));
   11658                 :          0 :         tbl_data->idx = idx;
   11659                 :          0 :         return &tbl_data->entry;
   11660                 :            : }
   11661                 :            : 
   11662                 :            : void
   11663                 :          0 : flow_dv_tbl_clone_free_cb(void *tool_ctx, struct mlx5_list_entry *entry)
   11664                 :            : {
   11665                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   11666                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data =
   11667                 :            :                     container_of(entry, struct mlx5_flow_tbl_data_entry, entry);
   11668                 :            : 
   11669                 :          0 :         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_JUMP], tbl_data->idx);
   11670                 :          0 : }
   11671                 :            : 
   11672                 :            : /**
   11673                 :            :  * Get a flow table.
   11674                 :            :  *
   11675                 :            :  * @param[in, out] dev
   11676                 :            :  *   Pointer to rte_eth_dev structure.
   11677                 :            :  * @param[in] table_level
   11678                 :            :  *   Table level to use.
   11679                 :            :  * @param[in] egress
   11680                 :            :  *   Direction of the table.
   11681                 :            :  * @param[in] transfer
   11682                 :            :  *   E-Switch or NIC flow.
   11683                 :            :  * @param[in] dummy
   11684                 :            :  *   Dummy entry for dv API.
   11685                 :            :  * @param[in] table_id
   11686                 :            :  *   Table id to use.
   11687                 :            :  * @param[out] error
   11688                 :            :  *   pointer to error structure.
   11689                 :            :  *
   11690                 :            :  * @return
   11691                 :            :  *   Returns tables resource based on the index, NULL in case of failed.
   11692                 :            :  */
   11693                 :            : struct mlx5_flow_tbl_resource *
   11694                 :          0 : flow_dv_tbl_resource_get(struct rte_eth_dev *dev,
   11695                 :            :                          uint32_t table_level, uint8_t egress,
   11696                 :            :                          uint8_t transfer,
   11697                 :            :                          bool external,
   11698                 :            :                          const struct mlx5_flow_tunnel *tunnel,
   11699                 :            :                          uint32_t group_id, uint8_t dummy,
   11700                 :            :                          uint32_t table_id,
   11701                 :            :                          struct rte_flow_error *error)
   11702                 :            : {
   11703                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   11704                 :          0 :         union mlx5_flow_tbl_key table_key = {
   11705                 :            :                 {
   11706                 :            :                         .level = table_level,
   11707                 :            :                         .id = table_id,
   11708                 :            :                         .reserved = 0,
   11709                 :          0 :                         .dummy = !!dummy,
   11710                 :          0 :                         .is_fdb = !!transfer,
   11711                 :          0 :                         .is_egress = !!egress,
   11712                 :            :                 }
   11713                 :            :         };
   11714                 :          0 :         struct mlx5_flow_tbl_tunnel_prm tt_prm = {
   11715                 :            :                 .tunnel = tunnel,
   11716                 :            :                 .group_id = group_id,
   11717                 :            :                 .external = external,
   11718                 :            :         };
   11719                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
   11720                 :            :                 .dev = dev,
   11721                 :            :                 .error = error,
   11722                 :            :                 .data = &table_key.v64,
   11723                 :            :                 .data2 = &tt_prm,
   11724                 :            :         };
   11725                 :            :         struct mlx5_list_entry *entry;
   11726                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data;
   11727                 :            : 
   11728                 :          0 :         entry = mlx5_hlist_register(priv->sh->flow_tbls, table_key.v64, &ctx);
   11729         [ #  # ]:          0 :         if (!entry) {
   11730                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   11731                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   11732                 :            :                                    "cannot get table");
   11733                 :          0 :                 return NULL;
   11734                 :            :         }
   11735         [ #  # ]:          0 :         DRV_LOG(DEBUG, "table_level %u table_id %u "
   11736                 :            :                 "tunnel %u group %u registered.",
   11737                 :            :                 table_level, table_id,
   11738                 :            :                 tunnel ? tunnel->tunnel_id : 0, group_id);
   11739                 :            :         tbl_data = container_of(entry, struct mlx5_flow_tbl_data_entry, entry);
   11740                 :          0 :         return &tbl_data->tbl;
   11741                 :            : }
   11742                 :            : 
   11743                 :            : void
   11744                 :          0 : flow_dv_tbl_remove_cb(void *tool_ctx, struct mlx5_list_entry *entry)
   11745                 :            : {
   11746                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   11747                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data =
   11748                 :            :                     container_of(entry, struct mlx5_flow_tbl_data_entry, entry);
   11749                 :            : 
   11750                 :            :         MLX5_ASSERT(entry && sh);
   11751         [ #  # ]:          0 :         if (tbl_data->jump.action)
   11752                 :            :                 mlx5_flow_os_destroy_flow_action(tbl_data->jump.action);
   11753         [ #  # ]:          0 :         if (tbl_data->tbl.obj)
   11754                 :            :                 mlx5_flow_os_destroy_flow_tbl(tbl_data->tbl.obj);
   11755         [ #  # ]:          0 :         if (tbl_data->tunnel_offload && tbl_data->external) {
   11756                 :            :                 struct mlx5_list_entry *he;
   11757                 :            :                 struct mlx5_hlist *tunnel_grp_hash;
   11758                 :          0 :                 struct mlx5_flow_tunnel_hub *thub = sh->tunnel_hub;
   11759                 :          0 :                 union tunnel_tbl_key tunnel_key = {
   11760                 :          0 :                         .tunnel_id = tbl_data->tunnel ?
   11761         [ #  # ]:          0 :                                         tbl_data->tunnel->tunnel_id : 0,
   11762                 :          0 :                         .group = tbl_data->group_id
   11763                 :            :                 };
   11764                 :          0 :                 uint32_t table_level = tbl_data->level;
   11765                 :          0 :                 struct mlx5_flow_cb_ctx ctx = {
   11766                 :            :                         .data = (void *)&tunnel_key.val,
   11767                 :            :                 };
   11768                 :            : 
   11769                 :            :                 tunnel_grp_hash = tbl_data->tunnel ?
   11770         [ #  # ]:          0 :                                         tbl_data->tunnel->groups :
   11771                 :            :                                         thub->groups;
   11772                 :          0 :                 he = mlx5_hlist_lookup(tunnel_grp_hash, tunnel_key.val, &ctx);
   11773         [ #  # ]:          0 :                 if (he)
   11774                 :          0 :                         mlx5_hlist_unregister(tunnel_grp_hash, he);
   11775         [ #  # ]:          0 :                 DRV_LOG(DEBUG,
   11776                 :            :                         "table_level %u id %u tunnel %u group %u released.",
   11777                 :            :                         table_level,
   11778                 :            :                         tbl_data->id,
   11779                 :            :                         tbl_data->tunnel ?
   11780                 :            :                         tbl_data->tunnel->tunnel_id : 0,
   11781                 :            :                         tbl_data->group_id);
   11782                 :            :         }
   11783         [ #  # ]:          0 :         if (tbl_data->matchers)
   11784                 :          0 :                 mlx5_list_destroy(tbl_data->matchers);
   11785                 :          0 :         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_JUMP], tbl_data->idx);
   11786                 :          0 : }
   11787                 :            : 
   11788                 :            : /**
   11789                 :            :  * Release a flow table.
   11790                 :            :  *
   11791                 :            :  * @param[in] sh
   11792                 :            :  *   Pointer to device shared structure.
   11793                 :            :  * @param[in] tbl
   11794                 :            :  *   Table resource to be released.
   11795                 :            :  *
   11796                 :            :  * @return
   11797                 :            :  *   Returns 0 if table was released, else return 1;
   11798                 :            :  */
   11799                 :            : int
   11800                 :          0 : flow_dv_tbl_resource_release(struct mlx5_dev_ctx_shared *sh,
   11801                 :            :                              struct mlx5_flow_tbl_resource *tbl)
   11802                 :            : {
   11803                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data =
   11804                 :          0 :                 container_of(tbl, struct mlx5_flow_tbl_data_entry, tbl);
   11805                 :            : 
   11806         [ #  # ]:          0 :         if (!tbl)
   11807                 :            :                 return 0;
   11808                 :          0 :         return mlx5_hlist_unregister(sh->flow_tbls, &tbl_data->entry);
   11809                 :            : }
   11810                 :            : 
   11811                 :            : int
   11812                 :          0 : flow_dv_matcher_match_cb(void *tool_ctx __rte_unused,
   11813                 :            :                          struct mlx5_list_entry *entry, void *cb_ctx)
   11814                 :            : {
   11815                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   11816                 :          0 :         struct mlx5_flow_dv_matcher *ref = ctx->data;
   11817                 :            :         struct mlx5_flow_dv_matcher *cur = container_of(entry, typeof(*cur),
   11818                 :            :                                                         entry);
   11819                 :            : 
   11820                 :          0 :         return cur->crc != ref->crc ||
   11821         [ #  # ]:          0 :                cur->priority != ref->priority ||
   11822                 :          0 :                memcmp((const void *)cur->mask.buf,
   11823         [ #  # ]:          0 :                       (const void *)ref->mask.buf, ref->mask.size);
   11824                 :            : }
   11825                 :            : 
   11826                 :            : struct mlx5_list_entry *
   11827                 :          0 : flow_dv_matcher_create_cb(void *tool_ctx, void *cb_ctx)
   11828                 :            : {
   11829                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   11830                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   11831                 :          0 :         struct mlx5_flow_dv_matcher *ref = ctx->data;
   11832                 :            :         struct mlx5_flow_dv_matcher *resource;
   11833                 :          0 :         struct mlx5dv_flow_matcher_attr dv_attr = {
   11834                 :            :                 .type = IBV_FLOW_ATTR_NORMAL,
   11835                 :          0 :                 .match_mask = (void *)&ref->mask,
   11836                 :            :         };
   11837                 :          0 :         struct mlx5_flow_tbl_data_entry *tbl = container_of(ref->tbl,
   11838                 :            :                                                             typeof(*tbl), tbl);
   11839                 :            :         int ret;
   11840                 :            : 
   11841                 :          0 :         resource = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*resource), 0,
   11842                 :            :                                SOCKET_ID_ANY);
   11843         [ #  # ]:          0 :         if (!resource) {
   11844                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
   11845                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   11846                 :            :                                    "cannot create matcher");
   11847                 :          0 :                 return NULL;
   11848                 :            :         }
   11849                 :          0 :         *resource = *ref;
   11850                 :          0 :         dv_attr.match_criteria_enable =
   11851         [ #  # ]:          0 :                 flow_dv_matcher_enable(resource->mask.buf);
   11852                 :            :         __flow_dv_adjust_buf_size(&ref->mask.size,
   11853                 :            :                                   dv_attr.match_criteria_enable);
   11854                 :          0 :         dv_attr.priority = ref->priority;
   11855         [ #  # ]:          0 :         if (tbl->is_egress)
   11856                 :          0 :                 dv_attr.flags |= IBV_FLOW_ATTR_FLAGS_EGRESS;
   11857                 :          0 :         ret = mlx5_flow_os_create_flow_matcher(sh->cdev->ctx, &dv_attr,
   11858                 :            :                                                tbl->tbl.obj,
   11859                 :            :                                                &resource->matcher_object);
   11860                 :            :         if (ret) {
   11861                 :          0 :                 mlx5_free(resource);
   11862                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
   11863                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   11864                 :            :                                    "cannot create matcher");
   11865                 :          0 :                 return NULL;
   11866                 :            :         }
   11867                 :          0 :         return &resource->entry;
   11868                 :            : }
   11869                 :            : 
   11870                 :            : /**
   11871                 :            :  * Register the flow matcher.
   11872                 :            :  *
   11873                 :            :  * @param[in, out] dev
   11874                 :            :  *   Pointer to rte_eth_dev structure.
   11875                 :            :  * @param[in, out] matcher
   11876                 :            :  *   Pointer to flow matcher.
   11877                 :            :  * @param[in, out] key
   11878                 :            :  *   Pointer to flow table key.
   11879                 :            :  * @parm[in, out] dev_flow
   11880                 :            :  *   Pointer to the dev_flow.
   11881                 :            :  * @param[out] error
   11882                 :            :  *   pointer to error structure.
   11883                 :            :  *
   11884                 :            :  * @return
   11885                 :            :  *   0 on success otherwise -errno and errno is set.
   11886                 :            :  */
   11887                 :            : static int
   11888                 :          0 : flow_dv_matcher_register(struct rte_eth_dev *dev,
   11889                 :            :                          struct mlx5_flow_dv_matcher *ref,
   11890                 :            :                          union mlx5_flow_tbl_key *key,
   11891                 :            :                          struct mlx5_flow *dev_flow,
   11892                 :            :                          const struct mlx5_flow_tunnel *tunnel,
   11893                 :            :                          uint32_t group_id,
   11894                 :            :                          struct rte_flow_error *error)
   11895                 :            : {
   11896                 :            :         struct mlx5_list_entry *entry;
   11897                 :            :         struct mlx5_flow_dv_matcher *resource;
   11898                 :            :         struct mlx5_flow_tbl_resource *tbl;
   11899                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data;
   11900                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
   11901                 :            :                 .error = error,
   11902                 :            :                 .data = ref,
   11903                 :            :         };
   11904                 :            :         /**
   11905                 :            :          * tunnel offload API requires this registration for cases when
   11906                 :            :          * tunnel match rule was inserted before tunnel set rule.
   11907                 :            :          */
   11908                 :          0 :         tbl = flow_dv_tbl_resource_get(dev, key->level,
   11909                 :          0 :                                        key->is_egress, key->is_fdb,
   11910                 :          0 :                                        dev_flow->external, tunnel,
   11911                 :          0 :                                        group_id, 0, key->id, error);
   11912         [ #  # ]:          0 :         if (!tbl)
   11913                 :          0 :                 return -rte_errno;      /* No need to refill the error info */
   11914                 :          0 :         tbl_data = container_of(tbl, struct mlx5_flow_tbl_data_entry, tbl);
   11915                 :          0 :         ref->tbl = tbl;
   11916                 :          0 :         entry = mlx5_list_register(tbl_data->matchers, &ctx);
   11917         [ #  # ]:          0 :         if (!entry) {
   11918                 :          0 :                 flow_dv_tbl_resource_release(MLX5_SH(dev), tbl);
   11919                 :          0 :                 return rte_flow_error_set(error, ENOMEM,
   11920                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   11921                 :            :                                           "cannot allocate ref memory");
   11922                 :            :         }
   11923                 :            :         resource = container_of(entry, typeof(*resource), entry);
   11924                 :          0 :         dev_flow->handle->dvh.matcher = resource;
   11925                 :          0 :         return 0;
   11926                 :            : }
   11927                 :            : 
   11928                 :            : struct mlx5_list_entry *
   11929                 :          0 : flow_dv_tag_create_cb(void *tool_ctx, void *cb_ctx)
   11930                 :            : {
   11931                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   11932                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   11933                 :            :         struct mlx5_flow_dv_tag_resource *entry;
   11934                 :          0 :         uint32_t idx = 0;
   11935                 :            :         int ret;
   11936                 :            : 
   11937                 :          0 :         entry = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_TAG], &idx);
   11938         [ #  # ]:          0 :         if (!entry) {
   11939                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
   11940                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   11941                 :            :                                    "cannot allocate resource memory");
   11942                 :          0 :                 return NULL;
   11943                 :            :         }
   11944                 :          0 :         entry->idx = idx;
   11945                 :          0 :         entry->tag_id = *(uint32_t *)(ctx->data);
   11946                 :            :         ret = mlx5_flow_os_create_flow_action_tag(entry->tag_id,
   11947                 :            :                                                   &entry->action);
   11948                 :            :         if (ret) {
   11949                 :          0 :                 mlx5_ipool_free(sh->ipool[MLX5_IPOOL_TAG], idx);
   11950                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
   11951                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   11952                 :            :                                    NULL, "cannot create action");
   11953                 :          0 :                 return NULL;
   11954                 :            :         }
   11955                 :          0 :         return &entry->entry;
   11956                 :            : }
   11957                 :            : 
   11958                 :            : int
   11959                 :          0 : flow_dv_tag_match_cb(void *tool_ctx __rte_unused, struct mlx5_list_entry *entry,
   11960                 :            :                      void *cb_ctx)
   11961                 :            : {
   11962                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   11963                 :            :         struct mlx5_flow_dv_tag_resource *tag =
   11964                 :            :                    container_of(entry, struct mlx5_flow_dv_tag_resource, entry);
   11965                 :            : 
   11966                 :          0 :         return *(uint32_t *)(ctx->data) != tag->tag_id;
   11967                 :            : }
   11968                 :            : 
   11969                 :            : struct mlx5_list_entry *
   11970                 :          0 : flow_dv_tag_clone_cb(void *tool_ctx, struct mlx5_list_entry *oentry,
   11971                 :            :                      void *cb_ctx)
   11972                 :            : {
   11973                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   11974                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   11975                 :            :         struct mlx5_flow_dv_tag_resource *entry;
   11976                 :          0 :         uint32_t idx = 0;
   11977                 :            : 
   11978                 :          0 :         entry = mlx5_ipool_malloc(sh->ipool[MLX5_IPOOL_TAG], &idx);
   11979         [ #  # ]:          0 :         if (!entry) {
   11980                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
   11981                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   11982                 :            :                                    "cannot allocate tag resource memory");
   11983                 :          0 :                 return NULL;
   11984                 :            :         }
   11985                 :            :         memcpy(entry, oentry, sizeof(*entry));
   11986                 :          0 :         entry->idx = idx;
   11987                 :          0 :         return &entry->entry;
   11988                 :            : }
   11989                 :            : 
   11990                 :            : void
   11991                 :          0 : flow_dv_tag_clone_free_cb(void *tool_ctx, struct mlx5_list_entry *entry)
   11992                 :            : {
   11993                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   11994                 :            :         struct mlx5_flow_dv_tag_resource *tag =
   11995                 :            :                    container_of(entry, struct mlx5_flow_dv_tag_resource, entry);
   11996                 :            : 
   11997                 :          0 :         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_TAG], tag->idx);
   11998                 :          0 : }
   11999                 :            : 
   12000                 :            : /**
   12001                 :            :  * Find existing tag resource or create and register a new one.
   12002                 :            :  *
   12003                 :            :  * @param dev[in, out]
   12004                 :            :  *   Pointer to rte_eth_dev structure.
   12005                 :            :  * @param[in, out] tag_be24
   12006                 :            :  *   Tag value in big endian then R-shift 8.
   12007                 :            :  * @parm[in, out] dev_flow
   12008                 :            :  *   Pointer to the dev_flow.
   12009                 :            :  * @param[out] error
   12010                 :            :  *   pointer to error structure.
   12011                 :            :  *
   12012                 :            :  * @return
   12013                 :            :  *   0 on success otherwise -errno and errno is set.
   12014                 :            :  */
   12015                 :            : static int
   12016                 :          0 : flow_dv_tag_resource_register
   12017                 :            :                         (struct rte_eth_dev *dev,
   12018                 :            :                          uint32_t tag_be24,
   12019                 :            :                          struct mlx5_flow *dev_flow,
   12020                 :            :                          struct rte_flow_error *error)
   12021                 :            : {
   12022                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12023                 :            :         struct mlx5_flow_dv_tag_resource *resource;
   12024                 :            :         struct mlx5_list_entry *entry;
   12025                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
   12026                 :            :                                         .error = error,
   12027                 :            :                                         .data = &tag_be24,
   12028                 :            :                                         };
   12029                 :            :         struct mlx5_hlist *tag_table;
   12030                 :            : 
   12031                 :          0 :         tag_table = flow_dv_hlist_prepare(priv->sh, &priv->sh->tag_table,
   12032                 :            :                                       "tags",
   12033                 :            :                                       MLX5_TAGS_HLIST_ARRAY_SIZE,
   12034                 :          0 :                                       false, false, priv->sh,
   12035                 :            :                                       flow_dv_tag_create_cb,
   12036                 :            :                                       flow_dv_tag_match_cb,
   12037                 :            :                                       flow_dv_tag_remove_cb,
   12038                 :            :                                       flow_dv_tag_clone_cb,
   12039                 :            :                                       flow_dv_tag_clone_free_cb,
   12040                 :            :                                       error);
   12041         [ #  # ]:          0 :         if (unlikely(!tag_table))
   12042                 :          0 :                 return -rte_errno;
   12043                 :          0 :         entry = mlx5_hlist_register(tag_table, tag_be24, &ctx);
   12044         [ #  # ]:          0 :         if (entry) {
   12045                 :            :                 resource = container_of(entry, struct mlx5_flow_dv_tag_resource,
   12046                 :            :                                         entry);
   12047                 :          0 :                 dev_flow->handle->dvh.rix_tag = resource->idx;
   12048                 :          0 :                 dev_flow->dv.tag_resource = resource;
   12049                 :          0 :                 return 0;
   12050                 :            :         }
   12051                 :          0 :         return -rte_errno;
   12052                 :            : }
   12053                 :            : 
   12054                 :            : void
   12055                 :          0 : flow_dv_tag_remove_cb(void *tool_ctx, struct mlx5_list_entry *entry)
   12056                 :            : {
   12057                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   12058                 :            :         struct mlx5_flow_dv_tag_resource *tag =
   12059                 :            :                    container_of(entry, struct mlx5_flow_dv_tag_resource, entry);
   12060                 :            : 
   12061                 :            :         MLX5_ASSERT(tag && sh && tag->action);
   12062                 :          0 :         claim_zero(mlx5_flow_os_destroy_flow_action(tag->action));
   12063                 :          0 :         DRV_LOG(DEBUG, "Tag %p: removed.", (void *)tag);
   12064                 :          0 :         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_TAG], tag->idx);
   12065                 :          0 : }
   12066                 :            : 
   12067                 :            : /**
   12068                 :            :  * Release the tag.
   12069                 :            :  *
   12070                 :            :  * @param dev
   12071                 :            :  *   Pointer to Ethernet device.
   12072                 :            :  * @param tag_idx
   12073                 :            :  *   Tag index.
   12074                 :            :  *
   12075                 :            :  * @return
   12076                 :            :  *   1 while a reference on it exists, 0 when freed.
   12077                 :            :  */
   12078                 :            : static int
   12079                 :          0 : flow_dv_tag_release(struct rte_eth_dev *dev,
   12080                 :            :                     uint32_t tag_idx)
   12081                 :            : {
   12082                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12083                 :            :         struct mlx5_flow_dv_tag_resource *tag;
   12084                 :            : 
   12085                 :          0 :         tag = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_TAG], tag_idx);
   12086         [ #  # ]:          0 :         if (!tag)
   12087                 :            :                 return 0;
   12088                 :          0 :         DRV_LOG(DEBUG, "port %u tag %p: refcnt %d--",
   12089                 :            :                 dev->data->port_id, (void *)tag, tag->entry.ref_cnt);
   12090                 :          0 :         return mlx5_hlist_unregister(priv->sh->tag_table, &tag->entry);
   12091                 :            : }
   12092                 :            : 
   12093                 :            : /**
   12094                 :            :  * Translate action PORT_ID / REPRESENTED_PORT to vport.
   12095                 :            :  *
   12096                 :            :  * @param[in] dev
   12097                 :            :  *   Pointer to rte_eth_dev structure.
   12098                 :            :  * @param[in] action
   12099                 :            :  *   Pointer to action PORT_ID / REPRESENTED_PORT.
   12100                 :            :  * @param[out] dst_port_id
   12101                 :            :  *   The target port ID.
   12102                 :            :  * @param[out] error
   12103                 :            :  *   Pointer to the error structure.
   12104                 :            :  *
   12105                 :            :  * @return
   12106                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   12107                 :            :  */
   12108                 :            : static int
   12109                 :          0 : flow_dv_translate_action_port_id(struct rte_eth_dev *dev,
   12110                 :            :                                  const struct rte_flow_action *action,
   12111                 :            :                                  uint32_t *dst_port_id,
   12112                 :            :                                  struct rte_flow_error *error)
   12113                 :            : {
   12114                 :            :         uint32_t port;
   12115                 :            :         struct mlx5_priv *priv;
   12116                 :            : 
   12117      [ #  #  # ]:          0 :         switch (action->type) {
   12118                 :          0 :         case RTE_FLOW_ACTION_TYPE_PORT_ID: {
   12119                 :            :                 const struct rte_flow_action_port_id *conf;
   12120                 :            : 
   12121                 :          0 :                 conf = (const struct rte_flow_action_port_id *)action->conf;
   12122         [ #  # ]:          0 :                 port = conf->original ? dev->data->port_id : conf->id;
   12123                 :            :                 break;
   12124                 :            :         }
   12125                 :          0 :         case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: {
   12126                 :            :                 const struct rte_flow_action_ethdev *ethdev;
   12127                 :            : 
   12128                 :          0 :                 ethdev = (const struct rte_flow_action_ethdev *)action->conf;
   12129                 :          0 :                 port = ethdev->port_id;
   12130                 :          0 :                 break;
   12131                 :            :         }
   12132                 :          0 :         default:
   12133                 :            :                 MLX5_ASSERT(false);
   12134                 :          0 :                 return rte_flow_error_set(error, EINVAL,
   12135                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
   12136                 :            :                                           "unknown E-Switch action");
   12137                 :            :         }
   12138                 :            : 
   12139                 :          0 :         priv = mlx5_port_to_eswitch_info(port, false);
   12140         [ #  # ]:          0 :         if (!priv)
   12141                 :          0 :                 return rte_flow_error_set(error, -rte_errno,
   12142                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
   12143                 :            :                                           NULL,
   12144                 :            :                                           "No eswitch info was found for port");
   12145                 :            : #ifdef HAVE_MLX5DV_DR_CREATE_DEST_IB_PORT
   12146                 :            :         /*
   12147                 :            :          * This parameter is transferred to
   12148                 :            :          * mlx5dv_dr_action_create_dest_ib_port().
   12149                 :            :          */
   12150                 :          0 :         *dst_port_id = priv->dev_port;
   12151                 :            : #else
   12152                 :            :         /*
   12153                 :            :          * Legacy mode, no LAG configurations is supported.
   12154                 :            :          * This parameter is transferred to
   12155                 :            :          * mlx5dv_dr_action_create_dest_vport().
   12156                 :            :          */
   12157                 :            :         *dst_port_id = priv->vport_id;
   12158                 :            : #endif
   12159                 :          0 :         return 0;
   12160                 :            : }
   12161                 :            : 
   12162                 :            : /**
   12163                 :            :  * Create a counter with aging configuration.
   12164                 :            :  *
   12165                 :            :  * @param[in] dev
   12166                 :            :  *   Pointer to rte_eth_dev structure.
   12167                 :            :  * @param[in] dev_flow
   12168                 :            :  *   Pointer to the mlx5_flow.
   12169                 :            :  * @param[out] count
   12170                 :            :  *   Pointer to the counter action configuration.
   12171                 :            :  * @param[in] age
   12172                 :            :  *   Pointer to the aging action configuration.
   12173                 :            :  *
   12174                 :            :  * @return
   12175                 :            :  *   Index to flow counter on success, 0 otherwise.
   12176                 :            :  */
   12177                 :            : static uint32_t
   12178                 :          0 : flow_dv_translate_create_counter(struct rte_eth_dev *dev,
   12179                 :            :                                 struct mlx5_flow *dev_flow,
   12180                 :            :                                 const struct rte_flow_action_count *count
   12181                 :            :                                         __rte_unused,
   12182                 :            :                                 const struct rte_flow_action_age *age)
   12183                 :            : {
   12184                 :            :         uint32_t counter;
   12185                 :            :         struct mlx5_age_param *age_param;
   12186                 :            : 
   12187                 :          0 :         counter = flow_dv_counter_alloc(dev, !!age);
   12188         [ #  # ]:          0 :         if (!counter || age == NULL)
   12189                 :            :                 return counter;
   12190                 :            :         age_param = flow_dv_counter_idx_get_age(dev, counter);
   12191         [ #  # ]:          0 :         age_param->context = age->context ? age->context :
   12192                 :          0 :                 (void *)(uintptr_t)(dev_flow->flow_idx);
   12193                 :          0 :         age_param->timeout = age->timeout;
   12194                 :          0 :         age_param->port_id = dev->data->port_id;
   12195                 :          0 :         __atomic_store_n(&age_param->sec_since_last_hit, 0, __ATOMIC_RELAXED);
   12196                 :          0 :         __atomic_store_n(&age_param->state, AGE_CANDIDATE, __ATOMIC_RELAXED);
   12197                 :          0 :         return counter;
   12198                 :            : }
   12199                 :            : 
   12200                 :            : /**
   12201                 :            :  * Add SQ matcher
   12202                 :            :  *
   12203                 :            :  * @param[in, out] matcher
   12204                 :            :  *   Flow matcher.
   12205                 :            :  * @param[in, out] key
   12206                 :            :  *   Flow matcher value.
   12207                 :            :  * @param[in] item
   12208                 :            :  *   Flow pattern to translate.
   12209                 :            :  * @param[in] key_type
   12210                 :            :  *   Set flow matcher mask or value.
   12211                 :            :  */
   12212                 :            : static void
   12213                 :          0 : flow_dv_translate_item_sq(void *key,
   12214                 :            :                           const struct rte_flow_item *item,
   12215                 :            :                           uint32_t key_type)
   12216                 :            : {
   12217                 :            :         const struct mlx5_rte_flow_item_sq *queue_m;
   12218                 :            :         const struct mlx5_rte_flow_item_sq *queue_v;
   12219                 :          0 :         const struct mlx5_rte_flow_item_sq queue_mask = {
   12220                 :            :                 .queue = UINT32_MAX,
   12221                 :            :         };
   12222                 :            :         void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
   12223                 :            :         uint32_t queue;
   12224                 :            : 
   12225   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, queue_v, queue_m, &queue_mask);
             #  #  #  # ]
   12226         [ #  # ]:          0 :         if (!queue_m || !queue_v)
   12227                 :          0 :                 return;
   12228         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_V) {
   12229                 :          0 :                 queue = queue_v->queue;
   12230         [ #  # ]:          0 :                 if (key_type == MLX5_SET_MATCHER_SW_V)
   12231                 :          0 :                         queue &= queue_m->queue;
   12232                 :            :         } else {
   12233                 :          0 :                 queue = queue_m->queue;
   12234                 :            :         }
   12235         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, source_sqn, queue);
   12236                 :            : }
   12237                 :            : 
   12238                 :            : /**
   12239                 :            :  * Set the hash fields according to the @p flow information.
   12240                 :            :  *
   12241                 :            :  * @param[in] item_flags
   12242                 :            :  *   The match pattern item flags.
   12243                 :            :  * @param[in] rss_desc
   12244                 :            :  *   Pointer to the mlx5_flow_rss_desc.
   12245                 :            :  * @param[out] hash_fields
   12246                 :            :  *   Pointer to the RSS hash fields.
   12247                 :            :  */
   12248                 :            : void
   12249                 :          0 : flow_dv_hashfields_set(uint64_t item_flags,
   12250                 :            :                        struct mlx5_flow_rss_desc *rss_desc,
   12251                 :            :                        uint64_t *hash_fields)
   12252                 :            : {
   12253                 :            :         uint64_t items = item_flags;
   12254                 :            :         uint64_t fields = 0;
   12255                 :            :         int rss_inner = 0;
   12256         [ #  # ]:          0 :         uint64_t rss_types = rte_eth_rss_hf_refine(rss_desc->types);
   12257                 :            : 
   12258                 :            :         *hash_fields = 0;
   12259                 :            : #ifdef HAVE_IBV_DEVICE_TUNNEL_SUPPORT
   12260         [ #  # ]:          0 :         if (rss_desc->level >= 2)
   12261                 :            :                 rss_inner = 1;
   12262                 :            : #endif
   12263   [ #  #  #  # ]:          0 :         if ((rss_inner && (items & MLX5_FLOW_LAYER_INNER_L3_IPV4)) ||
   12264         [ #  # ]:          0 :             (!rss_inner && (items & MLX5_FLOW_LAYER_OUTER_L3_IPV4))) {
   12265         [ #  # ]:          0 :                 if (rss_types & MLX5_IPV4_LAYER_TYPES) {
   12266         [ #  # ]:          0 :                         if (rss_types & RTE_ETH_RSS_L3_SRC_ONLY)
   12267                 :            :                                 fields |= IBV_RX_HASH_SRC_IPV4;
   12268         [ #  # ]:          0 :                         else if (rss_types & RTE_ETH_RSS_L3_DST_ONLY)
   12269                 :            :                                 fields |= IBV_RX_HASH_DST_IPV4;
   12270                 :            :                         else
   12271                 :            :                                 fields |= MLX5_IPV4_IBV_RX_HASH;
   12272                 :            :                 }
   12273   [ #  #  #  #  :          0 :         } else if ((rss_inner && (items & MLX5_FLOW_LAYER_INNER_L3_IPV6)) ||
                   #  # ]
   12274         [ #  # ]:          0 :                    (!rss_inner && (items & MLX5_FLOW_LAYER_OUTER_L3_IPV6))) {
   12275         [ #  # ]:          0 :                 if (rss_types & MLX5_IPV6_LAYER_TYPES) {
   12276         [ #  # ]:          0 :                         if (rss_types & RTE_ETH_RSS_L3_SRC_ONLY)
   12277                 :            :                                 fields |= IBV_RX_HASH_SRC_IPV6;
   12278         [ #  # ]:          0 :                         else if (rss_types & RTE_ETH_RSS_L3_DST_ONLY)
   12279                 :            :                                 fields |= IBV_RX_HASH_DST_IPV6;
   12280                 :            :                         else
   12281                 :            :                                 fields |= MLX5_IPV6_IBV_RX_HASH;
   12282                 :            :                 }
   12283                 :            :         }
   12284         [ #  # ]:          0 :         if (items & MLX5_FLOW_ITEM_ESP) {
   12285         [ #  # ]:          0 :                 if (rss_types & RTE_ETH_RSS_ESP)
   12286                 :          0 :                         fields |= IBV_RX_HASH_IPSEC_SPI;
   12287                 :            :         }
   12288         [ #  # ]:          0 :         if ((fields & ~IBV_RX_HASH_IPSEC_SPI) == 0) {
   12289                 :          0 :                 *hash_fields = fields;
   12290                 :            :                 /*
   12291                 :            :                  * There is no match between the RSS types and the
   12292                 :            :                  * L3 protocol (IPv4/IPv6) defined in the flow rule.
   12293                 :            :                  */
   12294                 :          0 :                 return;
   12295                 :            :         }
   12296   [ #  #  #  #  :          0 :         if ((rss_inner && (items & MLX5_FLOW_LAYER_INNER_L4_UDP)) ||
                   #  # ]
   12297         [ #  # ]:          0 :             (!rss_inner && (items & MLX5_FLOW_LAYER_OUTER_L4_UDP))) {
   12298         [ #  # ]:          0 :                 if (rss_types & RTE_ETH_RSS_UDP) {
   12299         [ #  # ]:          0 :                         if (rss_types & RTE_ETH_RSS_L4_SRC_ONLY)
   12300                 :          0 :                                 fields |= IBV_RX_HASH_SRC_PORT_UDP;
   12301         [ #  # ]:          0 :                         else if (rss_types & RTE_ETH_RSS_L4_DST_ONLY)
   12302                 :          0 :                                 fields |= IBV_RX_HASH_DST_PORT_UDP;
   12303                 :            :                         else
   12304                 :          0 :                                 fields |= MLX5_UDP_IBV_RX_HASH;
   12305                 :            :                 }
   12306   [ #  #  #  #  :          0 :         } else if ((rss_inner && (items & MLX5_FLOW_LAYER_INNER_L4_TCP)) ||
                   #  # ]
   12307         [ #  # ]:          0 :                    (!rss_inner && (items & MLX5_FLOW_LAYER_OUTER_L4_TCP))) {
   12308         [ #  # ]:          0 :                 if (rss_types & RTE_ETH_RSS_TCP) {
   12309         [ #  # ]:          0 :                         if (rss_types & RTE_ETH_RSS_L4_SRC_ONLY)
   12310                 :          0 :                                 fields |= IBV_RX_HASH_SRC_PORT_TCP;
   12311         [ #  # ]:          0 :                         else if (rss_types & RTE_ETH_RSS_L4_DST_ONLY)
   12312                 :          0 :                                 fields |= IBV_RX_HASH_DST_PORT_TCP;
   12313                 :            :                         else
   12314                 :          0 :                                 fields |= MLX5_TCP_IBV_RX_HASH;
   12315                 :            :                 }
   12316                 :            :         }
   12317         [ #  # ]:          0 :         if (rss_inner)
   12318                 :          0 :                 fields |= IBV_RX_HASH_INNER;
   12319                 :          0 :         *hash_fields = fields;
   12320                 :            : }
   12321                 :            : 
   12322                 :            : /**
   12323                 :            :  * Prepare an Rx Hash queue.
   12324                 :            :  *
   12325                 :            :  * @param dev
   12326                 :            :  *   Pointer to Ethernet device.
   12327                 :            :  * @param[in] dev_flow
   12328                 :            :  *   Pointer to the mlx5_flow.
   12329                 :            :  * @param[in] rss_desc
   12330                 :            :  *   Pointer to the mlx5_flow_rss_desc.
   12331                 :            :  * @param[out] hrxq_idx
   12332                 :            :  *   Hash Rx queue index.
   12333                 :            :  *
   12334                 :            :  * @return
   12335                 :            :  *   The Verbs/DevX object initialised, NULL otherwise and rte_errno is set.
   12336                 :            :  */
   12337                 :            : static struct mlx5_hrxq *
   12338                 :          0 : flow_dv_hrxq_prepare(struct rte_eth_dev *dev,
   12339                 :            :                      struct mlx5_flow *dev_flow,
   12340                 :            :                      struct mlx5_flow_rss_desc *rss_desc,
   12341                 :            :                      uint32_t *hrxq_idx)
   12342                 :            : {
   12343                 :          0 :         struct mlx5_flow_handle *dh = dev_flow->handle;
   12344                 :          0 :         uint32_t shared_rss = rss_desc->shared_rss;
   12345                 :            :         struct mlx5_hrxq *hrxq;
   12346                 :            : 
   12347                 :            :         MLX5_ASSERT(rss_desc->queue_num);
   12348                 :          0 :         rss_desc->symmetric_hash_function = dev_flow->symmetric_hash_function;
   12349                 :          0 :         rss_desc->key_len = MLX5_RSS_HASH_KEY_LEN;
   12350                 :          0 :         rss_desc->hash_fields = dev_flow->hash_fields;
   12351                 :          0 :         rss_desc->tunnel = !!(dh->layers & MLX5_FLOW_LAYER_TUNNEL);
   12352                 :          0 :         rss_desc->shared_rss = 0;
   12353         [ #  # ]:          0 :         if (rss_desc->hash_fields == 0)
   12354                 :          0 :                 rss_desc->queue_num = 1;
   12355                 :          0 :         hrxq = mlx5_hrxq_get(dev, rss_desc);
   12356         [ #  # ]:          0 :         *hrxq_idx = hrxq ? hrxq->idx : 0;
   12357                 :          0 :         rss_desc->shared_rss = shared_rss;
   12358                 :          0 :         return hrxq;
   12359                 :            : }
   12360                 :            : 
   12361                 :            : /**
   12362                 :            :  * Release sample sub action resource.
   12363                 :            :  *
   12364                 :            :  * @param[in, out] dev
   12365                 :            :  *   Pointer to rte_eth_dev structure.
   12366                 :            :  * @param[in] act_res
   12367                 :            :  *   Pointer to sample sub action resource.
   12368                 :            :  */
   12369                 :            : static void
   12370                 :          0 : flow_dv_sample_sub_actions_release(struct rte_eth_dev *dev,
   12371                 :            :                                    struct mlx5_flow_sub_actions_idx *act_res)
   12372                 :            : {
   12373         [ #  # ]:          0 :         if (act_res->rix_hrxq) {
   12374                 :          0 :                 mlx5_hrxq_release(dev, act_res->rix_hrxq);
   12375                 :          0 :                 act_res->rix_hrxq = 0;
   12376                 :            :         }
   12377         [ #  # ]:          0 :         if (act_res->rix_encap_decap) {
   12378                 :          0 :                 flow_dv_encap_decap_resource_release(dev,
   12379                 :            :                                                      act_res->rix_encap_decap);
   12380                 :          0 :                 act_res->rix_encap_decap = 0;
   12381                 :            :         }
   12382         [ #  # ]:          0 :         if (act_res->rix_port_id_action) {
   12383                 :          0 :                 flow_dv_port_id_action_resource_release(dev,
   12384                 :            :                                                 act_res->rix_port_id_action);
   12385                 :          0 :                 act_res->rix_port_id_action = 0;
   12386                 :            :         }
   12387         [ #  # ]:          0 :         if (act_res->rix_tag) {
   12388                 :          0 :                 flow_dv_tag_release(dev, act_res->rix_tag);
   12389                 :          0 :                 act_res->rix_tag = 0;
   12390                 :            :         }
   12391         [ #  # ]:          0 :         if (act_res->rix_jump) {
   12392                 :          0 :                 flow_dv_jump_tbl_resource_release(dev, act_res->rix_jump);
   12393                 :          0 :                 act_res->rix_jump = 0;
   12394                 :            :         }
   12395                 :          0 : }
   12396                 :            : 
   12397                 :            : int
   12398                 :          0 : flow_dv_sample_match_cb(void *tool_ctx __rte_unused,
   12399                 :            :                         struct mlx5_list_entry *entry, void *cb_ctx)
   12400                 :            : {
   12401                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   12402                 :          0 :         struct rte_eth_dev *dev = ctx->dev;
   12403                 :          0 :         struct mlx5_flow_dv_sample_resource *ctx_resource = ctx->data;
   12404                 :            :         struct mlx5_flow_dv_sample_resource *resource = container_of(entry,
   12405                 :            :                                                               typeof(*resource),
   12406                 :            :                                                               entry);
   12407                 :            : 
   12408         [ #  # ]:          0 :         if (ctx_resource->ratio == resource->ratio &&
   12409         [ #  # ]:          0 :             ctx_resource->ft_type == resource->ft_type &&
   12410         [ #  # ]:          0 :             ctx_resource->ft_id == resource->ft_id &&
   12411         [ #  # ]:          0 :             ctx_resource->set_action == resource->set_action &&
   12412                 :          0 :             !memcmp((void *)&ctx_resource->sample_act,
   12413         [ #  # ]:          0 :                     (void *)&resource->sample_act,
   12414                 :            :                     sizeof(struct mlx5_flow_sub_actions_list))) {
   12415                 :            :                 /*
   12416                 :            :                  * Existing sample action should release the prepared
   12417                 :            :                  * sub-actions reference counter.
   12418                 :            :                  */
   12419                 :          0 :                 flow_dv_sample_sub_actions_release(dev,
   12420                 :            :                                                    &ctx_resource->sample_idx);
   12421                 :          0 :                 return 0;
   12422                 :            :         }
   12423                 :            :         return 1;
   12424                 :            : }
   12425                 :            : 
   12426                 :            : struct mlx5_list_entry *
   12427                 :          0 : flow_dv_sample_create_cb(void *tool_ctx __rte_unused, void *cb_ctx)
   12428                 :            : {
   12429                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   12430                 :          0 :         struct rte_eth_dev *dev = ctx->dev;
   12431                 :          0 :         struct mlx5_flow_dv_sample_resource *ctx_resource = ctx->data;
   12432                 :          0 :         void **sample_dv_actions = ctx_resource->sub_actions;
   12433                 :            :         struct mlx5_flow_dv_sample_resource *resource;
   12434                 :            :         struct mlx5dv_dr_flow_sampler_attr sampler_attr;
   12435                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12436                 :          0 :         struct mlx5_dev_ctx_shared *sh = priv->sh;
   12437                 :            :         struct mlx5_flow_tbl_resource *tbl;
   12438                 :          0 :         uint32_t idx = 0;
   12439                 :            :         const uint32_t next_ft_step = 1;
   12440                 :          0 :         uint32_t next_ft_id = ctx_resource->ft_id + next_ft_step;
   12441                 :            :         uint8_t is_egress = 0;
   12442                 :            :         uint8_t is_transfer = 0;
   12443                 :          0 :         struct rte_flow_error *error = ctx->error;
   12444                 :            : 
   12445                 :            :         /* Register new sample resource. */
   12446                 :          0 :         resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_SAMPLE], &idx);
   12447         [ #  # ]:          0 :         if (!resource) {
   12448                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   12449                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12450                 :            :                                           NULL,
   12451                 :            :                                           "cannot allocate resource memory");
   12452                 :          0 :                 return NULL;
   12453                 :            :         }
   12454                 :          0 :         *resource = *ctx_resource;
   12455                 :            :         /* Create normal path table level */
   12456         [ #  # ]:          0 :         if (ctx_resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_FDB)
   12457                 :            :                 is_transfer = 1;
   12458         [ #  # ]:          0 :         else if (ctx_resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_NIC_TX)
   12459                 :            :                 is_egress = 1;
   12460                 :          0 :         tbl = flow_dv_tbl_resource_get(dev, next_ft_id,
   12461                 :            :                                         is_egress, is_transfer,
   12462                 :            :                                         true, NULL, 0, 0, 0, error);
   12463         [ #  # ]:          0 :         if (!tbl) {
   12464                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   12465                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12466                 :            :                                           NULL,
   12467                 :            :                                           "fail to create normal path table "
   12468                 :            :                                           "for sample");
   12469                 :          0 :                 goto error;
   12470                 :            :         }
   12471                 :          0 :         resource->normal_path_tbl = tbl;
   12472         [ #  # ]:          0 :         if (ctx_resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_FDB) {
   12473         [ #  # ]:          0 :                 if (!sh->default_miss_action) {
   12474                 :          0 :                         rte_flow_error_set(error, ENOMEM,
   12475                 :            :                                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12476                 :            :                                                 NULL,
   12477                 :            :                                                 "default miss action was not "
   12478                 :            :                                                 "created");
   12479                 :          0 :                         goto error;
   12480                 :            :                 }
   12481                 :          0 :                 sample_dv_actions[ctx_resource->sample_act.actions_num++] =
   12482                 :            :                                                 sh->default_miss_action;
   12483                 :            :         }
   12484                 :            :         /* Create a DR sample action */
   12485                 :          0 :         sampler_attr.sample_ratio = resource->ratio;
   12486                 :          0 :         sampler_attr.default_next_table = tbl->obj;
   12487                 :          0 :         sampler_attr.num_sample_actions = ctx_resource->sample_act.actions_num;
   12488                 :          0 :         sampler_attr.sample_actions = (struct mlx5dv_dr_action **)
   12489                 :            :                                                         &sample_dv_actions[0];
   12490                 :          0 :         sampler_attr.action = resource->set_action;
   12491                 :            :         if (mlx5_os_flow_dr_create_flow_action_sampler
   12492                 :            :                         (&sampler_attr, &resource->verbs_action)) {
   12493                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   12494                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12495                 :            :                                         NULL, "cannot create sample action");
   12496                 :          0 :                 goto error;
   12497                 :            :         }
   12498                 :          0 :         resource->idx = idx;
   12499                 :          0 :         resource->dev = dev;
   12500                 :          0 :         return &resource->entry;
   12501                 :          0 : error:
   12502         [ #  # ]:          0 :         if (resource->ft_type != MLX5DV_FLOW_TABLE_TYPE_FDB)
   12503                 :          0 :                 flow_dv_sample_sub_actions_release(dev,
   12504                 :            :                                                    &resource->sample_idx);
   12505         [ #  # ]:          0 :         if (resource->normal_path_tbl)
   12506                 :          0 :                 flow_dv_tbl_resource_release(MLX5_SH(dev),
   12507                 :            :                                 resource->normal_path_tbl);
   12508                 :          0 :         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_SAMPLE], idx);
   12509                 :          0 :         return NULL;
   12510                 :            : 
   12511                 :            : }
   12512                 :            : 
   12513                 :            : struct mlx5_list_entry *
   12514                 :          0 : flow_dv_sample_clone_cb(void *tool_ctx __rte_unused,
   12515                 :            :                          struct mlx5_list_entry *entry __rte_unused,
   12516                 :            :                          void *cb_ctx)
   12517                 :            : {
   12518                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   12519                 :          0 :         struct rte_eth_dev *dev = ctx->dev;
   12520                 :            :         struct mlx5_flow_dv_sample_resource *resource;
   12521                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12522                 :          0 :         struct mlx5_dev_ctx_shared *sh = priv->sh;
   12523                 :          0 :         uint32_t idx = 0;
   12524                 :            : 
   12525                 :          0 :         resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_SAMPLE], &idx);
   12526         [ #  # ]:          0 :         if (!resource) {
   12527                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
   12528                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12529                 :            :                                           NULL,
   12530                 :            :                                           "cannot allocate resource memory");
   12531                 :          0 :                 return NULL;
   12532                 :            :         }
   12533                 :            :         memcpy(resource, entry, sizeof(*resource));
   12534                 :          0 :         resource->idx = idx;
   12535                 :          0 :         resource->dev = dev;
   12536                 :          0 :         return &resource->entry;
   12537                 :            : }
   12538                 :            : 
   12539                 :            : void
   12540                 :          0 : flow_dv_sample_clone_free_cb(void *tool_ctx __rte_unused,
   12541                 :            :                              struct mlx5_list_entry *entry)
   12542                 :            : {
   12543                 :            :         struct mlx5_flow_dv_sample_resource *resource =
   12544                 :            :                                   container_of(entry, typeof(*resource), entry);
   12545                 :          0 :         struct rte_eth_dev *dev = resource->dev;
   12546                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12547                 :            : 
   12548                 :          0 :         mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_SAMPLE], resource->idx);
   12549                 :          0 : }
   12550                 :            : 
   12551                 :            : /**
   12552                 :            :  * Find existing sample resource or create and register a new one.
   12553                 :            :  *
   12554                 :            :  * @param[in, out] dev
   12555                 :            :  *   Pointer to rte_eth_dev structure.
   12556                 :            :  * @param[in] ref
   12557                 :            :  *   Pointer to sample resource reference.
   12558                 :            :  * @parm[in, out] dev_flow
   12559                 :            :  *   Pointer to the dev_flow.
   12560                 :            :  * @param[out] error
   12561                 :            :  *   pointer to error structure.
   12562                 :            :  *
   12563                 :            :  * @return
   12564                 :            :  *   0 on success otherwise -errno and errno is set.
   12565                 :            :  */
   12566                 :            : static int
   12567                 :          0 : flow_dv_sample_resource_register(struct rte_eth_dev *dev,
   12568                 :            :                          struct mlx5_flow_dv_sample_resource *ref,
   12569                 :            :                          struct mlx5_flow *dev_flow,
   12570                 :            :                          struct rte_flow_error *error)
   12571                 :            : {
   12572                 :            :         struct mlx5_flow_dv_sample_resource *resource;
   12573                 :            :         struct mlx5_list_entry *entry;
   12574                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12575                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
   12576                 :            :                 .dev = dev,
   12577                 :            :                 .error = error,
   12578                 :            :                 .data = ref,
   12579                 :            :         };
   12580                 :            : 
   12581                 :          0 :         entry = mlx5_list_register(priv->sh->sample_action_list, &ctx);
   12582         [ #  # ]:          0 :         if (!entry)
   12583                 :          0 :                 return -rte_errno;
   12584                 :            :         resource = container_of(entry, typeof(*resource), entry);
   12585                 :          0 :         dev_flow->handle->dvh.rix_sample = resource->idx;
   12586                 :          0 :         dev_flow->dv.sample_res = resource;
   12587                 :          0 :         return 0;
   12588                 :            : }
   12589                 :            : 
   12590                 :            : int
   12591                 :          0 : flow_dv_dest_array_match_cb(void *tool_ctx __rte_unused,
   12592                 :            :                             struct mlx5_list_entry *entry, void *cb_ctx)
   12593                 :            : {
   12594                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   12595                 :          0 :         struct mlx5_flow_dv_dest_array_resource *ctx_resource = ctx->data;
   12596                 :          0 :         struct rte_eth_dev *dev = ctx->dev;
   12597                 :            :         struct mlx5_flow_dv_dest_array_resource *resource =
   12598                 :            :                                   container_of(entry, typeof(*resource), entry);
   12599                 :            :         uint32_t idx = 0;
   12600                 :            : 
   12601         [ #  # ]:          0 :         if (ctx_resource->num_of_dest == resource->num_of_dest &&
   12602                 :          0 :             ctx_resource->ft_type == resource->ft_type &&
   12603                 :          0 :             !memcmp((void *)resource->sample_act,
   12604                 :          0 :                     (void *)ctx_resource->sample_act,
   12605         [ #  # ]:          0 :                    (ctx_resource->num_of_dest *
   12606                 :            :                    sizeof(struct mlx5_flow_sub_actions_list)))) {
   12607                 :            :                 /*
   12608                 :            :                  * Existing sample action should release the prepared
   12609                 :            :                  * sub-actions reference counter.
   12610                 :            :                  */
   12611         [ #  # ]:          0 :                 for (idx = 0; idx < ctx_resource->num_of_dest; idx++)
   12612                 :          0 :                         flow_dv_sample_sub_actions_release(dev,
   12613                 :            :                                         &ctx_resource->sample_idx[idx]);
   12614                 :            :                 return 0;
   12615                 :            :         }
   12616                 :            :         return 1;
   12617                 :            : }
   12618                 :            : 
   12619                 :            : struct mlx5_list_entry *
   12620                 :          0 : flow_dv_dest_array_create_cb(void *tool_ctx __rte_unused, void *cb_ctx)
   12621                 :            : {
   12622                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   12623                 :          0 :         struct rte_eth_dev *dev = ctx->dev;
   12624                 :            :         struct mlx5_flow_dv_dest_array_resource *resource;
   12625                 :          0 :         struct mlx5_flow_dv_dest_array_resource *ctx_resource = ctx->data;
   12626                 :          0 :         struct mlx5dv_dr_action_dest_attr *dest_attr[MLX5_MAX_DEST_NUM] = { 0 };
   12627                 :            :         struct mlx5dv_dr_action_dest_reformat dest_reformat[MLX5_MAX_DEST_NUM];
   12628                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12629                 :          0 :         struct mlx5_dev_ctx_shared *sh = priv->sh;
   12630                 :            :         struct mlx5_flow_sub_actions_list *sample_act;
   12631                 :            :         struct mlx5dv_dr_domain *domain;
   12632                 :          0 :         uint32_t idx = 0, res_idx = 0;
   12633                 :          0 :         struct rte_flow_error *error = ctx->error;
   12634                 :            :         uint64_t action_flags;
   12635                 :            :         int ret;
   12636                 :            : 
   12637                 :            :         /* Register new destination array resource. */
   12638                 :          0 :         resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_DEST_ARRAY],
   12639                 :            :                                             &res_idx);
   12640         [ #  # ]:          0 :         if (!resource) {
   12641                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   12642                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12643                 :            :                                           NULL,
   12644                 :            :                                           "cannot allocate resource memory");
   12645                 :          0 :                 return NULL;
   12646                 :            :         }
   12647                 :          0 :         *resource = *ctx_resource;
   12648         [ #  # ]:          0 :         if (resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_FDB)
   12649                 :          0 :                 domain = sh->fdb_domain;
   12650         [ #  # ]:          0 :         else if (resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_NIC_RX)
   12651                 :          0 :                 domain = sh->rx_domain;
   12652                 :            :         else
   12653                 :          0 :                 domain = sh->tx_domain;
   12654         [ #  # ]:          0 :         for (idx = 0; idx < ctx_resource->num_of_dest; idx++) {
   12655                 :          0 :                 dest_attr[idx] = (struct mlx5dv_dr_action_dest_attr *)
   12656                 :          0 :                                  mlx5_malloc(MLX5_MEM_ZERO,
   12657                 :            :                                  sizeof(struct mlx5dv_dr_action_dest_attr),
   12658                 :            :                                  0, SOCKET_ID_ANY);
   12659         [ #  # ]:          0 :                 if (!dest_attr[idx]) {
   12660                 :          0 :                         rte_flow_error_set(error, ENOMEM,
   12661                 :            :                                            RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12662                 :            :                                            NULL,
   12663                 :            :                                            "cannot allocate resource memory");
   12664                 :          0 :                         goto error;
   12665                 :            :                 }
   12666                 :          0 :                 dest_attr[idx]->type = MLX5DV_DR_ACTION_DEST;
   12667                 :            :                 sample_act = &ctx_resource->sample_act[idx];
   12668                 :          0 :                 action_flags = sample_act->action_flags;
   12669   [ #  #  #  #  :          0 :                 switch (action_flags) {
                      # ]
   12670                 :          0 :                 case MLX5_FLOW_ACTION_QUEUE:
   12671                 :          0 :                         dest_attr[idx]->dest = sample_act->dr_queue_action;
   12672                 :          0 :                         break;
   12673                 :          0 :                 case (MLX5_FLOW_ACTION_PORT_ID | MLX5_FLOW_ACTION_ENCAP):
   12674                 :          0 :                         dest_attr[idx]->type = MLX5DV_DR_ACTION_DEST_REFORMAT;
   12675                 :          0 :                         dest_attr[idx]->dest_reformat = &dest_reformat[idx];
   12676                 :          0 :                         dest_attr[idx]->dest_reformat->reformat =
   12677                 :          0 :                                         sample_act->dr_encap_action;
   12678                 :          0 :                         dest_attr[idx]->dest_reformat->dest =
   12679                 :          0 :                                         sample_act->dr_port_id_action;
   12680                 :          0 :                         break;
   12681                 :          0 :                 case MLX5_FLOW_ACTION_PORT_ID:
   12682                 :          0 :                         dest_attr[idx]->dest = sample_act->dr_port_id_action;
   12683                 :          0 :                         break;
   12684                 :          0 :                 case MLX5_FLOW_ACTION_JUMP:
   12685                 :          0 :                         dest_attr[idx]->dest = sample_act->dr_jump_action;
   12686                 :          0 :                         break;
   12687                 :          0 :                 default:
   12688                 :          0 :                         rte_flow_error_set(error, EINVAL,
   12689                 :            :                                            RTE_FLOW_ERROR_TYPE_ACTION,
   12690                 :            :                                            NULL,
   12691                 :            :                                            "unsupported actions type");
   12692                 :          0 :                         goto error;
   12693                 :            :                 }
   12694                 :            :         }
   12695                 :            :         /* create a dest array action */
   12696                 :          0 :         ret = mlx5_os_flow_dr_create_flow_action_dest_array
   12697                 :            :                                                 (domain,
   12698                 :          0 :                                                  resource->num_of_dest,
   12699                 :            :                                                  dest_attr,
   12700                 :            :                                                  &resource->action);
   12701                 :            :         if (ret) {
   12702                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   12703                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12704                 :            :                                    NULL,
   12705                 :            :                                    "cannot create destination array action");
   12706                 :          0 :                 goto error;
   12707                 :            :         }
   12708                 :          0 :         resource->idx = res_idx;
   12709                 :          0 :         resource->dev = dev;
   12710         [ #  # ]:          0 :         for (idx = 0; idx < ctx_resource->num_of_dest; idx++)
   12711                 :          0 :                 mlx5_free(dest_attr[idx]);
   12712                 :          0 :         return &resource->entry;
   12713                 :            : error:
   12714         [ #  # ]:          0 :         for (idx = 0; idx < ctx_resource->num_of_dest; idx++) {
   12715                 :          0 :                 flow_dv_sample_sub_actions_release(dev,
   12716                 :            :                                                    &resource->sample_idx[idx]);
   12717         [ #  # ]:          0 :                 if (dest_attr[idx])
   12718                 :          0 :                         mlx5_free(dest_attr[idx]);
   12719                 :            :         }
   12720                 :          0 :         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_DEST_ARRAY], res_idx);
   12721                 :          0 :         return NULL;
   12722                 :            : }
   12723                 :            : 
   12724                 :            : struct mlx5_list_entry *
   12725                 :          0 : flow_dv_dest_array_clone_cb(void *tool_ctx __rte_unused,
   12726                 :            :                             struct mlx5_list_entry *entry __rte_unused,
   12727                 :            :                             void *cb_ctx)
   12728                 :            : {
   12729                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   12730                 :          0 :         struct rte_eth_dev *dev = ctx->dev;
   12731                 :            :         struct mlx5_flow_dv_dest_array_resource *resource;
   12732                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12733                 :          0 :         struct mlx5_dev_ctx_shared *sh = priv->sh;
   12734                 :          0 :         uint32_t res_idx = 0;
   12735                 :          0 :         struct rte_flow_error *error = ctx->error;
   12736                 :            : 
   12737                 :          0 :         resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_DEST_ARRAY],
   12738                 :            :                                       &res_idx);
   12739         [ #  # ]:          0 :         if (!resource) {
   12740                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   12741                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12742                 :            :                                           NULL,
   12743                 :            :                                           "cannot allocate dest-array memory");
   12744                 :          0 :                 return NULL;
   12745                 :            :         }
   12746                 :            :         memcpy(resource, entry, sizeof(*resource));
   12747                 :          0 :         resource->idx = res_idx;
   12748                 :          0 :         resource->dev = dev;
   12749                 :          0 :         return &resource->entry;
   12750                 :            : }
   12751                 :            : 
   12752                 :            : void
   12753                 :          0 : flow_dv_dest_array_clone_free_cb(void *tool_ctx __rte_unused,
   12754                 :            :                                  struct mlx5_list_entry *entry)
   12755                 :            : {
   12756                 :            :         struct mlx5_flow_dv_dest_array_resource *resource =
   12757                 :            :                         container_of(entry, typeof(*resource), entry);
   12758                 :          0 :         struct rte_eth_dev *dev = resource->dev;
   12759                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12760                 :            : 
   12761                 :          0 :         mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_DEST_ARRAY], resource->idx);
   12762                 :          0 : }
   12763                 :            : 
   12764                 :            : /**
   12765                 :            :  * Find existing destination array resource or create and register a new one.
   12766                 :            :  *
   12767                 :            :  * @param[in, out] dev
   12768                 :            :  *   Pointer to rte_eth_dev structure.
   12769                 :            :  * @param[in] ref
   12770                 :            :  *   Pointer to destination array resource reference.
   12771                 :            :  * @parm[in, out] dev_flow
   12772                 :            :  *   Pointer to the dev_flow.
   12773                 :            :  * @param[out] error
   12774                 :            :  *   pointer to error structure.
   12775                 :            :  *
   12776                 :            :  * @return
   12777                 :            :  *   0 on success otherwise -errno and errno is set.
   12778                 :            :  */
   12779                 :            : static int
   12780                 :          0 : flow_dv_dest_array_resource_register(struct rte_eth_dev *dev,
   12781                 :            :                          struct mlx5_flow_dv_dest_array_resource *ref,
   12782                 :            :                          struct mlx5_flow *dev_flow,
   12783                 :            :                          struct rte_flow_error *error)
   12784                 :            : {
   12785                 :            :         struct mlx5_flow_dv_dest_array_resource *resource;
   12786                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12787                 :            :         struct mlx5_list_entry *entry;
   12788                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
   12789                 :            :                 .dev = dev,
   12790                 :            :                 .error = error,
   12791                 :            :                 .data = ref,
   12792                 :            :         };
   12793                 :            : 
   12794                 :          0 :         entry = mlx5_list_register(priv->sh->dest_array_list, &ctx);
   12795         [ #  # ]:          0 :         if (!entry)
   12796                 :          0 :                 return -rte_errno;
   12797                 :            :         resource = container_of(entry, typeof(*resource), entry);
   12798                 :          0 :         dev_flow->handle->dvh.rix_dest_array = resource->idx;
   12799                 :          0 :         dev_flow->dv.dest_array_res = resource;
   12800                 :          0 :         return 0;
   12801                 :            : }
   12802                 :            : 
   12803                 :            : /**
   12804                 :            :  * Convert Sample action to DV specification.
   12805                 :            :  *
   12806                 :            :  * @param[in] dev
   12807                 :            :  *   Pointer to rte_eth_dev structure.
   12808                 :            :  * @param[in] action
   12809                 :            :  *   Pointer to sample action structure.
   12810                 :            :  * @param[in, out] dev_flow
   12811                 :            :  *   Pointer to the mlx5_flow.
   12812                 :            :  * @param[in] attr
   12813                 :            :  *   Pointer to the flow attributes.
   12814                 :            :  * @param[in, out] num_of_dest
   12815                 :            :  *   Pointer to the num of destination.
   12816                 :            :  * @param[in, out] sample_actions
   12817                 :            :  *   Pointer to sample actions list.
   12818                 :            :  * @param[in, out] res
   12819                 :            :  *   Pointer to sample resource.
   12820                 :            :  * @param[out] error
   12821                 :            :  *   Pointer to the error structure.
   12822                 :            :  *
   12823                 :            :  * @return
   12824                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   12825                 :            :  */
   12826                 :            : static int
   12827                 :          0 : flow_dv_translate_action_sample(struct rte_eth_dev *dev,
   12828                 :            :                                 const struct rte_flow_action_sample *action,
   12829                 :            :                                 struct mlx5_flow *dev_flow,
   12830                 :            :                                 const struct rte_flow_attr *attr,
   12831                 :            :                                 uint32_t *num_of_dest,
   12832                 :            :                                 void **sample_actions,
   12833                 :            :                                 struct mlx5_flow_dv_sample_resource *res,
   12834                 :            :                                 struct rte_flow_error *error)
   12835                 :            : {
   12836                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12837                 :            :         const struct rte_flow_action *sub_actions;
   12838                 :            :         struct mlx5_flow_sub_actions_list *sample_act;
   12839                 :            :         struct mlx5_flow_sub_actions_idx *sample_idx;
   12840                 :          0 :         struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace();
   12841                 :          0 :         struct rte_flow *flow = dev_flow->flow;
   12842                 :            :         struct mlx5_flow_rss_desc *rss_desc;
   12843                 :            :         uint64_t action_flags = 0;
   12844                 :            : 
   12845                 :            :         MLX5_ASSERT(wks);
   12846                 :          0 :         rss_desc = &wks->rss_desc;
   12847                 :            :         sample_act = &res->sample_act;
   12848                 :            :         sample_idx = &res->sample_idx;
   12849                 :          0 :         res->ratio = action->ratio;
   12850                 :          0 :         sub_actions = action->actions;
   12851         [ #  # ]:          0 :         for (; sub_actions->type != RTE_FLOW_ACTION_TYPE_END; sub_actions++) {
   12852                 :            :                 int type = sub_actions->type;
   12853                 :            :                 uint32_t pre_rix = 0;
   12854                 :            :                 void *pre_r;
   12855   [ #  #  #  #  :          0 :                 switch (type) {
                #  #  # ]
   12856                 :          0 :                 case RTE_FLOW_ACTION_TYPE_QUEUE:
   12857                 :            :                 {
   12858                 :            :                         const struct rte_flow_action_queue *queue;
   12859                 :            :                         struct mlx5_hrxq *hrxq;
   12860                 :            :                         uint32_t hrxq_idx;
   12861                 :            : 
   12862                 :          0 :                         queue = sub_actions->conf;
   12863                 :          0 :                         rss_desc->queue_num = 1;
   12864                 :          0 :                         rss_desc->queue[0] = queue->index;
   12865                 :          0 :                         hrxq = flow_dv_hrxq_prepare(dev, dev_flow,
   12866                 :            :                                                     rss_desc, &hrxq_idx);
   12867         [ #  # ]:          0 :                         if (!hrxq)
   12868                 :          0 :                                 return rte_flow_error_set
   12869                 :            :                                         (error, rte_errno,
   12870                 :            :                                          RTE_FLOW_ERROR_TYPE_ACTION,
   12871                 :            :                                          NULL,
   12872                 :            :                                          "cannot create fate queue");
   12873                 :          0 :                         sample_act->dr_queue_action = hrxq->action;
   12874                 :          0 :                         sample_idx->rix_hrxq = hrxq_idx;
   12875                 :          0 :                         sample_actions[sample_act->actions_num++] =
   12876                 :            :                                                 hrxq->action;
   12877                 :          0 :                         (*num_of_dest)++;
   12878                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_QUEUE;
   12879         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_MARK)
   12880                 :          0 :                                 dev_flow->handle->rix_hrxq = hrxq_idx;
   12881                 :          0 :                         dev_flow->handle->fate_action =
   12882                 :            :                                         MLX5_FLOW_FATE_QUEUE;
   12883                 :          0 :                         break;
   12884                 :            :                 }
   12885                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RSS:
   12886                 :            :                 {
   12887                 :            :                         struct mlx5_hrxq *hrxq;
   12888                 :            :                         uint32_t hrxq_idx;
   12889                 :            :                         const struct rte_flow_action_rss *rss;
   12890                 :            :                         const uint8_t *rss_key;
   12891                 :            : 
   12892                 :          0 :                         rss = sub_actions->conf;
   12893                 :          0 :                         rss_desc->symmetric_hash_function =
   12894                 :          0 :                                 MLX5_RSS_IS_SYMM(rss->func);
   12895                 :          0 :                         memcpy(rss_desc->queue, rss->queue,
   12896         [ #  # ]:          0 :                                rss->queue_num * sizeof(uint16_t));
   12897                 :          0 :                         rss_desc->queue_num = rss->queue_num;
   12898                 :            :                         /* NULL RSS key indicates default RSS key. */
   12899         [ #  # ]:          0 :                         rss_key = !rss->key ? rss_hash_default_key : rss->key;
   12900                 :          0 :                         memcpy(rss_desc->key, rss_key, MLX5_RSS_HASH_KEY_LEN);
   12901                 :            :                         /*
   12902                 :            :                          * rss->level and rss.types should be set in advance
   12903                 :            :                          * when expanding items for RSS.
   12904                 :            :                          */
   12905                 :          0 :                         flow_dv_hashfields_set(dev_flow->handle->layers,
   12906                 :            :                                                rss_desc,
   12907                 :            :                                                &dev_flow->hash_fields);
   12908                 :          0 :                         hrxq = flow_dv_hrxq_prepare(dev, dev_flow,
   12909                 :            :                                                     rss_desc, &hrxq_idx);
   12910         [ #  # ]:          0 :                         if (!hrxq)
   12911                 :          0 :                                 return rte_flow_error_set
   12912                 :            :                                         (error, rte_errno,
   12913                 :            :                                          RTE_FLOW_ERROR_TYPE_ACTION,
   12914                 :            :                                          NULL,
   12915                 :            :                                          "cannot create fate queue");
   12916                 :          0 :                         sample_act->dr_queue_action = hrxq->action;
   12917                 :          0 :                         sample_idx->rix_hrxq = hrxq_idx;
   12918                 :          0 :                         sample_actions[sample_act->actions_num++] =
   12919                 :            :                                                 hrxq->action;
   12920                 :          0 :                         (*num_of_dest)++;
   12921                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_RSS;
   12922         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_MARK)
   12923                 :          0 :                                 dev_flow->handle->rix_hrxq = hrxq_idx;
   12924                 :          0 :                         dev_flow->handle->fate_action =
   12925                 :            :                                         MLX5_FLOW_FATE_QUEUE;
   12926                 :          0 :                         break;
   12927                 :            :                 }
   12928                 :          0 :                 case RTE_FLOW_ACTION_TYPE_MARK:
   12929                 :            :                 {
   12930                 :            :                         uint32_t tag_be = mlx5_flow_mark_set
   12931                 :            :                                 (((const struct rte_flow_action_mark *)
   12932         [ #  # ]:          0 :                                 (sub_actions->conf))->id);
   12933                 :            : 
   12934                 :          0 :                         wks->mark = 1;
   12935                 :          0 :                         pre_rix = dev_flow->handle->dvh.rix_tag;
   12936                 :            :                         /* Save the mark resource before sample */
   12937                 :          0 :                         pre_r = dev_flow->dv.tag_resource;
   12938         [ #  # ]:          0 :                         if (flow_dv_tag_resource_register(dev, tag_be,
   12939                 :            :                                                   dev_flow, error))
   12940                 :          0 :                                 return -rte_errno;
   12941                 :            :                         MLX5_ASSERT(dev_flow->dv.tag_resource);
   12942                 :          0 :                         sample_act->dr_tag_action =
   12943                 :          0 :                                 dev_flow->dv.tag_resource->action;
   12944                 :          0 :                         sample_idx->rix_tag =
   12945                 :          0 :                                 dev_flow->handle->dvh.rix_tag;
   12946                 :          0 :                         sample_actions[sample_act->actions_num++] =
   12947                 :            :                                                 sample_act->dr_tag_action;
   12948                 :            :                         /* Recover the mark resource after sample */
   12949                 :          0 :                         dev_flow->dv.tag_resource = pre_r;
   12950                 :          0 :                         dev_flow->handle->dvh.rix_tag = pre_rix;
   12951                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_MARK;
   12952                 :          0 :                         break;
   12953                 :            :                 }
   12954                 :          0 :                 case RTE_FLOW_ACTION_TYPE_COUNT:
   12955                 :            :                 {
   12956         [ #  # ]:          0 :                         if (!flow->counter) {
   12957                 :          0 :                                 flow->counter =
   12958                 :          0 :                                         flow_dv_translate_create_counter(dev,
   12959                 :          0 :                                                 dev_flow, sub_actions->conf,
   12960                 :            :                                                 0);
   12961         [ #  # ]:          0 :                                 if (!flow->counter)
   12962                 :          0 :                                         return rte_flow_error_set
   12963                 :            :                                                 (error, rte_errno,
   12964                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
   12965                 :            :                                                 NULL,
   12966                 :            :                                                 "cannot create counter"
   12967                 :            :                                                 " object.");
   12968                 :            :                         }
   12969                 :          0 :                         sample_act->dr_cnt_action =
   12970         [ #  # ]:          0 :                                   (flow_dv_counter_get_by_idx(dev,
   12971                 :          0 :                                   flow->counter, NULL))->action;
   12972                 :          0 :                         sample_actions[sample_act->actions_num++] =
   12973                 :            :                                                 sample_act->dr_cnt_action;
   12974                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_COUNT;
   12975                 :          0 :                         break;
   12976                 :            :                 }
   12977                 :          0 :                 case RTE_FLOW_ACTION_TYPE_PORT_ID:
   12978                 :            :                 case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
   12979                 :            :                 {
   12980                 :            :                         struct mlx5_flow_dv_port_id_action_resource
   12981                 :            :                                         port_id_resource;
   12982                 :          0 :                         uint32_t port_id = 0;
   12983                 :            : 
   12984                 :            :                         memset(&port_id_resource, 0, sizeof(port_id_resource));
   12985                 :            :                         /* Save the port id resource before sample */
   12986                 :          0 :                         pre_rix = dev_flow->handle->rix_port_id_action;
   12987                 :          0 :                         pre_r = dev_flow->dv.port_id_action;
   12988         [ #  # ]:          0 :                         if (flow_dv_translate_action_port_id(dev, sub_actions,
   12989                 :            :                                                              &port_id, error))
   12990                 :          0 :                                 return -rte_errno;
   12991                 :          0 :                         port_id_resource.port_id = port_id;
   12992         [ #  # ]:          0 :                         if (flow_dv_port_id_action_resource_register
   12993                 :            :                             (dev, &port_id_resource, dev_flow, error))
   12994                 :          0 :                                 return -rte_errno;
   12995                 :          0 :                         sample_act->dr_port_id_action =
   12996                 :          0 :                                 dev_flow->dv.port_id_action->action;
   12997                 :          0 :                         sample_idx->rix_port_id_action =
   12998                 :          0 :                                 dev_flow->handle->rix_port_id_action;
   12999                 :          0 :                         sample_actions[sample_act->actions_num++] =
   13000                 :            :                                                 sample_act->dr_port_id_action;
   13001                 :            :                         /* Recover the port id resource after sample */
   13002                 :          0 :                         dev_flow->dv.port_id_action = pre_r;
   13003                 :          0 :                         dev_flow->handle->rix_port_id_action = pre_rix;
   13004                 :          0 :                         (*num_of_dest)++;
   13005                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_PORT_ID;
   13006                 :          0 :                         break;
   13007                 :            :                 }
   13008                 :          0 :                 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
   13009                 :            :                 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
   13010                 :            :                 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
   13011                 :            :                         /* Save the encap resource before sample */
   13012                 :          0 :                         pre_rix = dev_flow->handle->dvh.rix_encap_decap;
   13013                 :          0 :                         pre_r = dev_flow->dv.encap_decap;
   13014         [ #  # ]:          0 :                         if (flow_dv_create_action_l2_encap(dev, sub_actions,
   13015                 :            :                                                            dev_flow,
   13016                 :          0 :                                                            attr->transfer,
   13017                 :            :                                                            error))
   13018                 :          0 :                                 return -rte_errno;
   13019                 :          0 :                         sample_act->dr_encap_action =
   13020                 :          0 :                                 dev_flow->dv.encap_decap->action;
   13021                 :          0 :                         sample_idx->rix_encap_decap =
   13022                 :          0 :                                 dev_flow->handle->dvh.rix_encap_decap;
   13023                 :          0 :                         sample_actions[sample_act->actions_num++] =
   13024                 :            :                                                 sample_act->dr_encap_action;
   13025                 :            :                         /* Recover the encap resource after sample */
   13026                 :          0 :                         dev_flow->dv.encap_decap = pre_r;
   13027                 :          0 :                         dev_flow->handle->dvh.rix_encap_decap = pre_rix;
   13028                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_ENCAP;
   13029                 :          0 :                         break;
   13030                 :          0 :                 default:
   13031                 :          0 :                         return rte_flow_error_set(error, EINVAL,
   13032                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   13033                 :            :                                 NULL,
   13034                 :            :                                 "Not support for sampler action");
   13035                 :            :                 }
   13036                 :            :         }
   13037                 :          0 :         sample_act->action_flags = action_flags;
   13038                 :          0 :         res->ft_id = dev_flow->dv.group;
   13039         [ #  # ]:          0 :         if (attr->transfer) {
   13040                 :            :                 union {
   13041                 :            :                         uint32_t action_in[MLX5_ST_SZ_DW(set_action_in)];
   13042                 :            :                         uint64_t set_action;
   13043                 :            :                 } action_ctx = { .set_action = 0 };
   13044                 :          0 :                 uint32_t vport_meta_tag = wks->vport_meta_tag ?
   13045         [ #  # ]:          0 :                                           wks->vport_meta_tag :
   13046                 :            :                                           priv->vport_meta_tag;
   13047                 :            : 
   13048                 :          0 :                 res->ft_type = MLX5DV_FLOW_TABLE_TYPE_FDB;
   13049                 :            :                 MLX5_SET(set_action_in, action_ctx.action_in, action_type,
   13050                 :            :                          MLX5_MODIFICATION_TYPE_SET);
   13051         [ #  # ]:          0 :                 MLX5_SET(set_action_in, action_ctx.action_in, field,
   13052                 :            :                          MLX5_MODI_META_REG_C_0);
   13053                 :          0 :                 MLX5_SET(set_action_in, action_ctx.action_in, data,
   13054                 :            :                          vport_meta_tag);
   13055                 :          0 :                 res->set_action = action_ctx.set_action;
   13056         [ #  # ]:          0 :         } else if (attr->ingress) {
   13057                 :          0 :                 res->ft_type = MLX5DV_FLOW_TABLE_TYPE_NIC_RX;
   13058                 :            :         } else {
   13059                 :          0 :                 res->ft_type = MLX5DV_FLOW_TABLE_TYPE_NIC_TX;
   13060                 :            :         }
   13061                 :            :         return 0;
   13062                 :            : }
   13063                 :            : 
   13064                 :            : static void *
   13065                 :          0 : flow_dv_translate_action_send_to_kernel(struct rte_eth_dev *dev,
   13066                 :            :                                         const struct rte_flow_attr *attr,
   13067                 :            :                                         struct rte_flow_error *error)
   13068                 :            : {
   13069                 :            :         struct mlx5_flow_tbl_resource *tbl;
   13070                 :            :         struct mlx5_dev_ctx_shared *sh;
   13071                 :            :         uint32_t priority;
   13072                 :            :         void *action;
   13073                 :            :         int ft_type;
   13074                 :            :         int ret;
   13075                 :            : 
   13076                 :          0 :         sh = MLX5_SH(dev);
   13077         [ #  # ]:          0 :         ft_type = (attr->ingress) ? MLX5DR_TABLE_TYPE_NIC_RX :
   13078         [ #  # ]:          0 :                   ((attr->transfer) ? MLX5DR_TABLE_TYPE_FDB :
   13079                 :            :                   MLX5DR_TABLE_TYPE_NIC_TX);
   13080         [ #  # ]:          0 :         if (sh->send_to_kernel_action[ft_type].action)
   13081                 :            :                 return sh->send_to_kernel_action[ft_type].action;
   13082                 :          0 :         priority = mlx5_get_send_to_kernel_priority(dev);
   13083         [ #  # ]:          0 :         if (priority == (uint32_t)-1) {
   13084                 :          0 :                 rte_flow_error_set(error, ENOTSUP,
   13085                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   13086                 :            :                                    "required priority is not available");
   13087                 :          0 :                 return NULL;
   13088                 :            :         }
   13089                 :          0 :         tbl = flow_dv_tbl_resource_get(dev, 0, attr->egress, attr->transfer, false, NULL, 0, 0, 0,
   13090                 :            :                                        error);
   13091         [ #  # ]:          0 :         if (!tbl) {
   13092                 :          0 :                 rte_flow_error_set(error, ENODATA,
   13093                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   13094                 :            :                                    "cannot find destination root table");
   13095                 :          0 :                 return NULL;
   13096                 :            :         }
   13097                 :          0 :         ret = mlx5_flow_os_create_flow_action_send_to_kernel(tbl->obj,
   13098                 :            :                                 priority, &action);
   13099                 :            :         if (ret) {
   13100                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   13101                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   13102                 :            :                                    "cannot create action");
   13103                 :          0 :                 goto err;
   13104                 :            :         }
   13105                 :            :         MLX5_ASSERT(action);
   13106                 :          0 :         sh->send_to_kernel_action[ft_type].action = action;
   13107                 :          0 :         sh->send_to_kernel_action[ft_type].tbl = tbl;
   13108                 :          0 :         return action;
   13109                 :            : err:
   13110                 :          0 :         flow_dv_tbl_resource_release(sh, tbl);
   13111                 :          0 :         return NULL;
   13112                 :            : }
   13113                 :            : 
   13114                 :            : /**
   13115                 :            :  * Convert Sample action to DV specification.
   13116                 :            :  *
   13117                 :            :  * @param[in] dev
   13118                 :            :  *   Pointer to rte_eth_dev structure.
   13119                 :            :  * @param[in, out] dev_flow
   13120                 :            :  *   Pointer to the mlx5_flow.
   13121                 :            :  * @param[in] num_of_dest
   13122                 :            :  *   The num of destination.
   13123                 :            :  * @param[in, out] res
   13124                 :            :  *   Pointer to sample resource.
   13125                 :            :  * @param[in, out] mdest_res
   13126                 :            :  *   Pointer to destination array resource.
   13127                 :            :  * @param[in] sample_actions
   13128                 :            :  *   Pointer to sample path actions list.
   13129                 :            :  * @param[in] action_flags
   13130                 :            :  *   Holds the actions detected until now.
   13131                 :            :  * @param[out] error
   13132                 :            :  *   Pointer to the error structure.
   13133                 :            :  *
   13134                 :            :  * @return
   13135                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   13136                 :            :  */
   13137                 :            : static int
   13138                 :          0 : flow_dv_create_action_sample(struct rte_eth_dev *dev,
   13139                 :            :                              struct mlx5_flow *dev_flow,
   13140                 :            :                              uint32_t num_of_dest,
   13141                 :            :                              struct mlx5_flow_dv_sample_resource *res,
   13142                 :            :                              struct mlx5_flow_dv_dest_array_resource *mdest_res,
   13143                 :            :                              void **sample_actions,
   13144                 :            :                              uint64_t action_flags,
   13145                 :            :                              struct rte_flow_error *error)
   13146                 :            : {
   13147                 :            :         /* update normal path action resource into last index of array */
   13148                 :            :         uint32_t dest_index = MLX5_MAX_DEST_NUM - 1;
   13149                 :            :         struct mlx5_flow_sub_actions_list *sample_act =
   13150                 :            :                                         &mdest_res->sample_act[dest_index];
   13151                 :          0 :         struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace();
   13152                 :            :         struct mlx5_flow_rss_desc *rss_desc;
   13153                 :            :         uint32_t normal_idx = 0;
   13154                 :            :         struct mlx5_hrxq *hrxq;
   13155                 :            :         uint32_t hrxq_idx;
   13156                 :            : 
   13157                 :            :         MLX5_ASSERT(wks);
   13158                 :          0 :         rss_desc = &wks->rss_desc;
   13159         [ #  # ]:          0 :         if (num_of_dest > 1) {
   13160         [ #  # ]:          0 :                 if (sample_act->action_flags & MLX5_FLOW_ACTION_QUEUE) {
   13161                 :            :                         /* Handle QP action for mirroring */
   13162                 :          0 :                         hrxq = flow_dv_hrxq_prepare(dev, dev_flow,
   13163                 :            :                                                     rss_desc, &hrxq_idx);
   13164         [ #  # ]:          0 :                         if (!hrxq)
   13165                 :          0 :                                 return rte_flow_error_set
   13166                 :            :                                      (error, rte_errno,
   13167                 :            :                                       RTE_FLOW_ERROR_TYPE_ACTION,
   13168                 :            :                                       NULL,
   13169                 :            :                                       "cannot create rx queue");
   13170                 :            :                         normal_idx++;
   13171                 :          0 :                         mdest_res->sample_idx[dest_index].rix_hrxq = hrxq_idx;
   13172                 :          0 :                         sample_act->dr_queue_action = hrxq->action;
   13173         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_MARK)
   13174                 :          0 :                                 dev_flow->handle->rix_hrxq = hrxq_idx;
   13175                 :          0 :                         dev_flow->handle->fate_action = MLX5_FLOW_FATE_QUEUE;
   13176                 :            :                 }
   13177         [ #  # ]:          0 :                 if (sample_act->action_flags & MLX5_FLOW_ACTION_ENCAP) {
   13178                 :          0 :                         normal_idx++;
   13179                 :          0 :                         mdest_res->sample_idx[dest_index].rix_encap_decap =
   13180                 :          0 :                                 dev_flow->handle->dvh.rix_encap_decap;
   13181                 :          0 :                         sample_act->dr_encap_action =
   13182                 :          0 :                                 dev_flow->dv.encap_decap->action;
   13183                 :          0 :                         dev_flow->handle->dvh.rix_encap_decap = 0;
   13184                 :            :                 }
   13185         [ #  # ]:          0 :                 if (sample_act->action_flags & MLX5_FLOW_ACTION_PORT_ID) {
   13186                 :          0 :                         normal_idx++;
   13187                 :          0 :                         mdest_res->sample_idx[dest_index].rix_port_id_action =
   13188                 :          0 :                                 dev_flow->handle->rix_port_id_action;
   13189                 :          0 :                         sample_act->dr_port_id_action =
   13190                 :          0 :                                 dev_flow->dv.port_id_action->action;
   13191                 :          0 :                         dev_flow->handle->rix_port_id_action = 0;
   13192                 :            :                 }
   13193         [ #  # ]:          0 :                 if (sample_act->action_flags & MLX5_FLOW_ACTION_JUMP) {
   13194                 :          0 :                         normal_idx++;
   13195                 :          0 :                         mdest_res->sample_idx[dest_index].rix_jump =
   13196                 :          0 :                                 dev_flow->handle->rix_jump;
   13197                 :          0 :                         sample_act->dr_jump_action =
   13198                 :          0 :                                 dev_flow->dv.jump->action;
   13199                 :          0 :                         dev_flow->handle->rix_jump = 0;
   13200                 :            :                 }
   13201                 :          0 :                 sample_act->actions_num = normal_idx;
   13202                 :            :                 /* update sample action resource into first index of array */
   13203                 :          0 :                 mdest_res->ft_type = res->ft_type;
   13204                 :          0 :                 memcpy(&mdest_res->sample_idx[0], &res->sample_idx,
   13205                 :            :                                 sizeof(struct mlx5_flow_sub_actions_idx));
   13206                 :          0 :                 memcpy(&mdest_res->sample_act[0], &res->sample_act,
   13207                 :            :                                 sizeof(struct mlx5_flow_sub_actions_list));
   13208                 :          0 :                 mdest_res->num_of_dest = num_of_dest;
   13209         [ #  # ]:          0 :                 if (flow_dv_dest_array_resource_register(dev, mdest_res,
   13210                 :            :                                                          dev_flow, error))
   13211                 :          0 :                         return rte_flow_error_set(error, EINVAL,
   13212                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
   13213                 :            :                                                   NULL, "can't create sample "
   13214                 :            :                                                   "action");
   13215                 :            :         } else {
   13216                 :          0 :                 res->sub_actions = sample_actions;
   13217         [ #  # ]:          0 :                 if (flow_dv_sample_resource_register(dev, res, dev_flow, error))
   13218                 :          0 :                         return rte_flow_error_set(error, EINVAL,
   13219                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
   13220                 :            :                                                   NULL,
   13221                 :            :                                                   "can't create sample action");
   13222                 :            :         }
   13223                 :            :         return 0;
   13224                 :            : }
   13225                 :            : 
   13226                 :            : /**
   13227                 :            :  * Remove an ASO age action from age actions list.
   13228                 :            :  *
   13229                 :            :  * @param[in] dev
   13230                 :            :  *   Pointer to the Ethernet device structure.
   13231                 :            :  * @param[in] age
   13232                 :            :  *   Pointer to the aso age action handler.
   13233                 :            :  */
   13234                 :            : static void
   13235                 :          0 : flow_dv_aso_age_remove_from_age(struct rte_eth_dev *dev,
   13236                 :            :                                 struct mlx5_aso_age_action *age)
   13237                 :            : {
   13238                 :            :         struct mlx5_age_info *age_info;
   13239                 :            :         struct mlx5_age_param *age_param = &age->age_params;
   13240                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13241                 :            :         uint16_t expected = AGE_CANDIDATE;
   13242                 :            : 
   13243                 :          0 :         age_info = GET_PORT_AGE_INFO(priv);
   13244         [ #  # ]:          0 :         if (!__atomic_compare_exchange_n(&age_param->state, &expected,
   13245                 :            :                                          AGE_FREE, false, __ATOMIC_RELAXED,
   13246                 :            :                                          __ATOMIC_RELAXED)) {
   13247                 :            :                 /**
   13248                 :            :                  * We need the lock even it is age timeout,
   13249                 :            :                  * since age action may still in process.
   13250                 :            :                  */
   13251                 :          0 :                 rte_spinlock_lock(&age_info->aged_sl);
   13252         [ #  # ]:          0 :                 LIST_REMOVE(age, next);
   13253                 :            :                 rte_spinlock_unlock(&age_info->aged_sl);
   13254                 :          0 :                 __atomic_store_n(&age_param->state, AGE_FREE, __ATOMIC_RELAXED);
   13255                 :            :         }
   13256                 :          0 : }
   13257                 :            : 
   13258                 :            : /**
   13259                 :            :  * Release an ASO age action.
   13260                 :            :  *
   13261                 :            :  * @param[in] dev
   13262                 :            :  *   Pointer to the Ethernet device structure.
   13263                 :            :  * @param[in] age_idx
   13264                 :            :  *   Index of ASO age action to release.
   13265                 :            :  * @param[in] flow
   13266                 :            :  *   True if the release operation is during flow destroy operation.
   13267                 :            :  *   False if the release operation is during action destroy operation.
   13268                 :            :  *
   13269                 :            :  * @return
   13270                 :            :  *   0 when age action was removed, otherwise the number of references.
   13271                 :            :  */
   13272                 :            : static int
   13273                 :          0 : flow_dv_aso_age_release(struct rte_eth_dev *dev, uint32_t age_idx)
   13274                 :            : {
   13275                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13276                 :          0 :         struct mlx5_aso_age_mng *mng = priv->sh->aso_age_mng;
   13277                 :          0 :         struct mlx5_aso_age_action *age = flow_aso_age_get_by_idx(dev, age_idx);
   13278                 :          0 :         uint32_t ret = __atomic_fetch_sub(&age->refcnt, 1, __ATOMIC_RELAXED) - 1;
   13279                 :            : 
   13280         [ #  # ]:          0 :         if (!ret) {
   13281                 :          0 :                 flow_dv_aso_age_remove_from_age(dev, age);
   13282                 :          0 :                 rte_spinlock_lock(&mng->free_sl);
   13283         [ #  # ]:          0 :                 LIST_INSERT_HEAD(&mng->free, age, next);
   13284                 :            :                 rte_spinlock_unlock(&mng->free_sl);
   13285                 :            :         }
   13286                 :          0 :         return ret;
   13287                 :            : }
   13288                 :            : 
   13289                 :            : /**
   13290                 :            :  * Resize the ASO age pools array by MLX5_ASO_AGE_CONTAINER_RESIZE pools.
   13291                 :            :  *
   13292                 :            :  * @param[in] dev
   13293                 :            :  *   Pointer to the Ethernet device structure.
   13294                 :            :  *
   13295                 :            :  * @return
   13296                 :            :  *   0 on success, otherwise negative errno value and rte_errno is set.
   13297                 :            :  */
   13298                 :            : static int
   13299                 :          0 : flow_dv_aso_age_pools_resize(struct rte_eth_dev *dev)
   13300                 :            : {
   13301                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13302                 :          0 :         struct mlx5_aso_age_mng *mng = priv->sh->aso_age_mng;
   13303                 :          0 :         void *old_pools = mng->pools;
   13304                 :          0 :         uint32_t resize = mng->n + MLX5_ASO_AGE_CONTAINER_RESIZE;
   13305                 :          0 :         uint32_t mem_size = sizeof(struct mlx5_aso_age_pool *) * resize;
   13306                 :          0 :         void *pools = mlx5_malloc(MLX5_MEM_ZERO, mem_size, 0, SOCKET_ID_ANY);
   13307                 :            : 
   13308         [ #  # ]:          0 :         if (!pools) {
   13309                 :          0 :                 rte_errno = ENOMEM;
   13310                 :          0 :                 return -ENOMEM;
   13311                 :            :         }
   13312         [ #  # ]:          0 :         if (old_pools) {
   13313                 :          0 :                 memcpy(pools, old_pools,
   13314                 :          0 :                        mng->n * sizeof(struct mlx5_flow_counter_pool *));
   13315                 :          0 :                 mlx5_free(old_pools);
   13316                 :            :         } else {
   13317                 :            :                 /* First ASO flow hit allocation - starting ASO data-path. */
   13318                 :          0 :                 int ret = mlx5_aso_flow_hit_queue_poll_start(priv->sh);
   13319                 :            : 
   13320         [ #  # ]:          0 :                 if (ret) {
   13321                 :          0 :                         mlx5_free(pools);
   13322                 :          0 :                         return ret;
   13323                 :            :                 }
   13324                 :            :         }
   13325                 :          0 :         mng->n = resize;
   13326                 :          0 :         mng->pools = pools;
   13327                 :          0 :         return 0;
   13328                 :            : }
   13329                 :            : 
   13330                 :            : /**
   13331                 :            :  * Create and initialize a new ASO aging pool.
   13332                 :            :  *
   13333                 :            :  * @param[in] dev
   13334                 :            :  *   Pointer to the Ethernet device structure.
   13335                 :            :  * @param[out] age_free
   13336                 :            :  *   Where to put the pointer of a new age action.
   13337                 :            :  *
   13338                 :            :  * @return
   13339                 :            :  *   The age actions pool pointer and @p age_free is set on success,
   13340                 :            :  *   NULL otherwise and rte_errno is set.
   13341                 :            :  */
   13342                 :            : static struct mlx5_aso_age_pool *
   13343                 :          0 : flow_dv_age_pool_create(struct rte_eth_dev *dev,
   13344                 :            :                         struct mlx5_aso_age_action **age_free)
   13345                 :            : {
   13346                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13347                 :          0 :         struct mlx5_aso_age_mng *mng = priv->sh->aso_age_mng;
   13348                 :            :         struct mlx5_aso_age_pool *pool = NULL;
   13349                 :            :         struct mlx5_devx_obj *obj = NULL;
   13350                 :            :         uint32_t i;
   13351                 :            : 
   13352                 :          0 :         obj = mlx5_devx_cmd_create_flow_hit_aso_obj(priv->sh->cdev->ctx,
   13353                 :          0 :                                                     priv->sh->cdev->pdn);
   13354         [ #  # ]:          0 :         if (!obj) {
   13355                 :          0 :                 rte_errno = ENODATA;
   13356                 :          0 :                 DRV_LOG(ERR, "Failed to create flow_hit_aso_obj using DevX.");
   13357                 :          0 :                 return NULL;
   13358                 :            :         }
   13359                 :          0 :         pool = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*pool), 0, SOCKET_ID_ANY);
   13360         [ #  # ]:          0 :         if (!pool) {
   13361                 :          0 :                 claim_zero(mlx5_devx_cmd_destroy(obj));
   13362                 :          0 :                 rte_errno = ENOMEM;
   13363                 :          0 :                 return NULL;
   13364                 :            :         }
   13365                 :          0 :         pool->flow_hit_aso_obj = obj;
   13366                 :          0 :         pool->time_of_last_age_check = MLX5_CURR_TIME_SEC;
   13367                 :          0 :         rte_rwlock_write_lock(&mng->resize_rwl);
   13368                 :          0 :         pool->index = mng->next;
   13369                 :            :         /* Resize pools array if there is no room for the new pool in it. */
   13370   [ #  #  #  # ]:          0 :         if (pool->index == mng->n && flow_dv_aso_age_pools_resize(dev)) {
   13371                 :          0 :                 claim_zero(mlx5_devx_cmd_destroy(obj));
   13372                 :          0 :                 mlx5_free(pool);
   13373                 :            :                 rte_rwlock_write_unlock(&mng->resize_rwl);
   13374                 :          0 :                 return NULL;
   13375                 :            :         }
   13376                 :          0 :         mng->pools[pool->index] = pool;
   13377                 :          0 :         mng->next++;
   13378                 :            :         rte_rwlock_write_unlock(&mng->resize_rwl);
   13379                 :            :         /* Assign the first action in the new pool, the rest go to free list. */
   13380                 :          0 :         *age_free = &pool->actions[0];
   13381         [ #  # ]:          0 :         for (i = 1; i < MLX5_ASO_AGE_ACTIONS_PER_POOL; i++) {
   13382                 :          0 :                 pool->actions[i].offset = i;
   13383         [ #  # ]:          0 :                 LIST_INSERT_HEAD(&mng->free, &pool->actions[i], next);
   13384                 :            :         }
   13385                 :            :         return pool;
   13386                 :            : }
   13387                 :            : 
   13388                 :            : /**
   13389                 :            :  * Allocate a ASO aging bit.
   13390                 :            :  *
   13391                 :            :  * @param[in] dev
   13392                 :            :  *   Pointer to the Ethernet device structure.
   13393                 :            :  * @param[out] error
   13394                 :            :  *   Pointer to the error structure.
   13395                 :            :  *
   13396                 :            :  * @return
   13397                 :            :  *   Index to ASO age action on success, 0 otherwise and rte_errno is set.
   13398                 :            :  */
   13399                 :            : static uint32_t
   13400                 :          0 : flow_dv_aso_age_alloc(struct rte_eth_dev *dev, struct rte_flow_error *error)
   13401                 :            : {
   13402                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13403                 :            :         const struct mlx5_aso_age_pool *pool;
   13404                 :          0 :         struct mlx5_aso_age_action *age_free = NULL;
   13405                 :          0 :         struct mlx5_aso_age_mng *mng = priv->sh->aso_age_mng;
   13406                 :            : 
   13407                 :            :         MLX5_ASSERT(mng);
   13408                 :            :         /* Try to get the next free age action bit. */
   13409                 :          0 :         rte_spinlock_lock(&mng->free_sl);
   13410                 :          0 :         age_free = LIST_FIRST(&mng->free);
   13411         [ #  # ]:          0 :         if (age_free) {
   13412         [ #  # ]:          0 :                 LIST_REMOVE(age_free, next);
   13413         [ #  # ]:          0 :         } else if (!flow_dv_age_pool_create(dev, &age_free)) {
   13414                 :            :                 rte_spinlock_unlock(&mng->free_sl);
   13415                 :          0 :                 rte_flow_error_set(error, rte_errno, RTE_FLOW_ERROR_TYPE_ACTION,
   13416                 :            :                                    NULL, "failed to create ASO age pool");
   13417                 :          0 :                 return 0; /* 0 is an error. */
   13418                 :            :         }
   13419                 :            :         rte_spinlock_unlock(&mng->free_sl);
   13420                 :          0 :         pool = container_of
   13421                 :            :           ((const struct mlx5_aso_age_action (*)[MLX5_ASO_AGE_ACTIONS_PER_POOL])
   13422                 :            :                   (age_free - age_free->offset), const struct mlx5_aso_age_pool,
   13423                 :            :                                                                        actions);
   13424         [ #  # ]:          0 :         if (!age_free->dr_action) {
   13425                 :          0 :                 int reg_c = mlx5_flow_get_reg_id(dev, MLX5_ASO_FLOW_HIT, 0,
   13426                 :            :                                                  error);
   13427                 :            : 
   13428         [ #  # ]:          0 :                 if (reg_c < 0) {
   13429                 :          0 :                         rte_flow_error_set(error, rte_errno,
   13430                 :            :                                            RTE_FLOW_ERROR_TYPE_ACTION,
   13431                 :            :                                            NULL, "failed to get reg_c "
   13432                 :            :                                            "for ASO flow hit");
   13433                 :          0 :                         return 0; /* 0 is an error. */
   13434                 :            :                 }
   13435                 :            : #ifdef HAVE_MLX5_DR_CREATE_ACTION_ASO
   13436                 :          0 :                 age_free->dr_action = mlx5_glue->dv_create_flow_action_aso
   13437                 :          0 :                                 (priv->sh->rx_domain,
   13438                 :          0 :                                  pool->flow_hit_aso_obj->obj, age_free->offset,
   13439                 :            :                                  MLX5DV_DR_ACTION_FLAGS_ASO_FIRST_HIT_SET,
   13440                 :          0 :                                  (reg_c - REG_C_0));
   13441                 :            : #endif /* HAVE_MLX5_DR_CREATE_ACTION_ASO */
   13442         [ #  # ]:          0 :                 if (!age_free->dr_action) {
   13443                 :          0 :                         rte_errno = errno;
   13444                 :            :                         rte_spinlock_lock(&mng->free_sl);
   13445         [ #  # ]:          0 :                         LIST_INSERT_HEAD(&mng->free, age_free, next);
   13446                 :            :                         rte_spinlock_unlock(&mng->free_sl);
   13447                 :          0 :                         rte_flow_error_set(error, rte_errno,
   13448                 :            :                                            RTE_FLOW_ERROR_TYPE_ACTION,
   13449                 :            :                                            NULL, "failed to create ASO "
   13450                 :            :                                            "flow hit action");
   13451                 :          0 :                         return 0; /* 0 is an error. */
   13452                 :            :                 }
   13453                 :            :         }
   13454                 :          0 :         __atomic_store_n(&age_free->refcnt, 1, __ATOMIC_RELAXED);
   13455                 :          0 :         return pool->index | ((age_free->offset + 1) << 16);
   13456                 :            : }
   13457                 :            : 
   13458                 :            : /**
   13459                 :            :  * Initialize flow ASO age parameters.
   13460                 :            :  *
   13461                 :            :  * @param[in] dev
   13462                 :            :  *   Pointer to rte_eth_dev structure.
   13463                 :            :  * @param[in] age_idx
   13464                 :            :  *   Index of ASO age action.
   13465                 :            :  * @param[in] context
   13466                 :            :  *   Pointer to flow counter age context.
   13467                 :            :  * @param[in] timeout
   13468                 :            :  *   Aging timeout in seconds.
   13469                 :            :  *
   13470                 :            :  */
   13471                 :            : static void
   13472                 :          0 : flow_dv_aso_age_params_init(struct rte_eth_dev *dev,
   13473                 :            :                             uint32_t age_idx,
   13474                 :            :                             void *context,
   13475                 :            :                             uint32_t timeout)
   13476                 :            : {
   13477                 :            :         struct mlx5_aso_age_action *aso_age;
   13478                 :            : 
   13479                 :          0 :         aso_age = flow_aso_age_get_by_idx(dev, age_idx);
   13480                 :            :         MLX5_ASSERT(aso_age);
   13481                 :          0 :         aso_age->age_params.context = context;
   13482                 :          0 :         aso_age->age_params.timeout = timeout;
   13483                 :          0 :         aso_age->age_params.port_id = dev->data->port_id;
   13484                 :          0 :         __atomic_store_n(&aso_age->age_params.sec_since_last_hit, 0,
   13485                 :            :                          __ATOMIC_RELAXED);
   13486                 :          0 :         __atomic_store_n(&aso_age->age_params.state, AGE_CANDIDATE,
   13487                 :            :                          __ATOMIC_RELAXED);
   13488                 :          0 : }
   13489                 :            : 
   13490                 :            : static void
   13491                 :          0 : flow_dv_translate_integrity_l4(const struct rte_flow_item_integrity *mask,
   13492                 :            :                                void *headers)
   13493                 :            : {
   13494                 :            :         /*
   13495                 :            :          * In HWS mode MLX5_ITEM_UPDATE() macro assigns the same pointer to
   13496                 :            :          * both mask and value, therefore ether can be used.
   13497                 :            :          * In SWS SW_V mode mask points to item mask and value points to item
   13498                 :            :          * spec. Integrity item value is used only if matching mask is set.
   13499                 :            :          * Use mask reference here to keep SWS functionality.
   13500                 :            :          */
   13501         [ #  # ]:          0 :         if (mask->l4_ok) {
   13502                 :            :                 /* RTE l4_ok filter aggregates hardware l4_ok and
   13503                 :            :                  * l4_checksum_ok filters.
   13504                 :            :                  * Positive RTE l4_ok match requires hardware match on both L4
   13505                 :            :                  * hardware integrity bits.
   13506                 :            :                  * PMD supports positive integrity item semantics only.
   13507                 :            :                  */
   13508         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers, l4_ok, 1);
   13509         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers, l4_checksum_ok, 1);
   13510         [ #  # ]:          0 :         } else if (mask->l4_csum_ok) {
   13511         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers, l4_checksum_ok, 1);
   13512                 :            :         }
   13513                 :          0 : }
   13514                 :            : 
   13515                 :            : static void
   13516                 :          0 : flow_dv_translate_integrity_l3(const struct rte_flow_item_integrity *mask,
   13517                 :            :                                void *headers, bool is_ipv4)
   13518                 :            : {
   13519                 :            :         /*
   13520                 :            :          * In HWS mode MLX5_ITEM_UPDATE() macro assigns the same pointer to
   13521                 :            :          * both mask and value, therefore ether can be used.
   13522                 :            :          * In SWS SW_V mode mask points to item mask and value points to item
   13523                 :            :          * spec. Integrity item value used only if matching mask is set.
   13524                 :            :          * Use mask reference here to keep SWS functionality.
   13525                 :            :          */
   13526         [ #  # ]:          0 :         if (mask->l3_ok) {
   13527                 :            :                 /* RTE l3_ok filter aggregates for IPv4 hardware l3_ok and
   13528                 :            :                  * ipv4_csum_ok filters.
   13529                 :            :                  * Positive RTE l3_ok match requires hardware match on both L3
   13530                 :            :                  * hardware integrity bits.
   13531                 :            :                  * PMD supports positive integrity item semantics only.
   13532                 :            :                  */
   13533         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers, l3_ok, 1);
   13534         [ #  # ]:          0 :                 if (is_ipv4) {
   13535         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, headers,
   13536                 :            :                                  ipv4_checksum_ok, 1);
   13537                 :            :                 }
   13538   [ #  #  #  # ]:          0 :         } else if (is_ipv4 && mask->ipv4_csum_ok) {
   13539         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers, ipv4_checksum_ok, 1);
   13540                 :            :         }
   13541                 :          0 : }
   13542                 :            : 
   13543                 :            : static void
   13544                 :          0 : set_integrity_bits(void *headers, const struct rte_flow_item *integrity_item,
   13545                 :            :                    bool is_l3_ip4, uint32_t key_type)
   13546                 :            : {
   13547                 :            :         const struct rte_flow_item_integrity *spec;
   13548                 :            :         const struct rte_flow_item_integrity *mask;
   13549                 :            : 
   13550                 :            :         /* Integrity bits validation cleared spec pointer */
   13551   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(integrity_item, key_type))
          #  #  #  #  #  
                      # ]
   13552                 :            :                 return;
   13553   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(integrity_item, key_type, spec, mask,
             #  #  #  # ]
   13554                 :            :                          &rte_flow_item_integrity_mask);
   13555                 :          0 :         flow_dv_translate_integrity_l3(mask, headers, is_l3_ip4);
   13556                 :          0 :         flow_dv_translate_integrity_l4(mask, headers);
   13557                 :            : }
   13558                 :            : 
   13559                 :            : static void
   13560                 :          0 : flow_dv_translate_item_integrity_post(void *key,
   13561                 :            :                                       const
   13562                 :            :                                       struct rte_flow_item *integrity_items[2],
   13563                 :            :                                       uint64_t pattern_flags, uint32_t key_type)
   13564                 :            : {
   13565                 :            :         void *headers;
   13566                 :            :         bool is_l3_ip4;
   13567                 :            : 
   13568         [ #  # ]:          0 :         if (pattern_flags & MLX5_FLOW_ITEM_INNER_INTEGRITY) {
   13569                 :          0 :                 headers = MLX5_ADDR_OF(fte_match_param, key, inner_headers);
   13570                 :          0 :                 is_l3_ip4 = (pattern_flags & MLX5_FLOW_LAYER_INNER_L3_IPV4) !=
   13571                 :            :                             0;
   13572                 :          0 :                 set_integrity_bits(headers, integrity_items[1], is_l3_ip4,
   13573                 :            :                                    key_type);
   13574                 :            :         }
   13575         [ #  # ]:          0 :         if (pattern_flags & MLX5_FLOW_ITEM_OUTER_INTEGRITY) {
   13576                 :            :                 headers = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
   13577                 :          0 :                 is_l3_ip4 = (pattern_flags & MLX5_FLOW_LAYER_OUTER_L3_IPV4) !=
   13578                 :            :                             0;
   13579                 :          0 :                 set_integrity_bits(headers, integrity_items[0], is_l3_ip4,
   13580                 :            :                                    key_type);
   13581                 :            :         }
   13582                 :          0 : }
   13583                 :            : 
   13584                 :            : static uint64_t
   13585                 :            : flow_dv_translate_item_integrity(const struct rte_flow_item *item,
   13586                 :            :                                  struct mlx5_dv_matcher_workspace *wks,
   13587                 :            :                                  uint64_t key_type)
   13588                 :            : {
   13589                 :          0 :         if ((key_type & MLX5_SET_MATCHER_SW) != 0) {
   13590                 :            :                 const struct rte_flow_item_integrity
   13591                 :          0 :                         *spec = (typeof(spec))item->spec;
   13592                 :            : 
   13593                 :            :                 /* SWS integrity bits validation cleared spec pointer */
   13594         [ #  # ]:          0 :                 if (spec->level > 1) {
   13595                 :          0 :                         wks->integrity_items[1] = item;
   13596                 :          0 :                         wks->last_item |= MLX5_FLOW_ITEM_INNER_INTEGRITY;
   13597                 :            :                 } else {
   13598                 :          0 :                         wks->integrity_items[0] = item;
   13599                 :          0 :                         wks->last_item |= MLX5_FLOW_ITEM_OUTER_INTEGRITY;
   13600                 :            :                 }
   13601                 :            :         } else {
   13602                 :            :                 /* HWS supports outer integrity only */
   13603                 :          0 :                 wks->integrity_items[0] = item;
   13604                 :          0 :                 wks->last_item |= MLX5_FLOW_ITEM_OUTER_INTEGRITY;
   13605                 :            :         }
   13606                 :          0 :         return wks->last_item;
   13607                 :            : }
   13608                 :            : 
   13609                 :            : /**
   13610                 :            :  * Prepares DV flow counter with aging configuration.
   13611                 :            :  * Gets it by index when exists, creates a new one when doesn't.
   13612                 :            :  *
   13613                 :            :  * @param[in] dev
   13614                 :            :  *   Pointer to rte_eth_dev structure.
   13615                 :            :  * @param[in] dev_flow
   13616                 :            :  *   Pointer to the mlx5_flow.
   13617                 :            :  * @param[in, out] flow
   13618                 :            :  *   Pointer to the sub flow.
   13619                 :            :  * @param[in] count
   13620                 :            :  *   Pointer to the counter action configuration.
   13621                 :            :  * @param[in] age
   13622                 :            :  *   Pointer to the aging action configuration.
   13623                 :            :  * @param[out] error
   13624                 :            :  *   Pointer to the error structure.
   13625                 :            :  *
   13626                 :            :  * @return
   13627                 :            :  *   Pointer to the counter, NULL otherwise.
   13628                 :            :  */
   13629                 :            : static struct mlx5_flow_counter *
   13630                 :          0 : flow_dv_prepare_counter(struct rte_eth_dev *dev,
   13631                 :            :                         struct mlx5_flow *dev_flow,
   13632                 :            :                         struct rte_flow *flow,
   13633                 :            :                         const struct rte_flow_action_count *count,
   13634                 :            :                         const struct rte_flow_action_age *age,
   13635                 :            :                         struct rte_flow_error *error)
   13636                 :            : {
   13637         [ #  # ]:          0 :         if (!flow->counter) {
   13638                 :          0 :                 flow->counter = flow_dv_translate_create_counter(dev, dev_flow,
   13639                 :            :                                                                  count, age);
   13640         [ #  # ]:          0 :                 if (!flow->counter) {
   13641                 :          0 :                         rte_flow_error_set(error, rte_errno,
   13642                 :            :                                            RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   13643                 :            :                                            "cannot create counter object.");
   13644                 :          0 :                         return NULL;
   13645                 :            :                 }
   13646                 :            :         }
   13647         [ #  # ]:          0 :         return flow_dv_counter_get_by_idx(dev, flow->counter, NULL);
   13648                 :            : }
   13649                 :            : 
   13650                 :            : /*
   13651                 :            :  * Release an ASO CT action by its own device.
   13652                 :            :  *
   13653                 :            :  * @param[in] dev
   13654                 :            :  *   Pointer to the Ethernet device structure.
   13655                 :            :  * @param[in] idx
   13656                 :            :  *   Index of ASO CT action to release.
   13657                 :            :  *
   13658                 :            :  * @return
   13659                 :            :  *   0 when CT action was removed, otherwise the number of references.
   13660                 :            :  */
   13661                 :            : static inline int
   13662                 :          0 : flow_dv_aso_ct_dev_release(struct rte_eth_dev *dev, uint32_t idx)
   13663                 :            : {
   13664                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13665                 :          0 :         struct mlx5_aso_ct_pools_mng *mng = priv->sh->ct_mng;
   13666                 :            :         uint32_t ret;
   13667                 :          0 :         struct mlx5_aso_ct_action *ct = flow_aso_ct_get_by_dev_idx(dev, idx);
   13668                 :            :         enum mlx5_aso_ct_state state =
   13669                 :          0 :                         __atomic_load_n(&ct->state, __ATOMIC_RELAXED);
   13670                 :            : 
   13671                 :            :         /* Cannot release when CT is in the ASO SQ. */
   13672         [ #  # ]:          0 :         if (state == ASO_CONNTRACK_WAIT || state == ASO_CONNTRACK_QUERY)
   13673                 :            :                 return -1;
   13674                 :          0 :         ret = __atomic_fetch_sub(&ct->refcnt, 1, __ATOMIC_RELAXED) - 1;
   13675         [ #  # ]:          0 :         if (!ret) {
   13676         [ #  # ]:          0 :                 if (ct->dr_action_orig) {
   13677                 :            : #ifdef HAVE_MLX5_DR_ACTION_ASO_CT
   13678                 :          0 :                         claim_zero(mlx5_glue->destroy_flow_action
   13679                 :            :                                         (ct->dr_action_orig));
   13680                 :            : #endif
   13681                 :          0 :                         ct->dr_action_orig = NULL;
   13682                 :            :                 }
   13683         [ #  # ]:          0 :                 if (ct->dr_action_rply) {
   13684                 :            : #ifdef HAVE_MLX5_DR_ACTION_ASO_CT
   13685                 :          0 :                         claim_zero(mlx5_glue->destroy_flow_action
   13686                 :            :                                         (ct->dr_action_rply));
   13687                 :            : #endif
   13688                 :          0 :                         ct->dr_action_rply = NULL;
   13689                 :            :                 }
   13690                 :            :                 /* Clear the state to free, no need in 1st allocation. */
   13691                 :          0 :                 MLX5_ASO_CT_UPDATE_STATE(ct, ASO_CONNTRACK_FREE);
   13692                 :          0 :                 rte_spinlock_lock(&mng->ct_sl);
   13693         [ #  # ]:          0 :                 LIST_INSERT_HEAD(&mng->free_cts, ct, next);
   13694                 :            :                 rte_spinlock_unlock(&mng->ct_sl);
   13695                 :            :         }
   13696                 :          0 :         return (int)ret;
   13697                 :            : }
   13698                 :            : 
   13699                 :            : static inline int
   13700                 :          0 : flow_dv_aso_ct_release(struct rte_eth_dev *dev, uint32_t own_idx,
   13701                 :            :                        struct rte_flow_error *error)
   13702                 :            : {
   13703                 :          0 :         uint16_t owner = (uint16_t)MLX5_INDIRECT_ACT_CT_GET_OWNER(own_idx);
   13704                 :          0 :         uint32_t idx = MLX5_INDIRECT_ACT_CT_GET_IDX(own_idx);
   13705                 :          0 :         struct rte_eth_dev *owndev = &rte_eth_devices[owner];
   13706                 :            :         int ret;
   13707                 :            : 
   13708                 :            :         MLX5_ASSERT(owner < RTE_MAX_ETHPORTS);
   13709         [ #  # ]:          0 :         if (dev->data->dev_started != 1)
   13710                 :          0 :                 return rte_flow_error_set(error, EAGAIN,
   13711                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
   13712                 :            :                                           NULL,
   13713                 :            :                                           "Indirect CT action cannot be destroyed when the port is stopped");
   13714                 :          0 :         ret = flow_dv_aso_ct_dev_release(owndev, idx);
   13715         [ #  # ]:          0 :         if (ret < 0)
   13716                 :          0 :                 return rte_flow_error_set(error, EAGAIN,
   13717                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
   13718                 :            :                                           NULL,
   13719                 :            :                                           "Current state prevents indirect CT action from being destroyed");
   13720                 :            :         return ret;
   13721                 :            : }
   13722                 :            : 
   13723                 :            : /*
   13724                 :            :  * Resize the ASO CT pools array by 64 pools.
   13725                 :            :  *
   13726                 :            :  * @param[in] dev
   13727                 :            :  *   Pointer to the Ethernet device structure.
   13728                 :            :  *
   13729                 :            :  * @return
   13730                 :            :  *   0 on success, otherwise negative errno value and rte_errno is set.
   13731                 :            :  */
   13732                 :            : static int
   13733                 :          0 : flow_dv_aso_ct_pools_resize(struct rte_eth_dev *dev)
   13734                 :            : {
   13735                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13736                 :          0 :         struct mlx5_aso_ct_pools_mng *mng = priv->sh->ct_mng;
   13737                 :          0 :         void *old_pools = mng->pools;
   13738                 :            :         /* Magic number now, need a macro. */
   13739                 :          0 :         uint32_t resize = mng->n + 64;
   13740                 :          0 :         uint32_t mem_size = sizeof(struct mlx5_aso_ct_pool *) * resize;
   13741                 :          0 :         void *pools = mlx5_malloc(MLX5_MEM_ZERO, mem_size, 0, SOCKET_ID_ANY);
   13742                 :            : 
   13743         [ #  # ]:          0 :         if (!pools) {
   13744                 :          0 :                 rte_errno = ENOMEM;
   13745                 :          0 :                 return -rte_errno;
   13746                 :            :         }
   13747                 :          0 :         rte_rwlock_write_lock(&mng->resize_rwl);
   13748                 :            :         /* ASO SQ/QP was already initialized in the startup. */
   13749         [ #  # ]:          0 :         if (old_pools) {
   13750                 :            :                 /* Realloc could be an alternative choice. */
   13751                 :          0 :                 rte_memcpy(pools, old_pools,
   13752         [ #  # ]:          0 :                            mng->n * sizeof(struct mlx5_aso_ct_pool *));
   13753                 :          0 :                 mlx5_free(old_pools);
   13754                 :            :         }
   13755                 :          0 :         mng->n = resize;
   13756                 :          0 :         mng->pools = pools;
   13757                 :            :         rte_rwlock_write_unlock(&mng->resize_rwl);
   13758                 :          0 :         return 0;
   13759                 :            : }
   13760                 :            : 
   13761                 :            : /*
   13762                 :            :  * Create and initialize a new ASO CT pool.
   13763                 :            :  *
   13764                 :            :  * @param[in] dev
   13765                 :            :  *   Pointer to the Ethernet device structure.
   13766                 :            :  * @param[out] ct_free
   13767                 :            :  *   Where to put the pointer of a new CT action.
   13768                 :            :  *
   13769                 :            :  * @return
   13770                 :            :  *   The CT actions pool pointer and @p ct_free is set on success,
   13771                 :            :  *   NULL otherwise and rte_errno is set.
   13772                 :            :  */
   13773                 :            : static struct mlx5_aso_ct_pool *
   13774                 :          0 : flow_dv_ct_pool_create(struct rte_eth_dev *dev,
   13775                 :            :                        struct mlx5_aso_ct_action **ct_free)
   13776                 :            : {
   13777                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13778                 :          0 :         struct mlx5_aso_ct_pools_mng *mng = priv->sh->ct_mng;
   13779                 :            :         struct mlx5_aso_ct_pool *pool = NULL;
   13780                 :            :         struct mlx5_devx_obj *obj = NULL;
   13781                 :            :         uint32_t i;
   13782                 :            :         uint32_t log_obj_size = rte_log2_u32(MLX5_ASO_CT_ACTIONS_PER_POOL);
   13783                 :            :         size_t mem_size;
   13784                 :            : 
   13785                 :          0 :         obj = mlx5_devx_cmd_create_conn_track_offload_obj(priv->sh->cdev->ctx,
   13786                 :          0 :                                                           priv->sh->cdev->pdn,
   13787                 :            :                                                           log_obj_size);
   13788         [ #  # ]:          0 :         if (!obj) {
   13789                 :          0 :                 rte_errno = ENODATA;
   13790                 :          0 :                 DRV_LOG(ERR, "Failed to create conn_track_offload_obj using DevX.");
   13791                 :          0 :                 return NULL;
   13792                 :            :         }
   13793                 :            :         mem_size = sizeof(struct mlx5_aso_ct_action) *
   13794                 :            :                    MLX5_ASO_CT_ACTIONS_PER_POOL +
   13795                 :            :                    sizeof(*pool);
   13796                 :          0 :         pool = mlx5_malloc(MLX5_MEM_ZERO, mem_size, 0, SOCKET_ID_ANY);
   13797         [ #  # ]:          0 :         if (!pool) {
   13798                 :          0 :                 rte_errno = ENOMEM;
   13799                 :          0 :                 claim_zero(mlx5_devx_cmd_destroy(obj));
   13800                 :          0 :                 return NULL;
   13801                 :            :         }
   13802                 :          0 :         pool->devx_obj = obj;
   13803                 :          0 :         pool->index = mng->next;
   13804                 :            :         /* Resize pools array if there is no room for the new pool in it. */
   13805   [ #  #  #  # ]:          0 :         if (pool->index == mng->n && flow_dv_aso_ct_pools_resize(dev)) {
   13806                 :          0 :                 claim_zero(mlx5_devx_cmd_destroy(obj));
   13807                 :          0 :                 mlx5_free(pool);
   13808                 :          0 :                 return NULL;
   13809                 :            :         }
   13810                 :          0 :         mng->pools[pool->index] = pool;
   13811                 :          0 :         mng->next++;
   13812                 :            :         /* Assign the first action in the new pool, the rest go to free list. */
   13813                 :          0 :         *ct_free = &pool->actions[0];
   13814                 :            :         /* Lock outside, the list operation is safe here. */
   13815         [ #  # ]:          0 :         for (i = 1; i < MLX5_ASO_CT_ACTIONS_PER_POOL; i++) {
   13816                 :            :                 /* refcnt is 0 when allocating the memory. */
   13817                 :          0 :                 pool->actions[i].offset = i;
   13818         [ #  # ]:          0 :                 LIST_INSERT_HEAD(&mng->free_cts, &pool->actions[i], next);
   13819                 :            :         }
   13820                 :            :         return pool;
   13821                 :            : }
   13822                 :            : 
   13823                 :            : /*
   13824                 :            :  * Allocate a ASO CT action from free list.
   13825                 :            :  *
   13826                 :            :  * @param[in] dev
   13827                 :            :  *   Pointer to the Ethernet device structure.
   13828                 :            :  * @param[out] error
   13829                 :            :  *   Pointer to the error structure.
   13830                 :            :  *
   13831                 :            :  * @return
   13832                 :            :  *   Index to ASO CT action on success, 0 otherwise and rte_errno is set.
   13833                 :            :  */
   13834                 :            : static uint32_t
   13835                 :          0 : flow_dv_aso_ct_alloc(struct rte_eth_dev *dev, struct rte_flow_error *error)
   13836                 :            : {
   13837                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13838                 :          0 :         struct mlx5_aso_ct_pools_mng *mng = priv->sh->ct_mng;
   13839                 :          0 :         struct mlx5_aso_ct_action *ct = NULL;
   13840                 :            :         struct mlx5_aso_ct_pool *pool;
   13841                 :            :         uint8_t reg_c;
   13842                 :            :         uint32_t ct_idx;
   13843                 :            : 
   13844                 :            :         MLX5_ASSERT(mng);
   13845         [ #  # ]:          0 :         if (!priv->sh->cdev->config.devx) {
   13846                 :          0 :                 rte_errno = ENOTSUP;
   13847                 :          0 :                 return 0;
   13848                 :            :         }
   13849                 :            :         /* Get a free CT action, if no, a new pool will be created. */
   13850                 :          0 :         rte_spinlock_lock(&mng->ct_sl);
   13851                 :          0 :         ct = LIST_FIRST(&mng->free_cts);
   13852         [ #  # ]:          0 :         if (ct) {
   13853         [ #  # ]:          0 :                 LIST_REMOVE(ct, next);
   13854         [ #  # ]:          0 :         } else if (!flow_dv_ct_pool_create(dev, &ct)) {
   13855                 :            :                 rte_spinlock_unlock(&mng->ct_sl);
   13856                 :          0 :                 rte_flow_error_set(error, rte_errno, RTE_FLOW_ERROR_TYPE_ACTION,
   13857                 :            :                                    NULL, "failed to create ASO CT pool");
   13858                 :          0 :                 return 0;
   13859                 :            :         }
   13860                 :            :         rte_spinlock_unlock(&mng->ct_sl);
   13861                 :          0 :         pool = container_of(ct, struct mlx5_aso_ct_pool, actions[ct->offset]);
   13862                 :          0 :         ct_idx = MLX5_MAKE_CT_IDX(pool->index, ct->offset);
   13863                 :            :         /* 0: inactive, 1: created, 2+: used by flows. */
   13864                 :          0 :         __atomic_store_n(&ct->refcnt, 1, __ATOMIC_RELAXED);
   13865                 :          0 :         reg_c = mlx5_flow_get_reg_id(dev, MLX5_ASO_CONNTRACK, 0, error);
   13866         [ #  # ]:          0 :         if (!ct->dr_action_orig) {
   13867                 :            : #ifdef HAVE_MLX5_DR_ACTION_ASO_CT
   13868                 :          0 :                 ct->dr_action_orig = mlx5_glue->dv_create_flow_action_aso
   13869                 :          0 :                         (priv->sh->rx_domain, pool->devx_obj->obj,
   13870                 :            :                          ct->offset,
   13871                 :            :                          MLX5DV_DR_ACTION_FLAGS_ASO_CT_DIRECTION_INITIATOR,
   13872                 :          0 :                          reg_c - REG_C_0);
   13873                 :            : #else
   13874                 :            :                 RTE_SET_USED(reg_c);
   13875                 :            : #endif
   13876         [ #  # ]:          0 :                 if (!ct->dr_action_orig) {
   13877                 :          0 :                         flow_dv_aso_ct_dev_release(dev, ct_idx);
   13878                 :          0 :                         rte_flow_error_set(error, rte_errno,
   13879                 :            :                                            RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   13880                 :            :                                            "failed to create ASO CT action");
   13881                 :          0 :                         return 0;
   13882                 :            :                 }
   13883                 :            :         }
   13884         [ #  # ]:          0 :         if (!ct->dr_action_rply) {
   13885                 :            : #ifdef HAVE_MLX5_DR_ACTION_ASO_CT
   13886                 :          0 :                 ct->dr_action_rply = mlx5_glue->dv_create_flow_action_aso
   13887                 :          0 :                         (priv->sh->rx_domain, pool->devx_obj->obj,
   13888                 :            :                          ct->offset,
   13889                 :            :                          MLX5DV_DR_ACTION_FLAGS_ASO_CT_DIRECTION_RESPONDER,
   13890                 :          0 :                          reg_c - REG_C_0);
   13891                 :            : #endif
   13892         [ #  # ]:          0 :                 if (!ct->dr_action_rply) {
   13893                 :          0 :                         flow_dv_aso_ct_dev_release(dev, ct_idx);
   13894                 :          0 :                         rte_flow_error_set(error, rte_errno,
   13895                 :            :                                            RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   13896                 :            :                                            "failed to create ASO CT action");
   13897                 :          0 :                         return 0;
   13898                 :            :                 }
   13899                 :            :         }
   13900                 :            :         return ct_idx;
   13901                 :            : }
   13902                 :            : 
   13903                 :            : /*
   13904                 :            :  * Create a conntrack object with context and actions by using ASO mechanism.
   13905                 :            :  *
   13906                 :            :  * @param[in] dev
   13907                 :            :  *   Pointer to rte_eth_dev structure.
   13908                 :            :  * @param[in] pro
   13909                 :            :  *   Pointer to conntrack information profile.
   13910                 :            :  * @param[out] error
   13911                 :            :  *   Pointer to the error structure.
   13912                 :            :  *
   13913                 :            :  * @return
   13914                 :            :  *   Index to conntrack object on success, 0 otherwise.
   13915                 :            :  */
   13916                 :            : static uint32_t
   13917                 :          0 : flow_dv_translate_create_conntrack(struct rte_eth_dev *dev,
   13918                 :            :                                    const struct rte_flow_action_conntrack *pro,
   13919                 :            :                                    struct rte_flow_error *error)
   13920                 :            : {
   13921                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13922                 :          0 :         struct mlx5_dev_ctx_shared *sh = priv->sh;
   13923                 :            :         struct mlx5_aso_ct_action *ct;
   13924                 :            :         uint32_t idx;
   13925                 :            : 
   13926         [ #  # ]:          0 :         if (!sh->ct_aso_en)
   13927                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
   13928                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   13929                 :            :                                           "Connection is not supported");
   13930         [ #  # ]:          0 :         if (dev->data->port_id >= MLX5_INDIRECT_ACT_CT_MAX_PORT) {
   13931                 :          0 :                 rte_flow_error_set(error, EINVAL,
   13932                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   13933                 :            :                                    "CT supports port indexes up to "
   13934                 :            :                                    RTE_STR(MLX5_ACTION_CTX_CT_MAX_PORT));
   13935                 :          0 :                 return 0;
   13936                 :            :         }
   13937                 :          0 :         idx = flow_dv_aso_ct_alloc(dev, error);
   13938         [ #  # ]:          0 :         if (!idx)
   13939                 :          0 :                 return rte_flow_error_set(error, rte_errno,
   13940                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   13941                 :            :                                           "Failed to allocate CT object");
   13942                 :          0 :         ct = flow_aso_ct_get_by_dev_idx(dev, idx);
   13943         [ #  # ]:          0 :         if (mlx5_aso_ct_update_by_wqe(sh, MLX5_HW_INV_QUEUE, ct, pro, NULL, true)) {
   13944                 :          0 :                 flow_dv_aso_ct_dev_release(dev, idx);
   13945                 :          0 :                 rte_flow_error_set(error, EBUSY,
   13946                 :            :                                    RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   13947                 :            :                                    "Failed to update CT");
   13948                 :          0 :                 return 0;
   13949                 :            :         }
   13950                 :          0 :         ct->is_original = !!pro->is_original_dir;
   13951                 :          0 :         ct->peer = pro->peer_port;
   13952                 :          0 :         return idx;
   13953                 :            : }
   13954                 :            : 
   13955                 :            : /**
   13956                 :            :  * Fill the flow matcher with DV spec.
   13957                 :            :  *
   13958                 :            :  * @param[in] dev
   13959                 :            :  *   Pointer to rte_eth_dev structure.
   13960                 :            :  * @param[in] items
   13961                 :            :  *   Pointer to the list of items.
   13962                 :            :  * @param[in] wks
   13963                 :            :  *   Pointer to the matcher workspace.
   13964                 :            :  * @param[in] key
   13965                 :            :  *   Pointer to the flow matcher key.
   13966                 :            :  * @param[in] key_type
   13967                 :            :  *   Key type.
   13968                 :            :  * @param[out] error
   13969                 :            :  *   Pointer to the error structure.
   13970                 :            :  *
   13971                 :            :  * @return
   13972                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   13973                 :            :  */
   13974                 :            : static int
   13975                 :          0 : flow_dv_translate_items(struct rte_eth_dev *dev,
   13976                 :            :                         const struct rte_flow_item *items,
   13977                 :            :                         struct mlx5_dv_matcher_workspace *wks,
   13978                 :            :                         void *key, uint32_t key_type,
   13979                 :            :                         struct rte_flow_error *error)
   13980                 :            : {
   13981                 :          0 :         struct mlx5_flow_rss_desc *rss_desc = wks->rss_desc;
   13982                 :          0 :         uint8_t next_protocol = wks->next_protocol;
   13983                 :          0 :         int tunnel = !!(wks->item_flags & MLX5_FLOW_LAYER_TUNNEL);
   13984                 :          0 :         int item_type = items->type;
   13985                 :          0 :         uint64_t last_item = wks->last_item;
   13986                 :            :         enum mlx5_l3_tunnel_detection l3_tunnel_detection;
   13987                 :            :         uint64_t l3_tunnel_flag;
   13988                 :            :         int ret;
   13989                 :            : 
   13990   [ #  #  #  #  :          0 :         switch (item_type) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
   13991                 :          0 :         case RTE_FLOW_ITEM_TYPE_ESP:
   13992                 :          0 :                 flow_dv_translate_item_esp(key, items, tunnel, key_type);
   13993                 :          0 :                 wks->priority = MLX5_PRIORITY_MAP_L4;
   13994                 :            :                 last_item = MLX5_FLOW_ITEM_ESP;
   13995                 :          0 :                 break;
   13996                 :          0 :         case RTE_FLOW_ITEM_TYPE_PORT_ID:
   13997                 :          0 :                 flow_dv_translate_item_port_id
   13998                 :            :                         (dev, key, items, wks->attr, key_type);
   13999                 :            :                 last_item = MLX5_FLOW_ITEM_PORT_ID;
   14000                 :          0 :                 break;
   14001                 :          0 :         case RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR:
   14002                 :          0 :                 flow_dv_translate_item_port_representor
   14003                 :            :                         (dev, key, key_type);
   14004                 :            :                 last_item = MLX5_FLOW_ITEM_PORT_REPRESENTOR;
   14005                 :          0 :                 break;
   14006                 :          0 :         case RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT:
   14007                 :          0 :                 flow_dv_translate_item_represented_port
   14008                 :            :                         (dev, key, items, wks->attr, key_type);
   14009                 :            :                 last_item = MLX5_FLOW_ITEM_REPRESENTED_PORT;
   14010                 :          0 :                 break;
   14011                 :          0 :         case RTE_FLOW_ITEM_TYPE_ETH:
   14012                 :          0 :                 flow_dv_translate_item_eth(key, items, tunnel,
   14013                 :            :                                            wks->group, key_type);
   14014         [ #  # ]:          0 :                 wks->priority = wks->action_flags &
   14015                 :          0 :                                 MLX5_FLOW_ACTION_DEFAULT_MISS &&
   14016         [ #  # ]:          0 :                                 !wks->external ?
   14017                 :            :                                 MLX5_PRIORITY_MAP_L3 :
   14018                 :            :                                 MLX5_PRIORITY_MAP_L2;
   14019         [ #  # ]:          0 :                 last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L2 :
   14020                 :            :                                      MLX5_FLOW_LAYER_OUTER_L2;
   14021                 :            :                 break;
   14022                 :          0 :         case RTE_FLOW_ITEM_TYPE_VLAN:
   14023                 :          0 :                 flow_dv_translate_item_vlan(key, items, tunnel, wks, key_type);
   14024                 :          0 :                 wks->priority = MLX5_PRIORITY_MAP_L2;
   14025                 :            :                 last_item = tunnel ? (MLX5_FLOW_LAYER_INNER_L2 |
   14026         [ #  # ]:          0 :                                           MLX5_FLOW_LAYER_INNER_VLAN) :
   14027                 :            :                                          (MLX5_FLOW_LAYER_OUTER_L2 |
   14028                 :            :                                           MLX5_FLOW_LAYER_OUTER_VLAN);
   14029                 :            :                 break;
   14030                 :            :         case RTE_FLOW_ITEM_TYPE_IPV4:
   14031                 :            :                 next_protocol = mlx5_flow_l3_next_protocol(items, key_type);
   14032                 :            :                 l3_tunnel_detection =
   14033                 :            :                         mlx5_flow_tunnel_ip_check(items, next_protocol,
   14034                 :            :                                                   wks->item_flags,
   14035                 :            :                                                   &l3_tunnel_flag);
   14036                 :            :                 if (l3_tunnel_detection == l3_tunnel_inner) {
   14037                 :          0 :                         wks->item_flags |= l3_tunnel_flag;
   14038                 :            :                         tunnel = 1;
   14039                 :            :                 }
   14040                 :          0 :                 flow_dv_translate_item_ipv4(key, items, tunnel,
   14041                 :            :                                             wks->group, key_type);
   14042                 :          0 :                 wks->priority = MLX5_PRIORITY_MAP_L3;
   14043         [ #  # ]:          0 :                 last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV4 :
   14044                 :            :                                      MLX5_FLOW_LAYER_OUTER_L3_IPV4;
   14045         [ #  # ]:          0 :                 if (l3_tunnel_detection == l3_tunnel_outer)
   14046                 :          0 :                         wks->item_flags |= l3_tunnel_flag;
   14047                 :            :                 break;
   14048                 :            :         case RTE_FLOW_ITEM_TYPE_IPV6:
   14049                 :            :                 next_protocol = mlx5_flow_l3_next_protocol(items, key_type);
   14050                 :            :                 l3_tunnel_detection =
   14051                 :            :                         mlx5_flow_tunnel_ip_check(items, next_protocol,
   14052                 :            :                                                   wks->item_flags,
   14053                 :            :                                                   &l3_tunnel_flag);
   14054                 :            :                 if (l3_tunnel_detection == l3_tunnel_inner) {
   14055                 :          0 :                         wks->item_flags |= l3_tunnel_flag;
   14056                 :            :                         tunnel = 1;
   14057                 :            :                 }
   14058                 :          0 :                 flow_dv_translate_item_ipv6(key, items, tunnel,
   14059                 :            :                                             wks->group, key_type);
   14060                 :          0 :                 wks->priority = MLX5_PRIORITY_MAP_L3;
   14061         [ #  # ]:          0 :                 last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV6 :
   14062                 :            :                                      MLX5_FLOW_LAYER_OUTER_L3_IPV6;
   14063         [ #  # ]:          0 :                 if (l3_tunnel_detection == l3_tunnel_outer)
   14064                 :          0 :                         wks->item_flags |= l3_tunnel_flag;
   14065                 :            :                 break;
   14066                 :          0 :         case RTE_FLOW_ITEM_TYPE_IPV6_FRAG_EXT:
   14067                 :          0 :                 flow_dv_translate_item_ipv6_frag_ext
   14068                 :            :                                         (key, items, tunnel, key_type);
   14069         [ #  # ]:          0 :                 last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV6_FRAG_EXT :
   14070                 :            :                                      MLX5_FLOW_LAYER_OUTER_L3_IPV6_FRAG_EXT;
   14071                 :            :                 next_protocol = mlx5_flow_l3_next_protocol(items, key_type);
   14072                 :            :                 break;
   14073                 :          0 :         case RTE_FLOW_ITEM_TYPE_TCP:
   14074                 :          0 :                 flow_dv_translate_item_tcp(key, items, tunnel, key_type);
   14075                 :          0 :                 wks->priority = MLX5_PRIORITY_MAP_L4;
   14076         [ #  # ]:          0 :                 last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L4_TCP :
   14077                 :            :                                      MLX5_FLOW_LAYER_OUTER_L4_TCP;
   14078                 :            :                 break;
   14079                 :          0 :         case RTE_FLOW_ITEM_TYPE_UDP:
   14080                 :          0 :                 flow_dv_translate_item_udp(key, items, tunnel, wks, key_type);
   14081                 :          0 :                 wks->priority = MLX5_PRIORITY_MAP_L4;
   14082         [ #  # ]:          0 :                 last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L4_UDP :
   14083                 :            :                                      MLX5_FLOW_LAYER_OUTER_L4_UDP;
   14084                 :            :                 break;
   14085                 :          0 :         case RTE_FLOW_ITEM_TYPE_GRE:
   14086         [ #  # ]:          0 :                 wks->priority = MLX5_TUNNEL_PRIO_GET(rss_desc);
   14087                 :          0 :                 wks->tunnel_item = items;
   14088                 :          0 :                 wks->gre_item = items;
   14089                 :            :                 last_item = MLX5_FLOW_LAYER_GRE;
   14090                 :          0 :                 break;
   14091                 :          0 :         case RTE_FLOW_ITEM_TYPE_GRE_KEY:
   14092                 :          0 :                 flow_dv_translate_item_gre_key(key, items, key_type);
   14093                 :            :                 last_item = MLX5_FLOW_LAYER_GRE_KEY;
   14094                 :          0 :                 break;
   14095                 :          0 :         case RTE_FLOW_ITEM_TYPE_GRE_OPTION:
   14096         [ #  # ]:          0 :                 wks->priority = MLX5_TUNNEL_PRIO_GET(rss_desc);
   14097                 :          0 :                 wks->tunnel_item = items;
   14098                 :            :                 last_item = MLX5_FLOW_LAYER_GRE;
   14099                 :          0 :                 break;
   14100                 :          0 :         case RTE_FLOW_ITEM_TYPE_NVGRE:
   14101         [ #  # ]:          0 :                 wks->priority = MLX5_TUNNEL_PRIO_GET(rss_desc);
   14102                 :          0 :                 wks->tunnel_item = items;
   14103                 :            :                 last_item = MLX5_FLOW_LAYER_GRE;
   14104                 :          0 :                 break;
   14105                 :          0 :         case RTE_FLOW_ITEM_TYPE_VXLAN:
   14106                 :          0 :                 flow_dv_translate_item_vxlan(dev, wks->attr, key,
   14107                 :            :                                              items, tunnel, wks, key_type);
   14108         [ #  # ]:          0 :                 wks->priority = MLX5_TUNNEL_PRIO_GET(rss_desc);
   14109                 :            :                 last_item = MLX5_FLOW_LAYER_VXLAN;
   14110                 :          0 :                 break;
   14111                 :          0 :         case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
   14112         [ #  # ]:          0 :                 wks->priority = MLX5_TUNNEL_PRIO_GET(rss_desc);
   14113                 :          0 :                 wks->tunnel_item = items;
   14114                 :            :                 last_item = MLX5_FLOW_LAYER_VXLAN_GPE;
   14115                 :          0 :                 break;
   14116                 :          0 :         case RTE_FLOW_ITEM_TYPE_GENEVE:
   14117         [ #  # ]:          0 :                 wks->priority = MLX5_TUNNEL_PRIO_GET(rss_desc);
   14118                 :          0 :                 wks->tunnel_item = items;
   14119                 :            :                 last_item = MLX5_FLOW_LAYER_GENEVE;
   14120                 :          0 :                 break;
   14121                 :          0 :         case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
   14122                 :          0 :                 ret = flow_dv_translate_item_geneve_opt
   14123                 :            :                                 (dev, key, items, key_type, error);
   14124         [ #  # ]:          0 :                 if (ret)
   14125                 :          0 :                         return rte_flow_error_set(error, -ret,
   14126                 :            :                                 RTE_FLOW_ERROR_TYPE_ITEM, NULL,
   14127                 :            :                                 "cannot create GENEVE TLV option");
   14128                 :          0 :                 wks->geneve_tlv_option = 1;
   14129                 :            :                 last_item = MLX5_FLOW_LAYER_GENEVE_OPT;
   14130                 :          0 :                 break;
   14131                 :          0 :         case RTE_FLOW_ITEM_TYPE_MPLS:
   14132                 :          0 :                 flow_dv_translate_item_mpls(key, items, last_item,
   14133                 :            :                                             tunnel, key_type);
   14134         [ #  # ]:          0 :                 wks->priority = MLX5_TUNNEL_PRIO_GET(rss_desc);
   14135                 :            :                 last_item = MLX5_FLOW_LAYER_MPLS;
   14136                 :          0 :                 break;
   14137                 :          0 :         case RTE_FLOW_ITEM_TYPE_MARK:
   14138                 :          0 :                 flow_dv_translate_item_mark(dev, key, items, key_type);
   14139                 :            :                 last_item = MLX5_FLOW_ITEM_MARK;
   14140                 :          0 :                 break;
   14141                 :          0 :         case RTE_FLOW_ITEM_TYPE_META:
   14142                 :          0 :                 flow_dv_translate_item_meta
   14143                 :            :                                 (dev, key, wks->attr, items, key_type);
   14144                 :            :                 last_item = MLX5_FLOW_ITEM_METADATA;
   14145                 :          0 :                 break;
   14146                 :          0 :         case RTE_FLOW_ITEM_TYPE_ICMP:
   14147                 :          0 :                 flow_dv_translate_item_icmp(key, items, tunnel, key_type);
   14148                 :          0 :                 wks->priority = MLX5_PRIORITY_MAP_L4;
   14149                 :            :                 last_item = MLX5_FLOW_LAYER_ICMP;
   14150                 :          0 :                 break;
   14151                 :          0 :         case RTE_FLOW_ITEM_TYPE_ICMP6:
   14152                 :          0 :                 flow_dv_translate_item_icmp6(key, items, tunnel, key_type);
   14153                 :          0 :                 wks->priority = MLX5_PRIORITY_MAP_L4;
   14154                 :            :                 last_item = MLX5_FLOW_LAYER_ICMP6;
   14155                 :          0 :                 break;
   14156                 :          0 :         case RTE_FLOW_ITEM_TYPE_ICMP6_ECHO_REQUEST:
   14157                 :            :         case RTE_FLOW_ITEM_TYPE_ICMP6_ECHO_REPLY:
   14158                 :          0 :                 flow_dv_translate_item_icmp6_echo(key, items, tunnel, key_type);
   14159                 :          0 :                 wks->priority = MLX5_PRIORITY_MAP_L4;
   14160                 :            :                 last_item = MLX5_FLOW_LAYER_ICMP6;
   14161                 :          0 :                 break;
   14162                 :          0 :         case RTE_FLOW_ITEM_TYPE_TAG:
   14163                 :          0 :                 flow_dv_translate_item_tag(dev, key, items, key_type);
   14164                 :            :                 last_item = MLX5_FLOW_ITEM_TAG;
   14165                 :          0 :                 break;
   14166                 :          0 :         case MLX5_RTE_FLOW_ITEM_TYPE_TAG:
   14167                 :          0 :                 flow_dv_translate_mlx5_item_tag(dev, key, items, key_type);
   14168                 :            :                 last_item = MLX5_FLOW_ITEM_TAG;
   14169                 :          0 :                 break;
   14170                 :          0 :         case MLX5_RTE_FLOW_ITEM_TYPE_SQ:
   14171                 :          0 :                 flow_dv_translate_item_sq(key, items, key_type);
   14172                 :            :                 last_item = MLX5_FLOW_ITEM_SQ;
   14173                 :          0 :                 break;
   14174                 :          0 :         case RTE_FLOW_ITEM_TYPE_GTP:
   14175                 :          0 :                 flow_dv_translate_item_gtp(key, items, tunnel, key_type);
   14176         [ #  # ]:          0 :                 wks->priority = MLX5_TUNNEL_PRIO_GET(rss_desc);
   14177                 :            :                 last_item = MLX5_FLOW_LAYER_GTP;
   14178                 :          0 :                 break;
   14179                 :          0 :         case RTE_FLOW_ITEM_TYPE_GTP_PSC:
   14180                 :          0 :                 ret = flow_dv_translate_item_gtp_psc(key, items, key_type);
   14181         [ #  # ]:          0 :                 if (ret)
   14182                 :          0 :                         return rte_flow_error_set(error, -ret,
   14183                 :            :                                 RTE_FLOW_ERROR_TYPE_ITEM, NULL,
   14184                 :            :                                 "cannot create GTP PSC item");
   14185                 :            :                 last_item = MLX5_FLOW_LAYER_GTP_PSC;
   14186                 :            :                 break;
   14187                 :          0 :         case RTE_FLOW_ITEM_TYPE_ECPRI:
   14188         [ #  # ]:          0 :                 if (!mlx5_flex_parser_ecpri_exist(dev)) {
   14189                 :            :                         /* Create it only the first time to be used. */
   14190                 :          0 :                         ret = mlx5_flex_parser_ecpri_alloc(dev);
   14191         [ #  # ]:          0 :                         if (ret)
   14192                 :          0 :                                 return rte_flow_error_set
   14193                 :            :                                         (error, -ret,
   14194                 :            :                                         RTE_FLOW_ERROR_TYPE_ITEM,
   14195                 :            :                                         NULL,
   14196                 :            :                                         "cannot create eCPRI parser");
   14197                 :            :                 }
   14198                 :          0 :                 flow_dv_translate_item_ecpri
   14199                 :            :                                 (dev, key, items, last_item, key_type);
   14200                 :            :                 /* No other protocol should follow eCPRI layer. */
   14201                 :            :                 last_item = MLX5_FLOW_LAYER_ECPRI;
   14202                 :          0 :                 break;
   14203                 :          0 :         case RTE_FLOW_ITEM_TYPE_METER_COLOR:
   14204                 :          0 :                 flow_dv_translate_item_meter_color(dev, key, items, key_type);
   14205                 :            :                 last_item = MLX5_FLOW_ITEM_METER_COLOR;
   14206                 :          0 :                 break;
   14207         [ #  # ]:          0 :         case RTE_FLOW_ITEM_TYPE_INTEGRITY:
   14208                 :            :                 last_item = flow_dv_translate_item_integrity(items,
   14209                 :            :                                                              wks, key_type);
   14210                 :          0 :                 break;
   14211                 :          0 :         case RTE_FLOW_ITEM_TYPE_AGGR_AFFINITY:
   14212                 :          0 :                 flow_dv_translate_item_aggr_affinity(key, items, key_type);
   14213                 :            :                 last_item = MLX5_FLOW_ITEM_AGGR_AFFINITY;
   14214                 :          0 :                 break;
   14215                 :          0 :         case RTE_FLOW_ITEM_TYPE_IB_BTH:
   14216                 :          0 :                 flow_dv_translate_item_ib_bth(key, items, tunnel, key_type);
   14217                 :            :                 last_item = MLX5_FLOW_ITEM_IB_BTH;
   14218                 :          0 :                 break;
   14219                 :          0 :         case RTE_FLOW_ITEM_TYPE_NSH:
   14220                 :            :                 last_item = MLX5_FLOW_ITEM_NSH;
   14221                 :          0 :                 break;
   14222                 :            :         default:
   14223                 :            :                 break;
   14224                 :            :         }
   14225                 :          0 :         wks->item_flags |= last_item;
   14226                 :          0 :         wks->last_item = last_item;
   14227                 :          0 :         wks->next_protocol = next_protocol;
   14228                 :          0 :         return 0;
   14229                 :            : }
   14230                 :            : 
   14231                 :            : /**
   14232                 :            :  * Fill the HW steering flow with DV spec.
   14233                 :            :  *
   14234                 :            :  * @param[in] items
   14235                 :            :  *   Pointer to the list of items.
   14236                 :            :  * @param[in] attr
   14237                 :            :  *   Pointer to the flow attributes.
   14238                 :            :  * @param[in] key
   14239                 :            :  *   Pointer to the flow matcher key.
   14240                 :            :  * @param[in] key_type
   14241                 :            :  *   Key type.
   14242                 :            :  * @param[in, out] item_flags
   14243                 :            :  *   Pointer to the flow item flags.
   14244                 :            :  * @param[out] error
   14245                 :            :  *   Pointer to the error structure.
   14246                 :            :  *
   14247                 :            :  * @return
   14248                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   14249                 :            :  */
   14250                 :            : int
   14251                 :          0 : flow_dv_translate_items_hws(const struct rte_flow_item *items,
   14252                 :            :                             struct mlx5_flow_attr *attr, void *key,
   14253                 :            :                             uint32_t key_type, uint64_t *item_flags,
   14254                 :            :                             uint8_t *match_criteria,
   14255                 :            :                             struct rte_flow_error *error)
   14256                 :            : {
   14257                 :          0 :         struct mlx5_flow_workspace *flow_wks = mlx5_flow_push_thread_workspace();
   14258                 :          0 :         struct mlx5_flow_rss_desc rss_desc = { .level = attr->rss_level };
   14259                 :          0 :         struct rte_flow_attr rattr = {
   14260                 :          0 :                 .group = attr->group,
   14261                 :          0 :                 .priority = attr->priority,
   14262                 :          0 :                 .ingress = !!(attr->tbl_type == MLX5DR_TABLE_TYPE_NIC_RX),
   14263                 :          0 :                 .egress = !!(attr->tbl_type == MLX5DR_TABLE_TYPE_NIC_TX),
   14264                 :          0 :                 .transfer = !!(attr->tbl_type == MLX5DR_TABLE_TYPE_FDB),
   14265                 :            :         };
   14266                 :          0 :         struct mlx5_dv_matcher_workspace wks = {
   14267                 :          0 :                 .action_flags = attr->act_flags,
   14268         [ #  # ]:          0 :                 .item_flags = item_flags ? *item_flags : 0,
   14269                 :            :                 .external = 0,
   14270                 :            :                 .next_protocol = 0xff,
   14271                 :            :                 .attr = &rattr,
   14272                 :            :                 .rss_desc = &rss_desc,
   14273                 :            :         };
   14274                 :            :         int ret = 0;
   14275                 :            : 
   14276                 :            :         RTE_SET_USED(flow_wks);
   14277         [ #  # ]:          0 :         for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {
   14278                 :            :                 if (!mlx5_flow_os_item_supported(items->type)) {
   14279                 :            :                         ret = rte_flow_error_set(error, ENOTSUP,
   14280                 :            :                                                  RTE_FLOW_ERROR_TYPE_ITEM,
   14281                 :            :                                                  NULL, "item not supported");
   14282                 :            :                         goto exit;
   14283                 :            :                 }
   14284                 :          0 :                 ret = flow_dv_translate_items(&rte_eth_devices[attr->port_id],
   14285                 :            :                         items, &wks, key, key_type,  NULL);
   14286         [ #  # ]:          0 :                 if (ret)
   14287                 :          0 :                         goto exit;
   14288                 :            :         }
   14289         [ #  # ]:          0 :         if (wks.item_flags & MLX5_FLOW_ITEM_INTEGRITY) {
   14290                 :          0 :                 flow_dv_translate_item_integrity_post(key,
   14291                 :            :                                                       wks.integrity_items,
   14292                 :            :                                                       wks.item_flags,
   14293                 :            :                                                       key_type);
   14294                 :            :         }
   14295         [ #  # ]:          0 :         if (wks.item_flags & MLX5_FLOW_LAYER_VXLAN_GPE) {
   14296                 :          0 :                 flow_dv_translate_item_vxlan_gpe(key,
   14297                 :            :                                                  wks.tunnel_item,
   14298                 :            :                                                  wks.item_flags,
   14299                 :            :                                                  key_type);
   14300         [ #  # ]:          0 :         } else if (wks.item_flags & MLX5_FLOW_LAYER_GENEVE) {
   14301                 :          0 :                 flow_dv_translate_item_geneve(key,
   14302                 :            :                                               wks.tunnel_item,
   14303                 :            :                                               wks.item_flags,
   14304                 :            :                                               key_type);
   14305         [ #  # ]:          0 :         } else if (wks.item_flags & MLX5_FLOW_LAYER_GRE) {
   14306         [ #  # ]:          0 :                 if (wks.tunnel_item->type == RTE_FLOW_ITEM_TYPE_GRE) {
   14307                 :          0 :                         flow_dv_translate_item_gre(key,
   14308                 :            :                                                    wks.tunnel_item,
   14309                 :            :                                                    wks.item_flags,
   14310                 :            :                                                    key_type);
   14311         [ #  # ]:          0 :                 } else if (wks.tunnel_item->type == RTE_FLOW_ITEM_TYPE_GRE_OPTION) {
   14312                 :          0 :                         flow_dv_translate_item_gre_option(key,
   14313                 :            :                                                           wks.tunnel_item,
   14314                 :            :                                                           wks.gre_item,
   14315                 :            :                                                           wks.item_flags,
   14316                 :            :                                                           key_type);
   14317         [ #  # ]:          0 :                 } else if (wks.tunnel_item->type == RTE_FLOW_ITEM_TYPE_NVGRE) {
   14318                 :          0 :                         flow_dv_translate_item_nvgre(key,
   14319                 :            :                                                      wks.tunnel_item,
   14320                 :            :                                                      wks.item_flags,
   14321                 :            :                                                      key_type);
   14322                 :            :                 } else {
   14323                 :            :                         MLX5_ASSERT(false);
   14324                 :            :                 }
   14325                 :            :         }
   14326                 :            : 
   14327         [ #  # ]:          0 :         if (match_criteria)
   14328                 :          0 :                 *match_criteria = flow_dv_matcher_enable(key);
   14329         [ #  # ]:          0 :         if (item_flags)
   14330                 :          0 :                 *item_flags = wks.item_flags;
   14331                 :          0 : exit:
   14332                 :          0 :         mlx5_flow_pop_thread_workspace();
   14333                 :          0 :         return ret;
   14334                 :            : }
   14335                 :            : 
   14336                 :            : /**
   14337                 :            :  * Fill the SW steering flow with DV spec.
   14338                 :            :  *
   14339                 :            :  * @param[in] dev
   14340                 :            :  *   Pointer to rte_eth_dev structure.
   14341                 :            :  * @param[in, out] dev_flow
   14342                 :            :  *   Pointer to the sub flow.
   14343                 :            :  * @param[in] attr
   14344                 :            :  *   Pointer to the flow attributes.
   14345                 :            :  * @param[in] items
   14346                 :            :  *   Pointer to the list of items.
   14347                 :            :  * @param[in, out] matcher
   14348                 :            :  *   Pointer to the flow matcher.
   14349                 :            :  * @param[out] error
   14350                 :            :  *   Pointer to the error structure.
   14351                 :            :  *
   14352                 :            :  * @return
   14353                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   14354                 :            :  */
   14355                 :            : static int
   14356                 :          0 : flow_dv_translate_items_sws(struct rte_eth_dev *dev,
   14357                 :            :                             struct mlx5_flow *dev_flow,
   14358                 :            :                             const struct rte_flow_attr *attr,
   14359                 :            :                             const struct rte_flow_item *items,
   14360                 :            :                             struct mlx5_flow_dv_matcher *matcher,
   14361                 :            :                             struct rte_flow_error *error)
   14362                 :            : {
   14363                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   14364                 :          0 :         void *match_mask = matcher->mask.buf;
   14365                 :          0 :         void *match_value = dev_flow->dv.value.buf;
   14366                 :          0 :         struct mlx5_dv_matcher_workspace wks = {
   14367                 :          0 :                 .action_flags = dev_flow->act_flags,
   14368                 :            :                 .item_flags = 0,
   14369                 :          0 :                 .external = dev_flow->external,
   14370                 :            :                 .next_protocol = 0xff,
   14371                 :          0 :                 .group = dev_flow->dv.group,
   14372                 :            :                 .attr = attr,
   14373                 :          0 :                 .rss_desc = &((struct mlx5_flow_workspace *)
   14374                 :            :                              mlx5_flow_get_thread_workspace())->rss_desc,
   14375                 :            :         };
   14376                 :          0 :         struct mlx5_dv_matcher_workspace wks_m = wks;
   14377                 :            :         int item_type;
   14378                 :            :         int ret = 0;
   14379                 :            :         int tunnel;
   14380                 :            : 
   14381         [ #  # ]:          0 :         for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {
   14382                 :          0 :                 if (!mlx5_flow_os_item_supported(items->type))
   14383                 :            :                         return rte_flow_error_set(error, ENOTSUP,
   14384                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM,
   14385                 :            :                                                   NULL, "item not supported");
   14386                 :          0 :                 tunnel = !!(wks.item_flags & MLX5_FLOW_LAYER_TUNNEL);
   14387                 :            :                 item_type = items->type;
   14388   [ #  #  #  # ]:          0 :                 switch (item_type) {
   14389                 :          0 :                 case RTE_FLOW_ITEM_TYPE_CONNTRACK:
   14390                 :          0 :                         flow_dv_translate_item_aso_ct(dev, match_mask,
   14391                 :            :                                                       match_value, items);
   14392                 :          0 :                         break;
   14393                 :          0 :                 case RTE_FLOW_ITEM_TYPE_FLEX:
   14394                 :          0 :                         flow_dv_translate_item_flex(dev, match_mask,
   14395                 :            :                                                     match_value, items,
   14396                 :            :                                                     dev_flow, tunnel != 0);
   14397         [ #  # ]:          0 :                         wks.last_item = tunnel ? MLX5_FLOW_ITEM_INNER_FLEX :
   14398                 :            :                                                  MLX5_FLOW_ITEM_OUTER_FLEX;
   14399                 :          0 :                         break;
   14400                 :          0 :                 case MLX5_RTE_FLOW_ITEM_TYPE_SQ:
   14401                 :          0 :                         flow_dv_translate_item_sq(match_value, items,
   14402                 :            :                                                   MLX5_SET_MATCHER_SW_V);
   14403                 :          0 :                         flow_dv_translate_item_sq(match_mask, items,
   14404                 :            :                                                   MLX5_SET_MATCHER_SW_M);
   14405                 :          0 :                         break;
   14406                 :          0 :                 default:
   14407                 :          0 :                         ret = flow_dv_translate_items(dev, items, &wks_m,
   14408                 :            :                                 match_mask, MLX5_SET_MATCHER_SW_M, error);
   14409         [ #  # ]:          0 :                         if (ret)
   14410                 :          0 :                                 return ret;
   14411                 :          0 :                         ret = flow_dv_translate_items(dev, items, &wks,
   14412                 :            :                                 match_value, MLX5_SET_MATCHER_SW_V, error);
   14413         [ #  # ]:          0 :                         if (ret)
   14414                 :          0 :                                 return ret;
   14415                 :            :                         break;
   14416                 :            :                 }
   14417                 :          0 :                 wks.item_flags |= wks.last_item;
   14418                 :            :         }
   14419                 :            :         /*
   14420                 :            :          * When E-Switch mode is enabled, we have two cases where we need to
   14421                 :            :          * set the source port manually.
   14422                 :            :          * The first one, is in case of NIC ingress steering rule, and the
   14423                 :            :          * second is E-Switch rule where no port_id item was found.
   14424                 :            :          * In both cases the source port is set according the current port
   14425                 :            :          * in use.
   14426                 :            :          */
   14427                 :          0 :         if (!(wks.item_flags & MLX5_FLOW_ITEM_PORT_ID) &&
   14428         [ #  # ]:          0 :             !(wks.item_flags & MLX5_FLOW_ITEM_REPRESENTED_PORT) &&
   14429                 :          0 :             !(wks.item_flags & MLX5_FLOW_ITEM_PORT_REPRESENTOR) &&
   14430         [ #  # ]:          0 :             priv->sh->esw_mode &&
   14431         [ #  # ]:          0 :             !attr->egress &&
   14432         [ #  # ]:          0 :             attr->group != MLX5_FLOW_MREG_CP_TABLE_GROUP) {
   14433         [ #  # ]:          0 :                 if (flow_dv_translate_item_port_id_all(dev, match_mask,
   14434                 :            :                                                    match_value, NULL, attr))
   14435                 :          0 :                         return -rte_errno;
   14436                 :            :         }
   14437         [ #  # ]:          0 :         if (wks.item_flags & MLX5_FLOW_ITEM_INTEGRITY) {
   14438                 :          0 :                 flow_dv_translate_item_integrity_post(match_mask,
   14439                 :            :                                                       wks_m.integrity_items,
   14440                 :            :                                                       wks_m.item_flags,
   14441                 :            :                                                       MLX5_SET_MATCHER_SW_M);
   14442                 :          0 :                 flow_dv_translate_item_integrity_post(match_value,
   14443                 :            :                                                       wks.integrity_items,
   14444                 :            :                                                       wks.item_flags,
   14445                 :            :                                                       MLX5_SET_MATCHER_SW_V);
   14446                 :            :         }
   14447         [ #  # ]:          0 :         if (wks.item_flags & MLX5_FLOW_LAYER_VXLAN_GPE) {
   14448                 :          0 :                 flow_dv_translate_item_vxlan_gpe(match_mask,
   14449                 :            :                                                  wks.tunnel_item,
   14450                 :            :                                                  wks.item_flags,
   14451                 :            :                                                  MLX5_SET_MATCHER_SW_M);
   14452                 :          0 :                 flow_dv_translate_item_vxlan_gpe(match_value,
   14453                 :            :                                                  wks.tunnel_item,
   14454                 :            :                                                  wks.item_flags,
   14455                 :            :                                                  MLX5_SET_MATCHER_SW_V);
   14456         [ #  # ]:          0 :         } else if (wks.item_flags & MLX5_FLOW_LAYER_GENEVE) {
   14457                 :          0 :                 flow_dv_translate_item_geneve(match_mask,
   14458                 :            :                                               wks.tunnel_item,
   14459                 :            :                                               wks.item_flags,
   14460                 :            :                                               MLX5_SET_MATCHER_SW_M);
   14461                 :          0 :                 flow_dv_translate_item_geneve(match_value,
   14462                 :            :                                               wks.tunnel_item,
   14463                 :            :                                               wks.item_flags,
   14464                 :            :                                               MLX5_SET_MATCHER_SW_V);
   14465         [ #  # ]:          0 :         } else if (wks.item_flags & MLX5_FLOW_LAYER_GRE) {
   14466         [ #  # ]:          0 :                 if (wks.tunnel_item->type == RTE_FLOW_ITEM_TYPE_GRE) {
   14467                 :          0 :                         flow_dv_translate_item_gre(match_mask,
   14468                 :            :                                                    wks.tunnel_item,
   14469                 :            :                                                    wks.item_flags,
   14470                 :            :                                                    MLX5_SET_MATCHER_SW_M);
   14471                 :          0 :                         flow_dv_translate_item_gre(match_value,
   14472                 :            :                                                    wks.tunnel_item,
   14473                 :            :                                                    wks.item_flags,
   14474                 :            :                                                    MLX5_SET_MATCHER_SW_V);
   14475         [ #  # ]:          0 :                 } else if (wks.tunnel_item->type == RTE_FLOW_ITEM_TYPE_NVGRE) {
   14476                 :          0 :                         flow_dv_translate_item_nvgre(match_mask,
   14477                 :            :                                                      wks.tunnel_item,
   14478                 :            :                                                      wks.item_flags,
   14479                 :            :                                                      MLX5_SET_MATCHER_SW_M);
   14480                 :          0 :                         flow_dv_translate_item_nvgre(match_value,
   14481                 :            :                                                      wks.tunnel_item,
   14482                 :            :                                                      wks.item_flags,
   14483                 :            :                                                      MLX5_SET_MATCHER_SW_V);
   14484         [ #  # ]:          0 :                 } else if (wks.tunnel_item->type == RTE_FLOW_ITEM_TYPE_GRE_OPTION) {
   14485                 :          0 :                         flow_dv_translate_item_gre_option(match_mask,
   14486                 :            :                                                           wks.tunnel_item,
   14487                 :            :                                                           wks.gre_item,
   14488                 :            :                                                           wks.item_flags,
   14489                 :            :                                                           MLX5_SET_MATCHER_SW_M);
   14490                 :          0 :                         flow_dv_translate_item_gre_option(match_value,
   14491                 :            :                                                           wks.tunnel_item,
   14492                 :            :                                                           wks.gre_item,
   14493                 :            :                                                           wks.item_flags,
   14494                 :            :                                                           MLX5_SET_MATCHER_SW_V);
   14495                 :            :                 } else {
   14496                 :            :                         MLX5_ASSERT(false);
   14497                 :            :                 }
   14498                 :            :         }
   14499                 :          0 :         dev_flow->handle->vf_vlan.tag = wks.vlan_tag;
   14500                 :          0 :         matcher->priority = wks.priority;
   14501                 :            : #ifdef RTE_LIBRTE_MLX5_DEBUG
   14502                 :            :         MLX5_ASSERT(!flow_dv_check_valid_spec(match_mask, match_value));
   14503                 :            : #endif
   14504                 :            :         /*
   14505                 :            :          * Layers may be already initialized from prefix flow if this dev_flow
   14506                 :            :          * is the suffix flow.
   14507                 :            :          */
   14508                 :          0 :         dev_flow->handle->layers |= wks.item_flags;
   14509                 :            :         /*
   14510                 :            :          * Update geneve_tlv_option flag only it is set in workspace.
   14511                 :            :          * Avoid be overwritten by other sub mlx5_flows.
   14512                 :            :          */
   14513         [ #  # ]:          0 :         if (wks.geneve_tlv_option)
   14514                 :          0 :                 dev_flow->flow->geneve_tlv_option += wks.geneve_tlv_option;
   14515                 :            :         return 0;
   14516                 :            : }
   14517                 :            : 
   14518                 :            : /**
   14519                 :            :  * Fill the flow with DV spec, lock free
   14520                 :            :  * (mutex should be acquired by caller).
   14521                 :            :  *
   14522                 :            :  * @param[in] dev
   14523                 :            :  *   Pointer to rte_eth_dev structure.
   14524                 :            :  * @param[in, out] dev_flow
   14525                 :            :  *   Pointer to the sub flow.
   14526                 :            :  * @param[in] attr
   14527                 :            :  *   Pointer to the flow attributes.
   14528                 :            :  * @param[in] items
   14529                 :            :  *   Pointer to the list of items.
   14530                 :            :  * @param[in] actions
   14531                 :            :  *   Pointer to the list of actions.
   14532                 :            :  * @param[out] error
   14533                 :            :  *   Pointer to the error structure.
   14534                 :            :  *
   14535                 :            :  * @return
   14536                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   14537                 :            :  */
   14538                 :            : static int
   14539                 :          0 : flow_dv_translate(struct rte_eth_dev *dev,
   14540                 :            :                   struct mlx5_flow *dev_flow,
   14541                 :            :                   const struct rte_flow_attr *attr,
   14542                 :            :                   const struct rte_flow_item items[],
   14543                 :            :                   const struct rte_flow_action actions[],
   14544                 :            :                   struct rte_flow_error *error)
   14545                 :            : {
   14546                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   14547                 :          0 :         struct mlx5_sh_config *dev_conf = &priv->sh->config;
   14548                 :          0 :         struct rte_flow *flow = dev_flow->flow;
   14549                 :          0 :         struct mlx5_flow_handle *handle = dev_flow->handle;
   14550                 :          0 :         struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace();
   14551                 :            :         struct mlx5_flow_rss_desc *rss_desc;
   14552                 :            :         uint64_t action_flags = 0;
   14553                 :          0 :         struct mlx5_flow_dv_matcher matcher = {
   14554                 :            :                 .mask = {
   14555                 :            :                         .size = sizeof(matcher.mask.buf),
   14556                 :            :                 },
   14557                 :            :         };
   14558                 :            :         int actions_n = 0;
   14559                 :            :         bool actions_end = false;
   14560                 :            :         union {
   14561                 :            :                 struct mlx5_flow_dv_modify_hdr_resource res;
   14562                 :            :                 uint8_t len[sizeof(struct mlx5_flow_dv_modify_hdr_resource) +
   14563                 :            :                             sizeof(struct mlx5_modification_cmd) *
   14564                 :            :                             (MLX5_MAX_MODIFY_NUM + 1)];
   14565                 :            :         } mhdr_dummy;
   14566                 :            :         struct mlx5_flow_dv_modify_hdr_resource *mhdr_res = &mhdr_dummy.res;
   14567                 :            :         const struct rte_flow_action_count *count = NULL;
   14568                 :            :         const struct rte_flow_action_age *non_shared_age = NULL;
   14569                 :          0 :         union flow_dv_attr flow_attr = { .attr = 0 };
   14570                 :            :         uint32_t tag_be;
   14571                 :            :         union mlx5_flow_tbl_key tbl_key;
   14572                 :            :         uint32_t modify_action_position = UINT32_MAX;
   14573                 :          0 :         struct rte_vlan_hdr vlan = { 0 };
   14574                 :            :         struct mlx5_flow_dv_dest_array_resource mdest_res;
   14575                 :            :         struct mlx5_flow_dv_sample_resource sample_res;
   14576                 :          0 :         void *sample_actions[MLX5_DV_MAX_NUMBER_OF_ACTIONS] = {0};
   14577                 :            :         const struct rte_flow_action_sample *sample = NULL;
   14578                 :            :         struct mlx5_flow_sub_actions_list *sample_act;
   14579                 :            :         uint32_t sample_act_pos = UINT32_MAX;
   14580                 :            :         uint32_t age_act_pos = UINT32_MAX;
   14581                 :            :         uint32_t ipv6_tc_off = 0;
   14582                 :          0 :         uint32_t num_of_dest = 0;
   14583                 :            :         int tmp_actions_n = 0;
   14584                 :            :         uint32_t table;
   14585                 :            :         int ret = 0;
   14586                 :            :         const struct mlx5_flow_tunnel *tunnel = NULL;
   14587                 :          0 :         struct flow_grp_info grp_info = {
   14588                 :          0 :                 .external = !!dev_flow->external,
   14589                 :          0 :                 .transfer = !!attr->transfer,
   14590                 :          0 :                 .fdb_def_rule = !!priv->fdb_def_rule,
   14591                 :          0 :                 .skip_scale = dev_flow->skip_scale &
   14592                 :            :                         (1 << MLX5_SCALE_FLOW_GROUP_BIT),
   14593                 :            :                 .std_tbl_fix = true,
   14594                 :            :         };
   14595                 :            : 
   14596         [ #  # ]:          0 :         if (!wks)
   14597                 :          0 :                 return rte_flow_error_set(error, ENOMEM,
   14598                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   14599                 :            :                                           NULL,
   14600                 :            :                                           "failed to push flow workspace");
   14601         [ #  # ]:          0 :         rss_desc = &wks->rss_desc;
   14602                 :            :         memset(&mdest_res, 0, sizeof(struct mlx5_flow_dv_dest_array_resource));
   14603                 :            :         memset(&sample_res, 0, sizeof(struct mlx5_flow_dv_sample_resource));
   14604         [ #  # ]:          0 :         mhdr_res->ft_type = attr->egress ? MLX5DV_FLOW_TABLE_TYPE_NIC_TX :
   14605                 :            :                                            MLX5DV_FLOW_TABLE_TYPE_NIC_RX;
   14606                 :            :         /* update normal path action resource into last index of array */
   14607                 :            :         sample_act = &mdest_res.sample_act[MLX5_MAX_DEST_NUM - 1];
   14608         [ #  # ]:          0 :         if (is_tunnel_offload_active(dev)) {
   14609         [ #  # ]:          0 :                 if (dev_flow->tunnel) {
   14610         [ #  # ]:          0 :                         RTE_VERIFY(dev_flow->tof_type ==
   14611                 :            :                                    MLX5_TUNNEL_OFFLOAD_MISS_RULE);
   14612                 :            :                         tunnel = dev_flow->tunnel;
   14613                 :            :                 } else {
   14614                 :          0 :                         tunnel = mlx5_get_tof(items, actions,
   14615                 :            :                                               &dev_flow->tof_type);
   14616                 :          0 :                         dev_flow->tunnel = tunnel;
   14617                 :            :                 }
   14618         [ #  # ]:          0 :                 grp_info.std_tbl_fix = tunnel_use_standard_attr_group_translate
   14619                 :            :                                         (dev, attr, tunnel, dev_flow->tof_type);
   14620                 :            :         }
   14621                 :          0 :         mhdr_res->ft_type = attr->egress ? MLX5DV_FLOW_TABLE_TYPE_NIC_TX :
   14622                 :            :                                            MLX5DV_FLOW_TABLE_TYPE_NIC_RX;
   14623                 :          0 :         ret = mlx5_flow_group_to_table(dev, tunnel, attr->group, &table,
   14624                 :            :                                        &grp_info, error);
   14625         [ #  # ]:          0 :         if (ret)
   14626                 :            :                 return ret;
   14627                 :          0 :         dev_flow->dv.group = table;
   14628         [ #  # ]:          0 :         if (attr->transfer)
   14629                 :          0 :                 mhdr_res->ft_type = MLX5DV_FLOW_TABLE_TYPE_FDB;
   14630                 :            :         /* number of actions must be set to 0 in case of dirty stack. */
   14631                 :          0 :         mhdr_res->actions_num = 0;
   14632         [ #  # ]:          0 :         if (is_flow_tunnel_match_rule(dev_flow->tof_type)) {
   14633                 :            :                 /*
   14634                 :            :                  * do not add decap action if match rule drops packet
   14635                 :            :                  * HW rejects rules with decap & drop
   14636                 :            :                  *
   14637                 :            :                  * if tunnel match rule was inserted before matching tunnel set
   14638                 :            :                  * rule flow table used in the match rule must be registered.
   14639                 :            :                  * current implementation handles that in the
   14640                 :            :                  * flow_dv_match_register() at the function end.
   14641                 :            :                  */
   14642                 :            :                 bool add_decap = true;
   14643                 :            :                 const struct rte_flow_action *ptr = actions;
   14644                 :            : 
   14645         [ #  # ]:          0 :                 for (; ptr->type != RTE_FLOW_ACTION_TYPE_END; ptr++) {
   14646         [ #  # ]:          0 :                         if (ptr->type == RTE_FLOW_ACTION_TYPE_DROP) {
   14647                 :            :                                 add_decap = false;
   14648                 :            :                                 break;
   14649                 :            :                         }
   14650                 :            :                 }
   14651         [ #  # ]:          0 :                 if (add_decap) {
   14652         [ #  # ]:          0 :                         if (flow_dv_create_action_l2_decap(dev, dev_flow,
   14653                 :          0 :                                                            attr->transfer,
   14654                 :            :                                                            error))
   14655                 :          0 :                                 return -rte_errno;
   14656                 :          0 :                         dev_flow->dv.actions[actions_n++] =
   14657                 :          0 :                                         dev_flow->dv.encap_decap->action;
   14658                 :            :                         action_flags |= MLX5_FLOW_ACTION_DECAP;
   14659                 :            :                 }
   14660                 :            :         }
   14661         [ #  # ]:          0 :         for (; !actions_end ; actions++) {
   14662                 :            :                 const struct rte_flow_action_queue *queue;
   14663                 :            :                 const struct rte_flow_action_rss *rss;
   14664                 :            :                 const struct rte_flow_action *action = actions;
   14665                 :            :                 const uint8_t *rss_key;
   14666                 :            :                 struct mlx5_flow_tbl_resource *tbl;
   14667                 :            :                 struct mlx5_aso_age_action *age_act;
   14668                 :            :                 struct mlx5_flow_counter *cnt_act;
   14669                 :          0 :                 uint32_t port_id = 0;
   14670                 :            :                 struct mlx5_flow_dv_port_id_action_resource port_id_resource;
   14671                 :          0 :                 int action_type = actions->type;
   14672                 :            :                 const struct rte_flow_action *found_action = NULL;
   14673                 :            :                 uint32_t jump_group = 0;
   14674                 :            :                 uint32_t owner_idx;
   14675                 :            :                 struct mlx5_aso_ct_action *ct;
   14676                 :            : 
   14677                 :            :                 if (!mlx5_flow_os_action_supported(action_type))
   14678                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
   14679                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
   14680                 :            :                                                   actions,
   14681                 :            :                                                   "action not supported");
   14682   [ #  #  #  #  :          0 :                 switch (action_type) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
   14683                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_TUNNEL_SET:
   14684                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_TUNNEL_SET;
   14685                 :          0 :                         break;
   14686                 :            :                 case RTE_FLOW_ACTION_TYPE_VOID:
   14687                 :            :                         break;
   14688                 :          0 :                 case RTE_FLOW_ACTION_TYPE_PORT_ID:
   14689                 :            :                 case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
   14690         [ #  # ]:          0 :                         if (flow_dv_translate_action_port_id(dev, action,
   14691                 :            :                                                              &port_id, error))
   14692                 :          0 :                                 return -rte_errno;
   14693                 :          0 :                         port_id_resource.port_id = port_id;
   14694                 :            :                         MLX5_ASSERT(!handle->rix_port_id_action);
   14695         [ #  # ]:          0 :                         if (flow_dv_port_id_action_resource_register
   14696                 :            :                             (dev, &port_id_resource, dev_flow, error))
   14697                 :          0 :                                 return -rte_errno;
   14698                 :          0 :                         dev_flow->dv.actions[actions_n++] =
   14699                 :          0 :                                         dev_flow->dv.port_id_action->action;
   14700                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_PORT_ID;
   14701                 :          0 :                         dev_flow->handle->fate_action = MLX5_FLOW_FATE_PORT_ID;
   14702                 :          0 :                         sample_act->action_flags |= MLX5_FLOW_ACTION_PORT_ID;
   14703                 :          0 :                         num_of_dest++;
   14704                 :          0 :                         break;
   14705                 :          0 :                 case RTE_FLOW_ACTION_TYPE_FLAG:
   14706                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_FLAG;
   14707                 :          0 :                         wks->mark = 1;
   14708         [ #  # ]:          0 :                         if (dev_conf->dv_xmeta_en != MLX5_XMETA_MODE_LEGACY) {
   14709                 :          0 :                                 struct rte_flow_action_mark mark = {
   14710                 :            :                                         .id = MLX5_FLOW_MARK_DEFAULT,
   14711                 :            :                                 };
   14712                 :            : 
   14713         [ #  # ]:          0 :                                 if (flow_dv_convert_action_mark(dev, &mark,
   14714                 :            :                                                                 mhdr_res,
   14715                 :            :                                                                 error))
   14716                 :          0 :                                         return -rte_errno;
   14717                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_MARK_EXT;
   14718                 :          0 :                                 break;
   14719                 :            :                         }
   14720                 :            :                         tag_be = mlx5_flow_mark_set(MLX5_FLOW_MARK_DEFAULT);
   14721                 :            :                         /*
   14722                 :            :                          * Only one FLAG or MARK is supported per device flow
   14723                 :            :                          * right now. So the pointer to the tag resource must be
   14724                 :            :                          * zero before the register process.
   14725                 :            :                          */
   14726                 :            :                         MLX5_ASSERT(!handle->dvh.rix_tag);
   14727         [ #  # ]:          0 :                         if (flow_dv_tag_resource_register(dev, tag_be,
   14728                 :            :                                                           dev_flow, error))
   14729                 :          0 :                                 return -rte_errno;
   14730                 :            :                         MLX5_ASSERT(dev_flow->dv.tag_resource);
   14731                 :          0 :                         dev_flow->dv.actions[actions_n++] =
   14732                 :          0 :                                         dev_flow->dv.tag_resource->action;
   14733                 :          0 :                         break;
   14734                 :          0 :                 case RTE_FLOW_ACTION_TYPE_MARK:
   14735                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_MARK;
   14736                 :          0 :                         wks->mark = 1;
   14737         [ #  # ]:          0 :                         if (dev_conf->dv_xmeta_en != MLX5_XMETA_MODE_LEGACY) {
   14738                 :          0 :                                 const struct rte_flow_action_mark *mark =
   14739                 :            :                                         (const struct rte_flow_action_mark *)
   14740                 :            :                                                 actions->conf;
   14741                 :            : 
   14742         [ #  # ]:          0 :                                 if (flow_dv_convert_action_mark(dev, mark,
   14743                 :            :                                                                 mhdr_res,
   14744                 :            :                                                                 error))
   14745                 :          0 :                                         return -rte_errno;
   14746                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_MARK_EXT;
   14747                 :          0 :                                 break;
   14748                 :            :                         }
   14749                 :            :                         /* Fall-through */
   14750                 :            :                 case MLX5_RTE_FLOW_ACTION_TYPE_MARK:
   14751                 :            :                         /* Legacy (non-extensive) MARK action. */
   14752                 :            :                         tag_be = mlx5_flow_mark_set
   14753                 :            :                               (((const struct rte_flow_action_mark *)
   14754         [ #  # ]:          0 :                                (actions->conf))->id);
   14755                 :            :                         MLX5_ASSERT(!handle->dvh.rix_tag);
   14756         [ #  # ]:          0 :                         if (flow_dv_tag_resource_register(dev, tag_be,
   14757                 :            :                                                           dev_flow, error))
   14758                 :          0 :                                 return -rte_errno;
   14759                 :            :                         MLX5_ASSERT(dev_flow->dv.tag_resource);
   14760                 :          0 :                         dev_flow->dv.actions[actions_n++] =
   14761                 :          0 :                                         dev_flow->dv.tag_resource->action;
   14762                 :          0 :                         break;
   14763                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_META:
   14764         [ #  # ]:          0 :                         if (flow_dv_convert_action_set_meta
   14765                 :            :                                 (dev, mhdr_res, attr,
   14766                 :            :                                  (const struct rte_flow_action_set_meta *)
   14767                 :          0 :                                   actions->conf, error))
   14768                 :          0 :                                 return -rte_errno;
   14769                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SET_META;
   14770                 :          0 :                         break;
   14771                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_TAG:
   14772         [ #  # ]:          0 :                         if (flow_dv_convert_action_set_tag
   14773                 :            :                                 (dev, mhdr_res,
   14774                 :            :                                  (const struct rte_flow_action_set_tag *)
   14775                 :          0 :                                   actions->conf, error))
   14776                 :          0 :                                 return -rte_errno;
   14777                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SET_TAG;
   14778                 :          0 :                         break;
   14779                 :          0 :                 case RTE_FLOW_ACTION_TYPE_DROP:
   14780                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_DROP;
   14781                 :          0 :                         dev_flow->handle->fate_action = MLX5_FLOW_FATE_DROP;
   14782                 :          0 :                         break;
   14783                 :          0 :                 case RTE_FLOW_ACTION_TYPE_QUEUE:
   14784                 :          0 :                         queue = actions->conf;
   14785                 :          0 :                         rss_desc->queue_num = 1;
   14786                 :          0 :                         rss_desc->queue[0] = queue->index;
   14787                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_QUEUE;
   14788                 :          0 :                         dev_flow->handle->fate_action = MLX5_FLOW_FATE_QUEUE;
   14789                 :          0 :                         sample_act->action_flags |= MLX5_FLOW_ACTION_QUEUE;
   14790                 :          0 :                         num_of_dest++;
   14791                 :          0 :                         break;
   14792                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RSS:
   14793                 :          0 :                         rss = actions->conf;
   14794                 :          0 :                         rss_desc->symmetric_hash_function =
   14795                 :          0 :                                 MLX5_RSS_IS_SYMM(rss->func);
   14796                 :          0 :                         memcpy(rss_desc->queue, rss->queue,
   14797         [ #  # ]:          0 :                                rss->queue_num * sizeof(uint16_t));
   14798                 :          0 :                         rss_desc->queue_num = rss->queue_num;
   14799                 :            :                         /* NULL RSS key indicates default RSS key. */
   14800         [ #  # ]:          0 :                         rss_key = !rss->key ? rss_hash_default_key : rss->key;
   14801         [ #  # ]:          0 :                         memcpy(rss_desc->key, rss_key, MLX5_RSS_HASH_KEY_LEN);
   14802                 :            :                         /*
   14803                 :            :                          * rss->level and rss.types should be set in advance
   14804                 :            :                          * when expanding items for RSS.
   14805                 :            :                          */
   14806                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_RSS;
   14807                 :          0 :                         dev_flow->handle->fate_action = rss_desc->shared_rss ?
   14808         [ #  # ]:          0 :                                 MLX5_FLOW_FATE_SHARED_RSS :
   14809                 :            :                                 MLX5_FLOW_FATE_QUEUE;
   14810                 :          0 :                         break;
   14811                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_AGE:
   14812                 :          0 :                         owner_idx = (uint32_t)(uintptr_t)action->conf;
   14813                 :          0 :                         age_act = flow_aso_age_get_by_idx(dev, owner_idx);
   14814         [ #  # ]:          0 :                         if (flow->age == 0) {
   14815                 :          0 :                                 flow->age = owner_idx;
   14816                 :          0 :                                 __atomic_fetch_add(&age_act->refcnt, 1,
   14817                 :            :                                                    __ATOMIC_RELAXED);
   14818                 :            :                         }
   14819                 :          0 :                         age_act_pos = actions_n++;
   14820                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_AGE;
   14821                 :          0 :                         break;
   14822                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SEND_TO_KERNEL:
   14823                 :          0 :                         dev_flow->dv.actions[actions_n] =
   14824                 :          0 :                                 flow_dv_translate_action_send_to_kernel(dev, attr,
   14825                 :            :                                                         error);
   14826         [ #  # ]:          0 :                         if (!dev_flow->dv.actions[actions_n])
   14827                 :          0 :                                 return -rte_errno;
   14828                 :          0 :                         actions_n++;
   14829                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SEND_TO_KERNEL;
   14830                 :          0 :                         dev_flow->handle->fate_action =
   14831                 :            :                                         MLX5_FLOW_FATE_SEND_TO_KERNEL;
   14832                 :          0 :                         break;
   14833                 :          0 :                 case RTE_FLOW_ACTION_TYPE_AGE:
   14834                 :          0 :                         non_shared_age = action->conf;
   14835                 :          0 :                         age_act_pos = actions_n++;
   14836                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_AGE;
   14837                 :          0 :                         break;
   14838                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_COUNT:
   14839         [ #  # ]:          0 :                         owner_idx = (uint32_t)(uintptr_t)action->conf;
   14840                 :            :                         cnt_act = flow_dv_counter_get_by_idx(dev, owner_idx,
   14841                 :            :                                                              NULL);
   14842                 :            :                         MLX5_ASSERT(cnt_act != NULL);
   14843                 :            :                         /**
   14844                 :            :                          * When creating meter drop flow in drop table, the
   14845                 :            :                          * counter should not overwrite the rte flow counter.
   14846                 :            :                          */
   14847         [ #  # ]:          0 :                         if (attr->group == MLX5_FLOW_TABLE_LEVEL_METER &&
   14848         [ #  # ]:          0 :                             dev_flow->dv.table_id == MLX5_MTR_TABLE_ID_DROP) {
   14849                 :          0 :                                 dev_flow->dv.actions[actions_n++] =
   14850                 :          0 :                                                         cnt_act->action;
   14851                 :            :                         } else {
   14852         [ #  # ]:          0 :                                 if (flow->counter == 0) {
   14853                 :          0 :                                         flow->counter = owner_idx;
   14854                 :          0 :                                         __atomic_fetch_add
   14855                 :          0 :                                                 (&cnt_act->shared_info.refcnt,
   14856                 :            :                                                  1, __ATOMIC_RELAXED);
   14857                 :            :                                 }
   14858                 :            :                                 /* Save information first, will apply later. */
   14859                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_COUNT;
   14860                 :            :                         }
   14861                 :            :                         break;
   14862                 :          0 :                 case RTE_FLOW_ACTION_TYPE_COUNT:
   14863         [ #  # ]:          0 :                         if (!priv->sh->cdev->config.devx) {
   14864                 :          0 :                                 return rte_flow_error_set
   14865                 :            :                                               (error, ENOTSUP,
   14866                 :            :                                                RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   14867                 :            :                                                NULL,
   14868                 :            :                                                "count action not supported");
   14869                 :            :                         }
   14870                 :            :                         /* Save information first, will apply later. */
   14871                 :          0 :                         count = action->conf;
   14872                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_COUNT;
   14873                 :          0 :                         break;
   14874                 :          0 :                 case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:
   14875                 :          0 :                         dev_flow->dv.actions[actions_n++] =
   14876                 :          0 :                                                 priv->sh->pop_vlan_action;
   14877                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_OF_POP_VLAN;
   14878                 :          0 :                         break;
   14879                 :          0 :                 case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
   14880         [ #  # ]:          0 :                         if (!(action_flags &
   14881                 :            :                               MLX5_FLOW_ACTION_OF_SET_VLAN_VID))
   14882                 :          0 :                                 flow_dev_get_vlan_info_from_items(items, &vlan);
   14883         [ #  # ]:          0 :                         vlan.eth_proto = rte_be_to_cpu_16
   14884                 :            :                              ((((const struct rte_flow_action_of_push_vlan *)
   14885                 :            :                                                    actions->conf)->ethertype));
   14886                 :          0 :                         found_action = mlx5_flow_find_action
   14887                 :            :                                         (actions + 1,
   14888                 :            :                                          RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID);
   14889         [ #  # ]:          0 :                         if (found_action)
   14890                 :          0 :                                 mlx5_update_vlan_vid_pcp(found_action, &vlan);
   14891                 :          0 :                         found_action = mlx5_flow_find_action
   14892                 :            :                                         (actions + 1,
   14893                 :            :                                          RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP);
   14894         [ #  # ]:          0 :                         if (found_action)
   14895                 :          0 :                                 mlx5_update_vlan_vid_pcp(found_action, &vlan);
   14896         [ #  # ]:          0 :                         if (flow_dv_create_action_push_vlan
   14897                 :            :                                             (dev, attr, &vlan, dev_flow, error))
   14898                 :          0 :                                 return -rte_errno;
   14899                 :          0 :                         dev_flow->dv.actions[actions_n++] =
   14900                 :          0 :                                         dev_flow->dv.push_vlan_res->action;
   14901                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_OF_PUSH_VLAN;
   14902                 :          0 :                         break;
   14903                 :            :                 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:
   14904                 :            :                         /* of_vlan_push action handled this action */
   14905                 :            :                         MLX5_ASSERT(action_flags &
   14906                 :            :                                     MLX5_FLOW_ACTION_OF_PUSH_VLAN);
   14907                 :            :                         break;
   14908                 :          0 :                 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
   14909         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_OF_PUSH_VLAN)
   14910                 :            :                                 break;
   14911                 :          0 :                         flow_dev_get_vlan_info_from_items(items, &vlan);
   14912                 :          0 :                         mlx5_update_vlan_vid_pcp(actions, &vlan);
   14913                 :            :                         /* If no VLAN push - this is a modify header action */
   14914         [ #  # ]:          0 :                         if (flow_dv_convert_action_modify_vlan_vid
   14915                 :            :                                                 (mhdr_res, actions, error))
   14916                 :          0 :                                 return -rte_errno;
   14917                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_OF_SET_VLAN_VID;
   14918                 :          0 :                         break;
   14919                 :          0 :                 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
   14920                 :            :                 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
   14921         [ #  # ]:          0 :                         if (flow_dv_create_action_l2_encap(dev, actions,
   14922                 :            :                                                            dev_flow,
   14923                 :          0 :                                                            attr->transfer,
   14924                 :            :                                                            error))
   14925                 :          0 :                                 return -rte_errno;
   14926                 :          0 :                         dev_flow->dv.actions[actions_n++] =
   14927                 :          0 :                                         dev_flow->dv.encap_decap->action;
   14928                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_ENCAP;
   14929         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
   14930                 :          0 :                                 sample_act->action_flags |=
   14931                 :            :                                                         MLX5_FLOW_ACTION_ENCAP;
   14932                 :            :                         break;
   14933                 :          0 :                 case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
   14934                 :            :                 case RTE_FLOW_ACTION_TYPE_NVGRE_DECAP:
   14935         [ #  # ]:          0 :                         if (flow_dv_create_action_l2_decap(dev, dev_flow,
   14936                 :          0 :                                                            attr->transfer,
   14937                 :            :                                                            error))
   14938                 :          0 :                                 return -rte_errno;
   14939                 :          0 :                         dev_flow->dv.actions[actions_n++] =
   14940                 :          0 :                                         dev_flow->dv.encap_decap->action;
   14941                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_DECAP;
   14942                 :          0 :                         break;
   14943                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
   14944                 :            :                         /* Handle encap with preceding decap. */
   14945         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_DECAP) {
   14946         [ #  # ]:          0 :                                 if (flow_dv_create_action_raw_encap
   14947                 :            :                                         (dev, actions, dev_flow, attr, error))
   14948                 :          0 :                                         return -rte_errno;
   14949                 :          0 :                                 dev_flow->dv.actions[actions_n++] =
   14950                 :          0 :                                         dev_flow->dv.encap_decap->action;
   14951                 :            :                         } else {
   14952                 :            :                                 /* Handle encap without preceding decap. */
   14953         [ #  # ]:          0 :                                 if (flow_dv_create_action_l2_encap
   14954                 :          0 :                                     (dev, actions, dev_flow, attr->transfer,
   14955                 :            :                                      error))
   14956                 :          0 :                                         return -rte_errno;
   14957                 :          0 :                                 dev_flow->dv.actions[actions_n++] =
   14958                 :          0 :                                         dev_flow->dv.encap_decap->action;
   14959                 :            :                         }
   14960                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_ENCAP;
   14961         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
   14962                 :          0 :                                 sample_act->action_flags |=
   14963                 :            :                                                         MLX5_FLOW_ACTION_ENCAP;
   14964                 :            :                         break;
   14965                 :            :                 case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
   14966         [ #  # ]:          0 :                         while ((++action)->type == RTE_FLOW_ACTION_TYPE_VOID)
   14967                 :            :                                 ;
   14968         [ #  # ]:          0 :                         if (action->type != RTE_FLOW_ACTION_TYPE_RAW_ENCAP) {
   14969         [ #  # ]:          0 :                                 if (flow_dv_create_action_l2_decap
   14970                 :          0 :                                     (dev, dev_flow, attr->transfer, error))
   14971                 :          0 :                                         return -rte_errno;
   14972                 :          0 :                                 dev_flow->dv.actions[actions_n++] =
   14973                 :          0 :                                         dev_flow->dv.encap_decap->action;
   14974                 :            :                         }
   14975                 :            :                         /* If decap is followed by encap, handle it at encap. */
   14976                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_DECAP;
   14977                 :          0 :                         break;
   14978                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_JUMP:
   14979                 :          0 :                         dev_flow->dv.actions[actions_n++] =
   14980                 :          0 :                                 (void *)(uintptr_t)action->conf;
   14981                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_JUMP;
   14982                 :          0 :                         break;
   14983                 :          0 :                 case RTE_FLOW_ACTION_TYPE_JUMP:
   14984                 :          0 :                         jump_group = ((const struct rte_flow_action_jump *)
   14985                 :          0 :                                                         action->conf)->group;
   14986                 :          0 :                         grp_info.std_tbl_fix = 0;
   14987         [ #  # ]:          0 :                         if (dev_flow->skip_scale &
   14988                 :            :                                 (1 << MLX5_SCALE_JUMP_FLOW_GROUP_BIT))
   14989                 :          0 :                                 grp_info.skip_scale = 1;
   14990                 :            :                         else
   14991                 :          0 :                                 grp_info.skip_scale = 0;
   14992                 :          0 :                         ret = mlx5_flow_group_to_table(dev, tunnel,
   14993                 :            :                                                        jump_group,
   14994                 :            :                                                        &table,
   14995                 :            :                                                        &grp_info, error);
   14996         [ #  # ]:          0 :                         if (ret)
   14997                 :          0 :                                 return ret;
   14998                 :          0 :                         tbl = flow_dv_tbl_resource_get(dev, table, attr->egress,
   14999                 :          0 :                                                        attr->transfer,
   15000                 :          0 :                                                        !!dev_flow->external,
   15001                 :            :                                                        tunnel, jump_group, 0,
   15002                 :            :                                                        0, error);
   15003         [ #  # ]:          0 :                         if (!tbl)
   15004                 :          0 :                                 return rte_flow_error_set
   15005                 :          0 :                                                 (error, errno,
   15006                 :            :                                                  RTE_FLOW_ERROR_TYPE_ACTION,
   15007                 :            :                                                  NULL,
   15008                 :            :                                                  "cannot create jump action.");
   15009                 :            :                         if (flow_dv_jump_tbl_resource_register
   15010                 :            :                             (dev, tbl, dev_flow, error)) {
   15011                 :            :                                 flow_dv_tbl_resource_release(MLX5_SH(dev), tbl);
   15012                 :            :                                 return rte_flow_error_set
   15013                 :            :                                                 (error, errno,
   15014                 :            :                                                  RTE_FLOW_ERROR_TYPE_ACTION,
   15015                 :            :                                                  NULL,
   15016                 :            :                                                  "cannot create jump action.");
   15017                 :            :                         }
   15018                 :          0 :                         dev_flow->dv.actions[actions_n++] =
   15019                 :          0 :                                         dev_flow->dv.jump->action;
   15020                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_JUMP;
   15021                 :          0 :                         dev_flow->handle->fate_action = MLX5_FLOW_FATE_JUMP;
   15022                 :          0 :                         sample_act->action_flags |= MLX5_FLOW_ACTION_JUMP;
   15023                 :          0 :                         num_of_dest++;
   15024                 :          0 :                         break;
   15025                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_MAC_SRC:
   15026                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_MAC_DST:
   15027         [ #  # ]:          0 :                         if (flow_dv_convert_action_modify_mac
   15028                 :            :                                         (mhdr_res, actions, error))
   15029                 :          0 :                                 return -rte_errno;
   15030                 :          0 :                         action_flags |= actions->type ==
   15031                 :            :                                         RTE_FLOW_ACTION_TYPE_SET_MAC_SRC ?
   15032         [ #  # ]:          0 :                                         MLX5_FLOW_ACTION_SET_MAC_SRC :
   15033                 :            :                                         MLX5_FLOW_ACTION_SET_MAC_DST;
   15034                 :          0 :                         break;
   15035                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:
   15036                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:
   15037         [ #  # ]:          0 :                         if (flow_dv_convert_action_modify_ipv4
   15038                 :            :                                         (mhdr_res, actions, error))
   15039                 :          0 :                                 return -rte_errno;
   15040                 :          0 :                         action_flags |= actions->type ==
   15041                 :            :                                         RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC ?
   15042         [ #  # ]:          0 :                                         MLX5_FLOW_ACTION_SET_IPV4_SRC :
   15043                 :            :                                         MLX5_FLOW_ACTION_SET_IPV4_DST;
   15044                 :          0 :                         break;
   15045                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC:
   15046                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_IPV6_DST:
   15047         [ #  # ]:          0 :                         if (flow_dv_convert_action_modify_ipv6
   15048                 :            :                                         (mhdr_res, actions, error))
   15049                 :          0 :                                 return -rte_errno;
   15050                 :          0 :                         action_flags |= actions->type ==
   15051                 :            :                                         RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC ?
   15052         [ #  # ]:          0 :                                         MLX5_FLOW_ACTION_SET_IPV6_SRC :
   15053                 :            :                                         MLX5_FLOW_ACTION_SET_IPV6_DST;
   15054                 :          0 :                         break;
   15055                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_TP_SRC:
   15056                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_TP_DST:
   15057         [ #  # ]:          0 :                         if (flow_dv_convert_action_modify_tp
   15058                 :            :                                         (mhdr_res, actions, items,
   15059                 :          0 :                                          &flow_attr, dev_flow, !!(action_flags &
   15060                 :            :                                          MLX5_FLOW_ACTION_DECAP), error))
   15061                 :          0 :                                 return -rte_errno;
   15062                 :          0 :                         action_flags |= actions->type ==
   15063                 :            :                                         RTE_FLOW_ACTION_TYPE_SET_TP_SRC ?
   15064         [ #  # ]:          0 :                                         MLX5_FLOW_ACTION_SET_TP_SRC :
   15065                 :            :                                         MLX5_FLOW_ACTION_SET_TP_DST;
   15066                 :          0 :                         break;
   15067                 :          0 :                 case RTE_FLOW_ACTION_TYPE_DEC_TTL:
   15068         [ #  # ]:          0 :                         if (flow_dv_convert_action_modify_dec_ttl
   15069                 :            :                                         (mhdr_res, items, &flow_attr, dev_flow,
   15070                 :          0 :                                          !!(action_flags &
   15071                 :            :                                          MLX5_FLOW_ACTION_DECAP), error))
   15072                 :          0 :                                 return -rte_errno;
   15073                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_DEC_TTL;
   15074                 :          0 :                         break;
   15075                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_TTL:
   15076         [ #  # ]:          0 :                         if (flow_dv_convert_action_modify_ttl
   15077                 :            :                                         (mhdr_res, actions, items, &flow_attr,
   15078                 :          0 :                                          dev_flow, !!(action_flags &
   15079                 :            :                                          MLX5_FLOW_ACTION_DECAP), error))
   15080                 :          0 :                                 return -rte_errno;
   15081                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SET_TTL;
   15082                 :          0 :                         break;
   15083                 :          0 :                 case RTE_FLOW_ACTION_TYPE_INC_TCP_SEQ:
   15084                 :            :                 case RTE_FLOW_ACTION_TYPE_DEC_TCP_SEQ:
   15085         [ #  # ]:          0 :                         if (flow_dv_convert_action_modify_tcp_seq
   15086                 :            :                                         (mhdr_res, actions, error))
   15087                 :          0 :                                 return -rte_errno;
   15088                 :          0 :                         action_flags |= actions->type ==
   15089                 :            :                                         RTE_FLOW_ACTION_TYPE_INC_TCP_SEQ ?
   15090         [ #  # ]:          0 :                                         MLX5_FLOW_ACTION_INC_TCP_SEQ :
   15091                 :            :                                         MLX5_FLOW_ACTION_DEC_TCP_SEQ;
   15092                 :          0 :                         break;
   15093                 :            : 
   15094                 :          0 :                 case RTE_FLOW_ACTION_TYPE_INC_TCP_ACK:
   15095                 :            :                 case RTE_FLOW_ACTION_TYPE_DEC_TCP_ACK:
   15096         [ #  # ]:          0 :                         if (flow_dv_convert_action_modify_tcp_ack
   15097                 :            :                                         (mhdr_res, actions, error))
   15098                 :          0 :                                 return -rte_errno;
   15099                 :          0 :                         action_flags |= actions->type ==
   15100                 :            :                                         RTE_FLOW_ACTION_TYPE_INC_TCP_ACK ?
   15101         [ #  # ]:          0 :                                         MLX5_FLOW_ACTION_INC_TCP_ACK :
   15102                 :            :                                         MLX5_FLOW_ACTION_DEC_TCP_ACK;
   15103                 :          0 :                         break;
   15104                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_TAG:
   15105         [ #  # ]:          0 :                         if (flow_dv_convert_action_set_reg
   15106                 :            :                                         (mhdr_res, actions, error))
   15107                 :          0 :                                 return -rte_errno;
   15108                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SET_TAG;
   15109                 :          0 :                         break;
   15110                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_COPY_MREG:
   15111         [ #  # ]:          0 :                         if (flow_dv_convert_action_copy_mreg
   15112                 :            :                                         (dev, mhdr_res, actions, error))
   15113                 :          0 :                                 return -rte_errno;
   15114                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SET_TAG;
   15115                 :          0 :                         break;
   15116                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_DEFAULT_MISS:
   15117                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_DEFAULT_MISS;
   15118                 :          0 :                         dev_flow->handle->fate_action =
   15119                 :            :                                         MLX5_FLOW_FATE_DEFAULT_MISS;
   15120                 :          0 :                         break;
   15121                 :          0 :                 case RTE_FLOW_ACTION_TYPE_METER:
   15122         [ #  # ]:          0 :                         if (!wks->fm)
   15123                 :          0 :                                 return rte_flow_error_set(error, rte_errno,
   15124                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION,
   15125                 :            :                                         NULL, "Failed to get meter in flow.");
   15126                 :            :                         /* Set the meter action. */
   15127                 :          0 :                         dev_flow->dv.actions[actions_n++] =
   15128                 :          0 :                                 wks->fm->meter_action_g;
   15129                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_METER;
   15130                 :          0 :                         break;
   15131                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_IPV4_DSCP:
   15132         [ #  # ]:          0 :                         if (flow_dv_convert_action_modify_ipv4_dscp(mhdr_res,
   15133                 :            :                                                               actions, error))
   15134                 :          0 :                                 return -rte_errno;
   15135                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SET_IPV4_DSCP;
   15136                 :          0 :                         break;
   15137                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_IPV6_DSCP:
   15138         [ #  # ]:          0 :                         if (mlx5_dv_modify_ipv6_traffic_class_supported(priv))
   15139                 :            :                                 ipv6_tc_off = MLX5_IPV6_HDR_DSCP_SHIFT;
   15140                 :            :                         else
   15141                 :            :                                 ipv6_tc_off = 0;
   15142         [ #  # ]:          0 :                         if (flow_dv_convert_action_modify_ipv6_dscp(mhdr_res,
   15143                 :            :                                                               actions, ipv6_tc_off, error))
   15144                 :          0 :                                 return -rte_errno;
   15145                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SET_IPV6_DSCP;
   15146                 :          0 :                         break;
   15147                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SAMPLE:
   15148                 :          0 :                         sample_act_pos = actions_n;
   15149                 :          0 :                         sample = (const struct rte_flow_action_sample *)
   15150                 :            :                                  action->conf;
   15151                 :          0 :                         actions_n++;
   15152                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SAMPLE;
   15153                 :            :                         /* put encap action into group if work with port id */
   15154         [ #  # ]:          0 :                         if ((action_flags & MLX5_FLOW_ACTION_ENCAP) &&
   15155                 :            :                             (action_flags & MLX5_FLOW_ACTION_PORT_ID))
   15156                 :          0 :                                 sample_act->action_flags |=
   15157                 :            :                                                         MLX5_FLOW_ACTION_ENCAP;
   15158                 :            :                         break;
   15159                 :          0 :                 case RTE_FLOW_ACTION_TYPE_MODIFY_FIELD:
   15160         [ #  # ]:          0 :                         if (flow_dv_convert_action_modify_field
   15161                 :            :                                         (dev, mhdr_res, actions, attr, error))
   15162                 :          0 :                                 return -rte_errno;
   15163                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_MODIFY_FIELD;
   15164                 :          0 :                         break;
   15165                 :          0 :                 case RTE_FLOW_ACTION_TYPE_CONNTRACK:
   15166                 :          0 :                         owner_idx = (uint32_t)(uintptr_t)action->conf;
   15167                 :          0 :                         ct = flow_aso_ct_get_by_idx(dev, owner_idx);
   15168         [ #  # ]:          0 :                         if (!ct)
   15169                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
   15170                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
   15171                 :            :                                                 NULL,
   15172                 :            :                                                 "Failed to get CT object.");
   15173         [ #  # ]:          0 :                         if (mlx5_aso_ct_available(priv->sh, MLX5_HW_INV_QUEUE, ct))
   15174                 :          0 :                                 return rte_flow_error_set(error, rte_errno,
   15175                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
   15176                 :            :                                                 NULL,
   15177                 :            :                                                 "CT is unavailable.");
   15178         [ #  # ]:          0 :                         if (ct->is_original)
   15179                 :          0 :                                 dev_flow->dv.actions[actions_n] =
   15180                 :          0 :                                                         ct->dr_action_orig;
   15181                 :            :                         else
   15182                 :          0 :                                 dev_flow->dv.actions[actions_n] =
   15183                 :          0 :                                                         ct->dr_action_rply;
   15184         [ #  # ]:          0 :                         if (flow->ct == 0) {
   15185                 :          0 :                                 flow->indirect_type =
   15186                 :            :                                                 MLX5_INDIRECT_ACTION_TYPE_CT;
   15187                 :          0 :                                 flow->ct = owner_idx;
   15188                 :          0 :                                 __atomic_fetch_add(&ct->refcnt, 1,
   15189                 :            :                                                    __ATOMIC_RELAXED);
   15190                 :            :                         }
   15191                 :          0 :                         actions_n++;
   15192                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_CT;
   15193                 :          0 :                         break;
   15194                 :          0 :                 case RTE_FLOW_ACTION_TYPE_END:
   15195                 :            :                         actions_end = true;
   15196         [ #  # ]:          0 :                         if (mhdr_res->actions_num) {
   15197                 :            :                                 /* create modify action if needed. */
   15198         [ #  # ]:          0 :                                 if (flow_dv_modify_hdr_resource_register
   15199                 :            :                                         (dev, mhdr_res, dev_flow, error))
   15200                 :          0 :                                         return -rte_errno;
   15201                 :          0 :                                 dev_flow->dv.actions[modify_action_position] =
   15202                 :          0 :                                         handle->dvh.modify_hdr->action;
   15203                 :            :                         }
   15204                 :            :                         /*
   15205                 :            :                          * Handle AGE and COUNT action by single HW counter
   15206                 :            :                          * when they are not shared.
   15207                 :            :                          */
   15208         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_AGE) {
   15209   [ #  #  #  # ]:          0 :                                 if ((non_shared_age && count) ||
   15210         [ #  # ]:          0 :                                     !flow_hit_aso_supported(priv, !dev_flow->dv.group)) {
   15211                 :            :                                         /* Creates age by counters. */
   15212                 :          0 :                                         cnt_act = flow_dv_prepare_counter
   15213                 :            :                                                                 (dev, dev_flow,
   15214                 :            :                                                                  flow, count,
   15215                 :            :                                                                  non_shared_age,
   15216                 :            :                                                                  error);
   15217         [ #  # ]:          0 :                                         if (!cnt_act)
   15218                 :          0 :                                                 return -rte_errno;
   15219                 :          0 :                                         dev_flow->dv.actions[age_act_pos] =
   15220                 :          0 :                                                                 cnt_act->action;
   15221                 :          0 :                                         break;
   15222                 :            :                                 }
   15223   [ #  #  #  # ]:          0 :                                 if (!flow->age && non_shared_age) {
   15224                 :          0 :                                         flow->age = flow_dv_aso_age_alloc
   15225                 :            :                                                                 (dev, error);
   15226         [ #  # ]:          0 :                                         if (!flow->age)
   15227                 :          0 :                                                 return -rte_errno;
   15228                 :          0 :                                         flow_dv_aso_age_params_init
   15229                 :            :                                                     (dev, flow->age,
   15230                 :          0 :                                                      non_shared_age->context ?
   15231                 :            :                                                      non_shared_age->context :
   15232                 :          0 :                                                      (void *)(uintptr_t)
   15233                 :          0 :                                                      (dev_flow->flow_idx),
   15234         [ #  # ]:          0 :                                                      non_shared_age->timeout);
   15235                 :            :                                 }
   15236                 :          0 :                                 age_act = flow_aso_age_get_by_idx(dev,
   15237                 :            :                                                                   flow->age);
   15238                 :          0 :                                 dev_flow->dv.actions[age_act_pos] =
   15239                 :          0 :                                                              age_act->dr_action;
   15240                 :            :                         }
   15241         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_COUNT) {
   15242                 :            :                                 /*
   15243                 :            :                                  * Create one count action, to be used
   15244                 :            :                                  * by all sub-flows.
   15245                 :            :                                  */
   15246                 :          0 :                                 cnt_act = flow_dv_prepare_counter(dev, dev_flow,
   15247                 :            :                                                                   flow, count,
   15248                 :            :                                                                   NULL, error);
   15249         [ #  # ]:          0 :                                 if (!cnt_act)
   15250                 :          0 :                                         return -rte_errno;
   15251                 :          0 :                                 dev_flow->dv.actions[actions_n++] =
   15252                 :          0 :                                                                 cnt_act->action;
   15253                 :            :                         }
   15254                 :            :                 default:
   15255                 :            :                         break;
   15256                 :            :                 }
   15257   [ #  #  #  # ]:          0 :                 if (mhdr_res->actions_num &&
   15258                 :            :                     modify_action_position == UINT32_MAX)
   15259                 :          0 :                         modify_action_position = actions_n++;
   15260                 :            :         }
   15261                 :          0 :         dev_flow->act_flags = action_flags;
   15262                 :          0 :         ret = flow_dv_translate_items_sws(dev, dev_flow, attr, items, &matcher,
   15263                 :            :                                       error);
   15264         [ #  # ]:          0 :         if (ret)
   15265                 :          0 :                 return -rte_errno;
   15266         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_RSS) {
   15267                 :          0 :                 dev_flow->symmetric_hash_function = rss_desc->symmetric_hash_function;
   15268                 :          0 :                 flow_dv_hashfields_set(dev_flow->handle->layers,
   15269                 :            :                                        rss_desc,
   15270                 :            :                                        &dev_flow->hash_fields);
   15271                 :            :         }
   15272                 :            :         /* If has RSS action in the sample action, the Sample/Mirror resource
   15273                 :            :          * should be registered after the hash filed be update.
   15274                 :            :          */
   15275         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_SAMPLE) {
   15276                 :          0 :                 ret = flow_dv_translate_action_sample(dev,
   15277                 :            :                                                       sample,
   15278                 :            :                                                       dev_flow, attr,
   15279                 :            :                                                       &num_of_dest,
   15280                 :            :                                                       sample_actions,
   15281                 :            :                                                       &sample_res,
   15282                 :            :                                                       error);
   15283         [ #  # ]:          0 :                 if (ret < 0)
   15284                 :            :                         return ret;
   15285                 :          0 :                 ret = flow_dv_create_action_sample(dev,
   15286                 :            :                                                    dev_flow,
   15287                 :            :                                                    num_of_dest,
   15288                 :            :                                                    &sample_res,
   15289                 :            :                                                    &mdest_res,
   15290                 :            :                                                    sample_actions,
   15291                 :            :                                                    action_flags,
   15292                 :            :                                                    error);
   15293         [ #  # ]:          0 :                 if (ret < 0)
   15294                 :          0 :                         return rte_flow_error_set
   15295                 :            :                                                 (error, rte_errno,
   15296                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
   15297                 :            :                                                 NULL,
   15298                 :            :                                                 "cannot create sample action");
   15299         [ #  # ]:          0 :                 if (num_of_dest > 1) {
   15300                 :          0 :                         dev_flow->dv.actions[sample_act_pos] =
   15301                 :          0 :                         dev_flow->dv.dest_array_res->action;
   15302                 :            :                 } else {
   15303                 :          0 :                         dev_flow->dv.actions[sample_act_pos] =
   15304                 :          0 :                         dev_flow->dv.sample_res->verbs_action;
   15305                 :            :                 }
   15306                 :            :         }
   15307                 :            :         /*
   15308                 :            :          * For multiple destination (sample action with ratio=1), the encap
   15309                 :            :          * action and port id action will be combined into group action.
   15310                 :            :          * So need remove the original these actions in the flow and only
   15311                 :            :          * use the sample action instead of.
   15312                 :            :          */
   15313         [ #  # ]:          0 :         if (num_of_dest > 1 &&
   15314   [ #  #  #  # ]:          0 :             (sample_act->dr_port_id_action || sample_act->dr_jump_action)) {
   15315                 :            :                 int i;
   15316                 :          0 :                 void *temp_actions[MLX5_DV_MAX_NUMBER_OF_ACTIONS] = {0};
   15317                 :            : 
   15318         [ #  # ]:          0 :                 for (i = 0; i < actions_n; i++) {
   15319         [ #  # ]:          0 :                         if ((sample_act->dr_encap_action &&
   15320                 :            :                                 sample_act->dr_encap_action ==
   15321   [ #  #  #  # ]:          0 :                                 dev_flow->dv.actions[i]) ||
   15322                 :          0 :                                 (sample_act->dr_port_id_action &&
   15323                 :            :                                 sample_act->dr_port_id_action ==
   15324         [ #  # ]:          0 :                                 dev_flow->dv.actions[i]) ||
   15325         [ #  # ]:          0 :                                 (sample_act->dr_jump_action &&
   15326                 :            :                                 sample_act->dr_jump_action ==
   15327         [ #  # ]:          0 :                                 dev_flow->dv.actions[i]))
   15328                 :          0 :                                 continue;
   15329                 :          0 :                         temp_actions[tmp_actions_n++] = dev_flow->dv.actions[i];
   15330                 :            :                 }
   15331                 :          0 :                 memcpy((void *)dev_flow->dv.actions,
   15332                 :            :                                 (void *)temp_actions,
   15333                 :            :                                 tmp_actions_n * sizeof(void *));
   15334                 :            :                 actions_n = tmp_actions_n;
   15335                 :            :         }
   15336                 :          0 :         dev_flow->dv.actions_n = actions_n;
   15337         [ #  # ]:          0 :         if (wks->skip_matcher_reg)
   15338                 :            :                 return 0;
   15339                 :            :         /* Register matcher. */
   15340                 :          0 :         matcher.crc = rte_raw_cksum((const void *)matcher.mask.buf,
   15341                 :            :                                     matcher.mask.size);
   15342                 :          0 :         matcher.priority = mlx5_get_matcher_priority(dev, attr,
   15343                 :          0 :                                                      matcher.priority,
   15344                 :          0 :                                                      dev_flow->external);
   15345                 :            :         /**
   15346                 :            :          * When creating meter drop flow in drop table, using original
   15347                 :            :          * 5-tuple match, the matcher priority should be lower than
   15348                 :            :          * mtr_id matcher.
   15349                 :            :          */
   15350         [ #  # ]:          0 :         if (attr->group == MLX5_FLOW_TABLE_LEVEL_METER &&
   15351   [ #  #  #  # ]:          0 :             dev_flow->dv.table_id == MLX5_MTR_TABLE_ID_DROP &&
   15352                 :            :             matcher.priority <= MLX5_REG_BITS)
   15353                 :          0 :                 matcher.priority += MLX5_REG_BITS;
   15354                 :            :         /* reserved field no needs to be set to 0 here. */
   15355                 :          0 :         tbl_key.is_fdb = attr->transfer;
   15356                 :          0 :         tbl_key.is_egress = attr->egress;
   15357                 :          0 :         tbl_key.level = dev_flow->dv.group;
   15358                 :          0 :         tbl_key.id = dev_flow->dv.table_id;
   15359         [ #  # ]:          0 :         if (flow_dv_matcher_register(dev, &matcher, &tbl_key, dev_flow,
   15360                 :            :                                      tunnel, attr->group, error))
   15361                 :          0 :                 return -rte_errno;
   15362                 :            :         return 0;
   15363                 :            : }
   15364                 :            : 
   15365                 :            : /**
   15366                 :            :  * Set hash RX queue by hash fields (see enum ibv_rx_hash_fields)
   15367                 :            :  * and tunnel.
   15368                 :            :  *
   15369                 :            :  * @param[in, out] action
   15370                 :            :  *   Shred RSS action holding hash RX queue objects.
   15371                 :            :  * @param[in] hash_fields
   15372                 :            :  *   Defines combination of packet fields to participate in RX hash.
   15373                 :            :  * @param[in] tunnel
   15374                 :            :  *   Tunnel type
   15375                 :            :  * @param[in] hrxq_idx
   15376                 :            :  *   Hash RX queue index to set.
   15377                 :            :  *
   15378                 :            :  * @return
   15379                 :            :  *   0 on success, otherwise negative errno value.
   15380                 :            :  */
   15381                 :            : static int
   15382                 :          0 : __flow_dv_action_rss_hrxq_set(struct mlx5_shared_action_rss *action,
   15383                 :            :                               const uint64_t hash_fields,
   15384                 :            :                               uint32_t hrxq_idx)
   15385                 :            : {
   15386                 :            :         uint32_t *hrxqs = action->hrxq;
   15387                 :            : 
   15388   [ #  #  #  #  :          0 :         switch (hash_fields & ~IBV_RX_HASH_INNER) {
          #  #  #  #  #  
                   #  # ]
   15389                 :          0 :         case MLX5_RSS_HASH_IPV4:
   15390                 :            :                 /* fall-through. */
   15391                 :            :         case MLX5_RSS_HASH_IPV4_DST_ONLY:
   15392                 :            :                 /* fall-through. */
   15393                 :            :         case MLX5_RSS_HASH_IPV4_SRC_ONLY:
   15394                 :          0 :                 hrxqs[0] = hrxq_idx;
   15395                 :          0 :                 return 0;
   15396                 :          0 :         case MLX5_RSS_HASH_IPV4_TCP:
   15397                 :            :                 /* fall-through. */
   15398                 :            :         case MLX5_RSS_HASH_IPV4_TCP_DST_ONLY:
   15399                 :            :                 /* fall-through. */
   15400                 :            :         case MLX5_RSS_HASH_IPV4_TCP_SRC_ONLY:
   15401                 :          0 :                 hrxqs[1] = hrxq_idx;
   15402                 :          0 :                 return 0;
   15403                 :          0 :         case MLX5_RSS_HASH_IPV4_UDP:
   15404                 :            :                 /* fall-through. */
   15405                 :            :         case MLX5_RSS_HASH_IPV4_UDP_DST_ONLY:
   15406                 :            :                 /* fall-through. */
   15407                 :            :         case MLX5_RSS_HASH_IPV4_UDP_SRC_ONLY:
   15408                 :          0 :                 hrxqs[2] = hrxq_idx;
   15409                 :          0 :                 return 0;
   15410                 :          0 :         case MLX5_RSS_HASH_IPV6:
   15411                 :            :                 /* fall-through. */
   15412                 :            :         case MLX5_RSS_HASH_IPV6_DST_ONLY:
   15413                 :            :                 /* fall-through. */
   15414                 :            :         case MLX5_RSS_HASH_IPV6_SRC_ONLY:
   15415                 :          0 :                 hrxqs[3] = hrxq_idx;
   15416                 :          0 :                 return 0;
   15417                 :          0 :         case MLX5_RSS_HASH_IPV6_TCP:
   15418                 :            :                 /* fall-through. */
   15419                 :            :         case MLX5_RSS_HASH_IPV6_TCP_DST_ONLY:
   15420                 :            :                 /* fall-through. */
   15421                 :            :         case MLX5_RSS_HASH_IPV6_TCP_SRC_ONLY:
   15422                 :          0 :                 hrxqs[4] = hrxq_idx;
   15423                 :          0 :                 return 0;
   15424                 :          0 :         case MLX5_RSS_HASH_IPV6_UDP:
   15425                 :            :                 /* fall-through. */
   15426                 :            :         case MLX5_RSS_HASH_IPV6_UDP_DST_ONLY:
   15427                 :            :                 /* fall-through. */
   15428                 :            :         case MLX5_RSS_HASH_IPV6_UDP_SRC_ONLY:
   15429                 :          0 :                 hrxqs[5] = hrxq_idx;
   15430                 :          0 :                 return 0;
   15431                 :          0 :         case MLX5_RSS_HASH_NONE:
   15432                 :          0 :                 hrxqs[6] = hrxq_idx;
   15433                 :          0 :                 return 0;
   15434                 :          0 :         case MLX5_RSS_HASH_IPV4_ESP:
   15435                 :          0 :                 hrxqs[7] = hrxq_idx;
   15436                 :          0 :                 return 0;
   15437                 :          0 :         case MLX5_RSS_HASH_IPV6_ESP:
   15438                 :          0 :                 hrxqs[8] = hrxq_idx;
   15439                 :          0 :                 return 0;
   15440                 :          0 :         case MLX5_RSS_HASH_ESP_SPI:
   15441                 :          0 :                 hrxqs[9] = hrxq_idx;
   15442                 :          0 :                 return 0;
   15443                 :            :         default:
   15444                 :            :                 return -1;
   15445                 :            :         }
   15446                 :            : }
   15447                 :            : 
   15448                 :            : /**
   15449                 :            :  * Look up for hash RX queue by hash fields (see enum ibv_rx_hash_fields)
   15450                 :            :  * and tunnel.
   15451                 :            :  *
   15452                 :            :  * @param[in] dev
   15453                 :            :  *   Pointer to the Ethernet device structure.
   15454                 :            :  * @param[in] idx
   15455                 :            :  *   Shared RSS action ID holding hash RX queue objects.
   15456                 :            :  * @param[in] hash_fields
   15457                 :            :  *   Defines combination of packet fields to participate in RX hash.
   15458                 :            :  * @param[in] tunnel
   15459                 :            :  *   Tunnel type
   15460                 :            :  *
   15461                 :            :  * @return
   15462                 :            :  *   Valid hash RX queue index, otherwise 0.
   15463                 :            :  */
   15464                 :            : uint32_t
   15465                 :          0 : flow_dv_action_rss_hrxq_lookup(struct rte_eth_dev *dev, uint32_t idx,
   15466                 :            :                                const uint64_t hash_fields)
   15467                 :            : {
   15468                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   15469                 :            :         struct mlx5_shared_action_rss *shared_rss =
   15470                 :          0 :             mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], idx);
   15471                 :            :         const uint32_t *hrxqs = shared_rss->hrxq;
   15472                 :            : 
   15473   [ #  #  #  #  :          0 :         switch (hash_fields & ~IBV_RX_HASH_INNER) {
          #  #  #  #  #  
                   #  # ]
   15474                 :          0 :         case MLX5_RSS_HASH_IPV4:
   15475                 :            :                 /* fall-through. */
   15476                 :            :         case MLX5_RSS_HASH_IPV4_DST_ONLY:
   15477                 :            :                 /* fall-through. */
   15478                 :            :         case MLX5_RSS_HASH_IPV4_SRC_ONLY:
   15479                 :          0 :                 return hrxqs[0];
   15480                 :          0 :         case MLX5_RSS_HASH_IPV4_TCP:
   15481                 :            :                 /* fall-through. */
   15482                 :            :         case MLX5_RSS_HASH_IPV4_TCP_DST_ONLY:
   15483                 :            :                 /* fall-through. */
   15484                 :            :         case MLX5_RSS_HASH_IPV4_TCP_SRC_ONLY:
   15485                 :          0 :                 return hrxqs[1];
   15486                 :          0 :         case MLX5_RSS_HASH_IPV4_UDP:
   15487                 :            :                 /* fall-through. */
   15488                 :            :         case MLX5_RSS_HASH_IPV4_UDP_DST_ONLY:
   15489                 :            :                 /* fall-through. */
   15490                 :            :         case MLX5_RSS_HASH_IPV4_UDP_SRC_ONLY:
   15491                 :          0 :                 return hrxqs[2];
   15492                 :          0 :         case MLX5_RSS_HASH_IPV6:
   15493                 :            :                 /* fall-through. */
   15494                 :            :         case MLX5_RSS_HASH_IPV6_DST_ONLY:
   15495                 :            :                 /* fall-through. */
   15496                 :            :         case MLX5_RSS_HASH_IPV6_SRC_ONLY:
   15497                 :          0 :                 return hrxqs[3];
   15498                 :          0 :         case MLX5_RSS_HASH_IPV6_TCP:
   15499                 :            :                 /* fall-through. */
   15500                 :            :         case MLX5_RSS_HASH_IPV6_TCP_DST_ONLY:
   15501                 :            :                 /* fall-through. */
   15502                 :            :         case MLX5_RSS_HASH_IPV6_TCP_SRC_ONLY:
   15503                 :          0 :                 return hrxqs[4];
   15504                 :          0 :         case MLX5_RSS_HASH_IPV6_UDP:
   15505                 :            :                 /* fall-through. */
   15506                 :            :         case MLX5_RSS_HASH_IPV6_UDP_DST_ONLY:
   15507                 :            :                 /* fall-through. */
   15508                 :            :         case MLX5_RSS_HASH_IPV6_UDP_SRC_ONLY:
   15509                 :          0 :                 return hrxqs[5];
   15510                 :          0 :         case MLX5_RSS_HASH_NONE:
   15511                 :          0 :                 return hrxqs[6];
   15512                 :          0 :         case MLX5_RSS_HASH_IPV4_ESP:
   15513                 :          0 :                 return hrxqs[7];
   15514                 :          0 :         case MLX5_RSS_HASH_IPV6_ESP:
   15515                 :          0 :                 return hrxqs[8];
   15516                 :          0 :         case MLX5_RSS_HASH_ESP_SPI:
   15517                 :          0 :                 return hrxqs[9];
   15518                 :            :         default:
   15519                 :            :                 return 0;
   15520                 :            :         }
   15521                 :            : 
   15522                 :            : }
   15523                 :            : 
   15524                 :            : /**
   15525                 :            :  * Apply the flow to the NIC, lock free,
   15526                 :            :  * (mutex should be acquired by caller).
   15527                 :            :  *
   15528                 :            :  * @param[in] dev
   15529                 :            :  *   Pointer to the Ethernet device structure.
   15530                 :            :  * @param[in, out] flow
   15531                 :            :  *   Pointer to flow structure.
   15532                 :            :  * @param[out] error
   15533                 :            :  *   Pointer to error structure.
   15534                 :            :  *
   15535                 :            :  * @return
   15536                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   15537                 :            :  */
   15538                 :            : static int
   15539                 :          0 : flow_dv_apply(struct rte_eth_dev *dev, struct rte_flow *flow,
   15540                 :            :               struct rte_flow_error *error)
   15541                 :            : {
   15542                 :            :         struct mlx5_flow_dv_workspace *dv;
   15543                 :            :         struct mlx5_flow_handle *dh;
   15544                 :            :         struct mlx5_flow_handle_dv *dv_h;
   15545                 :            :         struct mlx5_flow *dev_flow;
   15546                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   15547                 :            :         uint32_t handle_idx;
   15548                 :            :         int n;
   15549                 :            :         int err;
   15550                 :            :         int idx;
   15551                 :          0 :         struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace();
   15552                 :          0 :         struct mlx5_flow_rss_desc *rss_desc = &wks->rss_desc;
   15553                 :            :         uint8_t misc_mask;
   15554                 :            : 
   15555                 :            :         MLX5_ASSERT(wks);
   15556         [ #  # ]:          0 :         for (idx = wks->flow_idx - 1; idx >= 0; idx--) {
   15557                 :          0 :                 dev_flow = &wks->flows[idx];
   15558                 :            :                 dv = &dev_flow->dv;
   15559                 :          0 :                 dh = dev_flow->handle;
   15560                 :            :                 dv_h = &dh->dvh;
   15561                 :          0 :                 n = dv->actions_n;
   15562         [ #  # ]:          0 :                 if (dh->fate_action == MLX5_FLOW_FATE_DROP) {
   15563         [ #  # ]:          0 :                         if (dv->transfer) {
   15564                 :            :                                 MLX5_ASSERT(priv->sh->dr_drop_action);
   15565                 :          0 :                                 dv->actions[n++] = priv->sh->dr_drop_action;
   15566                 :            :                         } else {
   15567                 :            : #ifdef HAVE_MLX5DV_DR
   15568                 :            :                                 /* DR supports drop action placeholder. */
   15569                 :            :                                 MLX5_ASSERT(priv->sh->dr_drop_action);
   15570                 :          0 :                                 dv->actions[n++] = dv->group ?
   15571         [ #  # ]:          0 :                                         priv->sh->dr_drop_action :
   15572                 :            :                                         priv->root_drop_action;
   15573                 :            : #else
   15574                 :            :                                 /* For DV we use the explicit drop queue. */
   15575                 :            :                                 MLX5_ASSERT(priv->drop_queue.hrxq);
   15576                 :            :                                 dv->actions[n++] =
   15577                 :            :                                                 priv->drop_queue.hrxq->action;
   15578                 :            : #endif
   15579                 :            :                         }
   15580         [ #  # ]:          0 :                 } else if ((dh->fate_action == MLX5_FLOW_FATE_QUEUE &&
   15581   [ #  #  #  # ]:          0 :                            !dv_h->rix_sample && !dv_h->rix_dest_array)) {
   15582                 :            :                         struct mlx5_hrxq *hrxq;
   15583                 :            :                         uint32_t hrxq_idx;
   15584                 :            : 
   15585                 :          0 :                         hrxq = flow_dv_hrxq_prepare(dev, dev_flow, rss_desc,
   15586                 :            :                                                     &hrxq_idx);
   15587         [ #  # ]:          0 :                         if (!hrxq) {
   15588                 :          0 :                                 rte_flow_error_set
   15589                 :            :                                         (error, rte_errno,
   15590                 :            :                                          RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   15591                 :            :                                          "cannot get hash queue");
   15592                 :          0 :                                 goto error;
   15593                 :            :                         }
   15594                 :          0 :                         dh->rix_hrxq = hrxq_idx;
   15595                 :          0 :                         dv->actions[n++] = hrxq->action;
   15596         [ #  # ]:          0 :                 } else if (dh->fate_action == MLX5_FLOW_FATE_SHARED_RSS) {
   15597                 :            :                         struct mlx5_hrxq *hrxq = NULL;
   15598                 :            :                         uint32_t hrxq_idx;
   15599                 :            : 
   15600                 :          0 :                         hrxq_idx = flow_dv_action_rss_hrxq_lookup(dev,
   15601                 :            :                                                 rss_desc->shared_rss,
   15602                 :            :                                                 dev_flow->hash_fields);
   15603         [ #  # ]:          0 :                         if (hrxq_idx)
   15604                 :          0 :                                 hrxq = mlx5_ipool_get
   15605                 :          0 :                                         (priv->sh->ipool[MLX5_IPOOL_HRXQ],
   15606                 :            :                                          hrxq_idx);
   15607         [ #  # ]:          0 :                         if (!hrxq) {
   15608                 :          0 :                                 rte_flow_error_set
   15609                 :            :                                         (error, rte_errno,
   15610                 :            :                                          RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   15611                 :            :                                          "cannot get hash queue");
   15612                 :          0 :                                 goto error;
   15613                 :            :                         }
   15614                 :          0 :                         dh->rix_srss = rss_desc->shared_rss;
   15615                 :          0 :                         dv->actions[n++] = hrxq->action;
   15616         [ #  # ]:          0 :                 } else if (dh->fate_action == MLX5_FLOW_FATE_DEFAULT_MISS) {
   15617         [ #  # ]:          0 :                         if (!priv->sh->default_miss_action) {
   15618                 :          0 :                                 rte_flow_error_set
   15619                 :            :                                         (error, rte_errno,
   15620                 :            :                                          RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   15621                 :            :                                          "default miss action not be created.");
   15622                 :          0 :                                 goto error;
   15623                 :            :                         }
   15624                 :          0 :                         dv->actions[n++] = priv->sh->default_miss_action;
   15625                 :            :                 }
   15626         [ #  # ]:          0 :                 misc_mask = flow_dv_matcher_enable(dv_h->matcher->mask.buf);
   15627                 :            :                 __flow_dv_adjust_buf_size(&dv->value.size, misc_mask);
   15628                 :          0 :                 err = mlx5_flow_os_create_flow(dv_h->matcher->matcher_object,
   15629                 :          0 :                                                (void *)&dv->value, n,
   15630                 :          0 :                                                dv->actions, &dh->drv_flow);
   15631                 :            :                 if (err) {
   15632                 :          0 :                         rte_flow_error_set
   15633                 :          0 :                                 (error, errno,
   15634                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   15635                 :            :                                 NULL,
   15636         [ #  # ]:          0 :                                 (!priv->sh->config.allow_duplicate_pattern &&
   15637         [ #  # ]:          0 :                                 errno == EEXIST) ?
   15638                 :            :                                 "duplicating pattern is not allowed" :
   15639                 :            :                                 "hardware refuses to create flow");
   15640                 :          0 :                         goto error;
   15641                 :            :                 }
   15642         [ #  # ]:          0 :                 if (priv->vmwa_context &&
   15643   [ #  #  #  # ]:          0 :                     dh->vf_vlan.tag && !dh->vf_vlan.created) {
   15644                 :            :                         /*
   15645                 :            :                          * The rule contains the VLAN pattern.
   15646                 :            :                          * For VF we are going to create VLAN
   15647                 :            :                          * interface to make hypervisor set correct
   15648                 :            :                          * e-Switch vport context.
   15649                 :            :                          */
   15650                 :          0 :                         mlx5_vlan_vmwa_acquire(dev, &dh->vf_vlan);
   15651                 :            :                 }
   15652                 :            :         }
   15653                 :            :         return 0;
   15654                 :          0 : error:
   15655                 :          0 :         err = rte_errno; /* Save rte_errno before cleanup. */
   15656   [ #  #  #  #  :          0 :         SILIST_FOREACH(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW], flow->dev_handles,
                   #  # ]
   15657                 :            :                        handle_idx, dh, next) {
   15658                 :            :                 /* hrxq is union, don't clear it if the flag is not set. */
   15659   [ #  #  #  # ]:          0 :                 if (dh->fate_action == MLX5_FLOW_FATE_QUEUE && dh->rix_hrxq) {
   15660                 :          0 :                         mlx5_hrxq_release(dev, dh->rix_hrxq);
   15661                 :          0 :                         dh->rix_hrxq = 0;
   15662         [ #  # ]:          0 :                 } else if (dh->fate_action == MLX5_FLOW_FATE_SHARED_RSS) {
   15663                 :          0 :                         dh->rix_srss = 0;
   15664                 :            :                 }
   15665   [ #  #  #  # ]:          0 :                 if (dh->vf_vlan.tag && dh->vf_vlan.created)
   15666                 :          0 :                         mlx5_vlan_vmwa_release(dev, &dh->vf_vlan);
   15667                 :            :         }
   15668                 :          0 :         rte_errno = err; /* Restore rte_errno. */
   15669                 :          0 :         return -rte_errno;
   15670                 :            : }
   15671                 :            : 
   15672                 :            : void
   15673                 :          0 : flow_dv_matcher_remove_cb(void *tool_ctx __rte_unused,
   15674                 :            :                           struct mlx5_list_entry *entry)
   15675                 :            : {
   15676                 :            :         struct mlx5_flow_dv_matcher *resource = container_of(entry,
   15677                 :            :                                                              typeof(*resource),
   15678                 :            :                                                              entry);
   15679                 :            : 
   15680                 :          0 :         claim_zero(mlx5_flow_os_destroy_flow_matcher(resource->matcher_object));
   15681                 :          0 :         mlx5_free(resource);
   15682                 :          0 : }
   15683                 :            : 
   15684                 :            : /**
   15685                 :            :  * Release the flow matcher.
   15686                 :            :  *
   15687                 :            :  * @param dev
   15688                 :            :  *   Pointer to Ethernet device.
   15689                 :            :  * @param port_id
   15690                 :            :  *   Index to port ID action resource.
   15691                 :            :  *
   15692                 :            :  * @return
   15693                 :            :  *   1 while a reference on it exists, 0 when freed.
   15694                 :            :  */
   15695                 :            : static int
   15696                 :          0 : flow_dv_matcher_release(struct rte_eth_dev *dev,
   15697                 :            :                         struct mlx5_flow_handle *handle)
   15698                 :            : {
   15699                 :          0 :         struct mlx5_flow_dv_matcher *matcher = handle->dvh.matcher;
   15700                 :          0 :         struct mlx5_flow_tbl_data_entry *tbl = container_of(matcher->tbl,
   15701                 :            :                                                             typeof(*tbl), tbl);
   15702                 :            :         int ret;
   15703                 :            : 
   15704                 :            :         MLX5_ASSERT(matcher->matcher_object);
   15705                 :          0 :         ret = mlx5_list_unregister(tbl->matchers, &matcher->entry);
   15706                 :          0 :         flow_dv_tbl_resource_release(MLX5_SH(dev), &tbl->tbl);
   15707                 :          0 :         return ret;
   15708                 :            : }
   15709                 :            : 
   15710                 :            : void
   15711                 :          0 : flow_dv_encap_decap_remove_cb(void *tool_ctx, struct mlx5_list_entry *entry)
   15712                 :            : {
   15713                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   15714                 :            :         struct mlx5_flow_dv_encap_decap_resource *res =
   15715                 :            :                                        container_of(entry, typeof(*res), entry);
   15716                 :            : 
   15717                 :          0 :         claim_zero(mlx5_flow_os_destroy_flow_action(res->action));
   15718                 :          0 :         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_DECAP_ENCAP], res->idx);
   15719                 :          0 : }
   15720                 :            : 
   15721                 :            : /**
   15722                 :            :  * Release an encap/decap resource.
   15723                 :            :  *
   15724                 :            :  * @param dev
   15725                 :            :  *   Pointer to Ethernet device.
   15726                 :            :  * @param encap_decap_idx
   15727                 :            :  *   Index of encap decap resource.
   15728                 :            :  *
   15729                 :            :  * @return
   15730                 :            :  *   1 while a reference on it exists, 0 when freed.
   15731                 :            :  */
   15732                 :            : static int
   15733                 :          0 : flow_dv_encap_decap_resource_release(struct rte_eth_dev *dev,
   15734                 :            :                                      uint32_t encap_decap_idx)
   15735                 :            : {
   15736                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   15737                 :            :         struct mlx5_flow_dv_encap_decap_resource *resource;
   15738                 :            : 
   15739                 :          0 :         resource = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_DECAP_ENCAP],
   15740                 :            :                                   encap_decap_idx);
   15741         [ #  # ]:          0 :         if (!resource)
   15742                 :            :                 return 0;
   15743                 :            :         MLX5_ASSERT(resource->action);
   15744                 :          0 :         return mlx5_hlist_unregister(priv->sh->encaps_decaps, &resource->entry);
   15745                 :            : }
   15746                 :            : 
   15747                 :            : /**
   15748                 :            :  * Release an jump to table action resource.
   15749                 :            :  *
   15750                 :            :  * @param dev
   15751                 :            :  *   Pointer to Ethernet device.
   15752                 :            :  * @param rix_jump
   15753                 :            :  *   Index to the jump action resource.
   15754                 :            :  *
   15755                 :            :  * @return
   15756                 :            :  *   1 while a reference on it exists, 0 when freed.
   15757                 :            :  */
   15758                 :            : static int
   15759                 :          0 : flow_dv_jump_tbl_resource_release(struct rte_eth_dev *dev,
   15760                 :            :                                   uint32_t rix_jump)
   15761                 :            : {
   15762                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   15763                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data;
   15764                 :            : 
   15765                 :          0 :         tbl_data = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_JUMP],
   15766                 :            :                                   rix_jump);
   15767         [ #  # ]:          0 :         if (!tbl_data)
   15768                 :            :                 return 0;
   15769                 :          0 :         return flow_dv_tbl_resource_release(MLX5_SH(dev), &tbl_data->tbl);
   15770                 :            : }
   15771                 :            : 
   15772                 :            : void
   15773                 :          0 : flow_dv_modify_remove_cb(void *tool_ctx, struct mlx5_list_entry *entry)
   15774                 :            : {
   15775                 :            :         struct mlx5_flow_dv_modify_hdr_resource *res =
   15776                 :            :                 container_of(entry, typeof(*res), entry);
   15777                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   15778                 :            : 
   15779                 :          0 :         claim_zero(mlx5_flow_os_destroy_flow_action(res->action));
   15780                 :          0 :         mlx5_ipool_free(sh->mdh_ipools[res->actions_num - 1], res->idx);
   15781                 :          0 : }
   15782                 :            : 
   15783                 :            : /**
   15784                 :            :  * Release a modify-header resource.
   15785                 :            :  *
   15786                 :            :  * @param dev
   15787                 :            :  *   Pointer to Ethernet device.
   15788                 :            :  * @param handle
   15789                 :            :  *   Pointer to mlx5_flow_handle.
   15790                 :            :  *
   15791                 :            :  * @return
   15792                 :            :  *   1 while a reference on it exists, 0 when freed.
   15793                 :            :  */
   15794                 :            : static int
   15795                 :            : flow_dv_modify_hdr_resource_release(struct rte_eth_dev *dev,
   15796                 :            :                                     struct mlx5_flow_handle *handle)
   15797                 :            : {
   15798                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   15799                 :            :         struct mlx5_flow_dv_modify_hdr_resource *entry = handle->dvh.modify_hdr;
   15800                 :            : 
   15801                 :            :         MLX5_ASSERT(entry->action);
   15802                 :          0 :         return mlx5_hlist_unregister(priv->sh->modify_cmds, &entry->entry);
   15803                 :            : }
   15804                 :            : 
   15805                 :            : void
   15806                 :          0 : flow_dv_port_id_remove_cb(void *tool_ctx, struct mlx5_list_entry *entry)
   15807                 :            : {
   15808                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   15809                 :            :         struct mlx5_flow_dv_port_id_action_resource *resource =
   15810                 :            :                                   container_of(entry, typeof(*resource), entry);
   15811                 :            : 
   15812                 :          0 :         claim_zero(mlx5_flow_os_destroy_flow_action(resource->action));
   15813                 :          0 :         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_PORT_ID], resource->idx);
   15814                 :          0 : }
   15815                 :            : 
   15816                 :            : /**
   15817                 :            :  * Release port ID action resource.
   15818                 :            :  *
   15819                 :            :  * @param dev
   15820                 :            :  *   Pointer to Ethernet device.
   15821                 :            :  * @param handle
   15822                 :            :  *   Pointer to mlx5_flow_handle.
   15823                 :            :  *
   15824                 :            :  * @return
   15825                 :            :  *   1 while a reference on it exists, 0 when freed.
   15826                 :            :  */
   15827                 :            : static int
   15828                 :          0 : flow_dv_port_id_action_resource_release(struct rte_eth_dev *dev,
   15829                 :            :                                         uint32_t port_id)
   15830                 :            : {
   15831                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   15832                 :            :         struct mlx5_flow_dv_port_id_action_resource *resource;
   15833                 :            : 
   15834                 :          0 :         resource = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_PORT_ID], port_id);
   15835         [ #  # ]:          0 :         if (!resource)
   15836                 :            :                 return 0;
   15837                 :            :         MLX5_ASSERT(resource->action);
   15838                 :          0 :         return mlx5_list_unregister(priv->sh->port_id_action_list,
   15839                 :            :                                     &resource->entry);
   15840                 :            : }
   15841                 :            : 
   15842                 :            : /**
   15843                 :            :  * Release shared RSS action resource.
   15844                 :            :  *
   15845                 :            :  * @param dev
   15846                 :            :  *   Pointer to Ethernet device.
   15847                 :            :  * @param srss
   15848                 :            :  *   Shared RSS action index.
   15849                 :            :  */
   15850                 :            : static void
   15851                 :          0 : flow_dv_shared_rss_action_release(struct rte_eth_dev *dev, uint32_t srss)
   15852                 :            : {
   15853                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   15854                 :            :         struct mlx5_shared_action_rss *shared_rss;
   15855                 :            : 
   15856                 :          0 :         shared_rss = mlx5_ipool_get
   15857                 :          0 :                         (priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], srss);
   15858                 :          0 :         __atomic_fetch_sub(&shared_rss->refcnt, 1, __ATOMIC_RELAXED);
   15859                 :          0 : }
   15860                 :            : 
   15861                 :            : void
   15862                 :          0 : flow_dv_push_vlan_remove_cb(void *tool_ctx, struct mlx5_list_entry *entry)
   15863                 :            : {
   15864                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   15865                 :            :         struct mlx5_flow_dv_push_vlan_action_resource *resource =
   15866                 :            :                         container_of(entry, typeof(*resource), entry);
   15867                 :            : 
   15868                 :          0 :         claim_zero(mlx5_flow_os_destroy_flow_action(resource->action));
   15869                 :          0 :         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_PUSH_VLAN], resource->idx);
   15870                 :          0 : }
   15871                 :            : 
   15872                 :            : /**
   15873                 :            :  * Release push vlan action resource.
   15874                 :            :  *
   15875                 :            :  * @param dev
   15876                 :            :  *   Pointer to Ethernet device.
   15877                 :            :  * @param handle
   15878                 :            :  *   Pointer to mlx5_flow_handle.
   15879                 :            :  *
   15880                 :            :  * @return
   15881                 :            :  *   1 while a reference on it exists, 0 when freed.
   15882                 :            :  */
   15883                 :            : static int
   15884                 :          0 : flow_dv_push_vlan_action_resource_release(struct rte_eth_dev *dev,
   15885                 :            :                                           struct mlx5_flow_handle *handle)
   15886                 :            : {
   15887                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   15888                 :            :         struct mlx5_flow_dv_push_vlan_action_resource *resource;
   15889                 :          0 :         uint32_t idx = handle->dvh.rix_push_vlan;
   15890                 :            : 
   15891                 :          0 :         resource = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_PUSH_VLAN], idx);
   15892         [ #  # ]:          0 :         if (!resource)
   15893                 :            :                 return 0;
   15894                 :            :         MLX5_ASSERT(resource->action);
   15895                 :          0 :         return mlx5_list_unregister(priv->sh->push_vlan_action_list,
   15896                 :            :                                     &resource->entry);
   15897                 :            : }
   15898                 :            : 
   15899                 :            : /**
   15900                 :            :  * Release the fate resource.
   15901                 :            :  *
   15902                 :            :  * @param dev
   15903                 :            :  *   Pointer to Ethernet device.
   15904                 :            :  * @param handle
   15905                 :            :  *   Pointer to mlx5_flow_handle.
   15906                 :            :  */
   15907                 :            : static void
   15908                 :          0 : flow_dv_fate_resource_release(struct rte_eth_dev *dev,
   15909                 :            :                                struct mlx5_flow_handle *handle)
   15910                 :            : {
   15911         [ #  # ]:          0 :         if (!handle->rix_fate)
   15912                 :            :                 return;
   15913   [ #  #  #  #  :          0 :         switch (handle->fate_action) {
                      # ]
   15914                 :          0 :         case MLX5_FLOW_FATE_QUEUE:
   15915   [ #  #  #  # ]:          0 :                 if (!handle->dvh.rix_sample && !handle->dvh.rix_dest_array)
   15916                 :          0 :                         mlx5_hrxq_release(dev, handle->rix_hrxq);
   15917                 :            :                 break;
   15918                 :          0 :         case MLX5_FLOW_FATE_JUMP:
   15919                 :          0 :                 flow_dv_jump_tbl_resource_release(dev, handle->rix_jump);
   15920                 :          0 :                 break;
   15921                 :          0 :         case MLX5_FLOW_FATE_PORT_ID:
   15922                 :          0 :                 flow_dv_port_id_action_resource_release(dev,
   15923                 :            :                                 handle->rix_port_id_action);
   15924                 :          0 :                 break;
   15925                 :            :         case MLX5_FLOW_FATE_SEND_TO_KERNEL:
   15926                 :            :                 /* In case of send_to_kernel action the actual release of
   15927                 :            :                  * resource is done when all shared DR resources are released
   15928                 :            :                  * since this resource is created once and always reused.
   15929                 :            :                  */
   15930                 :            :                 break;
   15931                 :          0 :         default:
   15932                 :          0 :                 DRV_LOG(DEBUG, "Incorrect fate action:%d", handle->fate_action);
   15933                 :          0 :                 break;
   15934                 :            :         }
   15935                 :          0 :         handle->rix_fate = 0;
   15936                 :            : }
   15937                 :            : 
   15938                 :            : void
   15939                 :          0 : flow_dv_sample_remove_cb(void *tool_ctx __rte_unused,
   15940                 :            :                          struct mlx5_list_entry *entry)
   15941                 :            : {
   15942                 :            :         struct mlx5_flow_dv_sample_resource *resource = container_of(entry,
   15943                 :            :                                                               typeof(*resource),
   15944                 :            :                                                               entry);
   15945                 :          0 :         struct rte_eth_dev *dev = resource->dev;
   15946                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   15947                 :            : 
   15948         [ #  # ]:          0 :         if (resource->verbs_action)
   15949                 :            :                 claim_zero(mlx5_flow_os_destroy_flow_action
   15950                 :            :                                                       (resource->verbs_action));
   15951         [ #  # ]:          0 :         if (resource->normal_path_tbl)
   15952                 :          0 :                 flow_dv_tbl_resource_release(MLX5_SH(dev),
   15953                 :            :                                              resource->normal_path_tbl);
   15954                 :          0 :         flow_dv_sample_sub_actions_release(dev, &resource->sample_idx);
   15955                 :          0 :         mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_SAMPLE], resource->idx);
   15956                 :          0 :         DRV_LOG(DEBUG, "sample resource %p: removed", (void *)resource);
   15957                 :          0 : }
   15958                 :            : 
   15959                 :            : /**
   15960                 :            :  * Release an sample resource.
   15961                 :            :  *
   15962                 :            :  * @param dev
   15963                 :            :  *   Pointer to Ethernet device.
   15964                 :            :  * @param handle
   15965                 :            :  *   Pointer to mlx5_flow_handle.
   15966                 :            :  *
   15967                 :            :  * @return
   15968                 :            :  *   1 while a reference on it exists, 0 when freed.
   15969                 :            :  */
   15970                 :            : static int
   15971                 :          0 : flow_dv_sample_resource_release(struct rte_eth_dev *dev,
   15972                 :            :                                      struct mlx5_flow_handle *handle)
   15973                 :            : {
   15974                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   15975                 :            :         struct mlx5_flow_dv_sample_resource *resource;
   15976                 :            : 
   15977                 :          0 :         resource = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_SAMPLE],
   15978                 :            :                                   handle->dvh.rix_sample);
   15979         [ #  # ]:          0 :         if (!resource)
   15980                 :            :                 return 0;
   15981                 :            :         MLX5_ASSERT(resource->verbs_action);
   15982                 :          0 :         return mlx5_list_unregister(priv->sh->sample_action_list,
   15983                 :            :                                     &resource->entry);
   15984                 :            : }
   15985                 :            : 
   15986                 :            : void
   15987                 :          0 : flow_dv_dest_array_remove_cb(void *tool_ctx __rte_unused,
   15988                 :            :                              struct mlx5_list_entry *entry)
   15989                 :            : {
   15990                 :            :         struct mlx5_flow_dv_dest_array_resource *resource =
   15991                 :            :                         container_of(entry, typeof(*resource), entry);
   15992                 :          0 :         struct rte_eth_dev *dev = resource->dev;
   15993                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   15994                 :            :         uint32_t i = 0;
   15995                 :            : 
   15996                 :            :         MLX5_ASSERT(resource->action);
   15997         [ #  # ]:          0 :         if (resource->action)
   15998                 :            :                 claim_zero(mlx5_flow_os_destroy_flow_action(resource->action));
   15999         [ #  # ]:          0 :         for (; i < resource->num_of_dest; i++)
   16000                 :          0 :                 flow_dv_sample_sub_actions_release(dev,
   16001                 :            :                                                    &resource->sample_idx[i]);
   16002                 :          0 :         mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_DEST_ARRAY], resource->idx);
   16003                 :          0 :         DRV_LOG(DEBUG, "destination array resource %p: removed",
   16004                 :            :                 (void *)resource);
   16005                 :          0 : }
   16006                 :            : 
   16007                 :            : /**
   16008                 :            :  * Release an destination array resource.
   16009                 :            :  *
   16010                 :            :  * @param dev
   16011                 :            :  *   Pointer to Ethernet device.
   16012                 :            :  * @param handle
   16013                 :            :  *   Pointer to mlx5_flow_handle.
   16014                 :            :  *
   16015                 :            :  * @return
   16016                 :            :  *   1 while a reference on it exists, 0 when freed.
   16017                 :            :  */
   16018                 :            : static int
   16019                 :          0 : flow_dv_dest_array_resource_release(struct rte_eth_dev *dev,
   16020                 :            :                                     struct mlx5_flow_handle *handle)
   16021                 :            : {
   16022                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16023                 :            :         struct mlx5_flow_dv_dest_array_resource *resource;
   16024                 :            : 
   16025                 :          0 :         resource = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_DEST_ARRAY],
   16026                 :            :                                   handle->dvh.rix_dest_array);
   16027         [ #  # ]:          0 :         if (!resource)
   16028                 :            :                 return 0;
   16029                 :            :         MLX5_ASSERT(resource->action);
   16030                 :          0 :         return mlx5_list_unregister(priv->sh->dest_array_list,
   16031                 :            :                                     &resource->entry);
   16032                 :            : }
   16033                 :            : 
   16034                 :            : static void
   16035                 :          0 : flow_dev_geneve_tlv_option_resource_release(struct mlx5_dev_ctx_shared *sh)
   16036                 :            : {
   16037                 :          0 :         struct mlx5_geneve_tlv_option_resource *geneve_opt_resource =
   16038                 :            :                                 sh->geneve_tlv_option_resource;
   16039                 :          0 :         rte_spinlock_lock(&sh->geneve_tlv_opt_sl);
   16040         [ #  # ]:          0 :         if (geneve_opt_resource) {
   16041         [ #  # ]:          0 :                 if (!(__atomic_fetch_sub(&geneve_opt_resource->refcnt, 1,
   16042                 :            :                                          __ATOMIC_RELAXED) - 1)) {
   16043                 :          0 :                         claim_zero(mlx5_devx_cmd_destroy
   16044                 :            :                                         (geneve_opt_resource->obj));
   16045                 :          0 :                         mlx5_free(sh->geneve_tlv_option_resource);
   16046                 :          0 :                         sh->geneve_tlv_option_resource = NULL;
   16047                 :            :                 }
   16048                 :            :         }
   16049                 :            :         rte_spinlock_unlock(&sh->geneve_tlv_opt_sl);
   16050                 :          0 : }
   16051                 :            : 
   16052                 :            : /**
   16053                 :            :  * Remove the flow from the NIC but keeps it in memory.
   16054                 :            :  * Lock free, (mutex should be acquired by caller).
   16055                 :            :  *
   16056                 :            :  * @param[in] dev
   16057                 :            :  *   Pointer to Ethernet device.
   16058                 :            :  * @param[in, out] flow
   16059                 :            :  *   Pointer to flow structure.
   16060                 :            :  */
   16061                 :            : static void
   16062                 :          0 : flow_dv_remove(struct rte_eth_dev *dev, struct rte_flow *flow)
   16063                 :            : {
   16064                 :            :         struct mlx5_flow_handle *dh;
   16065                 :            :         uint32_t handle_idx;
   16066                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16067                 :            : 
   16068         [ #  # ]:          0 :         if (!flow)
   16069                 :            :                 return;
   16070                 :          0 :         handle_idx = flow->dev_handles;
   16071         [ #  # ]:          0 :         while (handle_idx) {
   16072                 :          0 :                 dh = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW],
   16073                 :            :                                     handle_idx);
   16074         [ #  # ]:          0 :                 if (!dh)
   16075                 :            :                         return;
   16076         [ #  # ]:          0 :                 if (dh->drv_flow) {
   16077                 :            :                         claim_zero(mlx5_flow_os_destroy_flow(dh->drv_flow));
   16078                 :          0 :                         dh->drv_flow = NULL;
   16079                 :            :                 }
   16080         [ #  # ]:          0 :                 if (dh->fate_action == MLX5_FLOW_FATE_QUEUE)
   16081                 :          0 :                         flow_dv_fate_resource_release(dev, dh);
   16082   [ #  #  #  # ]:          0 :                 if (dh->vf_vlan.tag && dh->vf_vlan.created)
   16083                 :          0 :                         mlx5_vlan_vmwa_release(dev, &dh->vf_vlan);
   16084                 :          0 :                 handle_idx = dh->next.next;
   16085                 :            :         }
   16086                 :            : }
   16087                 :            : 
   16088                 :            : /**
   16089                 :            :  * Remove the flow from the NIC and the memory.
   16090                 :            :  * Lock free, (mutex should be acquired by caller).
   16091                 :            :  *
   16092                 :            :  * @param[in] dev
   16093                 :            :  *   Pointer to the Ethernet device structure.
   16094                 :            :  * @param[in, out] flow
   16095                 :            :  *   Pointer to flow structure.
   16096                 :            :  */
   16097                 :            : static void
   16098                 :          0 : flow_dv_destroy(struct rte_eth_dev *dev, struct rte_flow *flow)
   16099                 :            : {
   16100                 :            :         struct mlx5_flow_handle *dev_handle;
   16101                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16102                 :            :         struct mlx5_flow_meter_info *fm = NULL;
   16103                 :            :         uint32_t srss = 0;
   16104                 :            : 
   16105         [ #  # ]:          0 :         if (!flow)
   16106                 :            :                 return;
   16107                 :          0 :         flow_dv_remove(dev, flow);
   16108         [ #  # ]:          0 :         if (flow->counter) {
   16109                 :          0 :                 flow_dv_counter_free(dev, flow->counter);
   16110                 :          0 :                 flow->counter = 0;
   16111                 :            :         }
   16112         [ #  # ]:          0 :         if (flow->meter) {
   16113                 :          0 :                 fm = flow_dv_meter_find_by_idx(priv, flow->meter);
   16114         [ #  # ]:          0 :                 if (fm)
   16115                 :          0 :                         mlx5_flow_meter_detach(priv, fm);
   16116                 :          0 :                 flow->meter = 0;
   16117                 :            :         }
   16118                 :            :         /* Keep the current age handling by default. */
   16119   [ #  #  #  # ]:          0 :         if (flow->indirect_type == MLX5_INDIRECT_ACTION_TYPE_CT && flow->ct)
   16120                 :          0 :                 flow_dv_aso_ct_release(dev, flow->ct, NULL);
   16121         [ #  # ]:          0 :         else if (flow->age)
   16122                 :          0 :                 flow_dv_aso_age_release(dev, flow->age);
   16123         [ #  # ]:          0 :         while (flow->geneve_tlv_option) {
   16124                 :          0 :                 flow_dev_geneve_tlv_option_resource_release(priv->sh);
   16125                 :          0 :                 flow->geneve_tlv_option--;
   16126                 :            :         }
   16127         [ #  # ]:          0 :         while (flow->dev_handles) {
   16128                 :            :                 uint32_t tmp_idx = flow->dev_handles;
   16129                 :            : 
   16130                 :          0 :                 dev_handle = mlx5_ipool_get(priv->sh->ipool
   16131                 :            :                                             [MLX5_IPOOL_MLX5_FLOW], tmp_idx);
   16132         [ #  # ]:          0 :                 if (!dev_handle)
   16133                 :            :                         return;
   16134                 :          0 :                 flow->dev_handles = dev_handle->next.next;
   16135         [ #  # ]:          0 :                 while (dev_handle->flex_item) {
   16136                 :          0 :                         int index = rte_bsf32(dev_handle->flex_item);
   16137                 :            : 
   16138                 :          0 :                         mlx5_flex_release_index(dev, index);
   16139                 :          0 :                         dev_handle->flex_item &= ~(uint8_t)RTE_BIT32(index);
   16140                 :            :                 }
   16141         [ #  # ]:          0 :                 if (dev_handle->dvh.matcher)
   16142                 :          0 :                         flow_dv_matcher_release(dev, dev_handle);
   16143         [ #  # ]:          0 :                 if (dev_handle->dvh.rix_sample)
   16144                 :          0 :                         flow_dv_sample_resource_release(dev, dev_handle);
   16145         [ #  # ]:          0 :                 if (dev_handle->dvh.rix_dest_array)
   16146                 :          0 :                         flow_dv_dest_array_resource_release(dev, dev_handle);
   16147         [ #  # ]:          0 :                 if (dev_handle->dvh.rix_encap_decap)
   16148                 :          0 :                         flow_dv_encap_decap_resource_release(dev,
   16149                 :            :                                 dev_handle->dvh.rix_encap_decap);
   16150         [ #  # ]:          0 :                 if (dev_handle->dvh.modify_hdr)
   16151                 :            :                         flow_dv_modify_hdr_resource_release(dev, dev_handle);
   16152         [ #  # ]:          0 :                 if (dev_handle->dvh.rix_push_vlan)
   16153                 :          0 :                         flow_dv_push_vlan_action_resource_release(dev,
   16154                 :            :                                                                   dev_handle);
   16155         [ #  # ]:          0 :                 if (dev_handle->dvh.rix_tag)
   16156                 :          0 :                         flow_dv_tag_release(dev,
   16157                 :            :                                             dev_handle->dvh.rix_tag);
   16158         [ #  # ]:          0 :                 if (dev_handle->fate_action != MLX5_FLOW_FATE_SHARED_RSS)
   16159                 :          0 :                         flow_dv_fate_resource_release(dev, dev_handle);
   16160         [ #  # ]:          0 :                 else if (!srss)
   16161                 :          0 :                         srss = dev_handle->rix_srss;
   16162   [ #  #  #  # ]:          0 :                 if (fm && dev_handle->is_meter_flow_id &&
   16163         [ #  # ]:          0 :                     dev_handle->split_flow_id)
   16164                 :          0 :                         mlx5_ipool_free(fm->flow_ipool,
   16165                 :            :                                         dev_handle->split_flow_id);
   16166         [ #  # ]:          0 :                 else if (dev_handle->split_flow_id &&
   16167         [ #  # ]:          0 :                     !dev_handle->is_meter_flow_id)
   16168                 :          0 :                         mlx5_ipool_free(priv->sh->ipool
   16169                 :            :                                         [MLX5_IPOOL_RSS_EXPANTION_FLOW_ID],
   16170                 :            :                                         dev_handle->split_flow_id);
   16171                 :          0 :                 mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW],
   16172                 :            :                            tmp_idx);
   16173                 :            :         }
   16174         [ #  # ]:          0 :         if (srss)
   16175                 :          0 :                 flow_dv_shared_rss_action_release(dev, srss);
   16176                 :            : }
   16177                 :            : 
   16178                 :            : /**
   16179                 :            :  * Release array of hash RX queue objects.
   16180                 :            :  * Helper function.
   16181                 :            :  *
   16182                 :            :  * @param[in] dev
   16183                 :            :  *   Pointer to the Ethernet device structure.
   16184                 :            :  * @param[in, out] hrxqs
   16185                 :            :  *   Array of hash RX queue objects.
   16186                 :            :  *
   16187                 :            :  * @return
   16188                 :            :  *   Total number of references to hash RX queue objects in *hrxqs* array
   16189                 :            :  *   after this operation.
   16190                 :            :  */
   16191                 :            : static int
   16192                 :          0 : __flow_dv_hrxqs_release(struct rte_eth_dev *dev,
   16193                 :            :                         uint32_t (*hrxqs)[MLX5_RSS_HASH_FIELDS_LEN])
   16194                 :            : {
   16195                 :            :         size_t i;
   16196                 :            :         int remaining = 0;
   16197                 :            : 
   16198         [ #  # ]:          0 :         for (i = 0; i < RTE_DIM(*hrxqs); i++) {
   16199                 :          0 :                 int ret = mlx5_hrxq_release(dev, (*hrxqs)[i]);
   16200                 :            : 
   16201         [ #  # ]:          0 :                 if (!ret)
   16202                 :          0 :                         (*hrxqs)[i] = 0;
   16203                 :          0 :                 remaining += ret;
   16204                 :            :         }
   16205                 :          0 :         return remaining;
   16206                 :            : }
   16207                 :            : 
   16208                 :            : /**
   16209                 :            :  * Release all hash RX queue objects representing shared RSS action.
   16210                 :            :  *
   16211                 :            :  * @param[in] dev
   16212                 :            :  *   Pointer to the Ethernet device structure.
   16213                 :            :  * @param[in, out] action
   16214                 :            :  *   Shared RSS action to remove hash RX queue objects from.
   16215                 :            :  *
   16216                 :            :  * @return
   16217                 :            :  *   Total number of references to hash RX queue objects stored in *action*
   16218                 :            :  *   after this operation.
   16219                 :            :  *   Expected to be 0 if no external references held.
   16220                 :            :  */
   16221                 :            : static int
   16222                 :            : __flow_dv_action_rss_hrxqs_release(struct rte_eth_dev *dev,
   16223                 :            :                                  struct mlx5_shared_action_rss *shared_rss)
   16224                 :            : {
   16225                 :          0 :         return __flow_dv_hrxqs_release(dev, &shared_rss->hrxq);
   16226                 :            : }
   16227                 :            : 
   16228                 :            : /**
   16229                 :            :  * Adjust L3/L4 hash value of pre-created shared RSS hrxq according to
   16230                 :            :  * user input.
   16231                 :            :  *
   16232                 :            :  * Only one hash value is available for one L3+L4 combination:
   16233                 :            :  * for example:
   16234                 :            :  * MLX5_RSS_HASH_IPV4, MLX5_RSS_HASH_IPV4_SRC_ONLY, and
   16235                 :            :  * MLX5_RSS_HASH_IPV4_DST_ONLY are mutually exclusive so they can share
   16236                 :            :  * same slot in mlx5_rss_hash_fields.
   16237                 :            :  *
   16238                 :            :  * @param[in] orig_rss_types
   16239                 :            :  *   RSS type as provided in shared RSS action.
   16240                 :            :  * @param[in, out] hash_field
   16241                 :            :  *   hash_field variable needed to be adjusted.
   16242                 :            :  *
   16243                 :            :  * @return
   16244                 :            :  *   void
   16245                 :            :  */
   16246                 :            : void
   16247         [ #  # ]:          0 : flow_dv_action_rss_l34_hash_adjust(uint64_t orig_rss_types,
   16248                 :            :                                    uint64_t *hash_field)
   16249                 :            : {
   16250                 :            :         uint64_t rss_types = rte_eth_rss_hf_refine(orig_rss_types);
   16251                 :            : 
   16252   [ #  #  #  #  :          0 :         switch (*hash_field & ~IBV_RX_HASH_INNER) {
                      # ]
   16253                 :          0 :         case MLX5_RSS_HASH_IPV4:
   16254         [ #  # ]:          0 :                 if (rss_types & MLX5_IPV4_LAYER_TYPES) {
   16255                 :          0 :                         *hash_field &= ~MLX5_RSS_HASH_IPV4;
   16256         [ #  # ]:          0 :                         if (rss_types & RTE_ETH_RSS_L3_DST_ONLY)
   16257                 :          0 :                                 *hash_field |= IBV_RX_HASH_DST_IPV4;
   16258         [ #  # ]:          0 :                         else if (rss_types & RTE_ETH_RSS_L3_SRC_ONLY)
   16259                 :          0 :                                 *hash_field |= IBV_RX_HASH_SRC_IPV4;
   16260                 :            :                         else
   16261                 :          0 :                                 *hash_field |= MLX5_RSS_HASH_IPV4;
   16262                 :            :                 }
   16263                 :            :                 return;
   16264                 :          0 :         case MLX5_RSS_HASH_IPV6:
   16265         [ #  # ]:          0 :                 if (rss_types & MLX5_IPV6_LAYER_TYPES) {
   16266                 :          0 :                         *hash_field &= ~MLX5_RSS_HASH_IPV6;
   16267         [ #  # ]:          0 :                         if (rss_types & RTE_ETH_RSS_L3_DST_ONLY)
   16268                 :          0 :                                 *hash_field |= IBV_RX_HASH_DST_IPV6;
   16269         [ #  # ]:          0 :                         else if (rss_types & RTE_ETH_RSS_L3_SRC_ONLY)
   16270                 :          0 :                                 *hash_field |= IBV_RX_HASH_SRC_IPV6;
   16271                 :            :                         else
   16272                 :          0 :                                 *hash_field |= MLX5_RSS_HASH_IPV6;
   16273                 :            :                 }
   16274                 :            :                 return;
   16275                 :          0 :         case MLX5_RSS_HASH_IPV4_UDP:
   16276                 :            :                 /* fall-through. */
   16277                 :            :         case MLX5_RSS_HASH_IPV6_UDP:
   16278         [ #  # ]:          0 :                 if (rss_types & RTE_ETH_RSS_UDP) {
   16279                 :          0 :                         *hash_field &= ~MLX5_UDP_IBV_RX_HASH;
   16280         [ #  # ]:          0 :                         if (rss_types & RTE_ETH_RSS_L4_DST_ONLY)
   16281                 :          0 :                                 *hash_field |= IBV_RX_HASH_DST_PORT_UDP;
   16282         [ #  # ]:          0 :                         else if (rss_types & RTE_ETH_RSS_L4_SRC_ONLY)
   16283                 :          0 :                                 *hash_field |= IBV_RX_HASH_SRC_PORT_UDP;
   16284                 :            :                         else
   16285                 :          0 :                                 *hash_field |= MLX5_UDP_IBV_RX_HASH;
   16286                 :            :                 }
   16287                 :            :                 return;
   16288                 :          0 :         case MLX5_RSS_HASH_IPV4_TCP:
   16289                 :            :                 /* fall-through. */
   16290                 :            :         case MLX5_RSS_HASH_IPV6_TCP:
   16291         [ #  # ]:          0 :                 if (rss_types & RTE_ETH_RSS_TCP) {
   16292                 :          0 :                         *hash_field &= ~MLX5_TCP_IBV_RX_HASH;
   16293         [ #  # ]:          0 :                         if (rss_types & RTE_ETH_RSS_L4_DST_ONLY)
   16294                 :          0 :                                 *hash_field |= IBV_RX_HASH_DST_PORT_TCP;
   16295         [ #  # ]:          0 :                         else if (rss_types & RTE_ETH_RSS_L4_SRC_ONLY)
   16296                 :          0 :                                 *hash_field |= IBV_RX_HASH_SRC_PORT_TCP;
   16297                 :            :                         else
   16298                 :          0 :                                 *hash_field |= MLX5_TCP_IBV_RX_HASH;
   16299                 :            :                 }
   16300                 :            :                 return;
   16301                 :            :         default:
   16302                 :            :                 return;
   16303                 :            :         }
   16304                 :            : }
   16305                 :            : 
   16306                 :            : /**
   16307                 :            :  * Setup shared RSS action.
   16308                 :            :  * Prepare set of hash RX queue objects sufficient to handle all valid
   16309                 :            :  * hash_fields combinations (see enum ibv_rx_hash_fields).
   16310                 :            :  *
   16311                 :            :  * @param[in] dev
   16312                 :            :  *   Pointer to the Ethernet device structure.
   16313                 :            :  * @param[in] action_idx
   16314                 :            :  *   Shared RSS action ipool index.
   16315                 :            :  * @param[in, out] action
   16316                 :            :  *   Partially initialized shared RSS action.
   16317                 :            :  * @param[out] error
   16318                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   16319                 :            :  *   error only.
   16320                 :            :  *
   16321                 :            :  * @return
   16322                 :            :  *   0 on success, otherwise negative errno value.
   16323                 :            :  */
   16324                 :            : static int
   16325                 :          0 : __flow_dv_action_rss_setup(struct rte_eth_dev *dev,
   16326                 :            :                            uint32_t action_idx,
   16327                 :            :                            struct mlx5_shared_action_rss *shared_rss,
   16328                 :            :                            struct rte_flow_error *error)
   16329                 :            : {
   16330                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16331                 :          0 :         struct mlx5_flow_rss_desc rss_desc = { 0 };
   16332                 :            :         size_t i;
   16333                 :            :         int err;
   16334                 :            : 
   16335                 :          0 :         shared_rss->ind_tbl = mlx5_ind_table_obj_new
   16336                 :            :                               (dev, shared_rss->origin.queue,
   16337                 :            :                                shared_rss->origin.queue_num,
   16338                 :            :                                true,
   16339                 :          0 :                                !!dev->data->dev_started);
   16340         [ #  # ]:          0 :         if (!shared_rss->ind_tbl)
   16341                 :          0 :                 return rte_flow_error_set(error, rte_errno,
   16342                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   16343                 :            :                                           "cannot setup indirection table");
   16344                 :          0 :         memcpy(rss_desc.key, shared_rss->origin.key, MLX5_RSS_HASH_KEY_LEN);
   16345                 :          0 :         rss_desc.key_len = MLX5_RSS_HASH_KEY_LEN;
   16346                 :          0 :         rss_desc.symmetric_hash_function =
   16347                 :          0 :                 MLX5_RSS_IS_SYMM(shared_rss->origin.func);
   16348                 :          0 :         rss_desc.const_q = shared_rss->origin.queue;
   16349                 :          0 :         rss_desc.queue_num = shared_rss->origin.queue_num;
   16350                 :            :         /* Set non-zero value to indicate a shared RSS. */
   16351                 :          0 :         rss_desc.shared_rss = action_idx;
   16352                 :          0 :         rss_desc.ind_tbl = shared_rss->ind_tbl;
   16353         [ #  # ]:          0 :         if (priv->sh->config.dv_flow_en == 2)
   16354                 :          0 :                 rss_desc.hws_flags = MLX5DR_ACTION_FLAG_HWS_RX;
   16355         [ #  # ]:          0 :         for (i = 0; i < MLX5_RSS_HASH_FIELDS_LEN; i++) {
   16356                 :            :                 struct mlx5_hrxq *hrxq;
   16357                 :          0 :                 uint64_t hash_fields = mlx5_rss_hash_fields[i];
   16358                 :            :                 int tunnel = 0;
   16359                 :            : 
   16360                 :          0 :                 flow_dv_action_rss_l34_hash_adjust(shared_rss->origin.types,
   16361                 :            :                                                    &hash_fields);
   16362         [ #  # ]:          0 :                 if (shared_rss->origin.level > 1) {
   16363                 :          0 :                         hash_fields |= IBV_RX_HASH_INNER;
   16364                 :            :                         tunnel = 1;
   16365                 :            :                 }
   16366                 :          0 :                 rss_desc.tunnel = tunnel;
   16367                 :          0 :                 rss_desc.hash_fields = hash_fields;
   16368                 :          0 :                 hrxq = mlx5_hrxq_get(dev, &rss_desc);
   16369         [ #  # ]:          0 :                 if (!hrxq) {
   16370                 :          0 :                         rte_flow_error_set
   16371                 :            :                                 (error, rte_errno,
   16372                 :            :                                  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   16373                 :            :                                  "cannot get hash queue");
   16374                 :          0 :                         goto error_hrxq_new;
   16375                 :            :                 }
   16376                 :          0 :                 err = __flow_dv_action_rss_hrxq_set
   16377                 :            :                         (shared_rss, hash_fields, hrxq->idx);
   16378                 :            :                 MLX5_ASSERT(!err);
   16379                 :            :         }
   16380                 :            :         return 0;
   16381                 :            : error_hrxq_new:
   16382                 :          0 :         err = rte_errno;
   16383                 :            :         __flow_dv_action_rss_hrxqs_release(dev, shared_rss);
   16384         [ #  # ]:          0 :         if (!mlx5_ind_table_obj_release(dev, shared_rss->ind_tbl, true))
   16385                 :          0 :                 shared_rss->ind_tbl = NULL;
   16386                 :          0 :         rte_errno = err;
   16387                 :          0 :         return -rte_errno;
   16388                 :            : }
   16389                 :            : 
   16390                 :            : /**
   16391                 :            :  * Create shared RSS action.
   16392                 :            :  *
   16393                 :            :  * @param[in] dev
   16394                 :            :  *   Pointer to the Ethernet device structure.
   16395                 :            :  * @param[in] conf
   16396                 :            :  *   Shared action configuration.
   16397                 :            :  * @param[in] rss
   16398                 :            :  *   RSS action specification used to create shared action.
   16399                 :            :  * @param[out] error
   16400                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   16401                 :            :  *   error only.
   16402                 :            :  *
   16403                 :            :  * @return
   16404                 :            :  *   A valid shared action ID in case of success, 0 otherwise and
   16405                 :            :  *   rte_errno is set.
   16406                 :            :  */
   16407                 :            : static uint32_t
   16408                 :          0 : __flow_dv_action_rss_create(struct rte_eth_dev *dev,
   16409                 :            :                             const struct rte_flow_indir_action_conf *conf,
   16410                 :            :                             const struct rte_flow_action_rss *rss,
   16411                 :            :                             struct rte_flow_error *error)
   16412                 :            : {
   16413                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16414                 :            :         struct mlx5_shared_action_rss *shared_rss = NULL;
   16415                 :            :         struct rte_flow_action_rss *origin;
   16416                 :            :         const uint8_t *rss_key;
   16417                 :            :         uint32_t idx;
   16418                 :            : 
   16419                 :            :         RTE_SET_USED(conf);
   16420                 :          0 :         shared_rss = mlx5_ipool_zmalloc
   16421                 :          0 :                          (priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], &idx);
   16422         [ #  # ]:          0 :         if (!shared_rss) {
   16423                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   16424                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   16425                 :            :                                    "cannot allocate resource memory");
   16426                 :          0 :                 goto error_rss_init;
   16427                 :            :         }
   16428         [ #  # ]:          0 :         if (idx > (1u << MLX5_INDIRECT_ACTION_TYPE_OFFSET)) {
   16429                 :          0 :                 rte_flow_error_set(error, E2BIG,
   16430                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   16431                 :            :                                    "rss action number out of range");
   16432                 :          0 :                 goto error_rss_init;
   16433                 :            :         }
   16434                 :            :         origin = &shared_rss->origin;
   16435                 :          0 :         origin->func = rss->func;
   16436                 :          0 :         origin->level = rss->level;
   16437                 :            :         /* RSS type 0 indicates default RSS type (RTE_ETH_RSS_IP). */
   16438         [ #  # ]:          0 :         origin->types = !rss->types ? RTE_ETH_RSS_IP : rss->types;
   16439                 :            :         /* NULL RSS key indicates default RSS key. */
   16440         [ #  # ]:          0 :         rss_key = !rss->key ? rss_hash_default_key : rss->key;
   16441                 :          0 :         memcpy(shared_rss->key, rss_key, MLX5_RSS_HASH_KEY_LEN);
   16442                 :          0 :         origin->key = &shared_rss->key[0];
   16443                 :          0 :         origin->key_len = MLX5_RSS_HASH_KEY_LEN;
   16444                 :          0 :         origin->queue = rss->queue;
   16445                 :          0 :         origin->queue_num = rss->queue_num;
   16446         [ #  # ]:          0 :         if (__flow_dv_action_rss_setup(dev, idx, shared_rss, error))
   16447                 :          0 :                 goto error_rss_init;
   16448                 :            :         /* Update queue with indirect table queue memoyr. */
   16449                 :          0 :         origin->queue = shared_rss->ind_tbl->queues;
   16450                 :            :         rte_spinlock_init(&shared_rss->action_rss_sl);
   16451                 :          0 :         __atomic_fetch_add(&shared_rss->refcnt, 1, __ATOMIC_RELAXED);
   16452                 :          0 :         rte_spinlock_lock(&priv->shared_act_sl);
   16453   [ #  #  #  # ]:          0 :         ILIST_INSERT(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS],
   16454                 :            :                      &priv->rss_shared_actions, idx, shared_rss, next);
   16455                 :            :         rte_spinlock_unlock(&priv->shared_act_sl);
   16456                 :          0 :         return idx;
   16457                 :          0 : error_rss_init:
   16458         [ #  # ]:          0 :         if (shared_rss) {
   16459         [ #  # ]:          0 :                 if (shared_rss->ind_tbl)
   16460                 :          0 :                         mlx5_ind_table_obj_release(dev, shared_rss->ind_tbl,
   16461                 :          0 :                                                    !!dev->data->dev_started);
   16462                 :          0 :                 mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS],
   16463                 :            :                                 idx);
   16464                 :            :         }
   16465                 :            :         return 0;
   16466                 :            : }
   16467                 :            : 
   16468                 :            : /**
   16469                 :            :  * Destroy the shared RSS action.
   16470                 :            :  * Release related hash RX queue objects.
   16471                 :            :  *
   16472                 :            :  * @param[in] dev
   16473                 :            :  *   Pointer to the Ethernet device structure.
   16474                 :            :  * @param[in] idx
   16475                 :            :  *   The shared RSS action object ID to be removed.
   16476                 :            :  * @param[out] error
   16477                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   16478                 :            :  *   error only.
   16479                 :            :  *
   16480                 :            :  * @return
   16481                 :            :  *   0 on success, otherwise negative errno value.
   16482                 :            :  */
   16483                 :            : static int
   16484                 :          0 : __flow_dv_action_rss_release(struct rte_eth_dev *dev, uint32_t idx,
   16485                 :            :                              struct rte_flow_error *error)
   16486                 :            : {
   16487                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16488                 :            :         struct mlx5_shared_action_rss *shared_rss =
   16489                 :          0 :             mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], idx);
   16490                 :            :         uint32_t old_refcnt = 1;
   16491                 :            :         int remaining;
   16492                 :            : 
   16493         [ #  # ]:          0 :         if (!shared_rss)
   16494                 :          0 :                 return rte_flow_error_set(error, EINVAL,
   16495                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   16496                 :            :                                           "invalid shared action");
   16497         [ #  # ]:          0 :         if (!__atomic_compare_exchange_n(&shared_rss->refcnt, &old_refcnt,
   16498                 :            :                                          0, 0, __ATOMIC_ACQUIRE,
   16499                 :            :                                          __ATOMIC_RELAXED))
   16500                 :          0 :                 return rte_flow_error_set(error, EBUSY,
   16501                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
   16502                 :            :                                           NULL,
   16503                 :            :                                           "shared rss has references");
   16504                 :            :         remaining = __flow_dv_action_rss_hrxqs_release(dev, shared_rss);
   16505         [ #  # ]:          0 :         if (remaining)
   16506                 :          0 :                 return rte_flow_error_set(error, EBUSY,
   16507                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
   16508                 :            :                                           NULL,
   16509                 :            :                                           "shared rss hrxq has references");
   16510                 :          0 :         remaining = mlx5_ind_table_obj_release(dev, shared_rss->ind_tbl,
   16511                 :          0 :                                                !!dev->data->dev_started);
   16512         [ #  # ]:          0 :         if (remaining)
   16513                 :          0 :                 return rte_flow_error_set(error, EBUSY,
   16514                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
   16515                 :            :                                           NULL,
   16516                 :            :                                           "shared rss indirection table has"
   16517                 :            :                                           " references");
   16518                 :          0 :         rte_spinlock_lock(&priv->shared_act_sl);
   16519   [ #  #  #  #  :          0 :         ILIST_REMOVE(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS],
          #  #  #  #  #  
                      # ]
   16520                 :            :                      &priv->rss_shared_actions, idx, shared_rss, next);
   16521                 :            :         rte_spinlock_unlock(&priv->shared_act_sl);
   16522                 :          0 :         mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS],
   16523                 :            :                         idx);
   16524                 :          0 :         return 0;
   16525                 :            : }
   16526                 :            : 
   16527                 :            : /**
   16528                 :            :  * Create indirect action, lock free,
   16529                 :            :  * (mutex should be acquired by caller).
   16530                 :            :  * Dispatcher for action type specific call.
   16531                 :            :  *
   16532                 :            :  * @param[in] dev
   16533                 :            :  *   Pointer to the Ethernet device structure.
   16534                 :            :  * @param[in] conf
   16535                 :            :  *   Shared action configuration.
   16536                 :            :  * @param[in] action
   16537                 :            :  *   Action specification used to create indirect action.
   16538                 :            :  * @param[out] error
   16539                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   16540                 :            :  *   error only.
   16541                 :            :  *
   16542                 :            :  * @return
   16543                 :            :  *   A valid shared action handle in case of success, NULL otherwise and
   16544                 :            :  *   rte_errno is set.
   16545                 :            :  */
   16546                 :            : struct rte_flow_action_handle *
   16547                 :          0 : flow_dv_action_create(struct rte_eth_dev *dev,
   16548                 :            :                       const struct rte_flow_indir_action_conf *conf,
   16549                 :            :                       const struct rte_flow_action *action,
   16550                 :            :                       struct rte_flow_error *err)
   16551                 :            : {
   16552                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16553                 :            :         uint32_t age_idx = 0;
   16554                 :            :         uint32_t idx = 0;
   16555                 :            :         uint32_t ret = 0;
   16556                 :            : 
   16557   [ #  #  #  #  :          0 :         switch (action->type) {
                      # ]
   16558                 :          0 :         case RTE_FLOW_ACTION_TYPE_RSS:
   16559                 :          0 :                 ret = __flow_dv_action_rss_create(dev, conf, action->conf, err);
   16560                 :            :                 idx = (MLX5_INDIRECT_ACTION_TYPE_RSS <<
   16561                 :            :                        MLX5_INDIRECT_ACTION_TYPE_OFFSET) | ret;
   16562                 :          0 :                 break;
   16563                 :          0 :         case RTE_FLOW_ACTION_TYPE_AGE:
   16564                 :          0 :                 age_idx = flow_dv_aso_age_alloc(dev, err);
   16565         [ #  # ]:          0 :                 if (!age_idx) {
   16566                 :          0 :                         ret = -rte_errno;
   16567                 :          0 :                         break;
   16568                 :            :                 }
   16569                 :          0 :                 idx = (MLX5_INDIRECT_ACTION_TYPE_AGE <<
   16570                 :            :                        MLX5_INDIRECT_ACTION_TYPE_OFFSET) | age_idx;
   16571                 :          0 :                 flow_dv_aso_age_params_init(dev, age_idx,
   16572                 :            :                                         ((const struct rte_flow_action_age *)
   16573                 :          0 :                                                 action->conf)->context ?
   16574                 :            :                                         ((const struct rte_flow_action_age *)
   16575                 :            :                                                 action->conf)->context :
   16576                 :          0 :                                         (void *)(uintptr_t)idx,
   16577                 :            :                                         ((const struct rte_flow_action_age *)
   16578         [ #  # ]:          0 :                                                 action->conf)->timeout);
   16579                 :            :                 ret = age_idx;
   16580                 :          0 :                 break;
   16581                 :          0 :         case RTE_FLOW_ACTION_TYPE_COUNT:
   16582                 :          0 :                 ret = flow_dv_translate_create_counter(dev, NULL, NULL, NULL);
   16583                 :          0 :                 idx = (MLX5_INDIRECT_ACTION_TYPE_COUNT <<
   16584                 :            :                        MLX5_INDIRECT_ACTION_TYPE_OFFSET) | ret;
   16585                 :          0 :                 break;
   16586                 :          0 :         case RTE_FLOW_ACTION_TYPE_CONNTRACK:
   16587                 :          0 :                 ret = flow_dv_translate_create_conntrack(dev, action->conf,
   16588                 :            :                                                          err);
   16589         [ #  # ]:          0 :                 if (!ret)
   16590                 :            :                         break;
   16591                 :          0 :                 idx = MLX5_INDIRECT_ACT_CT_GEN_IDX(PORT_ID(priv), ret);
   16592                 :          0 :                 break;
   16593                 :          0 :         default:
   16594                 :          0 :                 rte_flow_error_set(err, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION,
   16595                 :            :                                    NULL, "action type not supported");
   16596                 :            :                 break;
   16597                 :            :         }
   16598         [ #  # ]:          0 :         return ret ? (struct rte_flow_action_handle *)(uintptr_t)idx : NULL;
   16599                 :            : }
   16600                 :            : 
   16601                 :            : /**
   16602                 :            :  * Destroy the indirect action.
   16603                 :            :  * Release action related resources on the NIC and the memory.
   16604                 :            :  * Lock free, (mutex should be acquired by caller).
   16605                 :            :  * Dispatcher for action type specific call.
   16606                 :            :  *
   16607                 :            :  * @param[in] dev
   16608                 :            :  *   Pointer to the Ethernet device structure.
   16609                 :            :  * @param[in] handle
   16610                 :            :  *   The indirect action object handle to be removed.
   16611                 :            :  * @param[out] error
   16612                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   16613                 :            :  *   error only.
   16614                 :            :  *
   16615                 :            :  * @return
   16616                 :            :  *   0 on success, otherwise negative errno value.
   16617                 :            :  */
   16618                 :            : int
   16619                 :          0 : flow_dv_action_destroy(struct rte_eth_dev *dev,
   16620                 :            :                        struct rte_flow_action_handle *handle,
   16621                 :            :                        struct rte_flow_error *error)
   16622                 :            : {
   16623                 :          0 :         uint32_t act_idx = (uint32_t)(uintptr_t)handle;
   16624                 :          0 :         uint32_t type = act_idx >> MLX5_INDIRECT_ACTION_TYPE_OFFSET;
   16625                 :          0 :         uint32_t idx = act_idx & ((1u << MLX5_INDIRECT_ACTION_TYPE_OFFSET) - 1);
   16626                 :            :         struct mlx5_flow_counter *cnt;
   16627                 :            :         uint32_t no_flow_refcnt = 1;
   16628                 :            :         int ret;
   16629                 :            : 
   16630   [ #  #  #  #  :          0 :         switch (type) {
                      # ]
   16631                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_RSS:
   16632                 :          0 :                 return __flow_dv_action_rss_release(dev, idx, error);
   16633                 :            :         case MLX5_INDIRECT_ACTION_TYPE_COUNT:
   16634                 :            :                 cnt = flow_dv_counter_get_by_idx(dev, idx, NULL);
   16635         [ #  # ]:          0 :                 if (!__atomic_compare_exchange_n(&cnt->shared_info.refcnt,
   16636                 :            :                                                  &no_flow_refcnt, 1, false,
   16637                 :            :                                                  __ATOMIC_ACQUIRE,
   16638                 :            :                                                  __ATOMIC_RELAXED))
   16639                 :          0 :                         return rte_flow_error_set(error, EBUSY,
   16640                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
   16641                 :            :                                                   NULL,
   16642                 :            :                                                   "Indirect count action has references");
   16643                 :          0 :                 flow_dv_counter_free(dev, idx);
   16644                 :          0 :                 return 0;
   16645                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_AGE:
   16646                 :          0 :                 ret = flow_dv_aso_age_release(dev, idx);
   16647         [ #  # ]:          0 :                 if (ret)
   16648                 :            :                         /*
   16649                 :            :                          * In this case, the last flow has a reference will
   16650                 :            :                          * actually release the age action.
   16651                 :            :                          */
   16652                 :          0 :                         DRV_LOG(DEBUG, "Indirect age action %" PRIu32 " was"
   16653                 :            :                                 " released with references %d.", idx, ret);
   16654                 :            :                 return 0;
   16655                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_CT:
   16656                 :          0 :                 ret = flow_dv_aso_ct_release(dev, idx, error);
   16657         [ #  # ]:          0 :                 if (ret < 0)
   16658                 :            :                         return ret;
   16659         [ #  # ]:          0 :                 if (ret > 0)
   16660                 :          0 :                         DRV_LOG(DEBUG, "Connection tracking object %u still "
   16661                 :            :                                 "has references %d.", idx, ret);
   16662                 :            :                 return 0;
   16663                 :          0 :         default:
   16664                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
   16665                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
   16666                 :            :                                           NULL,
   16667                 :            :                                           "action type not supported");
   16668                 :            :         }
   16669                 :            : }
   16670                 :            : 
   16671                 :            : /**
   16672                 :            :  * Updates in place shared RSS action configuration.
   16673                 :            :  *
   16674                 :            :  * @param[in] dev
   16675                 :            :  *   Pointer to the Ethernet device structure.
   16676                 :            :  * @param[in] idx
   16677                 :            :  *   The shared RSS action object ID to be updated.
   16678                 :            :  * @param[in] action_conf
   16679                 :            :  *   RSS action specification used to modify *shared_rss*.
   16680                 :            :  * @param[out] error
   16681                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   16682                 :            :  *   error only.
   16683                 :            :  *
   16684                 :            :  * @return
   16685                 :            :  *   0 on success, otherwise negative errno value.
   16686                 :            :  * @note: currently only support update of RSS queues.
   16687                 :            :  */
   16688                 :            : static int
   16689                 :          0 : __flow_dv_action_rss_update(struct rte_eth_dev *dev, uint32_t idx,
   16690                 :            :                             const struct rte_flow_action_rss *action_conf,
   16691                 :            :                             struct rte_flow_error *error)
   16692                 :            : {
   16693                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16694                 :            :         struct mlx5_shared_action_rss *shared_rss =
   16695                 :          0 :             mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], idx);
   16696                 :            :         int ret = 0;
   16697                 :            :         void *queue = NULL;
   16698                 :            :         void *queue_i = NULL;
   16699                 :          0 :         uint32_t queue_size = action_conf->queue_num * sizeof(uint16_t);
   16700                 :          0 :         bool dev_started = !!dev->data->dev_started;
   16701                 :            : 
   16702         [ #  # ]:          0 :         if (!shared_rss)
   16703                 :          0 :                 return rte_flow_error_set(error, EINVAL,
   16704                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   16705                 :            :                                           "invalid shared action to update");
   16706         [ #  # ]:          0 :         if (priv->obj_ops.ind_table_modify == NULL)
   16707                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
   16708                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   16709                 :            :                                           "cannot modify indirection table");
   16710                 :          0 :         queue = mlx5_malloc(MLX5_MEM_ZERO,
   16711                 :          0 :                             RTE_ALIGN_CEIL(queue_size, sizeof(void *)),
   16712                 :            :                             0, SOCKET_ID_ANY);
   16713         [ #  # ]:          0 :         if (!queue)
   16714                 :          0 :                 return rte_flow_error_set(error, ENOMEM,
   16715                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   16716                 :            :                                           NULL,
   16717                 :            :                                           "cannot allocate resource memory");
   16718                 :          0 :         memcpy(queue, action_conf->queue, queue_size);
   16719                 :            :         MLX5_ASSERT(shared_rss->ind_tbl);
   16720                 :          0 :         rte_spinlock_lock(&shared_rss->action_rss_sl);
   16721                 :          0 :         queue_i = shared_rss->ind_tbl->queues;
   16722                 :          0 :         ret = mlx5_ind_table_obj_modify(dev, shared_rss->ind_tbl,
   16723                 :          0 :                                         queue, action_conf->queue_num,
   16724                 :            :                                         true /* standalone */,
   16725                 :            :                                         dev_started /* ref_new_qs */,
   16726                 :            :                                         dev_started /* deref_old_qs */);
   16727         [ #  # ]:          0 :         if (ret) {
   16728                 :          0 :                 ret = rte_flow_error_set(error, rte_errno,
   16729                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   16730                 :            :                                           "cannot update indirection table");
   16731                 :            :         } else {
   16732                 :            :                 /* Restore the queue to indirect table internal queue. */
   16733                 :            :                 memcpy(queue_i, queue, queue_size);
   16734                 :          0 :                 shared_rss->ind_tbl->queues = queue_i;
   16735                 :          0 :                 shared_rss->origin.queue_num = action_conf->queue_num;
   16736                 :            :         }
   16737                 :          0 :         mlx5_free(queue);
   16738                 :            :         rte_spinlock_unlock(&shared_rss->action_rss_sl);
   16739                 :          0 :         return ret;
   16740                 :            : }
   16741                 :            : 
   16742                 :            : /*
   16743                 :            :  * Updates in place conntrack context or direction.
   16744                 :            :  * Context update should be synchronized.
   16745                 :            :  *
   16746                 :            :  * @param[in] dev
   16747                 :            :  *   Pointer to the Ethernet device structure.
   16748                 :            :  * @param[in] idx
   16749                 :            :  *   The conntrack object ID to be updated.
   16750                 :            :  * @param[in] update
   16751                 :            :  *   Pointer to the structure of information to update.
   16752                 :            :  * @param[out] error
   16753                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   16754                 :            :  *   error only.
   16755                 :            :  *
   16756                 :            :  * @return
   16757                 :            :  *   0 on success, otherwise negative errno value.
   16758                 :            :  */
   16759                 :            : static int
   16760                 :          0 : __flow_dv_action_ct_update(struct rte_eth_dev *dev, uint32_t idx,
   16761                 :            :                            const struct rte_flow_modify_conntrack *update,
   16762                 :            :                            struct rte_flow_error *error)
   16763                 :            : {
   16764                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16765                 :            :         struct mlx5_aso_ct_action *ct;
   16766                 :            :         const struct rte_flow_action_conntrack *new_prf;
   16767                 :            :         int ret = 0;
   16768                 :          0 :         uint16_t owner = (uint16_t)MLX5_INDIRECT_ACT_CT_GET_OWNER(idx);
   16769                 :            :         uint32_t dev_idx;
   16770                 :            : 
   16771         [ #  # ]:          0 :         if (PORT_ID(priv) != owner)
   16772                 :          0 :                 return rte_flow_error_set(error, EACCES,
   16773                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   16774                 :            :                                           NULL,
   16775                 :            :                                           "CT object owned by another port");
   16776                 :          0 :         dev_idx = MLX5_INDIRECT_ACT_CT_GET_IDX(idx);
   16777                 :          0 :         ct = flow_aso_ct_get_by_dev_idx(dev, dev_idx);
   16778         [ #  # ]:          0 :         if (!ct->refcnt)
   16779                 :          0 :                 return rte_flow_error_set(error, ENOMEM,
   16780                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   16781                 :            :                                           NULL,
   16782                 :            :                                           "CT object is inactive");
   16783                 :          0 :         new_prf = &update->new_ct;
   16784         [ #  # ]:          0 :         if (update->direction)
   16785                 :          0 :                 ct->is_original = !!new_prf->is_original_dir;
   16786         [ #  # ]:          0 :         if (update->state) {
   16787                 :            :                 /* Only validate the profile when it needs to be updated. */
   16788                 :          0 :                 ret = mlx5_validate_action_ct(dev, new_prf, error);
   16789         [ #  # ]:          0 :                 if (ret)
   16790                 :            :                         return ret;
   16791                 :          0 :                 ret = mlx5_aso_ct_update_by_wqe(priv->sh, MLX5_HW_INV_QUEUE,
   16792                 :            :                                                 ct, new_prf, NULL, true);
   16793         [ #  # ]:          0 :                 if (ret)
   16794                 :          0 :                         return rte_flow_error_set(error, EIO,
   16795                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   16796                 :            :                                         NULL,
   16797                 :            :                                         "Failed to send CT context update WQE");
   16798                 :            :                 /* Block until ready or a failure, default is asynchronous. */
   16799                 :          0 :                 ret = mlx5_aso_ct_available(priv->sh, MLX5_HW_INV_QUEUE, ct);
   16800         [ #  # ]:          0 :                 if (ret)
   16801                 :          0 :                         rte_flow_error_set(error, rte_errno,
   16802                 :            :                                            RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   16803                 :            :                                            NULL,
   16804                 :            :                                            "Timeout to get the CT update");
   16805                 :            :         }
   16806                 :            :         return ret;
   16807                 :            : }
   16808                 :            : 
   16809                 :            : /**
   16810                 :            :  * Updates in place shared action configuration, lock free,
   16811                 :            :  * (mutex should be acquired by caller).
   16812                 :            :  *
   16813                 :            :  * @param[in] dev
   16814                 :            :  *   Pointer to the Ethernet device structure.
   16815                 :            :  * @param[in] handle
   16816                 :            :  *   The indirect action object handle to be updated.
   16817                 :            :  * @param[in] update
   16818                 :            :  *   Action specification used to modify the action pointed by *handle*.
   16819                 :            :  *   *update* could be of same type with the action pointed by the *handle*
   16820                 :            :  *   handle argument, or some other structures like a wrapper, depending on
   16821                 :            :  *   the indirect action type.
   16822                 :            :  * @param[out] error
   16823                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   16824                 :            :  *   error only.
   16825                 :            :  *
   16826                 :            :  * @return
   16827                 :            :  *   0 on success, otherwise negative errno value.
   16828                 :            :  */
   16829                 :            : int
   16830                 :          0 : flow_dv_action_update(struct rte_eth_dev *dev,
   16831                 :            :                         struct rte_flow_action_handle *handle,
   16832                 :            :                         const void *update,
   16833                 :            :                         struct rte_flow_error *err)
   16834                 :            : {
   16835                 :          0 :         uint32_t act_idx = (uint32_t)(uintptr_t)handle;
   16836                 :          0 :         uint32_t type = act_idx >> MLX5_INDIRECT_ACTION_TYPE_OFFSET;
   16837                 :          0 :         uint32_t idx = act_idx & ((1u << MLX5_INDIRECT_ACTION_TYPE_OFFSET) - 1);
   16838                 :            :         const void *action_conf;
   16839                 :            : 
   16840      [ #  #  # ]:          0 :         switch (type) {
   16841                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_RSS:
   16842                 :          0 :                 action_conf = ((const struct rte_flow_action *)update)->conf;
   16843                 :          0 :                 return __flow_dv_action_rss_update(dev, idx, action_conf, err);
   16844                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_CT:
   16845                 :          0 :                 return __flow_dv_action_ct_update(dev, idx, update, err);
   16846                 :          0 :         default:
   16847                 :          0 :                 return rte_flow_error_set(err, ENOTSUP,
   16848                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
   16849                 :            :                                           NULL,
   16850                 :            :                                           "action type update not supported");
   16851                 :            :         }
   16852                 :            : }
   16853                 :            : 
   16854                 :            : /**
   16855                 :            :  * Destroy the meter sub policy table rules.
   16856                 :            :  * Lock free, (mutex should be acquired by caller).
   16857                 :            :  *
   16858                 :            :  * @param[in] dev
   16859                 :            :  *   Pointer to Ethernet device.
   16860                 :            :  * @param[in] sub_policy
   16861                 :            :  *   Pointer to meter sub policy table.
   16862                 :            :  */
   16863                 :            : static void
   16864                 :          0 : __flow_dv_destroy_sub_policy_rules(struct rte_eth_dev *dev,
   16865                 :            :                              struct mlx5_flow_meter_sub_policy *sub_policy)
   16866                 :            : {
   16867                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16868                 :            :         struct mlx5_flow_tbl_data_entry *tbl;
   16869                 :          0 :         struct mlx5_flow_meter_policy *policy = sub_policy->main_policy;
   16870                 :            :         struct mlx5_flow_meter_info *next_fm;
   16871                 :            :         struct mlx5_sub_policy_color_rule *color_rule;
   16872                 :            :         void *tmp;
   16873                 :            :         uint32_t i;
   16874                 :            : 
   16875         [ #  # ]:          0 :         for (i = 0; i < RTE_COLORS; i++) {
   16876                 :            :                 next_fm = NULL;
   16877         [ #  # ]:          0 :                 if (i <= RTE_COLOR_YELLOW && policy &&
   16878         [ #  # ]:          0 :                     policy->act_cnt[i].fate_action == MLX5_FLOW_FATE_MTR)
   16879                 :          0 :                         next_fm = mlx5_flow_meter_find(priv,
   16880                 :            :                                         policy->act_cnt[i].next_mtr_id, NULL);
   16881         [ #  # ]:          0 :                 RTE_TAILQ_FOREACH_SAFE(color_rule, &sub_policy->color_rules[i],
   16882                 :            :                                    next_port, tmp) {
   16883                 :          0 :                         claim_zero(mlx5_flow_os_destroy_flow(color_rule->rule));
   16884                 :          0 :                         tbl = container_of(color_rule->matcher->tbl,
   16885                 :            :                                            typeof(*tbl), tbl);
   16886                 :          0 :                         mlx5_list_unregister(tbl->matchers,
   16887                 :            :                                              &color_rule->matcher->entry);
   16888         [ #  # ]:          0 :                         TAILQ_REMOVE(&sub_policy->color_rules[i],
   16889                 :            :                                      color_rule, next_port);
   16890                 :          0 :                         mlx5_free(color_rule);
   16891         [ #  # ]:          0 :                         if (next_fm)
   16892                 :          0 :                                 mlx5_flow_meter_detach(priv, next_fm);
   16893                 :            :                 }
   16894                 :            :         }
   16895         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_RTE_COLORS; i++) {
   16896         [ #  # ]:          0 :                 if (sub_policy->rix_hrxq[i]) {
   16897   [ #  #  #  # ]:          0 :                         if (policy && !policy->is_hierarchy)
   16898                 :          0 :                                 mlx5_hrxq_release(dev, sub_policy->rix_hrxq[i]);
   16899                 :          0 :                         sub_policy->rix_hrxq[i] = 0;
   16900                 :            :                 }
   16901         [ #  # ]:          0 :                 if (sub_policy->jump_tbl[i]) {
   16902                 :          0 :                         flow_dv_tbl_resource_release(MLX5_SH(dev),
   16903                 :            :                                                      sub_policy->jump_tbl[i]);
   16904                 :          0 :                         sub_policy->jump_tbl[i] = NULL;
   16905                 :            :                 }
   16906                 :            :         }
   16907         [ #  # ]:          0 :         if (sub_policy->tbl_rsc) {
   16908                 :          0 :                 flow_dv_tbl_resource_release(MLX5_SH(dev),
   16909                 :            :                                              sub_policy->tbl_rsc);
   16910                 :          0 :                 sub_policy->tbl_rsc = NULL;
   16911                 :            :         }
   16912                 :          0 : }
   16913                 :            : 
   16914                 :            : /**
   16915                 :            :  * Destroy policy rules, lock free,
   16916                 :            :  * (mutex should be acquired by caller).
   16917                 :            :  * Dispatcher for action type specific call.
   16918                 :            :  *
   16919                 :            :  * @param[in] dev
   16920                 :            :  *   Pointer to the Ethernet device structure.
   16921                 :            :  * @param[in] mtr_policy
   16922                 :            :  *   Meter policy struct.
   16923                 :            :  */
   16924                 :            : static void
   16925                 :          0 : flow_dv_destroy_policy_rules(struct rte_eth_dev *dev,
   16926                 :            :                              struct mlx5_flow_meter_policy *mtr_policy)
   16927                 :            : {
   16928                 :            :         uint32_t i, j;
   16929                 :            :         struct mlx5_flow_meter_sub_policy *sub_policy;
   16930                 :            :         uint16_t sub_policy_num;
   16931                 :            : 
   16932         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
   16933                 :          0 :                 sub_policy_num = (mtr_policy->sub_policy_num >>
   16934                 :          0 :                         (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i)) &
   16935                 :            :                         MLX5_MTR_SUB_POLICY_NUM_MASK;
   16936         [ #  # ]:          0 :                 for (j = 0; j < sub_policy_num; j++) {
   16937                 :          0 :                         sub_policy = mtr_policy->sub_policys[i][j];
   16938         [ #  # ]:          0 :                         if (sub_policy)
   16939                 :          0 :                                 __flow_dv_destroy_sub_policy_rules(dev,
   16940                 :            :                                                                    sub_policy);
   16941                 :            :                 }
   16942                 :            :         }
   16943                 :          0 : }
   16944                 :            : 
   16945                 :            : /**
   16946                 :            :  * Destroy policy action, lock free,
   16947                 :            :  * (mutex should be acquired by caller).
   16948                 :            :  * Dispatcher for action type specific call.
   16949                 :            :  *
   16950                 :            :  * @param[in] dev
   16951                 :            :  *   Pointer to the Ethernet device structure.
   16952                 :            :  * @param[in] mtr_policy
   16953                 :            :  *   Meter policy struct.
   16954                 :            :  */
   16955                 :            : static void
   16956                 :          0 : flow_dv_destroy_mtr_policy_acts(struct rte_eth_dev *dev,
   16957                 :            :                       struct mlx5_flow_meter_policy *mtr_policy)
   16958                 :            : {
   16959                 :            :         struct rte_flow_action *rss_action;
   16960                 :            :         struct mlx5_flow_handle dev_handle;
   16961                 :            :         uint32_t i, j;
   16962                 :            : 
   16963         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_RTE_COLORS; i++) {
   16964         [ #  # ]:          0 :                 if (mtr_policy->act_cnt[i].rix_mark) {
   16965                 :          0 :                         flow_dv_tag_release(dev,
   16966                 :            :                                 mtr_policy->act_cnt[i].rix_mark);
   16967                 :          0 :                         mtr_policy->act_cnt[i].rix_mark = 0;
   16968                 :            :                 }
   16969         [ #  # ]:          0 :                 if (mtr_policy->act_cnt[i].modify_hdr) {
   16970                 :            :                         dev_handle.dvh.modify_hdr =
   16971                 :            :                                 mtr_policy->act_cnt[i].modify_hdr;
   16972                 :            :                         flow_dv_modify_hdr_resource_release(dev, &dev_handle);
   16973                 :            :                 }
   16974   [ #  #  #  # ]:          0 :                 switch (mtr_policy->act_cnt[i].fate_action) {
   16975                 :          0 :                 case MLX5_FLOW_FATE_SHARED_RSS:
   16976                 :          0 :                         rss_action = mtr_policy->act_cnt[i].rss;
   16977                 :          0 :                         mlx5_free(rss_action);
   16978                 :          0 :                         break;
   16979                 :          0 :                 case MLX5_FLOW_FATE_PORT_ID:
   16980         [ #  # ]:          0 :                         if (mtr_policy->act_cnt[i].rix_port_id_action) {
   16981                 :          0 :                                 flow_dv_port_id_action_resource_release(dev,
   16982                 :            :                                 mtr_policy->act_cnt[i].rix_port_id_action);
   16983                 :          0 :                                 mtr_policy->act_cnt[i].rix_port_id_action = 0;
   16984                 :            :                         }
   16985                 :            :                         break;
   16986                 :            :                 case MLX5_FLOW_FATE_DROP:
   16987                 :            :                 case MLX5_FLOW_FATE_JUMP:
   16988         [ #  # ]:          0 :                         for (j = 0; j < MLX5_MTR_DOMAIN_MAX; j++)
   16989                 :          0 :                                 mtr_policy->act_cnt[i].dr_jump_action[j] =
   16990                 :            :                                                 NULL;
   16991                 :            :                         break;
   16992                 :            :                 default:
   16993                 :            :                         /*Queue action do nothing*/
   16994                 :            :                         break;
   16995                 :            :                 }
   16996                 :            :         }
   16997         [ #  # ]:          0 :         for (j = 0; j < MLX5_MTR_DOMAIN_MAX; j++)
   16998                 :          0 :                 mtr_policy->dr_drop_action[j] = NULL;
   16999                 :          0 : }
   17000                 :            : 
   17001                 :            : /**
   17002                 :            :  * Create yellow action for color aware meter.
   17003                 :            :  *
   17004                 :            :  * @param[in] dev
   17005                 :            :  *   Pointer to the Ethernet device structure.
   17006                 :            :  * @param[in] fm
   17007                 :            :  *   Meter information table.
   17008                 :            :  * @param[out] error
   17009                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   17010                 :            :  *   error only.
   17011                 :            :  *
   17012                 :            :  * @return
   17013                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   17014                 :            :  */
   17015                 :            : static int
   17016                 :          0 : __flow_dv_create_mtr_yellow_action(struct rte_eth_dev *dev,
   17017                 :            :                                    struct mlx5_flow_meter_info *fm,
   17018                 :            :                                    struct rte_mtr_error *error)
   17019                 :            : {
   17020                 :            : #ifdef HAVE_MLX5_DR_CREATE_ACTION_ASO
   17021                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   17022                 :            :         struct rte_flow_error flow_err;
   17023                 :            :         struct mlx5_aso_mtr *aso_mtr;
   17024                 :            :         struct mlx5_aso_mtr_pool *pool;
   17025                 :            :         uint8_t reg_id;
   17026                 :            : 
   17027                 :          0 :         aso_mtr = container_of(fm, struct mlx5_aso_mtr, fm);
   17028                 :          0 :         pool = container_of(aso_mtr, struct mlx5_aso_mtr_pool, mtrs[aso_mtr->offset]);
   17029                 :          0 :         reg_id = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR, 0, &flow_err);
   17030                 :          0 :         fm->meter_action_y =
   17031                 :          0 :                 mlx5_glue->dv_create_flow_action_aso(priv->sh->rx_domain,
   17032                 :          0 :                                                      pool->devx_obj->obj,
   17033                 :            :                                                      aso_mtr->offset,
   17034                 :            :                                                      (1 << MLX5_FLOW_COLOR_YELLOW),
   17035                 :          0 :                                                      reg_id - REG_C_0);
   17036                 :            : #else
   17037                 :            :         RTE_SET_USED(dev);
   17038                 :            : #endif
   17039         [ #  # ]:          0 :         if (!fm->meter_action_y) {
   17040                 :          0 :                 return -rte_mtr_error_set(error, EINVAL, RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
   17041                 :            :                                           "Fail to create yellow meter action.");
   17042                 :            :         }
   17043                 :            :         return 0;
   17044                 :            : }
   17045                 :            : 
   17046                 :            : /**
   17047                 :            :  * Create policy action per domain, lock free,
   17048                 :            :  * (mutex should be acquired by caller).
   17049                 :            :  * Dispatcher for action type specific call.
   17050                 :            :  *
   17051                 :            :  * @param[in] dev
   17052                 :            :  *   Pointer to the Ethernet device structure.
   17053                 :            :  * @param[in] mtr_policy
   17054                 :            :  *   Meter policy struct.
   17055                 :            :  * @param[in] action
   17056                 :            :  *   Action specification used to create meter actions.
   17057                 :            :  * @param[in] attr
   17058                 :            :  *   Pointer to the flow attributes.
   17059                 :            :  * @param[out] error
   17060                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   17061                 :            :  *   error only.
   17062                 :            :  *
   17063                 :            :  * @return
   17064                 :            :  *   0 on success, otherwise negative errno value.
   17065                 :            :  */
   17066                 :            : static int
   17067                 :          0 : __flow_dv_create_domain_policy_acts(struct rte_eth_dev *dev,
   17068                 :            :                         struct mlx5_flow_meter_policy *mtr_policy,
   17069                 :            :                         const struct rte_flow_action *actions[RTE_COLORS],
   17070                 :            :                         struct rte_flow_attr *attr,
   17071                 :            :                         enum mlx5_meter_domain domain,
   17072                 :            :                         struct rte_mtr_error *error)
   17073                 :            : {
   17074                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   17075                 :            :         struct rte_flow_error flow_err;
   17076                 :            :         const struct rte_flow_action *act;
   17077                 :            :         uint64_t action_flags;
   17078                 :            :         struct mlx5_flow_handle dh;
   17079                 :            :         struct mlx5_flow dev_flow;
   17080                 :            :         struct mlx5_flow_dv_port_id_action_resource port_id_action;
   17081                 :            :         int i, ret;
   17082                 :            :         uint8_t egress, transfer;
   17083                 :            :         struct mlx5_meter_policy_action_container *act_cnt = NULL;
   17084                 :            :         union {
   17085                 :            :                 struct mlx5_flow_dv_modify_hdr_resource res;
   17086                 :            :                 uint8_t len[sizeof(struct mlx5_flow_dv_modify_hdr_resource) +
   17087                 :            :                             sizeof(struct mlx5_modification_cmd) *
   17088                 :            :                             (MLX5_MAX_MODIFY_NUM + 1)];
   17089                 :            :         } mhdr_dummy;
   17090                 :            :         struct mlx5_flow_dv_modify_hdr_resource *mhdr_res = &mhdr_dummy.res;
   17091                 :            : 
   17092                 :          0 :         egress = (domain == MLX5_MTR_DOMAIN_EGRESS) ? 1 : 0;
   17093         [ #  # ]:          0 :         transfer = (domain == MLX5_MTR_DOMAIN_TRANSFER) ? 1 : 0;
   17094                 :            :         memset(&dh, 0, sizeof(struct mlx5_flow_handle));
   17095                 :            :         memset(&dev_flow, 0, sizeof(struct mlx5_flow));
   17096                 :            :         memset(&port_id_action, 0,
   17097                 :            :                sizeof(struct mlx5_flow_dv_port_id_action_resource));
   17098                 :            :         memset(mhdr_res, 0, sizeof(*mhdr_res));
   17099         [ #  # ]:          0 :         mhdr_res->ft_type = transfer ? MLX5DV_FLOW_TABLE_TYPE_FDB :
   17100                 :            :                                        (egress ? MLX5DV_FLOW_TABLE_TYPE_NIC_TX :
   17101                 :            :                                         MLX5DV_FLOW_TABLE_TYPE_NIC_RX);
   17102                 :          0 :         dev_flow.handle = &dh;
   17103                 :          0 :         dev_flow.dv.port_id_action = &port_id_action;
   17104                 :          0 :         dev_flow.external = true;
   17105         [ #  # ]:          0 :         for (i = 0; i < RTE_COLORS; i++) {
   17106         [ #  # ]:          0 :                 if (i < MLX5_MTR_RTE_COLORS)
   17107                 :          0 :                         act_cnt = &mtr_policy->act_cnt[i];
   17108                 :            :                 /* Skip the color policy actions creation. */
   17109   [ #  #  #  #  :          0 :                 if ((i == RTE_COLOR_YELLOW && mtr_policy->skip_y) ||
                   #  # ]
   17110         [ #  # ]:          0 :                     (i == RTE_COLOR_GREEN && mtr_policy->skip_g))
   17111                 :          0 :                         continue;
   17112                 :            :                 action_flags = 0;
   17113                 :          0 :                 for (act = actions[i];
   17114   [ #  #  #  # ]:          0 :                      act && act->type != RTE_FLOW_ACTION_TYPE_END; act++) {
   17115   [ #  #  #  #  :          0 :                         switch (act->type) {
          #  #  #  #  #  
                      # ]
   17116                 :          0 :                         case RTE_FLOW_ACTION_TYPE_MARK:
   17117                 :            :                         {
   17118                 :            :                                 uint32_t tag_be = mlx5_flow_mark_set
   17119                 :            :                                         (((const struct rte_flow_action_mark *)
   17120         [ #  # ]:          0 :                                         (act->conf))->id);
   17121                 :            : 
   17122         [ #  # ]:          0 :                                 if (i >= MLX5_MTR_RTE_COLORS)
   17123                 :          0 :                                         return -rte_mtr_error_set(error,
   17124                 :            :                                           ENOTSUP,
   17125                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   17126                 :            :                                           NULL,
   17127                 :            :                                           "cannot create policy "
   17128                 :            :                                           "mark action for this color");
   17129         [ #  # ]:          0 :                                 if (flow_dv_tag_resource_register(dev, tag_be,
   17130                 :            :                                                   &dev_flow, &flow_err))
   17131                 :          0 :                                         return -rte_mtr_error_set(error,
   17132                 :            :                                         ENOTSUP,
   17133                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   17134                 :            :                                         NULL,
   17135                 :            :                                         "cannot setup policy mark action");
   17136                 :            :                                 MLX5_ASSERT(dev_flow.dv.tag_resource);
   17137                 :          0 :                                 act_cnt->rix_mark =
   17138                 :          0 :                                         dev_flow.handle->dvh.rix_tag;
   17139                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_MARK;
   17140                 :          0 :                                 mtr_policy->mark = 1;
   17141                 :          0 :                                 break;
   17142                 :            :                         }
   17143                 :          0 :                         case RTE_FLOW_ACTION_TYPE_SET_TAG:
   17144         [ #  # ]:          0 :                                 if (i >= MLX5_MTR_RTE_COLORS)
   17145                 :          0 :                                         return -rte_mtr_error_set(error,
   17146                 :            :                                           ENOTSUP,
   17147                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   17148                 :            :                                           NULL,
   17149                 :            :                                           "cannot create policy "
   17150                 :            :                                           "set tag action for this color");
   17151         [ #  # ]:          0 :                                 if (flow_dv_convert_action_set_tag
   17152                 :            :                                 (dev, mhdr_res,
   17153                 :            :                                 (const struct rte_flow_action_set_tag *)
   17154                 :          0 :                                 act->conf,  &flow_err))
   17155                 :          0 :                                         return -rte_mtr_error_set(error,
   17156                 :            :                                         ENOTSUP,
   17157                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   17158                 :            :                                         NULL, "cannot convert policy "
   17159                 :            :                                         "set tag action");
   17160         [ #  # ]:          0 :                                 if (!mhdr_res->actions_num)
   17161                 :          0 :                                         return -rte_mtr_error_set(error,
   17162                 :            :                                         ENOTSUP,
   17163                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   17164                 :            :                                         NULL, "cannot find policy "
   17165                 :            :                                         "set tag action");
   17166                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_SET_TAG;
   17167                 :          0 :                                 break;
   17168                 :          0 :                         case RTE_FLOW_ACTION_TYPE_DROP:
   17169                 :            :                         {
   17170                 :          0 :                                 struct mlx5_flow_mtr_mng *mtrmng =
   17171                 :          0 :                                                 priv->sh->mtrmng;
   17172                 :            :                                 struct mlx5_flow_tbl_data_entry *tbl_data;
   17173                 :            : 
   17174                 :            :                                 /*
   17175                 :            :                                  * Create the drop table with
   17176                 :            :                                  * METER DROP level.
   17177                 :            :                                  */
   17178         [ #  # ]:          0 :                                 if (!mtrmng->drop_tbl[domain]) {
   17179                 :          0 :                                         mtrmng->drop_tbl[domain] =
   17180                 :          0 :                                         flow_dv_tbl_resource_get(dev,
   17181                 :            :                                         MLX5_FLOW_TABLE_LEVEL_METER,
   17182                 :            :                                         egress, transfer, false, NULL, 0,
   17183                 :            :                                         0, MLX5_MTR_TABLE_ID_DROP, &flow_err);
   17184         [ #  # ]:          0 :                                         if (!mtrmng->drop_tbl[domain])
   17185                 :          0 :                                                 return -rte_mtr_error_set
   17186                 :            :                                         (error, ENOTSUP,
   17187                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   17188                 :            :                                         NULL,
   17189                 :            :                                         "Failed to create meter drop table");
   17190                 :            :                                 }
   17191                 :          0 :                                 tbl_data = container_of
   17192                 :            :                                 (mtrmng->drop_tbl[domain],
   17193                 :            :                                 struct mlx5_flow_tbl_data_entry, tbl);
   17194         [ #  # ]:          0 :                                 if (i < MLX5_MTR_RTE_COLORS) {
   17195                 :          0 :                                         act_cnt->dr_jump_action[domain] =
   17196                 :          0 :                                                 tbl_data->jump.action;
   17197                 :          0 :                                         act_cnt->fate_action =
   17198                 :            :                                                 MLX5_FLOW_FATE_DROP;
   17199                 :            :                                 }
   17200         [ #  # ]:          0 :                                 if (i == RTE_COLOR_RED)
   17201                 :          0 :                                         mtr_policy->dr_drop_action[domain] =
   17202                 :          0 :                                                 tbl_data->jump.action;
   17203                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_DROP;
   17204                 :          0 :                                 break;
   17205                 :            :                         }
   17206                 :          0 :                         case RTE_FLOW_ACTION_TYPE_QUEUE:
   17207                 :            :                         {
   17208         [ #  # ]:          0 :                                 if (i >= MLX5_MTR_RTE_COLORS)
   17209                 :          0 :                                         return -rte_mtr_error_set(error,
   17210                 :            :                                         ENOTSUP,
   17211                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   17212                 :            :                                         NULL, "cannot create policy "
   17213                 :            :                                         "fate queue for this color");
   17214                 :          0 :                                 act_cnt->queue =
   17215                 :            :                                 ((const struct rte_flow_action_queue *)
   17216                 :          0 :                                         (act->conf))->index;
   17217                 :          0 :                                 act_cnt->fate_action =
   17218                 :            :                                         MLX5_FLOW_FATE_QUEUE;
   17219                 :          0 :                                 dev_flow.handle->fate_action =
   17220                 :            :                                         MLX5_FLOW_FATE_QUEUE;
   17221                 :          0 :                                 mtr_policy->is_queue = 1;
   17222                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_QUEUE;
   17223                 :          0 :                                 break;
   17224                 :            :                         }
   17225                 :          0 :                         case RTE_FLOW_ACTION_TYPE_RSS:
   17226                 :            :                         {
   17227                 :            :                                 int rss_size;
   17228                 :            : 
   17229         [ #  # ]:          0 :                                 if (i >= MLX5_MTR_RTE_COLORS)
   17230                 :          0 :                                         return -rte_mtr_error_set(error,
   17231                 :            :                                           ENOTSUP,
   17232                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   17233                 :            :                                           NULL,
   17234                 :            :                                           "cannot create policy "
   17235                 :            :                                           "rss action for this color");
   17236                 :            :                                 /*
   17237                 :            :                                  * Save RSS conf into policy struct
   17238                 :            :                                  * for translate stage.
   17239                 :            :                                  */
   17240                 :          0 :                                 rss_size = (int)rte_flow_conv
   17241                 :            :                                         (RTE_FLOW_CONV_OP_ACTION,
   17242                 :            :                                         NULL, 0, act, &flow_err);
   17243         [ #  # ]:          0 :                                 if (rss_size <= 0)
   17244                 :          0 :                                         return -rte_mtr_error_set(error,
   17245                 :            :                                           ENOTSUP,
   17246                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   17247                 :            :                                           NULL, "Get the wrong "
   17248                 :            :                                           "rss action struct size");
   17249                 :          0 :                                 act_cnt->rss = mlx5_malloc(MLX5_MEM_ZERO,
   17250                 :            :                                                 rss_size, 0, SOCKET_ID_ANY);
   17251         [ #  # ]:          0 :                                 if (!act_cnt->rss)
   17252                 :          0 :                                         return -rte_mtr_error_set(error,
   17253                 :            :                                           ENOTSUP,
   17254                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   17255                 :            :                                           NULL,
   17256                 :            :                                           "Fail to malloc rss action memory");
   17257                 :          0 :                                 ret = rte_flow_conv(RTE_FLOW_CONV_OP_ACTION,
   17258                 :            :                                         act_cnt->rss, rss_size,
   17259                 :            :                                         act, &flow_err);
   17260         [ #  # ]:          0 :                                 if (ret < 0)
   17261                 :          0 :                                         return -rte_mtr_error_set(error,
   17262                 :            :                                           ENOTSUP,
   17263                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   17264                 :            :                                           NULL, "Fail to save "
   17265                 :            :                                           "rss action into policy struct");
   17266                 :          0 :                                 act_cnt->fate_action =
   17267                 :            :                                         MLX5_FLOW_FATE_SHARED_RSS;
   17268                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_RSS;
   17269                 :          0 :                                 break;
   17270                 :            :                         }
   17271                 :          0 :                         case RTE_FLOW_ACTION_TYPE_PORT_ID:
   17272                 :            :                         case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
   17273                 :            :                         {
   17274                 :            :                                 struct mlx5_flow_dv_port_id_action_resource
   17275                 :            :                                         port_id_resource;
   17276                 :          0 :                                 uint32_t port_id = 0;
   17277                 :            : 
   17278         [ #  # ]:          0 :                                 if (i >= MLX5_MTR_RTE_COLORS)
   17279                 :          0 :                                         return -rte_mtr_error_set(error,
   17280                 :            :                                         ENOTSUP,
   17281                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   17282                 :            :                                         NULL, "cannot create policy "
   17283                 :            :                                         "port action for this color");
   17284                 :            :                                 memset(&port_id_resource, 0,
   17285                 :            :                                         sizeof(port_id_resource));
   17286         [ #  # ]:          0 :                                 if (flow_dv_translate_action_port_id(dev, act,
   17287                 :            :                                                 &port_id, &flow_err))
   17288                 :          0 :                                         return -rte_mtr_error_set(error,
   17289                 :            :                                         ENOTSUP,
   17290                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   17291                 :            :                                         NULL, "cannot translate "
   17292                 :            :                                         "policy port action");
   17293                 :          0 :                                 port_id_resource.port_id = port_id;
   17294         [ #  # ]:          0 :                                 if (flow_dv_port_id_action_resource_register
   17295                 :            :                                         (dev, &port_id_resource,
   17296                 :            :                                         &dev_flow, &flow_err))
   17297                 :          0 :                                         return -rte_mtr_error_set(error,
   17298                 :            :                                         ENOTSUP,
   17299                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   17300                 :            :                                         NULL, "cannot setup "
   17301                 :            :                                         "policy port action");
   17302                 :          0 :                                 act_cnt->rix_port_id_action =
   17303                 :          0 :                                         dev_flow.handle->rix_port_id_action;
   17304                 :          0 :                                 act_cnt->fate_action =
   17305                 :            :                                         MLX5_FLOW_FATE_PORT_ID;
   17306                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_PORT_ID;
   17307                 :          0 :                                 break;
   17308                 :            :                         }
   17309                 :          0 :                         case RTE_FLOW_ACTION_TYPE_JUMP:
   17310                 :            :                         {
   17311                 :            :                                 uint32_t jump_group = 0;
   17312                 :          0 :                                 uint32_t table = 0;
   17313                 :            :                                 struct mlx5_flow_tbl_data_entry *tbl_data;
   17314                 :          0 :                                 struct flow_grp_info grp_info = {
   17315                 :          0 :                                         .external = !!dev_flow.external,
   17316                 :            :                                         .transfer = !!transfer,
   17317                 :          0 :                                         .fdb_def_rule = !!priv->fdb_def_rule,
   17318                 :            :                                         .std_tbl_fix = 0,
   17319                 :          0 :                                         .skip_scale = dev_flow.skip_scale &
   17320                 :            :                                         (1 << MLX5_SCALE_FLOW_GROUP_BIT),
   17321                 :            :                                 };
   17322                 :          0 :                                 struct mlx5_flow_meter_sub_policy *sub_policy =
   17323                 :          0 :                                         mtr_policy->sub_policys[domain][0];
   17324                 :            : 
   17325         [ #  # ]:          0 :                                 if (i >= MLX5_MTR_RTE_COLORS)
   17326                 :          0 :                                         return -rte_mtr_error_set(error,
   17327                 :            :                                           ENOTSUP,
   17328                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   17329                 :            :                                           NULL,
   17330                 :            :                                           "cannot create policy "
   17331                 :            :                                           "jump action for this color");
   17332                 :          0 :                                 jump_group =
   17333                 :            :                                 ((const struct rte_flow_action_jump *)
   17334                 :          0 :                                                         act->conf)->group;
   17335         [ #  # ]:          0 :                                 if (mlx5_flow_group_to_table(dev, NULL,
   17336                 :            :                                                        jump_group,
   17337                 :            :                                                        &table,
   17338                 :            :                                                        &grp_info, &flow_err))
   17339                 :          0 :                                         return -rte_mtr_error_set(error,
   17340                 :            :                                         ENOTSUP,
   17341                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   17342                 :            :                                         NULL, "cannot setup "
   17343                 :            :                                         "policy jump action");
   17344                 :          0 :                                 sub_policy->jump_tbl[i] =
   17345                 :          0 :                                 flow_dv_tbl_resource_get(dev,
   17346                 :            :                                         table, egress,
   17347                 :            :                                         transfer,
   17348                 :            :                                         !!dev_flow.external,
   17349                 :            :                                         NULL, jump_group, 0,
   17350                 :            :                                         0, &flow_err);
   17351                 :            :                                 if
   17352         [ #  # ]:          0 :                                 (!sub_policy->jump_tbl[i])
   17353                 :          0 :                                         return  -rte_mtr_error_set(error,
   17354                 :            :                                         ENOTSUP,
   17355                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   17356                 :            :                                         NULL, "cannot create jump action.");
   17357                 :          0 :                                 tbl_data = container_of
   17358                 :            :                                 (sub_policy->jump_tbl[i],
   17359                 :            :                                 struct mlx5_flow_tbl_data_entry, tbl);
   17360                 :          0 :                                 act_cnt->dr_jump_action[domain] =
   17361                 :          0 :                                         tbl_data->jump.action;
   17362                 :          0 :                                 act_cnt->fate_action =
   17363                 :            :                                         MLX5_FLOW_FATE_JUMP;
   17364                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_JUMP;
   17365                 :          0 :                                 break;
   17366                 :            :                         }
   17367                 :          0 :                         case RTE_FLOW_ACTION_TYPE_MODIFY_FIELD:
   17368                 :            :                         {
   17369         [ #  # ]:          0 :                                 if (i >= MLX5_MTR_RTE_COLORS)
   17370                 :          0 :                                         return -rte_mtr_error_set(error,
   17371                 :            :                                           ENOTSUP,
   17372                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   17373                 :            :                                           NULL,
   17374                 :            :                                           "cannot create policy modify field for this color");
   17375         [ #  # ]:          0 :                                 if (flow_dv_convert_action_modify_field
   17376                 :            :                                         (dev, mhdr_res, act, attr, &flow_err))
   17377                 :          0 :                                         return -rte_mtr_error_set(error,
   17378                 :            :                                         ENOTSUP,
   17379                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   17380                 :            :                                         NULL, "cannot setup policy modify field action");
   17381         [ #  # ]:          0 :                                 if (!mhdr_res->actions_num)
   17382                 :          0 :                                         return -rte_mtr_error_set(error,
   17383                 :            :                                         ENOTSUP,
   17384                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   17385                 :            :                                         NULL, "cannot find policy modify field action");
   17386                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_MODIFY_FIELD;
   17387                 :          0 :                                 break;
   17388                 :            :                         }
   17389                 :            :                         /*
   17390                 :            :                          * No need to check meter hierarchy for R colors
   17391                 :            :                          * here since it is done in the validation stage.
   17392                 :            :                          */
   17393                 :          0 :                         case RTE_FLOW_ACTION_TYPE_METER:
   17394                 :            :                         {
   17395                 :            :                                 const struct rte_flow_action_meter *mtr;
   17396                 :            :                                 struct mlx5_flow_meter_info *next_fm;
   17397                 :            :                                 struct mlx5_flow_meter_policy *next_policy;
   17398                 :            :                                 struct rte_flow_action tag_action;
   17399                 :            :                                 struct mlx5_rte_flow_action_set_tag set_tag;
   17400                 :          0 :                                 uint32_t next_mtr_idx = 0;
   17401                 :            : 
   17402                 :          0 :                                 mtr = act->conf;
   17403                 :          0 :                                 next_fm = mlx5_flow_meter_find(priv,
   17404                 :          0 :                                                         mtr->mtr_id,
   17405                 :            :                                                         &next_mtr_idx);
   17406         [ #  # ]:          0 :                                 if (!next_fm)
   17407                 :          0 :                                         return -rte_mtr_error_set(error, EINVAL,
   17408                 :            :                                                 RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
   17409                 :            :                                                 "Fail to find next meter.");
   17410         [ #  # ]:          0 :                                 if (next_fm->def_policy)
   17411                 :          0 :                                         return -rte_mtr_error_set(error, EINVAL,
   17412                 :            :                                                 RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
   17413                 :            :                                 "Hierarchy only supports termination meter.");
   17414                 :          0 :                                 next_policy = mlx5_flow_meter_policy_find(dev,
   17415                 :            :                                                 next_fm->policy_id, NULL);
   17416                 :            :                                 MLX5_ASSERT(next_policy);
   17417         [ #  # ]:          0 :                                 if (next_fm->drop_cnt) {
   17418                 :          0 :                                         set_tag.id =
   17419                 :          0 :                                                 (enum modify_reg)
   17420                 :          0 :                                                 mlx5_flow_get_reg_id(dev,
   17421                 :            :                                                 MLX5_MTR_ID,
   17422                 :            :                                                 0,
   17423                 :            :                                                 (struct rte_flow_error *)error);
   17424                 :          0 :                                         set_tag.offset = (priv->mtr_reg_share ?
   17425                 :          0 :                                                 MLX5_MTR_COLOR_BITS : 0);
   17426         [ #  # ]:          0 :                                         set_tag.length = (priv->mtr_reg_share ?
   17427                 :            :                                                MLX5_MTR_IDLE_BITS_IN_COLOR_REG :
   17428                 :            :                                                MLX5_REG_BITS);
   17429                 :          0 :                                         set_tag.data = next_mtr_idx;
   17430                 :          0 :                                         tag_action.type =
   17431                 :            :                                                 (enum rte_flow_action_type)
   17432                 :            :                                                 MLX5_RTE_FLOW_ACTION_TYPE_TAG;
   17433                 :          0 :                                         tag_action.conf = &set_tag;
   17434         [ #  # ]:          0 :                                         if (flow_dv_convert_action_set_reg
   17435                 :            :                                                 (mhdr_res, &tag_action,
   17436                 :            :                                                 (struct rte_flow_error *)error))
   17437                 :          0 :                                                 return -rte_errno;
   17438                 :          0 :                                         action_flags |=
   17439                 :            :                                                 MLX5_FLOW_ACTION_SET_TAG;
   17440                 :            :                                 }
   17441   [ #  #  #  # ]:          0 :                                 if (i == RTE_COLOR_YELLOW && next_fm->color_aware &&
   17442         [ #  # ]:          0 :                                     !next_fm->meter_action_y)
   17443         [ #  # ]:          0 :                                         if (__flow_dv_create_mtr_yellow_action(dev, next_fm, error))
   17444                 :          0 :                                                 return -rte_errno;
   17445                 :          0 :                                 act_cnt->fate_action = MLX5_FLOW_FATE_MTR;
   17446                 :          0 :                                 act_cnt->next_mtr_id = next_fm->meter_id;
   17447                 :          0 :                                 act_cnt->next_sub_policy = NULL;
   17448                 :          0 :                                 mtr_policy->is_hierarchy = 1;
   17449         [ #  # ]:          0 :                                 if (next_policy->mark)
   17450                 :          0 :                                         mtr_policy->mark = 1;
   17451                 :          0 :                                 mtr_policy->hierarchy_match_port =
   17452                 :          0 :                                                         next_policy->hierarchy_match_port;
   17453                 :          0 :                                 action_flags |=
   17454                 :            :                                 MLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY;
   17455                 :          0 :                                 break;
   17456                 :            :                         }
   17457                 :            :                         default:
   17458                 :          0 :                                 return -rte_mtr_error_set(error, ENOTSUP,
   17459                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   17460                 :            :                                           NULL, "action type not supported");
   17461                 :            :                         }
   17462         [ #  # ]:          0 :                         if ((action_flags & MLX5_FLOW_ACTION_SET_TAG) ||
   17463                 :            :                             (action_flags & MLX5_FLOW_ACTION_MODIFY_FIELD)) {
   17464                 :            :                                 /* create modify action if needed. */
   17465                 :          0 :                                 dev_flow.dv.group = 1;
   17466         [ #  # ]:          0 :                                 if (flow_dv_modify_hdr_resource_register
   17467                 :            :                                         (dev, mhdr_res, &dev_flow, &flow_err))
   17468                 :          0 :                                         return -rte_mtr_error_set(error,
   17469                 :            :                                                 ENOTSUP,
   17470                 :            :                                                 RTE_MTR_ERROR_TYPE_METER_POLICY,
   17471                 :            :                                                 NULL, "cannot register policy set tag/modify field action");
   17472                 :          0 :                                 act_cnt->modify_hdr =
   17473                 :          0 :                                         dev_flow.handle->dvh.modify_hdr;
   17474                 :            :                         }
   17475                 :            :                 }
   17476                 :            :         }
   17477                 :            :         return 0;
   17478                 :            : }
   17479                 :            : 
   17480                 :            : /**
   17481                 :            :  * Create policy action per domain, lock free,
   17482                 :            :  * (mutex should be acquired by caller).
   17483                 :            :  * Dispatcher for action type specific call.
   17484                 :            :  *
   17485                 :            :  * @param[in] dev
   17486                 :            :  *   Pointer to the Ethernet device structure.
   17487                 :            :  * @param[in] mtr_policy
   17488                 :            :  *   Meter policy struct.
   17489                 :            :  * @param[in] action
   17490                 :            :  *   Action specification used to create meter actions.
   17491                 :            :  * @param[in] attr
   17492                 :            :  *   Pointer to the flow attributes.
   17493                 :            :  * @param[out] error
   17494                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   17495                 :            :  *   error only.
   17496                 :            :  *
   17497                 :            :  * @return
   17498                 :            :  *   0 on success, otherwise negative errno value.
   17499                 :            :  */
   17500                 :            : static int
   17501                 :          0 : flow_dv_create_mtr_policy_acts(struct rte_eth_dev *dev,
   17502                 :            :                       struct mlx5_flow_meter_policy *mtr_policy,
   17503                 :            :                       const struct rte_flow_action *actions[RTE_COLORS],
   17504                 :            :                       struct rte_flow_attr *attr,
   17505                 :            :                       struct rte_mtr_error *error)
   17506                 :            : {
   17507                 :            :         int ret, i;
   17508                 :            :         uint16_t sub_policy_num;
   17509                 :            : 
   17510         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
   17511                 :          0 :                 sub_policy_num = (mtr_policy->sub_policy_num >>
   17512                 :          0 :                         (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i)) &
   17513                 :            :                         MLX5_MTR_SUB_POLICY_NUM_MASK;
   17514         [ #  # ]:          0 :                 if (sub_policy_num) {
   17515                 :          0 :                         ret = __flow_dv_create_domain_policy_acts(dev,
   17516                 :            :                                 mtr_policy, actions, attr,
   17517                 :            :                                 (enum mlx5_meter_domain)i, error);
   17518                 :            :                         /* Cleaning resource is done in the caller level. */
   17519         [ #  # ]:          0 :                         if (ret)
   17520                 :          0 :                                 return ret;
   17521                 :            :                 }
   17522                 :            :         }
   17523                 :            :         return 0;
   17524                 :            : }
   17525                 :            : 
   17526                 :            : /**
   17527                 :            :  * Query a DV flow rule for its statistics via DevX.
   17528                 :            :  *
   17529                 :            :  * @param[in] dev
   17530                 :            :  *   Pointer to Ethernet device.
   17531                 :            :  * @param[in] cnt_idx
   17532                 :            :  *   Index to the flow counter.
   17533                 :            :  * @param[out] data
   17534                 :            :  *   Data retrieved by the query.
   17535                 :            :  * @param[out] error
   17536                 :            :  *   Perform verbose error reporting if not NULL.
   17537                 :            :  *
   17538                 :            :  * @return
   17539                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   17540                 :            :  */
   17541                 :            : static int
   17542                 :          0 : flow_dv_query_count(struct rte_eth_dev *dev, uint32_t cnt_idx, void *data,
   17543                 :            :                     struct rte_flow_error *error)
   17544                 :            : {
   17545                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   17546                 :            :         struct rte_flow_query_count *qc = data;
   17547                 :            : 
   17548         [ #  # ]:          0 :         if (!priv->sh->cdev->config.devx)
   17549                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
   17550                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   17551                 :            :                                           NULL,
   17552                 :            :                                           "counters are not supported");
   17553         [ #  # ]:          0 :         if (cnt_idx) {
   17554                 :            :                 uint64_t pkts, bytes;
   17555                 :            :                 struct mlx5_flow_counter *cnt;
   17556                 :          0 :                 int err = _flow_dv_query_count(dev, cnt_idx, &pkts, &bytes);
   17557                 :            : 
   17558         [ #  # ]:          0 :                 if (err)
   17559                 :          0 :                         return rte_flow_error_set(error, -err,
   17560                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   17561                 :            :                                         NULL, "cannot read counters");
   17562                 :            :                 cnt = flow_dv_counter_get_by_idx(dev, cnt_idx, NULL);
   17563                 :          0 :                 qc->hits_set = 1;
   17564                 :          0 :                 qc->bytes_set = 1;
   17565                 :          0 :                 qc->hits = pkts - cnt->hits;
   17566                 :          0 :                 qc->bytes = bytes - cnt->bytes;
   17567         [ #  # ]:          0 :                 if (qc->reset) {
   17568                 :          0 :                         cnt->hits = pkts;
   17569                 :          0 :                         cnt->bytes = bytes;
   17570                 :            :                 }
   17571                 :          0 :                 return 0;
   17572                 :            :         }
   17573                 :          0 :         return rte_flow_error_set(error, EINVAL,
   17574                 :            :                                   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   17575                 :            :                                   NULL,
   17576                 :            :                                   "counters are not available");
   17577                 :            : }
   17578                 :            : 
   17579                 :            : int
   17580                 :          0 : flow_dv_action_query(struct rte_eth_dev *dev,
   17581                 :            :                      const struct rte_flow_action_handle *handle, void *data,
   17582                 :            :                      struct rte_flow_error *error)
   17583                 :            : {
   17584                 :            :         struct mlx5_age_param *age_param;
   17585                 :            :         struct rte_flow_query_age *resp;
   17586                 :          0 :         uint32_t act_idx = (uint32_t)(uintptr_t)handle;
   17587                 :          0 :         uint32_t type = act_idx >> MLX5_INDIRECT_ACTION_TYPE_OFFSET;
   17588                 :          0 :         uint32_t idx = act_idx & ((1u << MLX5_INDIRECT_ACTION_TYPE_OFFSET) - 1);
   17589                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   17590                 :            :         struct mlx5_aso_ct_action *ct;
   17591                 :            :         uint16_t owner;
   17592                 :            :         uint32_t dev_idx;
   17593                 :            : 
   17594   [ #  #  #  # ]:          0 :         switch (type) {
   17595                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_AGE:
   17596                 :          0 :                 age_param = &flow_aso_age_get_by_idx(dev, idx)->age_params;
   17597                 :            :                 resp = data;
   17598                 :          0 :                 resp->aged = __atomic_load_n(&age_param->state,
   17599                 :            :                                               __ATOMIC_RELAXED) == AGE_TMOUT ?
   17600                 :          0 :                                                                           1 : 0;
   17601                 :          0 :                 resp->sec_since_last_hit_valid = !resp->aged;
   17602         [ #  # ]:          0 :                 if (resp->sec_since_last_hit_valid)
   17603                 :          0 :                         resp->sec_since_last_hit = __atomic_load_n
   17604                 :          0 :                              (&age_param->sec_since_last_hit, __ATOMIC_RELAXED);
   17605                 :            :                 return 0;
   17606                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_COUNT:
   17607                 :          0 :                 return flow_dv_query_count(dev, idx, data, error);
   17608                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_CT:
   17609                 :          0 :                 owner = (uint16_t)MLX5_INDIRECT_ACT_CT_GET_OWNER(idx);
   17610         [ #  # ]:          0 :                 if (owner != PORT_ID(priv))
   17611                 :          0 :                         return rte_flow_error_set(error, EACCES,
   17612                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   17613                 :            :                                         NULL,
   17614                 :            :                                         "CT object owned by another port");
   17615                 :          0 :                 dev_idx = MLX5_INDIRECT_ACT_CT_GET_IDX(idx);
   17616                 :          0 :                 ct = flow_aso_ct_get_by_dev_idx(dev, dev_idx);
   17617                 :            :                 MLX5_ASSERT(ct);
   17618         [ #  # ]:          0 :                 if (!ct->refcnt)
   17619                 :          0 :                         return rte_flow_error_set(error, EFAULT,
   17620                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   17621                 :            :                                         NULL,
   17622                 :            :                                         "CT object is inactive");
   17623                 :          0 :                 ((struct rte_flow_action_conntrack *)data)->peer_port =
   17624                 :          0 :                                                         ct->peer;
   17625                 :          0 :                 ((struct rte_flow_action_conntrack *)data)->is_original_dir =
   17626                 :          0 :                                                         ct->is_original;
   17627         [ #  # ]:          0 :                 if (mlx5_aso_ct_query_by_wqe(priv->sh, MLX5_HW_INV_QUEUE, ct,
   17628                 :            :                                         data, NULL, true))
   17629                 :          0 :                         return rte_flow_error_set(error, EIO,
   17630                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   17631                 :            :                                         NULL,
   17632                 :            :                                         "Failed to query CT context");
   17633                 :            :                 return 0;
   17634                 :          0 :         default:
   17635                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
   17636                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   17637                 :            :                                           "action type query not supported");
   17638                 :            :         }
   17639                 :            : }
   17640                 :            : 
   17641                 :            : /**
   17642                 :            :  * Query a flow rule AGE action for aging information.
   17643                 :            :  *
   17644                 :            :  * @param[in] dev
   17645                 :            :  *   Pointer to Ethernet device.
   17646                 :            :  * @param[in] flow
   17647                 :            :  *   Pointer to the sub flow.
   17648                 :            :  * @param[out] data
   17649                 :            :  *   data retrieved by the query.
   17650                 :            :  * @param[out] error
   17651                 :            :  *   Perform verbose error reporting if not NULL.
   17652                 :            :  *
   17653                 :            :  * @return
   17654                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   17655                 :            :  */
   17656                 :            : static int
   17657                 :          0 : flow_dv_query_age(struct rte_eth_dev *dev, struct rte_flow *flow,
   17658                 :            :                   void *data, struct rte_flow_error *error)
   17659                 :            : {
   17660                 :            :         struct rte_flow_query_age *resp = data;
   17661                 :            :         struct mlx5_age_param *age_param;
   17662                 :            : 
   17663         [ #  # ]:          0 :         if (flow->age) {
   17664                 :            :                 struct mlx5_aso_age_action *act =
   17665                 :          0 :                                      flow_aso_age_get_by_idx(dev, flow->age);
   17666                 :            : 
   17667                 :          0 :                 age_param = &act->age_params;
   17668         [ #  # ]:          0 :         } else if (flow->counter) {
   17669                 :            :                 age_param = flow_dv_counter_idx_get_age(dev, flow->counter);
   17670                 :            : 
   17671         [ #  # ]:          0 :                 if (!age_param || !age_param->timeout)
   17672                 :          0 :                         return rte_flow_error_set
   17673                 :            :                                         (error, EINVAL,
   17674                 :            :                                          RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   17675                 :            :                                          NULL, "cannot read age data");
   17676                 :            :         } else {
   17677                 :          0 :                 return rte_flow_error_set(error, EINVAL,
   17678                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   17679                 :            :                                           NULL, "age data not available");
   17680                 :            :         }
   17681                 :          0 :         resp->aged = __atomic_load_n(&age_param->state, __ATOMIC_RELAXED) ==
   17682                 :          0 :                                      AGE_TMOUT ? 1 : 0;
   17683                 :          0 :         resp->sec_since_last_hit_valid = !resp->aged;
   17684         [ #  # ]:          0 :         if (resp->sec_since_last_hit_valid)
   17685                 :          0 :                 resp->sec_since_last_hit = __atomic_load_n
   17686                 :          0 :                              (&age_param->sec_since_last_hit, __ATOMIC_RELAXED);
   17687                 :            :         return 0;
   17688                 :            : }
   17689                 :            : 
   17690                 :            : /**
   17691                 :            :  * Query a flow.
   17692                 :            :  *
   17693                 :            :  * @see rte_flow_query()
   17694                 :            :  * @see rte_flow_ops
   17695                 :            :  */
   17696                 :            : static int
   17697                 :          0 : flow_dv_query(struct rte_eth_dev *dev,
   17698                 :            :               struct rte_flow *flow __rte_unused,
   17699                 :            :               const struct rte_flow_action *actions __rte_unused,
   17700                 :            :               void *data __rte_unused,
   17701                 :            :               struct rte_flow_error *error __rte_unused)
   17702                 :            : {
   17703                 :            :         int ret = -EINVAL;
   17704                 :            : 
   17705         [ #  # ]:          0 :         for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
   17706   [ #  #  #  # ]:          0 :                 switch (actions->type) {
   17707                 :            :                 case RTE_FLOW_ACTION_TYPE_VOID:
   17708                 :            :                         break;
   17709                 :          0 :                 case RTE_FLOW_ACTION_TYPE_COUNT:
   17710                 :          0 :                         ret = flow_dv_query_count(dev, flow->counter, data,
   17711                 :            :                                                   error);
   17712                 :          0 :                         break;
   17713                 :          0 :                 case RTE_FLOW_ACTION_TYPE_AGE:
   17714                 :          0 :                         ret = flow_dv_query_age(dev, flow, data, error);
   17715                 :          0 :                         break;
   17716                 :          0 :                 default:
   17717                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
   17718                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
   17719                 :            :                                                   actions,
   17720                 :            :                                                   "action not supported");
   17721                 :            :                 }
   17722                 :            :         }
   17723                 :            :         return ret;
   17724                 :            : }
   17725                 :            : 
   17726                 :            : /**
   17727                 :            :  * Destroy the meter table set.
   17728                 :            :  * Lock free, (mutex should be acquired by caller).
   17729                 :            :  *
   17730                 :            :  * @param[in] dev
   17731                 :            :  *   Pointer to Ethernet device.
   17732                 :            :  * @param[in] fm
   17733                 :            :  *   Meter information table.
   17734                 :            :  */
   17735                 :            : static void
   17736                 :          0 : flow_dv_destroy_mtr_tbls(struct rte_eth_dev *dev,
   17737                 :            :                         struct mlx5_flow_meter_info *fm)
   17738                 :            : {
   17739                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   17740                 :            :         int i;
   17741                 :            : 
   17742   [ #  #  #  # ]:          0 :         if (!fm || !priv->sh->config.dv_flow_en)
   17743                 :            :                 return;
   17744         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
   17745         [ #  # ]:          0 :                 if (fm->drop_rule[i]) {
   17746                 :            :                         claim_zero(mlx5_flow_os_destroy_flow(fm->drop_rule[i]));
   17747                 :          0 :                         fm->drop_rule[i] = NULL;
   17748                 :            :                 }
   17749                 :            :         }
   17750                 :            : }
   17751                 :            : 
   17752                 :            : static void
   17753                 :          0 : flow_dv_destroy_mtr_drop_tbls(struct rte_eth_dev *dev)
   17754                 :            : {
   17755                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   17756                 :          0 :         struct mlx5_flow_mtr_mng *mtrmng = priv->sh->mtrmng;
   17757                 :            :         struct mlx5_flow_tbl_data_entry *tbl;
   17758                 :            :         int i, j;
   17759                 :            : 
   17760         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
   17761         [ #  # ]:          0 :                 if (mtrmng->def_rule[i]) {
   17762                 :            :                         claim_zero(mlx5_flow_os_destroy_flow
   17763                 :            :                                         (mtrmng->def_rule[i]));
   17764                 :          0 :                         mtrmng->def_rule[i] = NULL;
   17765                 :            :                 }
   17766         [ #  # ]:          0 :                 if (mtrmng->def_matcher[i]) {
   17767                 :          0 :                         tbl = container_of(mtrmng->def_matcher[i]->tbl,
   17768                 :            :                                 struct mlx5_flow_tbl_data_entry, tbl);
   17769                 :          0 :                         mlx5_list_unregister(tbl->matchers,
   17770                 :            :                                              &mtrmng->def_matcher[i]->entry);
   17771                 :          0 :                         mtrmng->def_matcher[i] = NULL;
   17772                 :            :                 }
   17773         [ #  # ]:          0 :                 for (j = 0; j < MLX5_REG_BITS; j++) {
   17774         [ #  # ]:          0 :                         if (mtrmng->drop_matcher[i][j]) {
   17775                 :            :                                 tbl =
   17776                 :          0 :                                 container_of(mtrmng->drop_matcher[i][j]->tbl,
   17777                 :            :                                              struct mlx5_flow_tbl_data_entry,
   17778                 :            :                                              tbl);
   17779                 :          0 :                                 mlx5_list_unregister(tbl->matchers,
   17780                 :            :                                             &mtrmng->drop_matcher[i][j]->entry);
   17781                 :          0 :                                 mtrmng->drop_matcher[i][j] = NULL;
   17782                 :            :                         }
   17783                 :            :                 }
   17784         [ #  # ]:          0 :                 if (mtrmng->drop_tbl[i]) {
   17785                 :          0 :                         flow_dv_tbl_resource_release(MLX5_SH(dev),
   17786                 :            :                                 mtrmng->drop_tbl[i]);
   17787                 :          0 :                         mtrmng->drop_tbl[i] = NULL;
   17788                 :            :                 }
   17789                 :            :         }
   17790                 :          0 : }
   17791                 :            : 
   17792                 :            : /* Number of meter flow actions, count and jump or count and drop. */
   17793                 :            : #define METER_ACTIONS 2
   17794                 :            : 
   17795                 :            : static void
   17796                 :          0 : __flow_dv_destroy_domain_def_policy(struct rte_eth_dev *dev,
   17797                 :            :                                     enum mlx5_meter_domain domain)
   17798                 :            : {
   17799                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   17800                 :          0 :         struct mlx5_flow_meter_def_policy *def_policy =
   17801                 :          0 :                         priv->sh->mtrmng->def_policy[domain];
   17802                 :            : 
   17803                 :          0 :         __flow_dv_destroy_sub_policy_rules(dev, &def_policy->sub_policy);
   17804                 :          0 :         mlx5_free(def_policy);
   17805                 :          0 :         priv->sh->mtrmng->def_policy[domain] = NULL;
   17806                 :          0 : }
   17807                 :            : 
   17808                 :            : /**
   17809                 :            :  * Destroy the default policy table set.
   17810                 :            :  *
   17811                 :            :  * @param[in] dev
   17812                 :            :  *   Pointer to Ethernet device.
   17813                 :            :  */
   17814                 :            : static void
   17815                 :          0 : flow_dv_destroy_def_policy(struct rte_eth_dev *dev)
   17816                 :            : {
   17817                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   17818                 :            :         int i;
   17819                 :            : 
   17820         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++)
   17821         [ #  # ]:          0 :                 if (priv->sh->mtrmng->def_policy[i])
   17822                 :          0 :                         __flow_dv_destroy_domain_def_policy(dev,
   17823                 :            :                                         (enum mlx5_meter_domain)i);
   17824                 :          0 :         priv->sh->mtrmng->def_policy_id = MLX5_INVALID_POLICY_ID;
   17825                 :          0 : }
   17826                 :            : 
   17827                 :            : static int
   17828                 :          0 : __flow_dv_create_policy_flow(struct rte_eth_dev *dev,
   17829                 :            :                         uint32_t color_reg_c_idx,
   17830                 :            :                         enum rte_color color, struct mlx5_flow_dv_matcher *matcher,
   17831                 :            :                         int actions_n, void *actions,
   17832                 :            :                         bool match_src_port, const struct rte_flow_item *item,
   17833                 :            :                         void **rule, const struct rte_flow_attr *attr)
   17834                 :            : {
   17835                 :            :         int ret;
   17836                 :          0 :         struct mlx5_flow_dv_match_params value = {
   17837                 :            :                 .size = sizeof(value.buf),
   17838                 :            :         };
   17839                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   17840                 :            :         uint8_t misc_mask;
   17841                 :            : 
   17842   [ #  #  #  # ]:          0 :         if (match_src_port && priv->sh->esw_mode) {
   17843   [ #  #  #  # ]:          0 :                 if (item && item->type == RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT)
   17844                 :          0 :                         ret = flow_dv_translate_item_represented_port(dev, value.buf,
   17845                 :            :                                                 item, attr, MLX5_SET_MATCHER_SW_V);
   17846   [ #  #  #  # ]:          0 :                 else if (item && item->type == RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR)
   17847                 :          0 :                         ret = flow_dv_translate_item_port_representor(dev, value.buf,
   17848                 :            :                                                                       MLX5_SET_MATCHER_SW_V);
   17849                 :            :                 else
   17850                 :          0 :                         ret = flow_dv_translate_item_port_id(dev, value.buf,
   17851                 :            :                                                 item, attr, MLX5_SET_MATCHER_SW_V);
   17852         [ #  # ]:          0 :                 if (ret) {
   17853                 :          0 :                         DRV_LOG(ERR, "Failed to create meter policy%d flow's"
   17854                 :            :                                 " value with port.", color);
   17855                 :          0 :                         return -1;
   17856                 :            :                 }
   17857                 :            :         }
   17858                 :          0 :         flow_dv_match_meta_reg(value.buf, (enum modify_reg)color_reg_c_idx,
   17859                 :            :                                rte_col_2_mlx5_col(color), UINT32_MAX);
   17860         [ #  # ]:          0 :         misc_mask = flow_dv_matcher_enable(matcher->mask.buf);
   17861                 :            :         __flow_dv_adjust_buf_size(&value.size, misc_mask);
   17862                 :          0 :         ret = mlx5_flow_os_create_flow(matcher->matcher_object, (void *)&value,
   17863                 :            :                                        actions_n, actions, rule);
   17864                 :            :         if (ret) {
   17865                 :          0 :                 DRV_LOG(ERR, "Failed to create meter policy%d flow.", color);
   17866                 :          0 :                 return -1;
   17867                 :            :         }
   17868                 :            :         return 0;
   17869                 :            : }
   17870                 :            : 
   17871                 :            : static int
   17872                 :          0 : __flow_dv_create_policy_matcher(struct rte_eth_dev *dev,
   17873                 :            :                         uint32_t color_reg_c_idx,
   17874                 :            :                         uint16_t priority,
   17875                 :            :                         struct mlx5_flow_meter_sub_policy *sub_policy,
   17876                 :            :                         const struct rte_flow_attr *attr,
   17877                 :            :                         bool match_src_port,
   17878                 :            :                         const struct rte_flow_item *item,
   17879                 :            :                         struct mlx5_flow_dv_matcher **policy_matcher,
   17880                 :            :                         struct rte_flow_error *error)
   17881                 :            : {
   17882                 :            :         struct mlx5_list_entry *entry;
   17883                 :          0 :         struct mlx5_flow_tbl_resource *tbl_rsc = sub_policy->tbl_rsc;
   17884                 :          0 :         struct mlx5_flow_dv_matcher matcher = {
   17885                 :            :                 .mask = {
   17886                 :            :                         .size = sizeof(matcher.mask.buf),
   17887                 :            :                 },
   17888                 :            :                 .tbl = tbl_rsc,
   17889                 :            :         };
   17890                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
   17891                 :            :                 .error = error,
   17892                 :            :                 .data = &matcher,
   17893                 :            :         };
   17894                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data;
   17895                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   17896                 :            :         const uint32_t color_mask = (UINT32_C(1) << MLX5_MTR_COLOR_BITS) - 1;
   17897                 :            :         int ret;
   17898                 :            : 
   17899   [ #  #  #  # ]:          0 :         if (match_src_port && priv->sh->esw_mode) {
   17900   [ #  #  #  # ]:          0 :                 if (item && item->type == RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT)
   17901                 :          0 :                         ret = flow_dv_translate_item_represented_port(dev, matcher.mask.buf,
   17902                 :            :                                                 item, attr, MLX5_SET_MATCHER_SW_M);
   17903   [ #  #  #  # ]:          0 :                 else if (item && item->type == RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR)
   17904                 :          0 :                         ret = flow_dv_translate_item_port_representor(dev, matcher.mask.buf,
   17905                 :            :                                                                       MLX5_SET_MATCHER_SW_M);
   17906                 :            :                 else
   17907                 :          0 :                         ret = flow_dv_translate_item_port_id(dev, matcher.mask.buf,
   17908                 :            :                                                 item, attr, MLX5_SET_MATCHER_SW_M);
   17909         [ #  # ]:          0 :                 if (ret) {
   17910                 :          0 :                         DRV_LOG(ERR, "Failed to register meter policy%d matcher"
   17911                 :            :                                 " with port.", priority);
   17912                 :          0 :                         return -1;
   17913                 :            :                 }
   17914                 :            :         }
   17915                 :          0 :         tbl_data = container_of(tbl_rsc, struct mlx5_flow_tbl_data_entry, tbl);
   17916                 :          0 :         flow_dv_match_meta_reg(matcher.mask.buf,
   17917                 :            :                 (enum modify_reg)color_reg_c_idx, color_mask, color_mask);
   17918                 :          0 :         matcher.priority = priority;
   17919                 :          0 :         matcher.crc = rte_raw_cksum((const void *)matcher.mask.buf,
   17920                 :            :                                     matcher.mask.size);
   17921                 :          0 :         entry = mlx5_list_register(tbl_data->matchers, &ctx);
   17922         [ #  # ]:          0 :         if (!entry) {
   17923                 :          0 :                 DRV_LOG(ERR, "Failed to register meter drop matcher.");
   17924                 :          0 :                 return -1;
   17925                 :            :         }
   17926                 :          0 :         *policy_matcher =
   17927                 :            :                 container_of(entry, struct mlx5_flow_dv_matcher, entry);
   17928                 :          0 :         return 0;
   17929                 :            : }
   17930                 :            : 
   17931                 :            : /**
   17932                 :            :  * Create the policy rules per domain.
   17933                 :            :  *
   17934                 :            :  * @param[in] dev
   17935                 :            :  *   Pointer to Ethernet device.
   17936                 :            :  * @param[in] sub_policy
   17937                 :            :  *    Pointer to sub policy table..
   17938                 :            :  * @param[in] egress
   17939                 :            :  *   Direction of the table.
   17940                 :            :  * @param[in] transfer
   17941                 :            :  *   E-Switch or NIC flow.
   17942                 :            :  * @param[in] acts
   17943                 :            :  *   Pointer to policy action list per color.
   17944                 :            :  *
   17945                 :            :  * @return
   17946                 :            :  *   0 on success, -1 otherwise.
   17947                 :            :  */
   17948                 :            : static int
   17949                 :          0 : __flow_dv_create_domain_policy_rules(struct rte_eth_dev *dev,
   17950                 :            :                 struct mlx5_flow_meter_sub_policy *sub_policy,
   17951                 :            :                 uint8_t egress, uint8_t transfer, bool match_src_port,
   17952                 :            :                 struct mlx5_meter_policy_acts acts[RTE_COLORS])
   17953                 :            : {
   17954                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   17955                 :            :         struct rte_flow_error flow_err;
   17956                 :            :         uint32_t color_reg_c_idx;
   17957                 :          0 :         struct rte_flow_attr attr = {
   17958                 :            :                 .group = MLX5_FLOW_TABLE_LEVEL_POLICY,
   17959                 :            :                 .priority = 0,
   17960                 :            :                 .ingress = 0,
   17961                 :          0 :                 .egress = !!egress,
   17962                 :          0 :                 .transfer = !!transfer,
   17963                 :            :                 .reserved = 0,
   17964                 :            :         };
   17965                 :            :         int i;
   17966                 :          0 :         int ret = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR, 0, &flow_err);
   17967                 :            :         struct mlx5_sub_policy_color_rule *color_rule;
   17968                 :          0 :         struct mlx5_sub_policy_color_rule *tmp_rules[RTE_COLORS] = {NULL};
   17969                 :            : 
   17970         [ #  # ]:          0 :         if (ret < 0)
   17971                 :            :                 return -1;
   17972                 :            :         /* Create policy table with POLICY level. */
   17973         [ #  # ]:          0 :         if (!sub_policy->tbl_rsc)
   17974                 :          0 :                 sub_policy->tbl_rsc = flow_dv_tbl_resource_get(dev,
   17975                 :            :                                 MLX5_FLOW_TABLE_LEVEL_POLICY,
   17976                 :            :                                 egress, transfer, false, NULL, 0, 0,
   17977                 :          0 :                                 sub_policy->idx, &flow_err);
   17978         [ #  # ]:          0 :         if (!sub_policy->tbl_rsc) {
   17979                 :          0 :                 DRV_LOG(ERR,
   17980                 :            :                         "Failed to create meter sub policy table.");
   17981                 :          0 :                 return -1;
   17982                 :            :         }
   17983                 :            :         /* Prepare matchers. */
   17984                 :          0 :         color_reg_c_idx = ret;
   17985         [ #  # ]:          0 :         for (i = 0; i < RTE_COLORS; i++) {
   17986                 :          0 :                 TAILQ_INIT(&sub_policy->color_rules[i]);
   17987         [ #  # ]:          0 :                 if (!acts[i].actions_n)
   17988                 :          0 :                         continue;
   17989                 :          0 :                 color_rule = mlx5_malloc(MLX5_MEM_ZERO,
   17990                 :            :                                 sizeof(struct mlx5_sub_policy_color_rule),
   17991                 :            :                                 0, SOCKET_ID_ANY);
   17992         [ #  # ]:          0 :                 if (!color_rule) {
   17993                 :          0 :                         DRV_LOG(ERR, "No memory to create color rule.");
   17994                 :          0 :                         goto err_exit;
   17995                 :            :                 }
   17996                 :          0 :                 tmp_rules[i] = color_rule;
   17997                 :          0 :                 TAILQ_INSERT_TAIL(&sub_policy->color_rules[i],
   17998                 :            :                                   color_rule, next_port);
   17999                 :          0 :                 color_rule->src_port = priv->representor_id;
   18000                 :            :                 /* No use. */
   18001                 :          0 :                 attr.priority = i;
   18002                 :            :                 /* Create matchers for colors. */
   18003         [ #  # ]:          0 :                 if (__flow_dv_create_policy_matcher(dev, color_reg_c_idx,
   18004                 :            :                                 MLX5_MTR_POLICY_MATCHER_PRIO, sub_policy,
   18005                 :            :                                 &attr, match_src_port, NULL,
   18006                 :            :                                 &color_rule->matcher, &flow_err)) {
   18007                 :          0 :                         DRV_LOG(ERR, "Failed to create color%u matcher.", i);
   18008                 :          0 :                         goto err_exit;
   18009                 :            :                 }
   18010                 :            :                 /* Create flow, matching color. */
   18011         [ #  # ]:          0 :                 if (__flow_dv_create_policy_flow(dev,
   18012                 :            :                                 color_reg_c_idx, (enum rte_color)i,
   18013                 :            :                                 color_rule->matcher,
   18014                 :          0 :                                 acts[i].actions_n, acts[i].dv_actions,
   18015                 :            :                                 match_src_port, NULL, &color_rule->rule,
   18016                 :            :                                 &attr)) {
   18017                 :          0 :                         DRV_LOG(ERR, "Failed to create color%u rule.", i);
   18018                 :          0 :                         goto err_exit;
   18019                 :            :                 }
   18020                 :            :         }
   18021                 :            :         return 0;
   18022                 :            : err_exit:
   18023                 :            :         /* All the policy rules will be cleared. */
   18024                 :            :         do {
   18025                 :          0 :                 color_rule = tmp_rules[i];
   18026         [ #  # ]:          0 :                 if (color_rule) {
   18027         [ #  # ]:          0 :                         if (color_rule->rule)
   18028                 :            :                                 mlx5_flow_os_destroy_flow(color_rule->rule);
   18029         [ #  # ]:          0 :                         if (color_rule->matcher) {
   18030                 :            :                                 struct mlx5_flow_tbl_data_entry *tbl =
   18031                 :          0 :                                         container_of(color_rule->matcher->tbl,
   18032                 :            :                                                      typeof(*tbl), tbl);
   18033                 :          0 :                                 mlx5_list_unregister(tbl->matchers,
   18034                 :            :                                                 &color_rule->matcher->entry);
   18035                 :            :                         }
   18036         [ #  # ]:          0 :                         TAILQ_REMOVE(&sub_policy->color_rules[i],
   18037                 :            :                                      color_rule, next_port);
   18038                 :          0 :                         mlx5_free(color_rule);
   18039                 :            :                 }
   18040         [ #  # ]:          0 :         } while (i--);
   18041                 :            :         return -1;
   18042                 :            : }
   18043                 :            : 
   18044                 :            : static int
   18045                 :          0 : __flow_dv_create_policy_acts_rules(struct rte_eth_dev *dev,
   18046                 :            :                         struct mlx5_flow_meter_policy *mtr_policy,
   18047                 :            :                         struct mlx5_flow_meter_sub_policy *sub_policy,
   18048                 :            :                         uint32_t domain)
   18049                 :            : {
   18050                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   18051                 :            :         struct mlx5_meter_policy_acts acts[RTE_COLORS];
   18052                 :            :         struct mlx5_flow_dv_tag_resource *tag;
   18053                 :            :         struct mlx5_flow_dv_port_id_action_resource *port_action;
   18054                 :            :         struct mlx5_hrxq *hrxq;
   18055                 :          0 :         struct mlx5_flow_meter_info *next_fm[RTE_COLORS] = {NULL};
   18056                 :            :         struct mlx5_flow_meter_policy *next_policy;
   18057                 :            :         struct mlx5_flow_meter_sub_policy *next_sub_policy;
   18058                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data;
   18059                 :            :         struct rte_flow_error error;
   18060                 :          0 :         uint8_t egress = (domain == MLX5_MTR_DOMAIN_EGRESS) ? 1 : 0;
   18061                 :          0 :         uint8_t transfer = (domain == MLX5_MTR_DOMAIN_TRANSFER) ? 1 : 0;
   18062   [ #  #  #  #  :          0 :         bool mtr_first = egress || (transfer && priv->representor_id != UINT16_MAX);
                   #  # ]
   18063                 :            :         bool match_src_port = false;
   18064                 :            :         int i;
   18065                 :            : 
   18066                 :            :         /* If RSS or Queue, no previous actions / rules is created. */
   18067         [ #  # ]:          0 :         for (i = 0; i < RTE_COLORS; i++) {
   18068                 :          0 :                 acts[i].actions_n = 0;
   18069         [ #  # ]:          0 :                 if (i == RTE_COLOR_RED) {
   18070                 :            :                         /* Only support drop on red. */
   18071                 :          0 :                         acts[i].dv_actions[0] =
   18072                 :          0 :                                 mtr_policy->dr_drop_action[domain];
   18073                 :          0 :                         acts[i].actions_n = 1;
   18074                 :          0 :                         continue;
   18075                 :            :                 }
   18076         [ #  # ]:          0 :                 if (mtr_policy->act_cnt[i].fate_action == MLX5_FLOW_FATE_MTR) {
   18077                 :          0 :                         struct rte_flow_attr attr = {
   18078                 :            :                                 .transfer = transfer
   18079                 :            :                         };
   18080                 :            : 
   18081                 :          0 :                         next_fm[i] = mlx5_flow_meter_find(priv,
   18082                 :            :                                         mtr_policy->act_cnt[i].next_mtr_id,
   18083                 :            :                                         NULL);
   18084         [ #  # ]:          0 :                         if (!next_fm[i]) {
   18085                 :          0 :                                 DRV_LOG(ERR,
   18086                 :            :                                         "Failed to get next hierarchy meter.");
   18087                 :          0 :                                 goto err_exit;
   18088                 :            :                         }
   18089         [ #  # ]:          0 :                         if (mlx5_flow_meter_attach(priv, next_fm[i],
   18090                 :            :                                                    &attr, &error)) {
   18091                 :          0 :                                 DRV_LOG(ERR, "%s", error.message);
   18092                 :          0 :                                 next_fm[i] = NULL;
   18093                 :          0 :                                 goto err_exit;
   18094                 :            :                         }
   18095                 :            :                         /* Meter action must be the first for TX. */
   18096         [ #  # ]:          0 :                         if (mtr_first) {
   18097                 :          0 :                                 acts[i].dv_actions[acts[i].actions_n] =
   18098         [ #  # ]:          0 :                                         (next_fm[i]->color_aware && i == RTE_COLOR_YELLOW) ?
   18099         [ #  # ]:          0 :                                                 next_fm[i]->meter_action_y :
   18100                 :            :                                                 next_fm[i]->meter_action_g;
   18101                 :          0 :                                 acts[i].actions_n++;
   18102                 :            :                         }
   18103                 :            :                 }
   18104         [ #  # ]:          0 :                 if (mtr_policy->act_cnt[i].rix_mark) {
   18105                 :          0 :                         tag = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_TAG],
   18106                 :            :                                         mtr_policy->act_cnt[i].rix_mark);
   18107         [ #  # ]:          0 :                         if (!tag) {
   18108                 :          0 :                                 DRV_LOG(ERR, "Failed to find "
   18109                 :            :                                 "mark action for policy.");
   18110                 :          0 :                                 goto err_exit;
   18111                 :            :                         }
   18112                 :          0 :                         acts[i].dv_actions[acts[i].actions_n] = tag->action;
   18113                 :          0 :                         acts[i].actions_n++;
   18114                 :            :                 }
   18115         [ #  # ]:          0 :                 if (mtr_policy->act_cnt[i].modify_hdr) {
   18116                 :          0 :                         acts[i].dv_actions[acts[i].actions_n] =
   18117                 :          0 :                                 mtr_policy->act_cnt[i].modify_hdr->action;
   18118                 :          0 :                         acts[i].actions_n++;
   18119                 :            :                 }
   18120         [ #  # ]:          0 :                 if (mtr_policy->act_cnt[i].fate_action) {
   18121   [ #  #  #  #  :          0 :                         switch (mtr_policy->act_cnt[i].fate_action) {
                      # ]
   18122                 :          0 :                         case MLX5_FLOW_FATE_PORT_ID:
   18123                 :          0 :                                 port_action = mlx5_ipool_get
   18124                 :          0 :                                         (priv->sh->ipool[MLX5_IPOOL_PORT_ID],
   18125                 :            :                                 mtr_policy->act_cnt[i].rix_port_id_action);
   18126         [ #  # ]:          0 :                                 if (!port_action) {
   18127                 :          0 :                                         DRV_LOG(ERR, "Failed to find "
   18128                 :            :                                                 "port action for policy.");
   18129                 :          0 :                                         goto err_exit;
   18130                 :            :                                 }
   18131                 :          0 :                                 acts[i].dv_actions[acts[i].actions_n] =
   18132                 :          0 :                                         port_action->action;
   18133                 :          0 :                                 acts[i].actions_n++;
   18134                 :            :                                 match_src_port = true;
   18135                 :          0 :                                 break;
   18136                 :          0 :                         case MLX5_FLOW_FATE_DROP:
   18137                 :            :                         case MLX5_FLOW_FATE_JUMP:
   18138                 :          0 :                                 acts[i].dv_actions[acts[i].actions_n] =
   18139                 :          0 :                                 mtr_policy->act_cnt[i].dr_jump_action[domain];
   18140                 :          0 :                                 acts[i].actions_n++;
   18141                 :          0 :                                 break;
   18142                 :          0 :                         case MLX5_FLOW_FATE_SHARED_RSS:
   18143                 :            :                         case MLX5_FLOW_FATE_QUEUE:
   18144                 :          0 :                                 hrxq = mlx5_ipool_get
   18145                 :          0 :                                         (priv->sh->ipool[MLX5_IPOOL_HRXQ],
   18146                 :            :                                          sub_policy->rix_hrxq[i]);
   18147         [ #  # ]:          0 :                                 if (!hrxq) {
   18148                 :          0 :                                         DRV_LOG(ERR, "Failed to find "
   18149                 :            :                                                 "queue action for policy.");
   18150                 :          0 :                                         goto err_exit;
   18151                 :            :                                 }
   18152                 :          0 :                                 acts[i].dv_actions[acts[i].actions_n] =
   18153                 :          0 :                                         hrxq->action;
   18154                 :          0 :                                 acts[i].actions_n++;
   18155                 :          0 :                                 break;
   18156                 :          0 :                         case MLX5_FLOW_FATE_MTR:
   18157         [ #  # ]:          0 :                                 if (!next_fm[i]) {
   18158                 :          0 :                                         DRV_LOG(ERR,
   18159                 :            :                                                 "No next hierarchy meter.");
   18160                 :          0 :                                         goto err_exit;
   18161                 :            :                                 }
   18162         [ #  # ]:          0 :                                 if (!mtr_first) {
   18163                 :          0 :                                         acts[i].dv_actions[acts[i].actions_n] =
   18164         [ #  # ]:          0 :                                                 (next_fm[i]->color_aware && i == RTE_COLOR_YELLOW) ?
   18165         [ #  # ]:          0 :                                                         next_fm[i]->meter_action_y :
   18166                 :            :                                                         next_fm[i]->meter_action_g;
   18167                 :          0 :                                         acts[i].actions_n++;
   18168                 :            :                                 }
   18169         [ #  # ]:          0 :                                 if (mtr_policy->act_cnt[i].next_sub_policy) {
   18170                 :            :                                         next_sub_policy =
   18171                 :            :                                         mtr_policy->act_cnt[i].next_sub_policy;
   18172                 :            :                                 } else {
   18173                 :            :                                         next_policy =
   18174                 :          0 :                                                 mlx5_flow_meter_policy_find(dev,
   18175                 :            :                                                                 next_fm[i]->policy_id, NULL);
   18176                 :            :                                         MLX5_ASSERT(next_policy);
   18177                 :          0 :                                         next_sub_policy =
   18178                 :          0 :                                         next_policy->sub_policys[domain][0];
   18179                 :            :                                 }
   18180                 :            :                                 tbl_data =
   18181                 :          0 :                                         container_of(next_sub_policy->tbl_rsc,
   18182                 :            :                                         struct mlx5_flow_tbl_data_entry, tbl);
   18183                 :          0 :                                 acts[i].dv_actions[acts[i].actions_n++] =
   18184                 :          0 :                                                         tbl_data->jump.action;
   18185         [ #  # ]:          0 :                                 if (mtr_policy->act_cnt[i].modify_hdr)
   18186                 :            :                                         match_src_port = !!transfer;
   18187                 :            :                                 break;
   18188                 :            :                         default:
   18189                 :            :                                 /*Queue action do nothing*/
   18190                 :            :                                 break;
   18191                 :            :                         }
   18192                 :            :                 }
   18193                 :            :         }
   18194         [ #  # ]:          0 :         if (__flow_dv_create_domain_policy_rules(dev, sub_policy,
   18195                 :            :                                 egress, transfer, match_src_port, acts)) {
   18196                 :          0 :                 DRV_LOG(ERR,
   18197                 :            :                         "Failed to create policy rules per domain.");
   18198                 :          0 :                 goto err_exit;
   18199                 :            :         }
   18200         [ #  # ]:          0 :         if (match_src_port) {
   18201                 :          0 :                 mtr_policy->match_port = match_src_port;
   18202                 :          0 :                 mtr_policy->hierarchy_match_port = match_src_port;
   18203                 :            :         }
   18204                 :            :         return 0;
   18205                 :            : err_exit:
   18206         [ #  # ]:          0 :         for (i = 0; i < RTE_COLORS; i++)
   18207         [ #  # ]:          0 :                 if (next_fm[i])
   18208                 :          0 :                         mlx5_flow_meter_detach(priv, next_fm[i]);
   18209                 :            :         return -1;
   18210                 :            : }
   18211                 :            : 
   18212                 :            : /**
   18213                 :            :  * Create the policy rules.
   18214                 :            :  *
   18215                 :            :  * @param[in] dev
   18216                 :            :  *   Pointer to Ethernet device.
   18217                 :            :  * @param[in,out] mtr_policy
   18218                 :            :  *   Pointer to meter policy table.
   18219                 :            :  *
   18220                 :            :  * @return
   18221                 :            :  *   0 on success, -1 otherwise.
   18222                 :            :  */
   18223                 :            : static int
   18224                 :          0 : flow_dv_create_policy_rules(struct rte_eth_dev *dev,
   18225                 :            :                              struct mlx5_flow_meter_policy *mtr_policy)
   18226                 :            : {
   18227                 :            :         int i;
   18228                 :            :         int ret = 0;
   18229                 :            :         uint16_t sub_policy_num;
   18230                 :          0 :         struct mlx5_flow_workspace *wks = mlx5_flow_push_thread_workspace();
   18231                 :            : 
   18232                 :            :         RTE_SET_USED(wks);
   18233         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
   18234                 :          0 :                 sub_policy_num = (mtr_policy->sub_policy_num >>
   18235                 :          0 :                         (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i)) &
   18236                 :            :                         MLX5_MTR_SUB_POLICY_NUM_MASK;
   18237         [ #  # ]:          0 :                 if (!sub_policy_num)
   18238                 :          0 :                         continue;
   18239                 :            :                 /* Prepare actions list and create policy rules. */
   18240         [ #  # ]:          0 :                 if (__flow_dv_create_policy_acts_rules(dev, mtr_policy,
   18241                 :          0 :                         mtr_policy->sub_policys[i][0], i)) {
   18242                 :          0 :                         DRV_LOG(ERR, "Failed to create policy action "
   18243                 :            :                                 "list per domain.");
   18244                 :            :                         ret = -1;
   18245                 :          0 :                         goto exit;
   18246                 :            :                 }
   18247                 :            :         }
   18248                 :          0 : exit:
   18249                 :          0 :         mlx5_flow_pop_thread_workspace();
   18250                 :          0 :         return ret;
   18251                 :            : }
   18252                 :            : 
   18253                 :            : static int
   18254                 :          0 : __flow_dv_create_domain_def_policy(struct rte_eth_dev *dev, uint32_t domain)
   18255                 :            : {
   18256                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   18257                 :          0 :         struct mlx5_flow_mtr_mng *mtrmng = priv->sh->mtrmng;
   18258                 :            :         struct mlx5_flow_meter_def_policy *def_policy;
   18259                 :            :         struct mlx5_flow_tbl_resource *jump_tbl;
   18260                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data;
   18261                 :            :         uint8_t egress, transfer;
   18262                 :            :         struct rte_flow_error error;
   18263                 :            :         struct mlx5_meter_policy_acts acts[RTE_COLORS];
   18264                 :            :         int ret;
   18265                 :            : 
   18266                 :          0 :         egress = (domain == MLX5_MTR_DOMAIN_EGRESS) ? 1 : 0;
   18267                 :          0 :         transfer = (domain == MLX5_MTR_DOMAIN_TRANSFER) ? 1 : 0;
   18268                 :          0 :         def_policy = mtrmng->def_policy[domain];
   18269         [ #  # ]:          0 :         if (!def_policy) {
   18270                 :          0 :                 def_policy = mlx5_malloc(MLX5_MEM_ZERO,
   18271                 :            :                         sizeof(struct mlx5_flow_meter_def_policy),
   18272                 :            :                         RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
   18273         [ #  # ]:          0 :                 if (!def_policy) {
   18274                 :          0 :                         DRV_LOG(ERR, "Failed to alloc default policy table.");
   18275                 :          0 :                         goto def_policy_error;
   18276                 :            :                 }
   18277                 :          0 :                 mtrmng->def_policy[domain] = def_policy;
   18278                 :            :                 /* Create the meter suffix table with SUFFIX level. */
   18279                 :          0 :                 jump_tbl = flow_dv_tbl_resource_get(dev,
   18280                 :            :                                 MLX5_FLOW_TABLE_LEVEL_METER,
   18281                 :            :                                 egress, transfer, false, NULL, 0,
   18282                 :            :                                 0, MLX5_MTR_TABLE_ID_SUFFIX, &error);
   18283         [ #  # ]:          0 :                 if (!jump_tbl) {
   18284                 :          0 :                         DRV_LOG(ERR,
   18285                 :            :                                 "Failed to create meter suffix table.");
   18286                 :          0 :                         goto def_policy_error;
   18287                 :            :                 }
   18288                 :          0 :                 def_policy->sub_policy.jump_tbl[RTE_COLOR_GREEN] = jump_tbl;
   18289                 :          0 :                 tbl_data = container_of(jump_tbl,
   18290                 :            :                                         struct mlx5_flow_tbl_data_entry, tbl);
   18291                 :          0 :                 def_policy->dr_jump_action[RTE_COLOR_GREEN] =
   18292                 :          0 :                                                 tbl_data->jump.action;
   18293                 :          0 :                 acts[RTE_COLOR_GREEN].dv_actions[0] = tbl_data->jump.action;
   18294                 :          0 :                 acts[RTE_COLOR_GREEN].actions_n = 1;
   18295                 :            :                 /*
   18296                 :            :                  * YELLOW has the same default policy as GREEN does.
   18297                 :            :                  * G & Y share the same table and action. The 2nd time of table
   18298                 :            :                  * resource getting is just to update the reference count for
   18299                 :            :                  * the releasing stage.
   18300                 :            :                  */
   18301                 :          0 :                 jump_tbl = flow_dv_tbl_resource_get(dev,
   18302                 :            :                                 MLX5_FLOW_TABLE_LEVEL_METER,
   18303                 :            :                                 egress, transfer, false, NULL, 0,
   18304                 :            :                                 0, MLX5_MTR_TABLE_ID_SUFFIX, &error);
   18305         [ #  # ]:          0 :                 if (!jump_tbl) {
   18306                 :          0 :                         DRV_LOG(ERR,
   18307                 :            :                                 "Failed to get meter suffix table.");
   18308                 :          0 :                         goto def_policy_error;
   18309                 :            :                 }
   18310                 :          0 :                 def_policy->sub_policy.jump_tbl[RTE_COLOR_YELLOW] = jump_tbl;
   18311                 :          0 :                 tbl_data = container_of(jump_tbl,
   18312                 :            :                                         struct mlx5_flow_tbl_data_entry, tbl);
   18313                 :          0 :                 def_policy->dr_jump_action[RTE_COLOR_YELLOW] =
   18314                 :          0 :                                                 tbl_data->jump.action;
   18315                 :          0 :                 acts[RTE_COLOR_YELLOW].dv_actions[0] = tbl_data->jump.action;
   18316                 :          0 :                 acts[RTE_COLOR_YELLOW].actions_n = 1;
   18317                 :            :                 /* Create jump action to the drop table. */
   18318         [ #  # ]:          0 :                 if (!mtrmng->drop_tbl[domain]) {
   18319                 :          0 :                         mtrmng->drop_tbl[domain] = flow_dv_tbl_resource_get
   18320                 :            :                                 (dev, MLX5_FLOW_TABLE_LEVEL_METER,
   18321                 :            :                                  egress, transfer, false, NULL, 0,
   18322                 :            :                                  0, MLX5_MTR_TABLE_ID_DROP, &error);
   18323         [ #  # ]:          0 :                         if (!mtrmng->drop_tbl[domain]) {
   18324                 :          0 :                                 DRV_LOG(ERR, "Failed to create meter "
   18325                 :            :                                         "drop table for default policy.");
   18326                 :          0 :                                 goto def_policy_error;
   18327                 :            :                         }
   18328                 :            :                 }
   18329                 :            :                 /* all RED: unique Drop table for jump action. */
   18330                 :          0 :                 tbl_data = container_of(mtrmng->drop_tbl[domain],
   18331                 :            :                                         struct mlx5_flow_tbl_data_entry, tbl);
   18332                 :          0 :                 def_policy->dr_jump_action[RTE_COLOR_RED] =
   18333                 :          0 :                                                 tbl_data->jump.action;
   18334                 :          0 :                 acts[RTE_COLOR_RED].dv_actions[0] = tbl_data->jump.action;
   18335                 :          0 :                 acts[RTE_COLOR_RED].actions_n = 1;
   18336                 :            :                 /* Create default policy rules. */
   18337                 :          0 :                 ret = __flow_dv_create_domain_policy_rules(dev,
   18338                 :            :                                         &def_policy->sub_policy,
   18339                 :            :                                         egress, transfer, false, acts);
   18340         [ #  # ]:          0 :                 if (ret) {
   18341                 :          0 :                         DRV_LOG(ERR, "Failed to create default policy rules.");
   18342                 :          0 :                         goto def_policy_error;
   18343                 :            :                 }
   18344                 :            :         }
   18345                 :            :         return 0;
   18346                 :          0 : def_policy_error:
   18347                 :          0 :         __flow_dv_destroy_domain_def_policy(dev,
   18348                 :            :                                             (enum mlx5_meter_domain)domain);
   18349                 :          0 :         return -1;
   18350                 :            : }
   18351                 :            : 
   18352                 :            : /**
   18353                 :            :  * Create the default policy table set.
   18354                 :            :  *
   18355                 :            :  * @param[in] dev
   18356                 :            :  *   Pointer to Ethernet device.
   18357                 :            :  * @return
   18358                 :            :  *   0 on success, -1 otherwise.
   18359                 :            :  */
   18360                 :            : static int
   18361                 :          0 : flow_dv_create_def_policy(struct rte_eth_dev *dev)
   18362                 :            : {
   18363                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   18364                 :            :         int i;
   18365                 :            : 
   18366                 :            :         /* Non-termination policy table. */
   18367         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
   18368   [ #  #  #  # ]:          0 :                 if (!priv->sh->config.dv_esw_en &&
   18369                 :            :                     i == MLX5_MTR_DOMAIN_TRANSFER)
   18370                 :          0 :                         continue;
   18371         [ #  # ]:          0 :                 if (__flow_dv_create_domain_def_policy(dev, i)) {
   18372                 :          0 :                         DRV_LOG(ERR, "Failed to create default policy");
   18373                 :            :                         /* Rollback the created default policies for others. */
   18374                 :          0 :                         flow_dv_destroy_def_policy(dev);
   18375                 :          0 :                         return -1;
   18376                 :            :                 }
   18377                 :            :         }
   18378                 :            :         return 0;
   18379                 :            : }
   18380                 :            : 
   18381                 :            : /**
   18382                 :            :  * Create the needed meter tables.
   18383                 :            :  * Lock free, (mutex should be acquired by caller).
   18384                 :            :  *
   18385                 :            :  * @param[in] dev
   18386                 :            :  *   Pointer to Ethernet device.
   18387                 :            :  * @param[in] fm
   18388                 :            :  *   Meter information table.
   18389                 :            :  * @param[in] mtr_idx
   18390                 :            :  *   Meter index.
   18391                 :            :  * @param[in] domain_bitmap
   18392                 :            :  *   Domain bitmap.
   18393                 :            :  * @return
   18394                 :            :  *   0 on success, -1 otherwise.
   18395                 :            :  */
   18396                 :            : static int
   18397                 :          0 : flow_dv_create_mtr_tbls(struct rte_eth_dev *dev,
   18398                 :            :                         struct mlx5_flow_meter_info *fm,
   18399                 :            :                         uint32_t mtr_idx,
   18400                 :            :                         uint8_t domain_bitmap)
   18401                 :            : {
   18402                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   18403                 :          0 :         struct mlx5_flow_mtr_mng *mtrmng = priv->sh->mtrmng;
   18404                 :            :         struct rte_flow_error error;
   18405                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data;
   18406                 :            :         uint8_t egress, transfer;
   18407                 :            :         void *actions[METER_ACTIONS];
   18408                 :            :         int domain, ret, i;
   18409                 :            :         struct mlx5_flow_counter *cnt;
   18410                 :          0 :         struct mlx5_flow_dv_match_params value = {
   18411                 :            :                 .size = sizeof(value.buf),
   18412                 :            :         };
   18413                 :          0 :         struct mlx5_flow_dv_match_params matcher_para = {
   18414                 :            :                 .size = sizeof(matcher_para.buf),
   18415                 :            :         };
   18416                 :          0 :         int mtr_id_reg_c = mlx5_flow_get_reg_id(dev, MLX5_MTR_ID,
   18417                 :            :                                                      0, &error);
   18418                 :          0 :         uint32_t mtr_id_mask = (UINT32_C(1) << mtrmng->max_mtr_bits) - 1;
   18419                 :          0 :         uint8_t mtr_id_offset = priv->mtr_reg_share ? MLX5_MTR_COLOR_BITS : 0;
   18420                 :            :         struct mlx5_list_entry *entry;
   18421                 :          0 :         struct mlx5_flow_dv_matcher matcher = {
   18422                 :            :                 .mask = {
   18423                 :            :                         .size = sizeof(matcher.mask.buf),
   18424                 :            :                 },
   18425                 :            :         };
   18426                 :            :         struct mlx5_flow_dv_matcher *drop_matcher;
   18427                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
   18428                 :            :                 .error = &error,
   18429                 :            :                 .data = &matcher,
   18430                 :            :         };
   18431                 :            :         uint8_t misc_mask;
   18432                 :            : 
   18433   [ #  #  #  # ]:          0 :         if (!priv->mtr_en || mtr_id_reg_c < 0) {
   18434                 :          0 :                 rte_errno = ENOTSUP;
   18435                 :          0 :                 return -1;
   18436                 :            :         }
   18437         [ #  # ]:          0 :         for (domain = 0; domain < MLX5_MTR_DOMAIN_MAX; domain++) {
   18438         [ #  # ]:          0 :                 if (!(domain_bitmap & (1 << domain)) ||
   18439   [ #  #  #  # ]:          0 :                         (mtrmng->def_rule[domain] && !fm->drop_cnt))
   18440                 :          0 :                         continue;
   18441                 :          0 :                 egress = (domain == MLX5_MTR_DOMAIN_EGRESS) ? 1 : 0;
   18442                 :          0 :                 transfer = (domain == MLX5_MTR_DOMAIN_TRANSFER) ? 1 : 0;
   18443                 :            :                 /* Create the drop table with METER DROP level. */
   18444         [ #  # ]:          0 :                 if (!mtrmng->drop_tbl[domain]) {
   18445                 :          0 :                         mtrmng->drop_tbl[domain] = flow_dv_tbl_resource_get(dev,
   18446                 :            :                                         MLX5_FLOW_TABLE_LEVEL_METER,
   18447                 :            :                                         egress, transfer, false, NULL, 0,
   18448                 :            :                                         0, MLX5_MTR_TABLE_ID_DROP, &error);
   18449         [ #  # ]:          0 :                         if (!mtrmng->drop_tbl[domain]) {
   18450                 :          0 :                                 DRV_LOG(ERR, "Failed to create meter drop table.");
   18451                 :          0 :                                 goto policy_error;
   18452                 :            :                         }
   18453                 :            :                 }
   18454                 :            :                 /* Create default matcher in drop table. */
   18455                 :          0 :                 matcher.tbl = mtrmng->drop_tbl[domain],
   18456                 :          0 :                 tbl_data = container_of(mtrmng->drop_tbl[domain],
   18457                 :            :                                 struct mlx5_flow_tbl_data_entry, tbl);
   18458         [ #  # ]:          0 :                 if (!mtrmng->def_matcher[domain]) {
   18459                 :          0 :                         flow_dv_match_meta_reg_all(matcher.mask.buf, value.buf,
   18460                 :            :                                        (enum modify_reg)mtr_id_reg_c,
   18461                 :            :                                        0, 0);
   18462                 :          0 :                         matcher.priority = MLX5_MTRS_DEFAULT_RULE_PRIORITY;
   18463                 :          0 :                         matcher.crc = rte_raw_cksum
   18464                 :            :                                         ((const void *)matcher.mask.buf,
   18465                 :            :                                         matcher.mask.size);
   18466                 :          0 :                         entry = mlx5_list_register(tbl_data->matchers, &ctx);
   18467         [ #  # ]:          0 :                         if (!entry) {
   18468                 :          0 :                                 DRV_LOG(ERR, "Failed to register meter "
   18469                 :            :                                 "drop default matcher.");
   18470                 :          0 :                                 goto policy_error;
   18471                 :            :                         }
   18472                 :          0 :                         mtrmng->def_matcher[domain] = container_of(entry,
   18473                 :            :                         struct mlx5_flow_dv_matcher, entry);
   18474                 :            :                 }
   18475                 :            :                 /* Create default rule in drop table. */
   18476         [ #  # ]:          0 :                 if (!mtrmng->def_rule[domain]) {
   18477                 :            :                         i = 0;
   18478                 :          0 :                         actions[i++] = priv->sh->dr_drop_action;
   18479                 :          0 :                         flow_dv_match_meta_reg_all(matcher_para.buf, value.buf,
   18480                 :            :                                 (enum modify_reg)mtr_id_reg_c, 0, 0);
   18481         [ #  # ]:          0 :                         misc_mask = flow_dv_matcher_enable(mtrmng->def_matcher[domain]->mask.buf);
   18482                 :            :                         __flow_dv_adjust_buf_size(&value.size, misc_mask);
   18483                 :          0 :                         ret = mlx5_flow_os_create_flow
   18484                 :            :                                 (mtrmng->def_matcher[domain]->matcher_object,
   18485                 :            :                                 (void *)&value, i, actions,
   18486                 :            :                                 &mtrmng->def_rule[domain]);
   18487                 :            :                         if (ret) {
   18488                 :          0 :                                 DRV_LOG(ERR, "Failed to create meter "
   18489                 :            :                                 "default drop rule for drop table.");
   18490                 :          0 :                                 goto policy_error;
   18491                 :            :                         }
   18492                 :            :                 }
   18493         [ #  # ]:          0 :                 if (!fm->drop_cnt)
   18494                 :          0 :                         continue;
   18495                 :            :                 MLX5_ASSERT(mtrmng->max_mtr_bits);
   18496         [ #  # ]:          0 :                 if (!mtrmng->drop_matcher[domain][mtrmng->max_mtr_bits - 1]) {
   18497                 :            :                         /* Create matchers for Drop. */
   18498                 :          0 :                         flow_dv_match_meta_reg_all(matcher.mask.buf, value.buf,
   18499                 :            :                                         (enum modify_reg)mtr_id_reg_c, 0,
   18500                 :            :                                         (mtr_id_mask << mtr_id_offset));
   18501                 :          0 :                         matcher.priority = MLX5_REG_BITS - mtrmng->max_mtr_bits;
   18502                 :          0 :                         matcher.crc = rte_raw_cksum
   18503                 :            :                                         ((const void *)matcher.mask.buf,
   18504                 :            :                                         matcher.mask.size);
   18505                 :          0 :                         entry = mlx5_list_register(tbl_data->matchers, &ctx);
   18506         [ #  # ]:          0 :                         if (!entry) {
   18507                 :          0 :                                 DRV_LOG(ERR,
   18508                 :            :                                 "Failed to register meter drop matcher.");
   18509                 :          0 :                                 goto policy_error;
   18510                 :            :                         }
   18511                 :          0 :                         mtrmng->drop_matcher[domain][mtrmng->max_mtr_bits - 1] =
   18512                 :            :                                 container_of(entry, struct mlx5_flow_dv_matcher,
   18513                 :            :                                              entry);
   18514                 :            :                 }
   18515                 :          0 :                 drop_matcher =
   18516                 :          0 :                         mtrmng->drop_matcher[domain][mtrmng->max_mtr_bits - 1];
   18517                 :            :                 /* Create drop rule, matching meter_id only. */
   18518                 :          0 :                 flow_dv_match_meta_reg_all(matcher_para.buf, value.buf,
   18519                 :            :                                 (enum modify_reg)mtr_id_reg_c,
   18520                 :            :                                 (mtr_idx << mtr_id_offset), UINT32_MAX);
   18521                 :            :                 i = 0;
   18522         [ #  # ]:          0 :                 cnt = flow_dv_counter_get_by_idx(dev,
   18523                 :            :                                         fm->drop_cnt, NULL);
   18524                 :          0 :                 actions[i++] = cnt->action;
   18525                 :          0 :                 actions[i++] = priv->sh->dr_drop_action;
   18526         [ #  # ]:          0 :                 misc_mask = flow_dv_matcher_enable(drop_matcher->mask.buf);
   18527                 :            :                 __flow_dv_adjust_buf_size(&value.size, misc_mask);
   18528                 :          0 :                 ret = mlx5_flow_os_create_flow(drop_matcher->matcher_object,
   18529                 :            :                                                (void *)&value, i, actions,
   18530                 :            :                                                &fm->drop_rule[domain]);
   18531                 :            :                 if (ret) {
   18532                 :          0 :                         DRV_LOG(ERR, "Failed to create meter "
   18533                 :            :                                 "drop rule for drop table.");
   18534                 :          0 :                                 goto policy_error;
   18535                 :            :                 }
   18536                 :            :         }
   18537                 :            :         return 0;
   18538                 :            : policy_error:
   18539         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
   18540         [ #  # ]:          0 :                 if (fm->drop_rule[i]) {
   18541                 :            :                         claim_zero(mlx5_flow_os_destroy_flow
   18542                 :            :                                 (fm->drop_rule[i]));
   18543                 :          0 :                         fm->drop_rule[i] = NULL;
   18544                 :            :                 }
   18545                 :            :         }
   18546                 :            :         return -1;
   18547                 :            : }
   18548                 :            : 
   18549                 :            : static struct mlx5_flow_meter_sub_policy *
   18550                 :          0 : __flow_dv_meter_get_rss_sub_policy(struct rte_eth_dev *dev,
   18551                 :            :                 struct mlx5_flow_meter_policy *mtr_policy,
   18552                 :            :                 struct mlx5_flow_rss_desc *rss_desc[MLX5_MTR_RTE_COLORS],
   18553                 :            :                 struct mlx5_flow_meter_sub_policy *next_sub_policy,
   18554                 :            :                 bool *is_reuse)
   18555                 :            : {
   18556                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   18557                 :            :         struct mlx5_flow_meter_sub_policy *sub_policy = NULL;
   18558                 :          0 :         uint32_t sub_policy_idx = 0;
   18559                 :          0 :         uint32_t hrxq_idx[MLX5_MTR_RTE_COLORS] = {0};
   18560                 :            :         uint32_t i, j;
   18561                 :            :         struct mlx5_hrxq *hrxq;
   18562                 :            :         struct mlx5_flow_handle dh;
   18563                 :            :         struct mlx5_meter_policy_action_container *act_cnt;
   18564                 :            :         uint32_t domain = MLX5_MTR_DOMAIN_INGRESS;
   18565                 :            :         uint16_t sub_policy_num;
   18566                 :          0 :         struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace();
   18567                 :            : 
   18568                 :            :         MLX5_ASSERT(wks);
   18569                 :          0 :         rte_spinlock_lock(&mtr_policy->sl);
   18570         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_RTE_COLORS; i++) {
   18571         [ #  # ]:          0 :                 if (!rss_desc[i])
   18572                 :          0 :                         continue;
   18573                 :          0 :                 hrxq = mlx5_hrxq_get(dev, rss_desc[i]);
   18574         [ #  # ]:          0 :                 if (!hrxq) {
   18575                 :            :                         rte_spinlock_unlock(&mtr_policy->sl);
   18576                 :          0 :                         return NULL;
   18577                 :            :                 }
   18578                 :          0 :                 hrxq_idx[i] = hrxq->idx;
   18579                 :            :         }
   18580                 :          0 :         sub_policy_num = (mtr_policy->sub_policy_num >>
   18581                 :            :                         (MLX5_MTR_SUB_POLICY_NUM_SHIFT * domain)) &
   18582                 :            :                         MLX5_MTR_SUB_POLICY_NUM_MASK;
   18583         [ #  # ]:          0 :         for (j = 0; j < sub_policy_num; j++) {
   18584         [ #  # ]:          0 :                 for (i = 0; i < MLX5_MTR_RTE_COLORS; i++) {
   18585         [ #  # ]:          0 :                         if (rss_desc[i] &&
   18586                 :          0 :                             hrxq_idx[i] !=
   18587         [ #  # ]:          0 :                             mtr_policy->sub_policys[domain][j]->rix_hrxq[i])
   18588                 :            :                                 break;
   18589                 :            :                 }
   18590         [ #  # ]:          0 :                 if (i >= MLX5_MTR_RTE_COLORS) {
   18591                 :            :                         /*
   18592                 :            :                          * Found the sub policy table with
   18593                 :            :                          * the same queue per color.
   18594                 :            :                          */
   18595                 :            :                         rte_spinlock_unlock(&mtr_policy->sl);
   18596         [ #  # ]:          0 :                         for (i = 0; i < MLX5_MTR_RTE_COLORS; i++)
   18597                 :          0 :                                 mlx5_hrxq_release(dev, hrxq_idx[i]);
   18598                 :          0 :                         *is_reuse = true;
   18599                 :          0 :                         return mtr_policy->sub_policys[domain][j];
   18600                 :            :                 }
   18601                 :            :         }
   18602                 :            :         /* Create sub policy. */
   18603         [ #  # ]:          0 :         if (!mtr_policy->sub_policys[domain][0]->rix_hrxq[RTE_COLOR_GREEN] &&
   18604                 :            :             !mtr_policy->sub_policys[domain][0]->rix_hrxq[RTE_COLOR_YELLOW]) {
   18605                 :            :                 /* Reuse the first pre-allocated sub_policy. */
   18606                 :            :                 sub_policy = mtr_policy->sub_policys[domain][0];
   18607                 :          0 :                 sub_policy_idx = sub_policy->idx;
   18608                 :            :         } else {
   18609                 :          0 :                 sub_policy = mlx5_ipool_zmalloc
   18610                 :          0 :                                 (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
   18611                 :            :                                  &sub_policy_idx);
   18612         [ #  # ]:          0 :                 if (!sub_policy ||
   18613         [ #  # ]:          0 :                     sub_policy_idx > MLX5_MAX_SUB_POLICY_TBL_NUM) {
   18614         [ #  # ]:          0 :                         for (i = 0; i < MLX5_MTR_RTE_COLORS; i++)
   18615                 :          0 :                                 mlx5_hrxq_release(dev, hrxq_idx[i]);
   18616                 :          0 :                         goto rss_sub_policy_error;
   18617                 :            :                 }
   18618                 :          0 :                 sub_policy->idx = sub_policy_idx;
   18619                 :          0 :                 sub_policy->main_policy = mtr_policy;
   18620                 :            :         }
   18621         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_RTE_COLORS; i++) {
   18622         [ #  # ]:          0 :                 if (!rss_desc[i])
   18623                 :          0 :                         continue;
   18624                 :          0 :                 sub_policy->rix_hrxq[i] = hrxq_idx[i];
   18625         [ #  # ]:          0 :                 if (mtr_policy->is_hierarchy) {
   18626                 :            :                         act_cnt = &mtr_policy->act_cnt[i];
   18627                 :          0 :                         act_cnt->next_sub_policy = next_sub_policy;
   18628                 :          0 :                         mlx5_hrxq_release(dev, hrxq_idx[i]);
   18629                 :            :                 } else {
   18630                 :            :                         /*
   18631                 :            :                          * Overwrite the last action from
   18632                 :            :                          * RSS action to Queue action.
   18633                 :            :                          */
   18634                 :          0 :                         hrxq = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_HRXQ],
   18635                 :            :                                               hrxq_idx[i]);
   18636         [ #  # ]:          0 :                         if (!hrxq) {
   18637                 :          0 :                                 DRV_LOG(ERR, "Failed to get policy hrxq");
   18638                 :          0 :                                 goto rss_sub_policy_error;
   18639                 :            :                         }
   18640                 :            :                         act_cnt = &mtr_policy->act_cnt[i];
   18641   [ #  #  #  # ]:          0 :                         if (act_cnt->rix_mark || act_cnt->modify_hdr) {
   18642                 :            :                                 memset(&dh, 0, sizeof(struct mlx5_flow_handle));
   18643         [ #  # ]:          0 :                                 if (act_cnt->rix_mark)
   18644                 :          0 :                                         wks->mark = 1;
   18645                 :          0 :                                 dh.fate_action = MLX5_FLOW_FATE_QUEUE;
   18646                 :          0 :                                 dh.rix_hrxq = hrxq_idx[i];
   18647                 :          0 :                                 flow_drv_rxq_flags_set(dev, &dh);
   18648                 :            :                         }
   18649                 :            :                 }
   18650                 :            :         }
   18651         [ #  # ]:          0 :         if (__flow_dv_create_policy_acts_rules(dev, mtr_policy,
   18652                 :            :                                                sub_policy, domain)) {
   18653                 :          0 :                 DRV_LOG(ERR, "Failed to create policy "
   18654                 :            :                         "rules for ingress domain.");
   18655                 :          0 :                 goto rss_sub_policy_error;
   18656                 :            :         }
   18657         [ #  # ]:          0 :         if (sub_policy != mtr_policy->sub_policys[domain][0]) {
   18658                 :          0 :                 i = (mtr_policy->sub_policy_num >>
   18659                 :            :                         (MLX5_MTR_SUB_POLICY_NUM_SHIFT * domain)) &
   18660                 :            :                         MLX5_MTR_SUB_POLICY_NUM_MASK;
   18661         [ #  # ]:          0 :                 if (i >= MLX5_MTR_RSS_MAX_SUB_POLICY) {
   18662                 :          0 :                         DRV_LOG(ERR, "No free sub-policy slot.");
   18663                 :          0 :                         goto rss_sub_policy_error;
   18664                 :            :                 }
   18665                 :          0 :                 mtr_policy->sub_policys[domain][i] = sub_policy;
   18666                 :          0 :                 i++;
   18667                 :          0 :                 mtr_policy->sub_policy_num &= ~(MLX5_MTR_SUB_POLICY_NUM_MASK <<
   18668                 :            :                         (MLX5_MTR_SUB_POLICY_NUM_SHIFT * domain));
   18669                 :          0 :                 mtr_policy->sub_policy_num |=
   18670                 :          0 :                         (i & MLX5_MTR_SUB_POLICY_NUM_MASK) <<
   18671                 :            :                         (MLX5_MTR_SUB_POLICY_NUM_SHIFT * domain);
   18672                 :            :         }
   18673                 :            :         rte_spinlock_unlock(&mtr_policy->sl);
   18674                 :          0 :         *is_reuse = false;
   18675                 :          0 :         return sub_policy;
   18676                 :          0 : rss_sub_policy_error:
   18677         [ #  # ]:          0 :         if (sub_policy) {
   18678                 :          0 :                 __flow_dv_destroy_sub_policy_rules(dev, sub_policy);
   18679         [ #  # ]:          0 :                 if (sub_policy != mtr_policy->sub_policys[domain][0]) {
   18680                 :          0 :                         i = (mtr_policy->sub_policy_num >>
   18681                 :            :                         (MLX5_MTR_SUB_POLICY_NUM_SHIFT * domain)) &
   18682                 :            :                         MLX5_MTR_SUB_POLICY_NUM_MASK;
   18683                 :          0 :                         mtr_policy->sub_policys[domain][i] = NULL;
   18684                 :          0 :                         mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
   18685                 :          0 :                                         sub_policy->idx);
   18686                 :            :                 }
   18687                 :            :         }
   18688                 :            :         rte_spinlock_unlock(&mtr_policy->sl);
   18689                 :          0 :         return NULL;
   18690                 :            : }
   18691                 :            : 
   18692                 :            : /**
   18693                 :            :  * Find the policy table for prefix table with RSS.
   18694                 :            :  *
   18695                 :            :  * @param[in] dev
   18696                 :            :  *   Pointer to Ethernet device.
   18697                 :            :  * @param[in] mtr_policy
   18698                 :            :  *   Pointer to meter policy table.
   18699                 :            :  * @param[in] rss_desc
   18700                 :            :  *   Pointer to rss_desc
   18701                 :            :  * @return
   18702                 :            :  *   Pointer to table set on success, NULL otherwise and rte_errno is set.
   18703                 :            :  */
   18704                 :            : static struct mlx5_flow_meter_sub_policy *
   18705                 :          0 : flow_dv_meter_sub_policy_rss_prepare(struct rte_eth_dev *dev,
   18706                 :            :                 struct mlx5_flow_meter_policy *mtr_policy,
   18707                 :            :                 struct mlx5_flow_rss_desc *rss_desc[MLX5_MTR_RTE_COLORS])
   18708                 :            : {
   18709                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   18710                 :            :         struct mlx5_flow_meter_sub_policy *sub_policy = NULL;
   18711                 :            :         struct mlx5_flow_meter_info *next_fm;
   18712                 :            :         struct mlx5_flow_meter_policy *next_policy;
   18713                 :            :         struct mlx5_flow_meter_sub_policy *next_sub_policy = NULL;
   18714                 :            :         struct mlx5_flow_meter_policy *policies[MLX5_MTR_CHAIN_MAX_NUM];
   18715                 :            :         struct mlx5_flow_meter_sub_policy *sub_policies[MLX5_MTR_CHAIN_MAX_NUM];
   18716                 :            :         uint32_t domain = MLX5_MTR_DOMAIN_INGRESS;
   18717                 :            :         bool reuse_sub_policy;
   18718                 :            :         uint32_t i = 0;
   18719                 :            :         uint32_t j = 0;
   18720                 :            : 
   18721                 :            :         while (true) {
   18722                 :            :                 /* Iterate hierarchy to get all policies in this hierarchy. */
   18723                 :          0 :                 policies[i++] = mtr_policy;
   18724         [ #  # ]:          0 :                 if (!mtr_policy->is_hierarchy)
   18725                 :            :                         break;
   18726         [ #  # ]:          0 :                 if (i >= MLX5_MTR_CHAIN_MAX_NUM) {
   18727                 :          0 :                         DRV_LOG(ERR, "Exceed max meter number in hierarchy.");
   18728                 :          0 :                         return NULL;
   18729                 :            :                 }
   18730                 :          0 :                 rte_spinlock_lock(&mtr_policy->sl);
   18731                 :          0 :                 next_fm = mlx5_flow_meter_hierarchy_next_meter(priv, mtr_policy, NULL);
   18732                 :            :                 rte_spinlock_unlock(&mtr_policy->sl);
   18733         [ #  # ]:          0 :                 if (!next_fm) {
   18734                 :          0 :                         DRV_LOG(ERR, "Failed to get next meter in hierarchy.");
   18735                 :          0 :                         return NULL;
   18736                 :            :                 }
   18737                 :            :                 next_policy =
   18738                 :          0 :                         mlx5_flow_meter_policy_find(dev, next_fm->policy_id,
   18739                 :            :                                                     NULL);
   18740                 :            :                 MLX5_ASSERT(next_policy);
   18741                 :            :                 mtr_policy = next_policy;
   18742                 :            :         }
   18743         [ #  # ]:          0 :         while (i) {
   18744                 :            :                 /**
   18745                 :            :                  * From last policy to the first one in hierarchy,
   18746                 :            :                  * create / get the sub policy for each of them.
   18747                 :            :                  */
   18748                 :          0 :                 sub_policy = __flow_dv_meter_get_rss_sub_policy(dev,
   18749                 :            :                                                         policies[--i],
   18750                 :            :                                                         rss_desc,
   18751                 :            :                                                         next_sub_policy,
   18752                 :            :                                                         &reuse_sub_policy);
   18753         [ #  # ]:          0 :                 if (!sub_policy) {
   18754                 :          0 :                         DRV_LOG(ERR, "Failed to get the sub policy.");
   18755                 :          0 :                         goto err_exit;
   18756                 :            :                 }
   18757         [ #  # ]:          0 :                 if (!reuse_sub_policy)
   18758                 :          0 :                         sub_policies[j++] = sub_policy;
   18759                 :            :                 next_sub_policy = sub_policy;
   18760                 :            :         }
   18761                 :            :         return sub_policy;
   18762                 :            : err_exit:
   18763         [ #  # ]:          0 :         while (j) {
   18764                 :            :                 uint16_t sub_policy_num;
   18765                 :            : 
   18766                 :          0 :                 sub_policy = sub_policies[--j];
   18767                 :          0 :                 mtr_policy = sub_policy->main_policy;
   18768                 :          0 :                 __flow_dv_destroy_sub_policy_rules(dev, sub_policy);
   18769         [ #  # ]:          0 :                 if (sub_policy != mtr_policy->sub_policys[domain][0]) {
   18770                 :          0 :                         sub_policy_num = (mtr_policy->sub_policy_num >>
   18771                 :            :                                 (MLX5_MTR_SUB_POLICY_NUM_SHIFT * domain)) &
   18772                 :            :                                 MLX5_MTR_SUB_POLICY_NUM_MASK;
   18773                 :          0 :                         mtr_policy->sub_policys[domain][sub_policy_num - 1] =
   18774                 :            :                                                                         NULL;
   18775                 :          0 :                         sub_policy_num--;
   18776                 :          0 :                         mtr_policy->sub_policy_num &=
   18777                 :          0 :                                 ~(MLX5_MTR_SUB_POLICY_NUM_MASK <<
   18778                 :          0 :                                   (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i));
   18779                 :          0 :                         mtr_policy->sub_policy_num |=
   18780                 :          0 :                         (sub_policy_num & MLX5_MTR_SUB_POLICY_NUM_MASK) <<
   18781                 :            :                         (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i);
   18782                 :          0 :                         mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
   18783                 :          0 :                                         sub_policy->idx);
   18784                 :            :                 }
   18785                 :            :         }
   18786                 :            :         return NULL;
   18787                 :            : }
   18788                 :            : 
   18789                 :            : /**
   18790                 :            :  * Check if need to create hierarchy tag rule.
   18791                 :            :  *
   18792                 :            :  * @param[in] priv
   18793                 :            :  *   Pointer to mlx5_priv.
   18794                 :            :  * @param[in] mtr_policy
   18795                 :            :  *   Pointer to current meter policy.
   18796                 :            :  * @param[in] src_port
   18797                 :            :  *   The src port this extra rule should use.
   18798                 :            :  * @param[out] next_fm
   18799                 :            :  *   Pointer to next meter in hierarchy.
   18800                 :            :  * @param[out] skip
   18801                 :            :  *   Indicate if skip the tag rule creation.
   18802                 :            :  * @param[out] error
   18803                 :            :  *   Perform verbose error reporting if not NULL.
   18804                 :            :  * @return
   18805                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   18806                 :            :  */
   18807                 :            : static int
   18808                 :          0 : mlx5_meter_hierarchy_skip_tag_rule(struct mlx5_priv *priv,
   18809                 :            :                                    struct mlx5_flow_meter_policy *mtr_policy,
   18810                 :            :                                    int32_t src_port,
   18811                 :            :                                    struct mlx5_flow_meter_info **next_fm,
   18812                 :            :                                    bool *skip,
   18813                 :            :                                    struct rte_flow_error *error)
   18814                 :            : {
   18815                 :            :         struct mlx5_flow_meter_sub_policy *sub_policy;
   18816                 :            :         struct mlx5_sub_policy_color_rule *color_rule;
   18817                 :            :         uint32_t domain = MLX5_MTR_DOMAIN_TRANSFER;
   18818                 :            :         int ret = 0;
   18819                 :            :         int i;
   18820                 :            : 
   18821                 :          0 :         *next_fm = NULL;
   18822                 :          0 :         *skip = false;
   18823                 :          0 :         rte_spinlock_lock(&mtr_policy->sl);
   18824         [ #  # ]:          0 :         if (mtr_policy->is_hierarchy) {
   18825                 :          0 :                 *next_fm = mlx5_flow_meter_hierarchy_next_meter(priv, mtr_policy, NULL);
   18826         [ #  # ]:          0 :                 if (!*next_fm) {
   18827                 :          0 :                         ret = rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
   18828                 :            :                                                 NULL, "Failed to find next meter in hierarchy.");
   18829                 :          0 :                         goto exit;
   18830                 :            :                 }
   18831                 :            :         }
   18832         [ #  # ]:          0 :         if (!mtr_policy->match_port) {
   18833                 :          0 :                 *skip = true;
   18834                 :          0 :                 goto exit;
   18835                 :            :         }
   18836                 :          0 :         sub_policy = mtr_policy->sub_policys[domain][0];
   18837         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_RTE_COLORS; i++) {
   18838         [ #  # ]:          0 :                 if (mtr_policy->act_cnt[i].fate_action != MLX5_FLOW_FATE_MTR &&
   18839                 :            :                     mtr_policy->act_cnt[i].fate_action != MLX5_FLOW_FATE_PORT_ID)
   18840                 :          0 :                         continue;
   18841         [ #  # ]:          0 :                 TAILQ_FOREACH(color_rule, &sub_policy->color_rules[i], next_port)
   18842         [ #  # ]:          0 :                         if (color_rule->src_port == src_port) {
   18843                 :          0 :                                 *skip = true;
   18844                 :          0 :                                 goto exit;
   18845                 :            :                         }
   18846                 :            :         }
   18847                 :          0 : exit:
   18848                 :            :         rte_spinlock_unlock(&mtr_policy->sl);
   18849                 :          0 :         return ret;
   18850                 :            : }
   18851                 :            : 
   18852                 :            : /**
   18853                 :            :  * Create the sub policy tag rule for all meters in hierarchy.
   18854                 :            :  *
   18855                 :            :  * @param[in] dev
   18856                 :            :  *   Pointer to Ethernet device.
   18857                 :            :  * @param[in] fm
   18858                 :            :  *   Meter information table.
   18859                 :            :  * @param[in] src_port
   18860                 :            :  *   The src port this extra rule should use.
   18861                 :            :  * @param[in] item
   18862                 :            :  *   The src port match item.
   18863                 :            :  * @param[out] error
   18864                 :            :  *   Perform verbose error reporting if not NULL.
   18865                 :            :  * @return
   18866                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   18867                 :            :  */
   18868                 :            : static int
   18869                 :          0 : flow_dv_meter_hierarchy_rule_create(struct rte_eth_dev *dev,
   18870                 :            :                                 struct mlx5_flow_meter_info *fm,
   18871                 :            :                                 int32_t src_port,
   18872                 :            :                                 const struct rte_flow_item *item,
   18873                 :            :                                 struct rte_flow_error *error)
   18874                 :            : {
   18875                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   18876                 :            :         struct mlx5_flow_meter_policy *mtr_policy;
   18877                 :            :         struct mlx5_flow_meter_sub_policy *sub_policy;
   18878                 :          0 :         struct mlx5_flow_meter_info *next_fm = NULL;
   18879                 :            :         struct mlx5_flow_meter_policy *next_policy;
   18880                 :            :         struct mlx5_flow_meter_sub_policy *next_sub_policy;
   18881                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data;
   18882                 :            :         struct mlx5_sub_policy_color_rule *color_rule;
   18883                 :            :         struct mlx5_meter_policy_acts acts;
   18884                 :            :         uint32_t color_reg_c_idx;
   18885                 :            :         bool mtr_first = (src_port != UINT16_MAX) ? true : false;
   18886                 :          0 :         struct rte_flow_attr attr = {
   18887                 :            :                 .group = MLX5_FLOW_TABLE_LEVEL_POLICY,
   18888                 :            :                 .priority = 0,
   18889                 :            :                 .ingress = 0,
   18890                 :            :                 .egress = 0,
   18891                 :            :                 .transfer = 1,
   18892                 :            :                 .reserved = 0,
   18893                 :            :         };
   18894                 :            :         uint32_t domain = MLX5_MTR_DOMAIN_TRANSFER;
   18895                 :            :         struct {
   18896                 :            :                 struct mlx5_flow_meter_policy *fm_policy;
   18897                 :            :                 struct mlx5_flow_meter_info *next_fm;
   18898                 :            :                 struct mlx5_sub_policy_color_rule *tag_rule[RTE_COLORS];
   18899                 :          0 :         } fm_info[MLX5_MTR_CHAIN_MAX_NUM] = { {0} };
   18900                 :            :         uint32_t fm_cnt = 0;
   18901                 :            :         uint32_t i, j;
   18902                 :            : 
   18903                 :          0 :         color_reg_c_idx = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR, 0, error);
   18904                 :            :         /* Get all fms who need to create the tag color rule. */
   18905                 :            :         do {
   18906                 :          0 :                 bool skip = false;
   18907                 :            : 
   18908                 :          0 :                 mtr_policy = mlx5_flow_meter_policy_find(dev, fm->policy_id, NULL);
   18909                 :            :                 MLX5_ASSERT(mtr_policy);
   18910         [ #  # ]:          0 :                 if (mlx5_meter_hierarchy_skip_tag_rule(priv, mtr_policy, src_port,
   18911                 :            :                                                        &next_fm, &skip, error))
   18912                 :          0 :                         goto err_exit;
   18913         [ #  # ]:          0 :                 if (!skip) {
   18914                 :          0 :                         fm_info[fm_cnt].fm_policy = mtr_policy;
   18915                 :          0 :                         fm_info[fm_cnt].next_fm = next_fm;
   18916         [ #  # ]:          0 :                         if (++fm_cnt >= MLX5_MTR_CHAIN_MAX_NUM) {
   18917                 :          0 :                                 rte_flow_error_set(error, errno,
   18918                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   18919                 :            :                                         "Exceed max meter number in hierarchy.");
   18920                 :          0 :                                 goto err_exit;
   18921                 :            :                         }
   18922                 :            :                 }
   18923                 :          0 :                 fm = next_fm;
   18924         [ #  # ]:          0 :         } while (fm);
   18925                 :            :         /* Create tag color rules for all needed fms. */
   18926         [ #  # ]:          0 :         for (i = 0; i < fm_cnt; i++) {
   18927                 :            :                 void *mtr_action;
   18928                 :            : 
   18929                 :          0 :                 mtr_policy = fm_info[i].fm_policy;
   18930                 :          0 :                 rte_spinlock_lock(&mtr_policy->sl);
   18931                 :          0 :                 sub_policy = mtr_policy->sub_policys[domain][0];
   18932         [ #  # ]:          0 :                 for (j = 0; j < RTE_COLORS; j++) {
   18933                 :            :                         uint8_t act_n = 0;
   18934                 :            :                         struct mlx5_flow_dv_modify_hdr_resource *modify_hdr = NULL;
   18935                 :            :                         struct mlx5_flow_dv_port_id_action_resource *port_action;
   18936                 :            :                         uint8_t fate_action;
   18937                 :            : 
   18938         [ #  # ]:          0 :                         if (j == RTE_COLOR_RED) {
   18939                 :            :                                 fate_action = MLX5_FLOW_FATE_DROP;
   18940                 :            :                         } else {
   18941                 :          0 :                                 fate_action = mtr_policy->act_cnt[j].fate_action;
   18942                 :          0 :                                 modify_hdr = mtr_policy->act_cnt[j].modify_hdr;
   18943                 :          0 :                                 if (fate_action != MLX5_FLOW_FATE_MTR &&
   18944   [ #  #  #  # ]:          0 :                                     fate_action != MLX5_FLOW_FATE_PORT_ID &&
   18945                 :            :                                     fate_action != MLX5_FLOW_FATE_DROP)
   18946                 :          0 :                                         continue;
   18947                 :            :                         }
   18948                 :          0 :                         color_rule = mlx5_malloc(MLX5_MEM_ZERO,
   18949                 :            :                                                  sizeof(struct mlx5_sub_policy_color_rule),
   18950                 :            :                                                  0, SOCKET_ID_ANY);
   18951         [ #  # ]:          0 :                         if (!color_rule) {
   18952                 :            :                                 rte_spinlock_unlock(&mtr_policy->sl);
   18953                 :          0 :                                 rte_flow_error_set(error, ENOMEM,
   18954                 :            :                                                    RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   18955                 :            :                                                    "No memory to create tag color rule.");
   18956                 :          0 :                                 goto err_exit;
   18957                 :            :                         }
   18958                 :          0 :                         color_rule->src_port = src_port;
   18959                 :            :                         /* Prepare to create color rule. */
   18960         [ #  # ]:          0 :                         if (fate_action == MLX5_FLOW_FATE_MTR) {
   18961                 :          0 :                                 next_fm = fm_info[i].next_fm;
   18962         [ #  # ]:          0 :                                 if (mlx5_flow_meter_attach(priv, next_fm, &attr, error)) {
   18963                 :          0 :                                         mlx5_free(color_rule);
   18964                 :            :                                         rte_spinlock_unlock(&mtr_policy->sl);
   18965                 :          0 :                                         goto err_exit;
   18966                 :            :                                 }
   18967         [ #  # ]:          0 :                                 mtr_action = (next_fm->color_aware && j == RTE_COLOR_YELLOW) ?
   18968         [ #  # ]:          0 :                                                                         next_fm->meter_action_y :
   18969                 :            :                                                                         next_fm->meter_action_g;
   18970                 :          0 :                                 next_policy = mlx5_flow_meter_policy_find(dev, next_fm->policy_id,
   18971                 :            :                                                                           NULL);
   18972                 :            :                                 MLX5_ASSERT(next_policy);
   18973                 :          0 :                                 next_sub_policy = next_policy->sub_policys[domain][0];
   18974                 :          0 :                                 tbl_data = container_of(next_sub_policy->tbl_rsc,
   18975                 :            :                                                         struct mlx5_flow_tbl_data_entry, tbl);
   18976         [ #  # ]:          0 :                                 if (mtr_first) {
   18977                 :          0 :                                         acts.dv_actions[act_n++] = mtr_action;
   18978         [ #  # ]:          0 :                                         if (modify_hdr)
   18979                 :          0 :                                                 acts.dv_actions[act_n++] = modify_hdr->action;
   18980                 :            :                                 } else {
   18981         [ #  # ]:          0 :                                         if (modify_hdr)
   18982                 :          0 :                                                 acts.dv_actions[act_n++] = modify_hdr->action;
   18983                 :          0 :                                         acts.dv_actions[act_n++] = mtr_action;
   18984                 :            :                                 }
   18985                 :          0 :                                 acts.dv_actions[act_n++] = tbl_data->jump.action;
   18986                 :          0 :                                 acts.actions_n = act_n;
   18987         [ #  # ]:          0 :                         } else if (fate_action == MLX5_FLOW_FATE_PORT_ID) {
   18988                 :            :                                 port_action =
   18989                 :          0 :                                         mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_PORT_ID],
   18990                 :            :                                                        mtr_policy->act_cnt[j].rix_port_id_action);
   18991         [ #  # ]:          0 :                                 if (!port_action) {
   18992                 :          0 :                                         mlx5_free(color_rule);
   18993                 :            :                                         rte_spinlock_unlock(&mtr_policy->sl);
   18994                 :          0 :                                         goto err_exit;
   18995                 :            :                                 }
   18996         [ #  # ]:          0 :                                 if (modify_hdr)
   18997                 :          0 :                                         acts.dv_actions[act_n++] = modify_hdr->action;
   18998                 :          0 :                                 acts.dv_actions[act_n++] = port_action->action;
   18999                 :          0 :                                 acts.actions_n = act_n;
   19000                 :            :                         } else {
   19001                 :          0 :                                 acts.dv_actions[act_n++] = mtr_policy->dr_drop_action[domain];
   19002                 :          0 :                                 acts.actions_n = act_n;
   19003                 :            :                         }
   19004                 :          0 :                         fm_info[i].tag_rule[j] = color_rule;
   19005                 :          0 :                         TAILQ_INSERT_TAIL(&sub_policy->color_rules[j], color_rule, next_port);
   19006         [ #  # ]:          0 :                         if (__flow_dv_create_policy_matcher(dev, color_reg_c_idx,
   19007                 :            :                                                 MLX5_MTR_POLICY_MATCHER_PRIO, sub_policy,
   19008                 :            :                                                 &attr, true, item, &color_rule->matcher, error)) {
   19009                 :            :                                 rte_spinlock_unlock(&mtr_policy->sl);
   19010                 :          0 :                                 rte_flow_error_set(error, errno,
   19011                 :            :                                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   19012                 :            :                                                    "Failed to create hierarchy meter matcher.");
   19013                 :          0 :                                 goto err_exit;
   19014                 :            :                         }
   19015         [ #  # ]:          0 :                         if (__flow_dv_create_policy_flow(dev, color_reg_c_idx, (enum rte_color)j,
   19016                 :            :                                                 color_rule->matcher,
   19017                 :          0 :                                                 acts.actions_n, acts.dv_actions,
   19018                 :            :                                                 true, item, &color_rule->rule, &attr)) {
   19019                 :            :                                 rte_spinlock_unlock(&mtr_policy->sl);
   19020                 :          0 :                                 rte_flow_error_set(error, errno,
   19021                 :            :                                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   19022                 :            :                                                    "Failed to create hierarchy meter rule.");
   19023                 :          0 :                                 goto err_exit;
   19024                 :            :                         }
   19025                 :            :                 }
   19026                 :            :                 rte_spinlock_unlock(&mtr_policy->sl);
   19027                 :            :         }
   19028                 :            :         return 0;
   19029                 :          0 : err_exit:
   19030         [ #  # ]:          0 :         for (i = 0; i < fm_cnt; i++) {
   19031                 :          0 :                 mtr_policy = fm_info[i].fm_policy;
   19032                 :          0 :                 rte_spinlock_lock(&mtr_policy->sl);
   19033                 :          0 :                 sub_policy = mtr_policy->sub_policys[domain][0];
   19034         [ #  # ]:          0 :                 for (j = 0; j < RTE_COLORS; j++) {
   19035                 :          0 :                         color_rule = fm_info[i].tag_rule[j];
   19036         [ #  # ]:          0 :                         if (!color_rule)
   19037                 :          0 :                                 continue;
   19038         [ #  # ]:          0 :                         if (color_rule->rule)
   19039                 :            :                                 mlx5_flow_os_destroy_flow(color_rule->rule);
   19040         [ #  # ]:          0 :                         if (color_rule->matcher) {
   19041                 :            :                                 struct mlx5_flow_tbl_data_entry *tbl =
   19042                 :          0 :                                         container_of(color_rule->matcher->tbl, typeof(*tbl), tbl);
   19043                 :          0 :                                 mlx5_list_unregister(tbl->matchers, &color_rule->matcher->entry);
   19044                 :            :                         }
   19045         [ #  # ]:          0 :                         if (fm_info[i].next_fm)
   19046                 :          0 :                                 mlx5_flow_meter_detach(priv, fm_info[i].next_fm);
   19047         [ #  # ]:          0 :                         TAILQ_REMOVE(&sub_policy->color_rules[j], color_rule, next_port);
   19048                 :          0 :                         mlx5_free(color_rule);
   19049                 :            :                 }
   19050                 :            :                 rte_spinlock_unlock(&mtr_policy->sl);
   19051                 :            :         }
   19052                 :          0 :         return -rte_errno;
   19053                 :            : }
   19054                 :            : 
   19055                 :            : /**
   19056                 :            :  * Destroy the sub policy table with RX queue.
   19057                 :            :  *
   19058                 :            :  * @param[in] dev
   19059                 :            :  *   Pointer to Ethernet device.
   19060                 :            :  * @param[in] mtr_policy
   19061                 :            :  *   Pointer to meter policy table.
   19062                 :            :  */
   19063                 :            : static void
   19064                 :          0 : flow_dv_destroy_sub_policy_with_rxq(struct rte_eth_dev *dev,
   19065                 :            :                                     struct mlx5_flow_meter_policy *mtr_policy)
   19066                 :            : {
   19067                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   19068                 :            :         struct mlx5_flow_meter_sub_policy *sub_policy = NULL;
   19069                 :            :         uint32_t domain = MLX5_MTR_DOMAIN_INGRESS;
   19070                 :            :         uint32_t i, j;
   19071                 :            :         uint16_t sub_policy_num, new_policy_num;
   19072                 :            : 
   19073                 :          0 :         rte_spinlock_lock(&mtr_policy->sl);
   19074         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_RTE_COLORS; i++) {
   19075      [ #  #  # ]:          0 :                 switch (mtr_policy->act_cnt[i].fate_action) {
   19076                 :          0 :                 case MLX5_FLOW_FATE_SHARED_RSS:
   19077                 :          0 :                         sub_policy_num = (mtr_policy->sub_policy_num >>
   19078                 :            :                         (MLX5_MTR_SUB_POLICY_NUM_SHIFT * domain)) &
   19079                 :            :                         MLX5_MTR_SUB_POLICY_NUM_MASK;
   19080                 :            :                         new_policy_num = sub_policy_num;
   19081         [ #  # ]:          0 :                         for (j = 0; j < sub_policy_num; j++) {
   19082                 :          0 :                                 sub_policy =
   19083                 :          0 :                                         mtr_policy->sub_policys[domain][j];
   19084         [ #  # ]:          0 :                                 if (sub_policy) {
   19085                 :          0 :                                         __flow_dv_destroy_sub_policy_rules(dev,
   19086                 :            :                                                 sub_policy);
   19087                 :          0 :                                 if (sub_policy !=
   19088         [ #  # ]:          0 :                                         mtr_policy->sub_policys[domain][0]) {
   19089                 :          0 :                                         mtr_policy->sub_policys[domain][j] =
   19090                 :            :                                                                 NULL;
   19091                 :          0 :                                         mlx5_ipool_free
   19092                 :          0 :                                 (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
   19093                 :          0 :                                                 sub_policy->idx);
   19094                 :          0 :                                                 new_policy_num--;
   19095                 :            :                                         }
   19096                 :            :                                 }
   19097                 :            :                         }
   19098         [ #  # ]:          0 :                         if (new_policy_num != sub_policy_num) {
   19099                 :          0 :                                 mtr_policy->sub_policy_num &=
   19100                 :            :                                 ~(MLX5_MTR_SUB_POLICY_NUM_MASK <<
   19101                 :            :                                 (MLX5_MTR_SUB_POLICY_NUM_SHIFT * domain));
   19102                 :          0 :                                 mtr_policy->sub_policy_num |=
   19103                 :            :                                 (new_policy_num &
   19104                 :            :                                         MLX5_MTR_SUB_POLICY_NUM_MASK) <<
   19105                 :            :                                 (MLX5_MTR_SUB_POLICY_NUM_SHIFT * domain);
   19106                 :            :                         }
   19107                 :            :                         break;
   19108                 :          0 :                 case MLX5_FLOW_FATE_QUEUE:
   19109                 :          0 :                         sub_policy = mtr_policy->sub_policys[domain][0];
   19110                 :          0 :                         __flow_dv_destroy_sub_policy_rules(dev,
   19111                 :            :                                                            sub_policy);
   19112                 :          0 :                         break;
   19113                 :            :                 default:
   19114                 :            :                         /*Other actions without queue and do nothing*/
   19115                 :            :                         break;
   19116                 :            :                 }
   19117                 :            :         }
   19118                 :            :         rte_spinlock_unlock(&mtr_policy->sl);
   19119                 :          0 : }
   19120                 :            : /**
   19121                 :            :  * Check whether the DR drop action is supported on the root table or not.
   19122                 :            :  *
   19123                 :            :  * Create a simple flow with DR drop action on root table to validate
   19124                 :            :  * if DR drop action on root table is supported or not.
   19125                 :            :  *
   19126                 :            :  * @param[in] dev
   19127                 :            :  *   Pointer to rte_eth_dev structure.
   19128                 :            :  *
   19129                 :            :  * @return
   19130                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   19131                 :            :  */
   19132                 :            : int
   19133                 :          0 : mlx5_flow_discover_dr_action_support(struct rte_eth_dev *dev)
   19134                 :            : {
   19135                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   19136                 :          0 :         struct mlx5_dev_ctx_shared *sh = priv->sh;
   19137                 :          0 :         struct mlx5_flow_dv_match_params mask = {
   19138                 :            :                 .size = sizeof(mask.buf),
   19139                 :            :         };
   19140                 :          0 :         struct mlx5_flow_dv_match_params value = {
   19141                 :            :                 .size = sizeof(value.buf),
   19142                 :            :         };
   19143                 :          0 :         struct mlx5dv_flow_matcher_attr dv_attr = {
   19144                 :            :                 .type = IBV_FLOW_ATTR_NORMAL,
   19145                 :            :                 .priority = 0,
   19146                 :            :                 .match_criteria_enable = 0,
   19147                 :            :                 .match_mask = (void *)&mask,
   19148                 :            :         };
   19149                 :            :         struct mlx5_flow_tbl_resource *tbl = NULL;
   19150                 :            :         void *matcher = NULL;
   19151                 :            :         void *flow = NULL;
   19152                 :            :         int ret = -1;
   19153                 :            : 
   19154                 :          0 :         tbl = flow_dv_tbl_resource_get(dev, 0, 0, 0, false, NULL,
   19155                 :            :                                         0, 0, 0, NULL);
   19156         [ #  # ]:          0 :         if (!tbl)
   19157                 :          0 :                 goto err;
   19158         [ #  # ]:          0 :         dv_attr.match_criteria_enable = flow_dv_matcher_enable(mask.buf);
   19159                 :            :         __flow_dv_adjust_buf_size(&mask.size, dv_attr.match_criteria_enable);
   19160                 :          0 :         ret = mlx5_flow_os_create_flow_matcher(sh->cdev->ctx, &dv_attr,
   19161                 :            :                                                tbl->obj, &matcher);
   19162                 :            :         if (ret)
   19163                 :          0 :                 goto err;
   19164         [ #  # ]:          0 :         __flow_dv_adjust_buf_size(&value.size, dv_attr.match_criteria_enable);
   19165                 :          0 :         ret = mlx5_flow_os_create_flow(matcher, (void *)&value, 1,
   19166                 :            :                                        &sh->dr_drop_action, &flow);
   19167                 :          0 : err:
   19168                 :            :         /*
   19169                 :            :          * If DR drop action is not supported on root table, flow create will
   19170                 :            :          * be failed with EOPNOTSUPP or EPROTONOSUPPORT.
   19171                 :            :          */
   19172         [ #  # ]:          0 :         if (!flow) {
   19173         [ #  # ]:          0 :                 if (matcher &&
   19174         [ #  # ]:          0 :                     (errno == EPROTONOSUPPORT || errno == EOPNOTSUPP))
   19175                 :          0 :                         DRV_LOG(INFO, "DR drop action is not supported in root table.");
   19176                 :            :                 else
   19177                 :          0 :                         DRV_LOG(ERR, "Unexpected error in DR drop action support detection");
   19178                 :            :                 ret = -1;
   19179                 :            :         } else {
   19180                 :            :                 claim_zero(mlx5_flow_os_destroy_flow(flow));
   19181                 :            :         }
   19182         [ #  # ]:          0 :         if (matcher)
   19183                 :            :                 claim_zero(mlx5_flow_os_destroy_flow_matcher(matcher));
   19184         [ #  # ]:          0 :         if (tbl)
   19185                 :          0 :                 flow_dv_tbl_resource_release(MLX5_SH(dev), tbl);
   19186                 :          0 :         return ret;
   19187                 :            : }
   19188                 :            : 
   19189                 :            : /**
   19190                 :            :  * Validate the batch counter support in root table.
   19191                 :            :  *
   19192                 :            :  * Create a simple flow with invalid counter and drop action on root table to
   19193                 :            :  * validate if batch counter with offset on root table is supported or not.
   19194                 :            :  *
   19195                 :            :  * @param[in] dev
   19196                 :            :  *   Pointer to rte_eth_dev structure.
   19197                 :            :  *
   19198                 :            :  * @return
   19199                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   19200                 :            :  */
   19201                 :            : int
   19202                 :          0 : mlx5_flow_dv_discover_counter_offset_support(struct rte_eth_dev *dev)
   19203                 :            : {
   19204                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   19205                 :          0 :         struct mlx5_dev_ctx_shared *sh = priv->sh;
   19206                 :          0 :         struct mlx5_flow_dv_match_params mask = {
   19207                 :            :                 .size = sizeof(mask.buf),
   19208                 :            :         };
   19209                 :          0 :         struct mlx5_flow_dv_match_params value = {
   19210                 :            :                 .size = sizeof(value.buf),
   19211                 :            :         };
   19212                 :          0 :         struct mlx5dv_flow_matcher_attr dv_attr = {
   19213                 :            :                 .type = IBV_FLOW_ATTR_NORMAL | IBV_FLOW_ATTR_FLAGS_EGRESS,
   19214                 :            :                 .priority = 0,
   19215                 :            :                 .match_criteria_enable = 0,
   19216                 :            :                 .match_mask = (void *)&mask,
   19217                 :            :         };
   19218                 :          0 :         void *actions[2] = { 0 };
   19219                 :            :         struct mlx5_flow_tbl_resource *tbl = NULL;
   19220                 :            :         struct mlx5_devx_obj *dcs = NULL;
   19221                 :            :         void *matcher = NULL;
   19222                 :            :         void *flow = NULL;
   19223                 :            :         int ret = -1;
   19224                 :            : 
   19225                 :          0 :         tbl = flow_dv_tbl_resource_get(dev, 0, 1, 0, false, NULL,
   19226                 :            :                                         0, 0, 0, NULL);
   19227         [ #  # ]:          0 :         if (!tbl)
   19228                 :          0 :                 goto err;
   19229                 :          0 :         dcs = mlx5_devx_cmd_flow_counter_alloc(priv->sh->cdev->ctx, 0x4);
   19230         [ #  # ]:          0 :         if (!dcs)
   19231                 :          0 :                 goto err;
   19232                 :          0 :         ret = mlx5_flow_os_create_flow_action_count(dcs->obj, UINT16_MAX,
   19233                 :            :                                                     &actions[0]);
   19234                 :            :         if (ret)
   19235                 :          0 :                 goto err;
   19236         [ #  # ]:          0 :         dv_attr.match_criteria_enable = flow_dv_matcher_enable(mask.buf);
   19237                 :            :         __flow_dv_adjust_buf_size(&mask.size, dv_attr.match_criteria_enable);
   19238                 :          0 :         ret = mlx5_flow_os_create_flow_matcher(sh->cdev->ctx, &dv_attr,
   19239                 :            :                                                tbl->obj, &matcher);
   19240                 :            :         if (ret)
   19241                 :          0 :                 goto err;
   19242         [ #  # ]:          0 :         __flow_dv_adjust_buf_size(&value.size, dv_attr.match_criteria_enable);
   19243                 :            :         ret = mlx5_flow_os_create_flow(matcher, (void *)&value, 1,
   19244                 :            :                                        actions, &flow);
   19245                 :          0 : err:
   19246                 :            :         /*
   19247                 :            :          * If batch counter with offset is not supported, the driver will not
   19248                 :            :          * validate the invalid offset value, flow create should success.
   19249                 :            :          * In this case, it means batch counter is not supported in root table.
   19250                 :            :          *
   19251                 :            :          * Otherwise, if flow create is failed, counter offset is supported.
   19252                 :            :          */
   19253         [ #  # ]:          0 :         if (flow) {
   19254                 :          0 :                 DRV_LOG(INFO, "Batch counter is not supported in root "
   19255                 :            :                               "table. Switch to fallback mode.");
   19256                 :          0 :                 rte_errno = ENOTSUP;
   19257                 :            :                 ret = -rte_errno;
   19258                 :            :                 claim_zero(mlx5_flow_os_destroy_flow(flow));
   19259                 :            :         } else {
   19260                 :            :                 /* Check matcher to make sure validate fail at flow create. */
   19261   [ #  #  #  # ]:          0 :                 if (!matcher || (matcher && errno != EINVAL))
   19262                 :          0 :                         DRV_LOG(ERR, "Unexpected error in counter offset "
   19263                 :            :                                      "support detection");
   19264                 :            :                 ret = 0;
   19265                 :            :         }
   19266         [ #  # ]:          0 :         if (actions[0])
   19267                 :            :                 claim_zero(mlx5_flow_os_destroy_flow_action(actions[0]));
   19268         [ #  # ]:          0 :         if (matcher)
   19269                 :            :                 claim_zero(mlx5_flow_os_destroy_flow_matcher(matcher));
   19270         [ #  # ]:          0 :         if (tbl)
   19271                 :          0 :                 flow_dv_tbl_resource_release(MLX5_SH(dev), tbl);
   19272         [ #  # ]:          0 :         if (dcs)
   19273                 :          0 :                 claim_zero(mlx5_devx_cmd_destroy(dcs));
   19274                 :          0 :         return ret;
   19275                 :            : }
   19276                 :            : 
   19277                 :            : /**
   19278                 :            :  * Query a devx counter.
   19279                 :            :  *
   19280                 :            :  * @param[in] dev
   19281                 :            :  *   Pointer to the Ethernet device structure.
   19282                 :            :  * @param[in] cnt
   19283                 :            :  *   Index to the flow counter.
   19284                 :            :  * @param[in] clear
   19285                 :            :  *   Set to clear the counter statistics.
   19286                 :            :  * @param[out] pkts
   19287                 :            :  *   The statistics value of packets.
   19288                 :            :  * @param[out] bytes
   19289                 :            :  *   The statistics value of bytes.
   19290                 :            :  *
   19291                 :            :  * @return
   19292                 :            :  *   0 on success, otherwise return -1.
   19293                 :            :  */
   19294                 :            : static int
   19295                 :          0 : flow_dv_counter_query(struct rte_eth_dev *dev, uint32_t counter, bool clear,
   19296                 :            :                       uint64_t *pkts, uint64_t *bytes, void **action)
   19297                 :            : {
   19298                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   19299                 :            :         struct mlx5_flow_counter *cnt;
   19300                 :            :         uint64_t inn_pkts, inn_bytes;
   19301                 :            :         int ret;
   19302                 :            : 
   19303         [ #  # ]:          0 :         if (!priv->sh->cdev->config.devx)
   19304                 :            :                 return -1;
   19305                 :            : 
   19306                 :          0 :         ret = _flow_dv_query_count(dev, counter, &inn_pkts, &inn_bytes);
   19307         [ #  # ]:          0 :         if (ret)
   19308                 :            :                 return -1;
   19309                 :            :         cnt = flow_dv_counter_get_by_idx(dev, counter, NULL);
   19310         [ #  # ]:          0 :         if (cnt && action)
   19311                 :          0 :                 *action = cnt->action;
   19312                 :            : 
   19313                 :          0 :         *pkts = inn_pkts - cnt->hits;
   19314                 :          0 :         *bytes = inn_bytes - cnt->bytes;
   19315         [ #  # ]:          0 :         if (clear) {
   19316                 :          0 :                 cnt->hits = inn_pkts;
   19317                 :          0 :                 cnt->bytes = inn_bytes;
   19318                 :            :         }
   19319                 :            :         return 0;
   19320                 :            : }
   19321                 :            : 
   19322                 :            : /**
   19323                 :            :  * Get aged-out flows.
   19324                 :            :  *
   19325                 :            :  * @param[in] dev
   19326                 :            :  *   Pointer to the Ethernet device structure.
   19327                 :            :  * @param[in] context
   19328                 :            :  *   The address of an array of pointers to the aged-out flows contexts.
   19329                 :            :  * @param[in] nb_contexts
   19330                 :            :  *   The length of context array pointers.
   19331                 :            :  * @param[out] error
   19332                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   19333                 :            :  *   error only.
   19334                 :            :  *
   19335                 :            :  * @return
   19336                 :            :  *   how many contexts get in success, otherwise negative errno value.
   19337                 :            :  *   if nb_contexts is 0, return the amount of all aged contexts.
   19338                 :            :  *   if nb_contexts is not 0 , return the amount of aged flows reported
   19339                 :            :  *   in the context array.
   19340                 :            :  * @note: only stub for now
   19341                 :            :  */
   19342                 :            : static int
   19343                 :          0 : flow_dv_get_aged_flows(struct rte_eth_dev *dev,
   19344                 :            :                     void **context,
   19345                 :            :                     uint32_t nb_contexts,
   19346                 :            :                     struct rte_flow_error *error)
   19347                 :            : {
   19348                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   19349                 :            :         struct mlx5_age_info *age_info;
   19350                 :            :         struct mlx5_age_param *age_param;
   19351                 :            :         struct mlx5_flow_counter *counter;
   19352                 :            :         struct mlx5_aso_age_action *act;
   19353                 :            :         int nb_flows = 0;
   19354                 :            : 
   19355         [ #  # ]:          0 :         if (nb_contexts && !context)
   19356                 :          0 :                 return rte_flow_error_set(error, EINVAL,
   19357                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   19358                 :            :                                           NULL, "empty context");
   19359                 :          0 :         age_info = GET_PORT_AGE_INFO(priv);
   19360                 :          0 :         rte_spinlock_lock(&age_info->aged_sl);
   19361         [ #  # ]:          0 :         LIST_FOREACH(act, &age_info->aged_aso, next) {
   19362                 :          0 :                 nb_flows++;
   19363         [ #  # ]:          0 :                 if (nb_contexts) {
   19364                 :          0 :                         context[nb_flows - 1] = act->age_params.context;
   19365         [ #  # ]:          0 :                         if (!(--nb_contexts))
   19366                 :            :                                 break;
   19367                 :            :                 }
   19368                 :            :         }
   19369         [ #  # ]:          0 :         TAILQ_FOREACH(counter, &age_info->aged_counters, next) {
   19370                 :          0 :                 nb_flows++;
   19371         [ #  # ]:          0 :                 if (nb_contexts) {
   19372                 :            :                         age_param = MLX5_CNT_TO_AGE(counter);
   19373                 :          0 :                         context[nb_flows - 1] = age_param->context;
   19374         [ #  # ]:          0 :                         if (!(--nb_contexts))
   19375                 :            :                                 break;
   19376                 :            :                 }
   19377                 :            :         }
   19378                 :            :         rte_spinlock_unlock(&age_info->aged_sl);
   19379                 :          0 :         MLX5_AGE_SET(age_info, MLX5_AGE_TRIGGER);
   19380                 :          0 :         return nb_flows;
   19381                 :            : }
   19382                 :            : 
   19383                 :            : /*
   19384                 :            :  * Mutex-protected thunk to lock-free flow_dv_counter_alloc().
   19385                 :            :  */
   19386                 :            : static uint32_t
   19387                 :          0 : flow_dv_counter_allocate(struct rte_eth_dev *dev)
   19388                 :            : {
   19389                 :          0 :         return flow_dv_counter_alloc(dev, 0);
   19390                 :            : }
   19391                 :            : 
   19392                 :            : /**
   19393                 :            :  * Validate indirect action.
   19394                 :            :  * Dispatcher for action type specific validation.
   19395                 :            :  *
   19396                 :            :  * @param[in] dev
   19397                 :            :  *   Pointer to the Ethernet device structure.
   19398                 :            :  * @param[in] conf
   19399                 :            :  *   Indirect action configuration.
   19400                 :            :  * @param[in] action
   19401                 :            :  *   The indirect action object to validate.
   19402                 :            :  * @param[out] error
   19403                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   19404                 :            :  *   error only.
   19405                 :            :  *
   19406                 :            :  * @return
   19407                 :            :  *   0 on success, otherwise negative errno value.
   19408                 :            :  */
   19409                 :            : int
   19410                 :          0 : flow_dv_action_validate(struct rte_eth_dev *dev,
   19411                 :            :                         const struct rte_flow_indir_action_conf *conf,
   19412                 :            :                         const struct rte_flow_action *action,
   19413                 :            :                         struct rte_flow_error *err)
   19414                 :            : {
   19415                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   19416                 :            :         /* called from RTE API */
   19417                 :            : 
   19418                 :            :         RTE_SET_USED(conf);
   19419   [ #  #  #  #  :          0 :         switch (action->type) {
                      # ]
   19420                 :          0 :         case RTE_FLOW_ACTION_TYPE_RSS:
   19421                 :            :                 /*
   19422                 :            :                  * priv->obj_ops is set according to driver capabilities.
   19423                 :            :                  * When DevX capabilities are
   19424                 :            :                  * sufficient, it is set to devx_obj_ops.
   19425                 :            :                  * Otherwise, it is set to ibv_obj_ops.
   19426                 :            :                  * ibv_obj_ops doesn't support ind_table_modify operation.
   19427                 :            :                  * In this case the indirect RSS action can't be used.
   19428                 :            :                  */
   19429         [ #  # ]:          0 :                 if (priv->obj_ops.ind_table_modify == NULL)
   19430                 :          0 :                         return rte_flow_error_set
   19431                 :            :                                         (err, ENOTSUP,
   19432                 :            :                                          RTE_FLOW_ERROR_TYPE_ACTION,
   19433                 :            :                                          NULL,
   19434                 :            :                                          "Indirect RSS action not supported");
   19435                 :          0 :                 return mlx5_validate_action_rss(dev, action, err);
   19436                 :          0 :         case RTE_FLOW_ACTION_TYPE_AGE:
   19437         [ #  # ]:          0 :                 if (!priv->sh->aso_age_mng)
   19438                 :          0 :                         return rte_flow_error_set(err, ENOTSUP,
   19439                 :            :                                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   19440                 :            :                                                 NULL,
   19441                 :            :                                                 "Indirect age action not supported");
   19442                 :          0 :                 return flow_dv_validate_action_age(0, action, dev, err);
   19443                 :          0 :         case RTE_FLOW_ACTION_TYPE_COUNT:
   19444                 :          0 :                 return flow_dv_validate_action_count(dev, true, 0, false, err);
   19445                 :          0 :         case RTE_FLOW_ACTION_TYPE_CONNTRACK:
   19446         [ #  # ]:          0 :                 if (!priv->sh->ct_aso_en)
   19447                 :          0 :                         return rte_flow_error_set(err, ENOTSUP,
   19448                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   19449                 :            :                                         "ASO CT is not supported");
   19450                 :          0 :                 return mlx5_validate_action_ct(dev, action->conf, err);
   19451                 :          0 :         default:
   19452                 :          0 :                 return rte_flow_error_set(err, ENOTSUP,
   19453                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
   19454                 :            :                                           NULL,
   19455                 :            :                                           "action type not supported");
   19456                 :            :         }
   19457                 :            : }
   19458                 :            : 
   19459                 :            : /*
   19460                 :            :  * Check if the RSS configurations for colors of a meter policy match
   19461                 :            :  * each other, except the queues.
   19462                 :            :  *
   19463                 :            :  * @param[in] r1
   19464                 :            :  *   Pointer to the first RSS flow action.
   19465                 :            :  * @param[in] r2
   19466                 :            :  *   Pointer to the second RSS flow action.
   19467                 :            :  *
   19468                 :            :  * @return
   19469                 :            :  *   0 on match, 1 on conflict.
   19470                 :            :  */
   19471                 :            : static inline int
   19472                 :          0 : flow_dv_mtr_policy_rss_compare(const struct rte_flow_action_rss *r1,
   19473                 :            :                                const struct rte_flow_action_rss *r2)
   19474                 :            : {
   19475         [ #  # ]:          0 :         if (r1 == NULL || r2 == NULL)
   19476                 :            :                 return 0;
   19477   [ #  #  #  #  :          0 :         if (!(r1->level <= 1 && r2->level <= 1) &&
                   #  # ]
   19478         [ #  # ]:          0 :             !(r1->level > 1 && r2->level > 1))
   19479                 :            :                 return 1;
   19480         [ #  # ]:          0 :         if (r1->func != r2->func)
   19481                 :            :                 return 1;
   19482         [ #  # ]:          0 :         if (r1->types != r2->types &&
   19483         [ #  # ]:          0 :             !((r1->types == 0 || r1->types == RTE_ETH_RSS_IP) &&
   19484         [ #  # ]:          0 :               (r2->types == 0 || r2->types == RTE_ETH_RSS_IP)))
   19485                 :            :                 return 1;
   19486   [ #  #  #  # ]:          0 :         if (r1->key || r2->key) {
   19487         [ #  # ]:          0 :                 const void *key1 = r1->key ? r1->key : rss_hash_default_key;
   19488         [ #  # ]:          0 :                 const void *key2 = r2->key ? r2->key : rss_hash_default_key;
   19489                 :            : 
   19490         [ #  # ]:          0 :                 if (memcmp(key1, key2, MLX5_RSS_HASH_KEY_LEN))
   19491                 :          0 :                         return 1;
   19492                 :            :         }
   19493                 :            :         return 0;
   19494                 :            : }
   19495                 :            : 
   19496                 :            : /**
   19497                 :            :  * Validate the meter hierarchy chain for meter policy.
   19498                 :            :  *
   19499                 :            :  * @param[in] dev
   19500                 :            :  *   Pointer to the Ethernet device structure.
   19501                 :            :  * @param[in] meter_id
   19502                 :            :  *   Meter id.
   19503                 :            :  * @param[in] action_flags
   19504                 :            :  *   Holds the actions detected until now.
   19505                 :            :  * @param[out] is_rss
   19506                 :            :  *   Is RSS or not.
   19507                 :            :  * @param[out] hierarchy_domain
   19508                 :            :  *   The domain bitmap for hierarchy policy.
   19509                 :            :  * @param[out] error
   19510                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   19511                 :            :  *   error only.
   19512                 :            :  *
   19513                 :            :  * @return
   19514                 :            :  *   0 on success, otherwise negative errno value with error set.
   19515                 :            :  */
   19516                 :            : static int
   19517                 :          0 : flow_dv_validate_policy_mtr_hierarchy(struct rte_eth_dev *dev,
   19518                 :            :                                   uint32_t meter_id,
   19519                 :            :                                   uint64_t action_flags,
   19520                 :            :                                   bool *is_rss,
   19521                 :            :                                   uint8_t *hierarchy_domain,
   19522                 :            :                                   struct rte_mtr_error *error)
   19523                 :            : {
   19524                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   19525                 :            :         struct mlx5_flow_meter_info *fm;
   19526                 :            :         struct mlx5_flow_meter_policy *policy;
   19527                 :            :         uint8_t cnt = 1;
   19528                 :            : 
   19529         [ #  # ]:          0 :         if (action_flags & (MLX5_FLOW_FATE_ACTIONS |
   19530                 :            :                             MLX5_FLOW_FATE_ESWITCH_ACTIONS))
   19531                 :          0 :                 return -rte_mtr_error_set(error, EINVAL,
   19532                 :            :                                         RTE_MTR_ERROR_TYPE_POLICER_ACTION_GREEN,
   19533                 :            :                                         NULL,
   19534                 :            :                                         "Multiple fate actions not supported.");
   19535                 :          0 :         *hierarchy_domain = 0;
   19536                 :          0 :         fm = mlx5_flow_meter_find(priv, meter_id, NULL);
   19537                 :            :         while (true) {
   19538         [ #  # ]:          0 :                 if (!fm)
   19539                 :          0 :                         return -rte_mtr_error_set(error, EINVAL,
   19540                 :            :                                                 RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
   19541                 :            :                                         "Meter not found in meter hierarchy.");
   19542         [ #  # ]:          0 :                 if (fm->def_policy)
   19543                 :          0 :                         return -rte_mtr_error_set(error, EINVAL,
   19544                 :            :                                         RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
   19545                 :            :                         "Non termination meter not supported in hierarchy.");
   19546         [ #  # ]:          0 :                 if (!fm->shared)
   19547                 :          0 :                         return -rte_mtr_error_set(error, EINVAL,
   19548                 :            :                                         RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
   19549                 :            :                                         "Only shared meter supported in hierarchy.");
   19550                 :          0 :                 policy = mlx5_flow_meter_policy_find(dev, fm->policy_id, NULL);
   19551                 :            :                 MLX5_ASSERT(policy);
   19552                 :            :                 /**
   19553                 :            :                  * Only inherit the supported domains of the first meter in
   19554                 :            :                  * hierarchy.
   19555                 :            :                  * One meter supports at least one domain.
   19556                 :            :                  */
   19557         [ #  # ]:          0 :                 if (!*hierarchy_domain) {
   19558         [ #  # ]:          0 :                         if (policy->transfer)
   19559                 :          0 :                                 *hierarchy_domain |=
   19560                 :            :                                                 MLX5_MTR_DOMAIN_TRANSFER_BIT;
   19561         [ #  # ]:          0 :                         if (policy->ingress)
   19562                 :          0 :                                 *hierarchy_domain |=
   19563                 :            :                                                 MLX5_MTR_DOMAIN_INGRESS_BIT;
   19564         [ #  # ]:          0 :                         if (policy->egress)
   19565                 :          0 :                                 *hierarchy_domain |= MLX5_MTR_DOMAIN_EGRESS_BIT;
   19566                 :            :                 }
   19567         [ #  # ]:          0 :                 if (!policy->is_hierarchy) {
   19568                 :          0 :                         *is_rss = policy->is_rss;
   19569                 :            :                         break;
   19570                 :            :                 }
   19571                 :          0 :                 rte_spinlock_lock(&policy->sl);
   19572                 :          0 :                 fm = mlx5_flow_meter_hierarchy_next_meter(priv, policy, NULL);
   19573                 :            :                 rte_spinlock_unlock(&policy->sl);
   19574         [ #  # ]:          0 :                 if (++cnt >= MLX5_MTR_CHAIN_MAX_NUM)
   19575                 :          0 :                         return -rte_mtr_error_set(error, EINVAL,
   19576                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY, NULL,
   19577                 :            :                                         "Exceed max hierarchy meter number.");
   19578                 :            :         }
   19579                 :          0 :         return 0;
   19580                 :            : }
   19581                 :            : 
   19582                 :            : /**
   19583                 :            :  * Validate meter policy actions.
   19584                 :            :  * Dispatcher for action type specific validation.
   19585                 :            :  *
   19586                 :            :  * @param[in] dev
   19587                 :            :  *   Pointer to the Ethernet device structure.
   19588                 :            :  * @param[in] action
   19589                 :            :  *   The meter policy action object to validate.
   19590                 :            :  * @param[in] attr
   19591                 :            :  *   Attributes of flow to determine steering domain.
   19592                 :            :  * @param[out] error
   19593                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   19594                 :            :  *   error only.
   19595                 :            :  *
   19596                 :            :  * @return
   19597                 :            :  *   0 on success, otherwise negative errno value.
   19598                 :            :  */
   19599                 :            : static int
   19600                 :          0 : flow_dv_validate_mtr_policy_acts(struct rte_eth_dev *dev,
   19601                 :            :                         const struct rte_flow_action *actions[RTE_COLORS],
   19602                 :            :                         struct rte_flow_attr *attr,
   19603                 :            :                         bool *is_rss,
   19604                 :            :                         uint8_t *domain_bitmap,
   19605                 :            :                         uint8_t *policy_mode,
   19606                 :            :                         struct rte_mtr_error *error)
   19607                 :            : {
   19608                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   19609                 :          0 :         struct mlx5_sh_config *dev_conf = &priv->sh->config;
   19610                 :            :         const struct rte_flow_action *act;
   19611                 :          0 :         uint64_t action_flags[RTE_COLORS] = {0};
   19612                 :            :         int actions_n;
   19613                 :            :         int i, ret;
   19614                 :            :         struct rte_flow_error flow_err;
   19615                 :          0 :         uint8_t domain_color[RTE_COLORS] = {0};
   19616                 :            :         uint8_t def_domain = MLX5_MTR_ALL_DOMAIN_BIT;
   19617                 :          0 :         uint8_t hierarchy_domain = 0;
   19618                 :            :         const struct rte_flow_action_meter *mtr;
   19619                 :            :         const struct rte_flow_action_meter *next_mtr = NULL;
   19620                 :            :         bool def_green = false;
   19621                 :            :         bool def_yellow = false;
   19622                 :          0 :         const struct rte_flow_action_rss *rss_color[RTE_COLORS] = {NULL};
   19623                 :            :         /* Called from RTE API */
   19624   [ #  #  #  #  :          0 :         bool is_root = !(attr->group || (attr->transfer && priv->fdb_def_rule));
                   #  # ]
   19625                 :            : 
   19626         [ #  # ]:          0 :         if (!dev_conf->dv_esw_en)
   19627                 :            :                 def_domain &= ~MLX5_MTR_DOMAIN_TRANSFER_BIT;
   19628                 :          0 :         *domain_bitmap = def_domain;
   19629                 :            :         /* Red color could only support DROP action. */
   19630         [ #  # ]:          0 :         if (!actions[RTE_COLOR_RED] ||
   19631         [ #  # ]:          0 :             actions[RTE_COLOR_RED]->type != RTE_FLOW_ACTION_TYPE_DROP)
   19632                 :          0 :                 return -rte_mtr_error_set(error, ENOTSUP,
   19633                 :            :                                 RTE_MTR_ERROR_TYPE_METER_POLICY,
   19634                 :            :                                 NULL, "Red color only supports drop action.");
   19635                 :            :         /*
   19636                 :            :          * Check default policy actions:
   19637                 :            :          * Green / Yellow: no action, Red: drop action
   19638                 :            :          * Either G or Y will trigger default policy actions to be created.
   19639                 :            :          */
   19640         [ #  # ]:          0 :         if (!actions[RTE_COLOR_GREEN] ||
   19641         [ #  # ]:          0 :             actions[RTE_COLOR_GREEN]->type == RTE_FLOW_ACTION_TYPE_END)
   19642                 :            :                 def_green = true;
   19643         [ #  # ]:          0 :         if (!actions[RTE_COLOR_YELLOW] ||
   19644         [ #  # ]:          0 :             actions[RTE_COLOR_YELLOW]->type == RTE_FLOW_ACTION_TYPE_END)
   19645                 :            :                 def_yellow = true;
   19646         [ #  # ]:          0 :         if (def_green && def_yellow) {
   19647                 :          0 :                 *policy_mode = MLX5_MTR_POLICY_MODE_DEF;
   19648                 :          0 :                 return 0;
   19649         [ #  # ]:          0 :         } else if (!def_green && def_yellow) {
   19650                 :          0 :                 *policy_mode = MLX5_MTR_POLICY_MODE_OG;
   19651         [ #  # ]:          0 :         } else if (def_green && !def_yellow) {
   19652                 :          0 :                 *policy_mode = MLX5_MTR_POLICY_MODE_OY;
   19653                 :            :         } else {
   19654                 :          0 :                 *policy_mode = MLX5_MTR_POLICY_MODE_ALL;
   19655                 :            :         }
   19656                 :            :         /* Set to empty string in case of NULL pointer access by user. */
   19657                 :          0 :         flow_err.message = "";
   19658         [ #  # ]:          0 :         for (i = 0; i < RTE_COLORS; i++) {
   19659                 :          0 :                 act = actions[i];
   19660                 :          0 :                 for (action_flags[i] = 0, actions_n = 0;
   19661   [ #  #  #  # ]:          0 :                      act && act->type != RTE_FLOW_ACTION_TYPE_END;
   19662                 :          0 :                      act++) {
   19663         [ #  # ]:          0 :                         if (actions_n == MLX5_DV_MAX_NUMBER_OF_ACTIONS)
   19664                 :          0 :                                 return -rte_mtr_error_set(error, ENOTSUP,
   19665                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   19666                 :            :                                           NULL, "too many actions");
   19667   [ #  #  #  #  :          0 :                         switch (act->type) {
          #  #  #  #  #  
                      # ]
   19668                 :          0 :                         case RTE_FLOW_ACTION_TYPE_PORT_ID:
   19669                 :            :                         case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
   19670         [ #  # ]:          0 :                                 if (!dev_conf->dv_esw_en)
   19671                 :          0 :                                         return -rte_mtr_error_set(error,
   19672                 :            :                                         ENOTSUP,
   19673                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   19674                 :            :                                         NULL, "PORT action validate check"
   19675                 :            :                                         " fail for ESW disable");
   19676                 :          0 :                                 ret = flow_dv_validate_action_port_id(dev,
   19677                 :            :                                                 action_flags[i],
   19678                 :            :                                                 act, attr, &flow_err);
   19679         [ #  # ]:          0 :                                 if (ret)
   19680                 :          0 :                                         return -rte_mtr_error_set(error,
   19681                 :            :                                         ENOTSUP,
   19682                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   19683         [ #  # ]:          0 :                                         NULL, flow_err.message ?
   19684                 :            :                                         flow_err.message :
   19685                 :            :                                         "PORT action validate check fail");
   19686                 :          0 :                                 ++actions_n;
   19687                 :          0 :                                 action_flags[i] |= MLX5_FLOW_ACTION_PORT_ID;
   19688                 :          0 :                                 break;
   19689                 :          0 :                         case RTE_FLOW_ACTION_TYPE_MARK:
   19690                 :          0 :                                 ret = flow_dv_validate_action_mark(dev, act,
   19691                 :            :                                                            action_flags[i],
   19692                 :            :                                                            attr, &flow_err);
   19693         [ #  # ]:          0 :                                 if (ret < 0)
   19694                 :          0 :                                         return -rte_mtr_error_set(error,
   19695                 :            :                                         ENOTSUP,
   19696                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   19697         [ #  # ]:          0 :                                         NULL, flow_err.message ?
   19698                 :            :                                         flow_err.message :
   19699                 :            :                                         "Mark action validate check fail");
   19700         [ #  # ]:          0 :                                 if (dev_conf->dv_xmeta_en !=
   19701                 :            :                                         MLX5_XMETA_MODE_LEGACY)
   19702                 :          0 :                                         return -rte_mtr_error_set(error,
   19703                 :            :                                         ENOTSUP,
   19704                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   19705                 :            :                                         NULL, "Extend MARK action is "
   19706                 :            :                                         "not supported. Please try use "
   19707                 :            :                                         "default policy for meter.");
   19708                 :          0 :                                 action_flags[i] |= MLX5_FLOW_ACTION_MARK;
   19709                 :          0 :                                 ++actions_n;
   19710                 :          0 :                                 break;
   19711                 :          0 :                         case RTE_FLOW_ACTION_TYPE_SET_TAG:
   19712                 :          0 :                                 ret = flow_dv_validate_action_set_tag(dev,
   19713                 :            :                                                         act, action_flags[i],
   19714                 :            :                                                         attr, &flow_err);
   19715         [ #  # ]:          0 :                                 if (ret)
   19716                 :          0 :                                         return -rte_mtr_error_set(error,
   19717                 :            :                                         ENOTSUP,
   19718                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   19719         [ #  # ]:          0 :                                         NULL, flow_err.message ?
   19720                 :            :                                         flow_err.message :
   19721                 :            :                                         "Set tag action validate check fail");
   19722                 :          0 :                                 action_flags[i] |= MLX5_FLOW_ACTION_SET_TAG;
   19723                 :          0 :                                 ++actions_n;
   19724                 :          0 :                                 break;
   19725                 :          0 :                         case RTE_FLOW_ACTION_TYPE_DROP:
   19726                 :          0 :                                 ret = mlx5_flow_validate_action_drop
   19727                 :            :                                         (dev, false, attr, &flow_err);
   19728         [ #  # ]:          0 :                                 if (ret < 0)
   19729                 :          0 :                                         return -rte_mtr_error_set(error,
   19730                 :            :                                         ENOTSUP,
   19731                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   19732         [ #  # ]:          0 :                                         NULL, flow_err.message ?
   19733                 :            :                                         flow_err.message :
   19734                 :            :                                         "Drop action validate check fail");
   19735                 :          0 :                                 action_flags[i] |= MLX5_FLOW_ACTION_DROP;
   19736                 :          0 :                                 ++actions_n;
   19737                 :          0 :                                 break;
   19738                 :          0 :                         case RTE_FLOW_ACTION_TYPE_QUEUE:
   19739                 :            :                                 /*
   19740                 :            :                                  * Check whether extensive
   19741                 :            :                                  * metadata feature is engaged.
   19742                 :            :                                  */
   19743         [ #  # ]:          0 :                                 if (dev_conf->dv_flow_en &&
   19744         [ #  # ]:          0 :                                     (dev_conf->dv_xmeta_en !=
   19745         [ #  # ]:          0 :                                      MLX5_XMETA_MODE_LEGACY) &&
   19746                 :          0 :                                     mlx5_flow_ext_mreg_supported(dev))
   19747                 :          0 :                                         return -rte_mtr_error_set(error,
   19748                 :            :                                           ENOTSUP,
   19749                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   19750                 :            :                                           NULL, "Queue action with meta "
   19751                 :            :                                           "is not supported. Please try use "
   19752                 :            :                                           "default policy for meter.");
   19753                 :          0 :                                 ret = mlx5_flow_validate_action_queue(act,
   19754                 :            :                                                         action_flags[i], dev,
   19755                 :            :                                                         attr, &flow_err);
   19756         [ #  # ]:          0 :                                 if (ret < 0)
   19757                 :          0 :                                         return -rte_mtr_error_set(error,
   19758                 :            :                                           ENOTSUP,
   19759                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   19760         [ #  # ]:          0 :                                           NULL, flow_err.message ?
   19761                 :            :                                           flow_err.message :
   19762                 :            :                                           "Queue action validate check fail");
   19763                 :          0 :                                 action_flags[i] |= MLX5_FLOW_ACTION_QUEUE;
   19764                 :          0 :                                 ++actions_n;
   19765                 :          0 :                                 break;
   19766                 :          0 :                         case RTE_FLOW_ACTION_TYPE_RSS:
   19767         [ #  # ]:          0 :                                 if (dev_conf->dv_flow_en &&
   19768         [ #  # ]:          0 :                                     (dev_conf->dv_xmeta_en !=
   19769         [ #  # ]:          0 :                                      MLX5_XMETA_MODE_LEGACY) &&
   19770                 :          0 :                                     mlx5_flow_ext_mreg_supported(dev))
   19771                 :          0 :                                         return -rte_mtr_error_set(error,
   19772                 :            :                                           ENOTSUP,
   19773                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   19774                 :            :                                           NULL, "RSS action with meta "
   19775                 :            :                                           "is not supported. Please try use "
   19776                 :            :                                           "default policy for meter.");
   19777                 :          0 :                                 ret = mlx5_validate_action_rss(dev, act,
   19778                 :            :                                                                &flow_err);
   19779         [ #  # ]:          0 :                                 if (ret < 0)
   19780                 :          0 :                                         return -rte_mtr_error_set(error,
   19781                 :            :                                           ENOTSUP,
   19782                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   19783         [ #  # ]:          0 :                                           NULL, flow_err.message ?
   19784                 :            :                                           flow_err.message :
   19785                 :            :                                           "RSS action validate check fail");
   19786                 :          0 :                                 action_flags[i] |= MLX5_FLOW_ACTION_RSS;
   19787                 :          0 :                                 ++actions_n;
   19788                 :            :                                 /* Either G or Y will set the RSS. */
   19789                 :          0 :                                 rss_color[i] = act->conf;
   19790                 :          0 :                                 break;
   19791                 :          0 :                         case RTE_FLOW_ACTION_TYPE_JUMP:
   19792                 :          0 :                                 ret = flow_dv_validate_action_jump(dev,
   19793                 :            :                                         NULL, act, action_flags[i],
   19794                 :            :                                         attr, true, &flow_err);
   19795         [ #  # ]:          0 :                                 if (ret)
   19796                 :          0 :                                         return -rte_mtr_error_set(error,
   19797                 :            :                                           ENOTSUP,
   19798                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   19799         [ #  # ]:          0 :                                           NULL, flow_err.message ?
   19800                 :            :                                           flow_err.message :
   19801                 :            :                                           "Jump action validate check fail");
   19802                 :          0 :                                 ++actions_n;
   19803                 :          0 :                                 action_flags[i] |= MLX5_FLOW_ACTION_JUMP;
   19804                 :          0 :                                 break;
   19805                 :          0 :                         case RTE_FLOW_ACTION_TYPE_METER:
   19806                 :          0 :                                 mtr = act->conf;
   19807   [ #  #  #  # ]:          0 :                                 if (next_mtr && next_mtr->mtr_id != mtr->mtr_id)
   19808                 :          0 :                                         return -rte_mtr_error_set(error, ENOTSUP,
   19809                 :            :                                                 RTE_MTR_ERROR_TYPE_METER_POLICY, NULL,
   19810                 :            :                                                 "Green and Yellow must use the same meter.");
   19811                 :          0 :                                 ret = flow_dv_validate_policy_mtr_hierarchy(dev,
   19812                 :          0 :                                                         mtr->mtr_id,
   19813                 :            :                                                         action_flags[i],
   19814                 :            :                                                         is_rss,
   19815                 :            :                                                         &hierarchy_domain,
   19816                 :            :                                                         error);
   19817         [ #  # ]:          0 :                                 if (ret)
   19818                 :          0 :                                         return ret;
   19819                 :          0 :                                 ++actions_n;
   19820                 :          0 :                                 action_flags[i] |=
   19821                 :            :                                 MLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY;
   19822                 :            :                                 next_mtr = mtr;
   19823                 :          0 :                                 break;
   19824                 :          0 :                         case RTE_FLOW_ACTION_TYPE_MODIFY_FIELD:
   19825                 :          0 :                                 ret = flow_dv_validate_action_modify_field(dev,
   19826                 :            :                                         action_flags[i], act, attr, is_root, &flow_err);
   19827         [ #  # ]:          0 :                                 if (ret < 0)
   19828                 :          0 :                                         return -rte_mtr_error_set(error,
   19829                 :            :                                           ENOTSUP,
   19830                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   19831         [ #  # ]:          0 :                                           NULL, flow_err.message ?
   19832                 :            :                                           flow_err.message :
   19833                 :            :                                           "Modify field action validate check fail");
   19834                 :          0 :                                 ++actions_n;
   19835                 :          0 :                                 action_flags[i] |= MLX5_FLOW_ACTION_MODIFY_FIELD;
   19836                 :          0 :                                 break;
   19837                 :            :                         default:
   19838                 :          0 :                                 return -rte_mtr_error_set(error, ENOTSUP,
   19839                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   19840                 :            :                                         NULL,
   19841                 :            :                                         "Doesn't support optional action");
   19842                 :            :                         }
   19843                 :            :                 }
   19844         [ #  # ]:          0 :                 if (action_flags[i] & MLX5_FLOW_ACTION_PORT_ID) {
   19845                 :          0 :                         domain_color[i] = MLX5_MTR_DOMAIN_TRANSFER_BIT;
   19846         [ #  # ]:          0 :                 } else if ((action_flags[i] &
   19847                 :          0 :                           (MLX5_FLOW_ACTION_RSS | MLX5_FLOW_ACTION_QUEUE)) ||
   19848         [ #  # ]:          0 :                           (action_flags[i] & MLX5_FLOW_ACTION_MARK)) {
   19849                 :            :                         /*
   19850                 :            :                          * Only support MLX5_XMETA_MODE_LEGACY
   19851                 :            :                          * so MARK action is only in ingress domain.
   19852                 :            :                          */
   19853                 :          0 :                         domain_color[i] = MLX5_MTR_DOMAIN_INGRESS_BIT;
   19854                 :            :                 } else {
   19855                 :          0 :                         domain_color[i] = def_domain;
   19856         [ #  # ]:          0 :                         if (action_flags[i] &&
   19857         [ #  # ]:          0 :                             !(action_flags[i] & MLX5_FLOW_FATE_ESWITCH_ACTIONS))
   19858                 :          0 :                                 domain_color[i] &=
   19859                 :            :                                 ~MLX5_MTR_DOMAIN_TRANSFER_BIT;
   19860                 :            :                 }
   19861         [ #  # ]:          0 :                 if (action_flags[i] &
   19862                 :            :                     MLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY)
   19863                 :          0 :                         domain_color[i] &= hierarchy_domain;
   19864                 :            :                 /*
   19865                 :            :                  * Non-termination actions only support NIC Tx domain.
   19866                 :            :                  * The adjustion should be skipped when there is no
   19867                 :            :                  * action or only END is provided. The default domains
   19868                 :            :                  * bit-mask is set to find the MIN intersection.
   19869                 :            :                  * The action flags checking should also be skipped.
   19870                 :            :                  */
   19871         [ #  # ]:          0 :                 if ((def_green && i == RTE_COLOR_GREEN) ||
   19872         [ #  # ]:          0 :                     (def_yellow && i == RTE_COLOR_YELLOW))
   19873                 :          0 :                         continue;
   19874                 :            :                 /*
   19875                 :            :                  * Validate the drop action mutual exclusion
   19876                 :            :                  * with other actions. Drop action is mutually-exclusive
   19877                 :            :                  * with any other action, except for Count action.
   19878                 :            :                  */
   19879         [ #  # ]:          0 :                 if ((action_flags[i] & MLX5_FLOW_ACTION_DROP) &&
   19880         [ #  # ]:          0 :                     (action_flags[i] & ~MLX5_FLOW_ACTION_DROP)) {
   19881                 :          0 :                         return -rte_mtr_error_set(error, ENOTSUP,
   19882                 :            :                                 RTE_MTR_ERROR_TYPE_METER_POLICY,
   19883                 :            :                                 NULL, "Drop action is mutually-exclusive "
   19884                 :            :                                 "with any other action");
   19885                 :            :                 }
   19886                 :            :                 /* Eswitch has few restrictions on using items and actions */
   19887         [ #  # ]:          0 :                 if (domain_color[i] & MLX5_MTR_DOMAIN_TRANSFER_BIT) {
   19888         [ #  # ]:          0 :                         if (!mlx5_flow_ext_mreg_supported(dev) &&
   19889         [ #  # ]:          0 :                             action_flags[i] & MLX5_FLOW_ACTION_MARK)
   19890                 :          0 :                                 return -rte_mtr_error_set(error, ENOTSUP,
   19891                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   19892                 :            :                                         NULL, "unsupported action MARK");
   19893         [ #  # ]:          0 :                         if (action_flags[i] & MLX5_FLOW_ACTION_QUEUE)
   19894                 :          0 :                                 return -rte_mtr_error_set(error, ENOTSUP,
   19895                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   19896                 :            :                                         NULL, "unsupported action QUEUE");
   19897         [ #  # ]:          0 :                         if (action_flags[i] & MLX5_FLOW_ACTION_RSS)
   19898                 :          0 :                                 return -rte_mtr_error_set(error, ENOTSUP,
   19899                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   19900                 :            :                                         NULL, "unsupported action RSS");
   19901         [ #  # ]:          0 :                         if (!(action_flags[i] & MLX5_FLOW_FATE_ESWITCH_ACTIONS))
   19902                 :          0 :                                 return -rte_mtr_error_set(error, ENOTSUP,
   19903                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   19904                 :            :                                         NULL, "no fate action is found");
   19905                 :            :                 } else {
   19906   [ #  #  #  # ]:          0 :                         if (!(action_flags[i] & MLX5_FLOW_FATE_ACTIONS) &&
   19907                 :            :                             (domain_color[i] & MLX5_MTR_DOMAIN_INGRESS_BIT)) {
   19908         [ #  # ]:          0 :                                 if ((domain_color[i] &
   19909                 :            :                                      MLX5_MTR_DOMAIN_EGRESS_BIT))
   19910                 :          0 :                                         domain_color[i] =
   19911                 :            :                                                 MLX5_MTR_DOMAIN_EGRESS_BIT;
   19912                 :            :                                 else
   19913                 :          0 :                                         return -rte_mtr_error_set(error,
   19914                 :            :                                                 ENOTSUP,
   19915                 :            :                                                 RTE_MTR_ERROR_TYPE_METER_POLICY,
   19916                 :            :                                                 NULL,
   19917                 :            :                                                 "no fate action is found");
   19918                 :            :                         }
   19919                 :            :                 }
   19920                 :            :         }
   19921   [ #  #  #  # ]:          0 :         if (next_mtr && *policy_mode == MLX5_MTR_POLICY_MODE_ALL) {
   19922         [ #  # ]:          0 :                 if (!(action_flags[RTE_COLOR_GREEN] & action_flags[RTE_COLOR_YELLOW] &
   19923                 :            :                       MLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY))
   19924                 :          0 :                         return -rte_mtr_error_set(error, EINVAL, RTE_MTR_ERROR_TYPE_METER_POLICY,
   19925                 :            :                                                   NULL,
   19926                 :            :                                                   "Meter hierarchy supports meter action only.");
   19927                 :            :         }
   19928                 :            :         /* If both colors have RSS, the attributes should be the same. */
   19929         [ #  # ]:          0 :         if (flow_dv_mtr_policy_rss_compare(rss_color[RTE_COLOR_GREEN],
   19930                 :            :                                            rss_color[RTE_COLOR_YELLOW]))
   19931                 :          0 :                 return -rte_mtr_error_set(error, EINVAL,
   19932                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   19933                 :            :                                           NULL, "policy RSS attr conflict");
   19934   [ #  #  #  # ]:          0 :         if (rss_color[RTE_COLOR_GREEN] || rss_color[RTE_COLOR_YELLOW])
   19935                 :          0 :                 *is_rss = true;
   19936                 :            :         /* "domain_color[C]" is non-zero for each color, default is ALL. */
   19937         [ #  # ]:          0 :         if (!def_green && !def_yellow &&
   19938         [ #  # ]:          0 :             domain_color[RTE_COLOR_GREEN] != domain_color[RTE_COLOR_YELLOW] &&
   19939         [ #  # ]:          0 :             !(action_flags[RTE_COLOR_GREEN] & MLX5_FLOW_ACTION_DROP) &&
   19940         [ #  # ]:          0 :             !(action_flags[RTE_COLOR_YELLOW] & MLX5_FLOW_ACTION_DROP))
   19941                 :          0 :                 return -rte_mtr_error_set(error, EINVAL,
   19942                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   19943                 :            :                                           NULL, "policy domains conflict");
   19944                 :            :         /*
   19945                 :            :          * At least one color policy is listed in the actions, the domains
   19946                 :            :          * to be supported should be the intersection.
   19947                 :            :          */
   19948                 :          0 :         *domain_bitmap = domain_color[RTE_COLOR_GREEN] &
   19949                 :          0 :                          domain_color[RTE_COLOR_YELLOW];
   19950                 :          0 :         return 0;
   19951                 :            : }
   19952                 :            : 
   19953                 :            : static int
   19954                 :          0 : flow_dv_sync_domain(struct rte_eth_dev *dev, uint32_t domains, uint32_t flags)
   19955                 :            : {
   19956                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   19957                 :            :         int ret = 0;
   19958                 :            : 
   19959   [ #  #  #  # ]:          0 :         if ((domains & RTE_PMD_MLX5_DOMAIN_BIT_NIC_RX) && priv->sh->rx_domain != NULL) {
   19960                 :            :                 ret = mlx5_os_flow_dr_sync_domain(priv->sh->rx_domain,
   19961                 :            :                                                 flags);
   19962         [ #  # ]:          0 :                 if (ret != 0)
   19963                 :            :                         return ret;
   19964                 :            :         }
   19965   [ #  #  #  # ]:          0 :         if ((domains & RTE_PMD_MLX5_DOMAIN_BIT_NIC_TX) && priv->sh->tx_domain != NULL) {
   19966                 :            :                 ret = mlx5_os_flow_dr_sync_domain(priv->sh->tx_domain, flags);
   19967         [ #  # ]:          0 :                 if (ret != 0)
   19968                 :            :                         return ret;
   19969                 :            :         }
   19970   [ #  #  #  # ]:          0 :         if ((domains & RTE_PMD_MLX5_DOMAIN_BIT_FDB) && priv->sh->fdb_domain != NULL) {
   19971                 :            :                 ret = mlx5_os_flow_dr_sync_domain(priv->sh->fdb_domain, flags);
   19972         [ #  # ]:          0 :                 if (ret != 0)
   19973                 :          0 :                         return ret;
   19974                 :            :         }
   19975                 :            :         return 0;
   19976                 :            : }
   19977                 :            : 
   19978                 :            : /**
   19979                 :            :  * Discover the number of available flow priorities
   19980                 :            :  * by trying to create a flow with the highest priority value
   19981                 :            :  * for each possible number.
   19982                 :            :  *
   19983                 :            :  * @param[in] dev
   19984                 :            :  *   Ethernet device.
   19985                 :            :  * @param[in] vprio
   19986                 :            :  *   List of possible number of available priorities.
   19987                 :            :  * @param[in] vprio_n
   19988                 :            :  *   Size of @p vprio array.
   19989                 :            :  * @return
   19990                 :            :  *   On success, number of available flow priorities.
   19991                 :            :  *   On failure, a negative errno-style code and rte_errno is set.
   19992                 :            :  */
   19993                 :            : static int
   19994                 :          0 : flow_dv_discover_priorities(struct rte_eth_dev *dev,
   19995                 :            :                             const uint16_t *vprio, int vprio_n)
   19996                 :            : {
   19997                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   19998                 :          0 :         struct mlx5_indexed_pool *pool = priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW];
   19999                 :            :         struct rte_flow_item_eth eth;
   20000                 :          0 :         struct rte_flow_item item = {
   20001                 :            :                 .type = RTE_FLOW_ITEM_TYPE_ETH,
   20002                 :            :                 .spec = &eth,
   20003                 :            :                 .mask = &eth,
   20004                 :            :         };
   20005                 :          0 :         struct mlx5_flow_dv_matcher matcher = {
   20006                 :            :                 .mask = {
   20007                 :            :                         .size = sizeof(matcher.mask.buf),
   20008                 :            :                 },
   20009                 :            :         };
   20010                 :            :         union mlx5_flow_tbl_key tbl_key;
   20011                 :            :         struct mlx5_flow flow;
   20012                 :            :         void *action;
   20013                 :            :         struct rte_flow_error error;
   20014                 :            :         uint8_t misc_mask;
   20015                 :            :         int i, err, ret = -ENOTSUP;
   20016                 :            : 
   20017                 :            :         /*
   20018                 :            :          * Prepare a flow with a catch-all pattern and a drop action.
   20019                 :            :          * Use drop queue, because shared drop action may be unavailable.
   20020                 :            :          */
   20021                 :          0 :         action = priv->drop_queue.hrxq->action;
   20022         [ #  # ]:          0 :         if (action == NULL) {
   20023                 :          0 :                 DRV_LOG(ERR, "Priority discovery requires a drop action");
   20024                 :          0 :                 rte_errno = ENOTSUP;
   20025                 :          0 :                 return -rte_errno;
   20026                 :            :         }
   20027                 :            :         memset(&flow, 0, sizeof(flow));
   20028                 :          0 :         flow.handle = mlx5_ipool_zmalloc(pool, &flow.handle_idx);
   20029         [ #  # ]:          0 :         if (flow.handle == NULL) {
   20030                 :          0 :                 DRV_LOG(ERR, "Cannot create flow handle");
   20031                 :          0 :                 rte_errno = ENOMEM;
   20032                 :          0 :                 return -rte_errno;
   20033                 :            :         }
   20034                 :          0 :         flow.ingress = true;
   20035                 :          0 :         flow.dv.value.size = MLX5_ST_SZ_BYTES(fte_match_param);
   20036                 :          0 :         flow.dv.actions[0] = action;
   20037                 :          0 :         flow.dv.actions_n = 1;
   20038                 :            :         memset(&eth, 0, sizeof(eth));
   20039                 :          0 :         flow_dv_translate_item_eth(matcher.mask.buf, &item,
   20040                 :            :                                    /* inner */ false, /* group */ 0,
   20041                 :            :                                    MLX5_SET_MATCHER_SW_M);
   20042                 :          0 :         flow_dv_translate_item_eth(flow.dv.value.buf, &item,
   20043                 :            :                                    /* inner */ false, /* group */ 0,
   20044                 :            :                                    MLX5_SET_MATCHER_SW_V);
   20045                 :          0 :         matcher.crc = rte_raw_cksum(matcher.mask.buf, matcher.mask.size);
   20046         [ #  # ]:          0 :         for (i = 0; i < vprio_n; i++) {
   20047                 :            :                 /* Configure the next proposed maximum priority. */
   20048                 :          0 :                 matcher.priority = vprio[i] - 1;
   20049                 :            :                 memset(&tbl_key, 0, sizeof(tbl_key));
   20050                 :          0 :                 err = flow_dv_matcher_register(dev, &matcher, &tbl_key, &flow,
   20051                 :            :                                                /* tunnel */ NULL,
   20052                 :            :                                                /* group */ 0,
   20053                 :            :                                                &error);
   20054         [ #  # ]:          0 :                 if (err != 0) {
   20055                 :            :                         /* This action is pure SW and must always succeed. */
   20056                 :          0 :                         DRV_LOG(ERR, "Cannot register matcher");
   20057                 :          0 :                         ret = -rte_errno;
   20058                 :          0 :                         break;
   20059                 :            :                 }
   20060                 :            :                 /* Try to apply the flow to HW. */
   20061         [ #  # ]:          0 :                 misc_mask = flow_dv_matcher_enable(flow.handle->dvh.matcher->mask.buf);
   20062                 :            :                 __flow_dv_adjust_buf_size(&flow.dv.value.size, misc_mask);
   20063                 :          0 :                 err = mlx5_flow_os_create_flow
   20064                 :            :                                 (flow.handle->dvh.matcher->matcher_object,
   20065                 :          0 :                                  (void *)&flow.dv.value, flow.dv.actions_n,
   20066                 :            :                                  flow.dv.actions, &flow.handle->drv_flow);
   20067                 :            :                 if (err == 0) {
   20068                 :          0 :                         claim_zero(mlx5_flow_os_destroy_flow
   20069                 :            :                                                 (flow.handle->drv_flow));
   20070                 :          0 :                         flow.handle->drv_flow = NULL;
   20071                 :            :                 }
   20072                 :          0 :                 claim_zero(flow_dv_matcher_release(dev, flow.handle));
   20073         [ #  # ]:          0 :                 if (err != 0)
   20074                 :            :                         break;
   20075                 :          0 :                 ret = vprio[i];
   20076                 :            :         }
   20077                 :          0 :         mlx5_ipool_free(pool, flow.handle_idx);
   20078                 :            :         /* Set rte_errno if no expected priority value matched. */
   20079         [ #  # ]:          0 :         if (ret < 0)
   20080                 :          0 :                 rte_errno = -ret;
   20081                 :            :         return ret;
   20082                 :            : }
   20083                 :            : 
   20084                 :            : const struct mlx5_flow_driver_ops mlx5_flow_dv_drv_ops = {
   20085                 :            :         .validate = flow_dv_validate,
   20086                 :            :         .prepare = flow_dv_prepare,
   20087                 :            :         .translate = flow_dv_translate,
   20088                 :            :         .apply = flow_dv_apply,
   20089                 :            :         .remove = flow_dv_remove,
   20090                 :            :         .destroy = flow_dv_destroy,
   20091                 :            :         .query = flow_dv_query,
   20092                 :            :         .create_mtr_tbls = flow_dv_create_mtr_tbls,
   20093                 :            :         .destroy_mtr_tbls = flow_dv_destroy_mtr_tbls,
   20094                 :            :         .destroy_mtr_drop_tbls = flow_dv_destroy_mtr_drop_tbls,
   20095                 :            :         .create_meter = flow_dv_mtr_alloc,
   20096                 :            :         .free_meter = flow_dv_aso_mtr_release_to_pool,
   20097                 :            :         .validate_mtr_acts = flow_dv_validate_mtr_policy_acts,
   20098                 :            :         .create_mtr_acts = flow_dv_create_mtr_policy_acts,
   20099                 :            :         .destroy_mtr_acts = flow_dv_destroy_mtr_policy_acts,
   20100                 :            :         .create_policy_rules = flow_dv_create_policy_rules,
   20101                 :            :         .destroy_policy_rules = flow_dv_destroy_policy_rules,
   20102                 :            :         .create_def_policy = flow_dv_create_def_policy,
   20103                 :            :         .destroy_def_policy = flow_dv_destroy_def_policy,
   20104                 :            :         .meter_sub_policy_rss_prepare = flow_dv_meter_sub_policy_rss_prepare,
   20105                 :            :         .meter_hierarchy_rule_create = flow_dv_meter_hierarchy_rule_create,
   20106                 :            :         .destroy_sub_policy_with_rxq = flow_dv_destroy_sub_policy_with_rxq,
   20107                 :            :         .counter_alloc = flow_dv_counter_allocate,
   20108                 :            :         .counter_free = flow_dv_counter_free,
   20109                 :            :         .counter_query = flow_dv_counter_query,
   20110                 :            :         .get_aged_flows = flow_dv_get_aged_flows,
   20111                 :            :         .action_validate = flow_dv_action_validate,
   20112                 :            :         .action_create = flow_dv_action_create,
   20113                 :            :         .action_destroy = flow_dv_action_destroy,
   20114                 :            :         .action_update = flow_dv_action_update,
   20115                 :            :         .action_query = flow_dv_action_query,
   20116                 :            :         .sync_domain = flow_dv_sync_domain,
   20117                 :            :         .discover_priorities = flow_dv_discover_priorities,
   20118                 :            :         .item_create = flow_dv_item_create,
   20119                 :            :         .item_release = flow_dv_item_release,
   20120                 :            : };
   20121                 :            : 
   20122                 :            : #endif /* HAVE_IBV_FLOW_DV_SUPPORT */

Generated by: LCOV version 1.14