LCOV - code coverage report
Current view: top level - drivers/net/mlx5 - mlx5_flow_hw.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 6002 0.0 %
Date: 2025-02-01 18:54:23 Functions: 0 255 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 5545 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright (c) 2022 NVIDIA Corporation & Affiliates
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <rte_flow.h>
       6                 :            : #include <rte_flow_driver.h>
       7                 :            : #include <rte_stdatomic.h>
       8                 :            : 
       9                 :            : #include <mlx5_malloc.h>
      10                 :            : 
      11                 :            : #include "mlx5.h"
      12                 :            : #include "mlx5_common.h"
      13                 :            : #include "mlx5_defs.h"
      14                 :            : #include "mlx5_flow.h"
      15                 :            : #include "mlx5_flow_os.h"
      16                 :            : #include "mlx5_rx.h"
      17                 :            : 
      18                 :            : #if defined(HAVE_IBV_FLOW_DV_SUPPORT) || !defined(HAVE_INFINIBAND_VERBS_H)
      19                 :            : #include "mlx5_hws_cnt.h"
      20                 :            : 
      21                 :            : /** Fast path async flow API functions. */
      22                 :            : static struct rte_flow_fp_ops mlx5_flow_hw_fp_ops;
      23                 :            : 
      24                 :            : /* The maximum actions support in the flow. */
      25                 :            : #define MLX5_HW_MAX_ACTS 16
      26                 :            : 
      27                 :            : /*
      28                 :            :  * The default ipool threshold value indicates which per_core_cache
      29                 :            :  * value to set.
      30                 :            :  */
      31                 :            : #define MLX5_HW_IPOOL_SIZE_THRESHOLD (1 << 19)
      32                 :            : /* The default min local cache size. */
      33                 :            : #define MLX5_HW_IPOOL_CACHE_MIN (1 << 9)
      34                 :            : 
      35                 :            : /* Default push burst threshold. */
      36                 :            : #define BURST_THR 32u
      37                 :            : 
      38                 :            : /* Default queue to flush the flows. */
      39                 :            : #define MLX5_DEFAULT_FLUSH_QUEUE 0
      40                 :            : 
      41                 :            : /* Maximum number of rules in control flow tables. */
      42                 :            : #define MLX5_HW_CTRL_FLOW_NB_RULES (4096)
      43                 :            : 
      44                 :            : /* Lowest flow group usable by an application if group translation is done. */
      45                 :            : #define MLX5_HW_LOWEST_USABLE_GROUP (1)
      46                 :            : 
      47                 :            : /* Maximum group index usable by user applications for transfer flows. */
      48                 :            : #define MLX5_HW_MAX_TRANSFER_GROUP (UINT32_MAX - 1)
      49                 :            : 
      50                 :            : /* Maximum group index usable by user applications for egress flows. */
      51                 :            : #define MLX5_HW_MAX_EGRESS_GROUP (UINT32_MAX - 1)
      52                 :            : 
      53                 :            : /* Lowest priority for HW root table. */
      54                 :            : #define MLX5_HW_LOWEST_PRIO_ROOT 15
      55                 :            : 
      56                 :            : /* Lowest priority for HW non-root table. */
      57                 :            : #define MLX5_HW_LOWEST_PRIO_NON_ROOT (UINT32_MAX)
      58                 :            : 
      59                 :            : /* Priorities for Rx control flow rules. */
      60                 :            : #define MLX5_HW_CTRL_RX_PRIO_L2 (MLX5_HW_LOWEST_PRIO_ROOT)
      61                 :            : #define MLX5_HW_CTRL_RX_PRIO_L3 (MLX5_HW_LOWEST_PRIO_ROOT - 1)
      62                 :            : #define MLX5_HW_CTRL_RX_PRIO_L4 (MLX5_HW_LOWEST_PRIO_ROOT - 2)
      63                 :            : 
      64                 :            : #define MLX5_HW_VLAN_PUSH_TYPE_IDX 0
      65                 :            : #define MLX5_HW_VLAN_PUSH_VID_IDX 1
      66                 :            : #define MLX5_HW_VLAN_PUSH_PCP_IDX 2
      67                 :            : 
      68                 :            : #define MLX5_MIRROR_MAX_CLONES_NUM 3
      69                 :            : #define MLX5_MIRROR_MAX_SAMPLE_ACTIONS_LEN 4
      70                 :            : 
      71                 :            : #define MLX5_HW_PORT_IS_PROXY(priv) \
      72                 :            :         (!!((priv)->sh->esw_mode && (priv)->master))
      73                 :            : 
      74                 :            : 
      75                 :            : struct mlx5_indlst_legacy {
      76                 :            :         struct mlx5_indirect_list indirect;
      77                 :            :         struct rte_flow_action_handle *handle;
      78                 :            :         enum rte_flow_action_type legacy_type;
      79                 :            : };
      80                 :            : 
      81                 :            : #define MLX5_CONST_ENCAP_ITEM(encap_type, ptr) \
      82                 :            : (((const struct encap_type *)(ptr))->definition)
      83                 :            : 
      84                 :            : /**
      85                 :            :  * Returns the size of a struct with a following layout:
      86                 :            :  *
      87                 :            :  * @code{.c}
      88                 :            :  * struct rte_flow_hw {
      89                 :            :  *     // rte_flow_hw fields
      90                 :            :  *     uint8_t rule[mlx5dr_rule_get_handle_size()];
      91                 :            :  * };
      92                 :            :  * @endcode
      93                 :            :  *
      94                 :            :  * Such struct is used as a basic container for HW Steering flow rule.
      95                 :            :  */
      96                 :            : static size_t
      97                 :            : mlx5_flow_hw_entry_size(void)
      98                 :            : {
      99                 :          0 :         return sizeof(struct rte_flow_hw) + mlx5dr_rule_get_handle_size();
     100                 :            : }
     101                 :            : 
     102                 :            : /**
     103                 :            :  * Returns the size of "auxed" rte_flow_hw structure which is assumed to be laid out as follows:
     104                 :            :  *
     105                 :            :  * @code{.c}
     106                 :            :  * struct {
     107                 :            :  *     struct rte_flow_hw {
     108                 :            :  *         // rte_flow_hw fields
     109                 :            :  *         uint8_t rule[mlx5dr_rule_get_handle_size()];
     110                 :            :  *     } flow;
     111                 :            :  *     struct rte_flow_hw_aux aux;
     112                 :            :  * };
     113                 :            :  * @endcode
     114                 :            :  *
     115                 :            :  * Such struct is used whenever rte_flow_hw_aux cannot be allocated separately from the rte_flow_hw
     116                 :            :  * e.g., when table is resizable.
     117                 :            :  */
     118                 :            : static size_t
     119                 :            : mlx5_flow_hw_auxed_entry_size(void)
     120                 :            : {
     121                 :          0 :         size_t rule_size = mlx5dr_rule_get_handle_size();
     122                 :            : 
     123                 :          0 :         return sizeof(struct rte_flow_hw) + rule_size + sizeof(struct rte_flow_hw_aux);
     124                 :            : }
     125                 :            : 
     126                 :            : /**
     127                 :            :  * Returns a valid pointer to rte_flow_hw_aux associated with given rte_flow_hw
     128                 :            :  * depending on template table configuration.
     129                 :            :  */
     130                 :            : static __rte_always_inline struct rte_flow_hw_aux *
     131                 :            : mlx5_flow_hw_aux(uint16_t port_id, struct rte_flow_hw *flow)
     132                 :            : {
     133                 :          0 :         struct rte_flow_template_table *table = flow->table;
     134                 :            : 
     135   [ #  #  #  #  :          0 :         if (rte_flow_template_table_resizable(port_id, &table->cfg.attr)) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     136                 :          0 :                 size_t offset = sizeof(struct rte_flow_hw) + mlx5dr_rule_get_handle_size();
     137                 :            : 
     138                 :          0 :                 return RTE_PTR_ADD(flow, offset);
     139                 :            :         } else {
     140   [ #  #  #  #  :          0 :                 return ((flow->nt_rule) ? flow->nt2hws->flow_aux : &table->flow_aux[flow->idx - 1]);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     141                 :            :         }
     142                 :            : }
     143                 :            : 
     144                 :            : static __rte_always_inline void
     145                 :            : mlx5_flow_hw_aux_set_age_idx(struct rte_flow_hw *flow,
     146                 :            :                              struct rte_flow_hw_aux *aux,
     147                 :            :                              uint32_t age_idx)
     148                 :            : {
     149                 :            :         /*
     150                 :            :          * Only when creating a flow rule, the type will be set explicitly.
     151                 :            :          * Or else, it should be none in the rule update case.
     152                 :            :          */
     153   [ #  #  #  #  :          0 :         if (unlikely(flow->operation_type == MLX5_FLOW_HW_FLOW_OP_TYPE_UPDATE))
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
     154                 :          0 :                 aux->upd.age_idx = age_idx;
     155                 :            :         else
     156                 :          0 :                 aux->orig.age_idx = age_idx;
     157                 :            : }
     158                 :            : 
     159                 :            : static __rte_always_inline uint32_t
     160                 :            : mlx5_flow_hw_aux_get_age_idx(struct rte_flow_hw *flow, struct rte_flow_hw_aux *aux)
     161                 :            : {
     162   [ #  #  #  #  :          0 :         if (unlikely(flow->operation_type == MLX5_FLOW_HW_FLOW_OP_TYPE_UPDATE))
          #  #  #  #  #  
                #  #  # ]
     163                 :          0 :                 return aux->upd.age_idx;
     164                 :            :         else
     165                 :          0 :                 return aux->orig.age_idx;
     166                 :            : }
     167                 :            : 
     168                 :            : static __rte_always_inline void
     169                 :            : mlx5_flow_hw_aux_set_mtr_id(struct rte_flow_hw *flow,
     170                 :            :                             struct rte_flow_hw_aux *aux,
     171                 :            :                             uint32_t mtr_id)
     172                 :            : {
     173   [ #  #  #  #  :          0 :         if (unlikely(flow->operation_type == MLX5_FLOW_HW_FLOW_OP_TYPE_UPDATE))
          #  #  #  #  #  
                      # ]
     174                 :          0 :                 aux->upd.mtr_id = mtr_id;
     175                 :            :         else
     176                 :          0 :                 aux->orig.mtr_id = mtr_id;
     177                 :            : }
     178                 :            : 
     179                 :            : static __rte_always_inline uint32_t
     180                 :            : mlx5_flow_hw_aux_get_mtr_id(struct rte_flow_hw *flow, struct rte_flow_hw_aux *aux)
     181                 :            : {
     182         [ #  # ]:          0 :         if (unlikely(flow->operation_type == MLX5_FLOW_HW_FLOW_OP_TYPE_UPDATE))
     183                 :          0 :                 return aux->upd.mtr_id;
     184                 :            :         else
     185                 :          0 :                 return aux->orig.mtr_id;
     186                 :            : }
     187                 :            : 
     188                 :            : static __rte_always_inline struct mlx5_hw_q_job *
     189                 :            : flow_hw_action_job_init(struct mlx5_priv *priv, uint32_t queue,
     190                 :            :                         const struct rte_flow_action_handle *handle,
     191                 :            :                         void *user_data, void *query_data,
     192                 :            :                         enum mlx5_hw_job_type type,
     193                 :            :                         enum mlx5_hw_indirect_type indirect_type,
     194                 :            :                         struct rte_flow_error *error);
     195                 :            : static void
     196                 :            : flow_hw_age_count_release(struct mlx5_priv *priv, uint32_t queue, struct rte_flow_hw *flow,
     197                 :            :                           struct rte_flow_error *error);
     198                 :            : 
     199                 :            : static int
     200                 :            : mlx5_tbl_multi_pattern_process(struct rte_eth_dev *dev,
     201                 :            :                                struct rte_flow_template_table *tbl,
     202                 :            :                                struct mlx5_multi_pattern_segment *segment,
     203                 :            :                                uint32_t bulk_size,
     204                 :            :                                struct rte_flow_error *error);
     205                 :            : static void
     206                 :            : mlx5_destroy_multi_pattern_segment(struct mlx5_multi_pattern_segment *segment);
     207                 :            : 
     208                 :            : static __rte_always_inline enum mlx5_indirect_list_type
     209                 :            : flow_hw_inlist_type_get(const struct rte_flow_action *actions);
     210                 :            : 
     211                 :            : static int
     212                 :            : flow_hw_allocate_actions(struct rte_eth_dev *dev,
     213                 :            :                          uint64_t action_flags,
     214                 :            :                          struct rte_flow_error *error);
     215                 :            : 
     216                 :            : bool
     217                 :          0 : mlx5_hw_ctx_validate(const struct rte_eth_dev *dev, struct rte_flow_error *error)
     218                 :            : {
     219                 :          0 :         const struct mlx5_priv *priv = dev->data->dev_private;
     220                 :            : 
     221         [ #  # ]:          0 :         if (!priv->dr_ctx) {
     222                 :          0 :                 rte_flow_error_set(error, EINVAL,
     223                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
     224                 :            :                                    "non-template flow engine was not configured");
     225                 :          0 :                 return false;
     226                 :            :         }
     227                 :            :         return true;
     228                 :            : }
     229                 :            : 
     230                 :            : static int
     231                 :            : flow_hw_allocate_actions(struct rte_eth_dev *dev,
     232                 :            :                          uint64_t action_flags,
     233                 :            :                          struct rte_flow_error *error);
     234                 :            : 
     235                 :            : static __rte_always_inline int
     236                 :            : mlx5_multi_pattern_reformat_to_index(enum mlx5dr_action_type type)
     237                 :            : {
     238                 :            :         switch (type) {
     239                 :            :         case MLX5DR_ACTION_TYP_REFORMAT_TNL_L2_TO_L2:
     240                 :            :                 return 0;
     241                 :            :         case MLX5DR_ACTION_TYP_REFORMAT_L2_TO_TNL_L2:
     242                 :            :                 return 1;
     243                 :            :         case MLX5DR_ACTION_TYP_REFORMAT_TNL_L3_TO_L2:
     244                 :            :                 return 2;
     245                 :            :         case MLX5DR_ACTION_TYP_REFORMAT_L2_TO_TNL_L3:
     246                 :            :                 return 3;
     247                 :            :         default:
     248                 :            :                 break;
     249                 :            :         }
     250                 :            :         return -1;
     251                 :            : }
     252                 :            : 
     253                 :            : /* Include only supported reformat actions for BWC non template API. */
     254                 :            : static __rte_always_inline int
     255                 :            : mlx5_bwc_multi_pattern_reformat_to_index(enum mlx5dr_action_type type)
     256                 :            : {
     257                 :          0 :         switch (type) {
     258                 :            :         case MLX5DR_ACTION_TYP_REFORMAT_TNL_L2_TO_L2:
     259                 :            :         case MLX5DR_ACTION_TYP_REFORMAT_L2_TO_TNL_L2:
     260                 :            :         case MLX5DR_ACTION_TYP_REFORMAT_TNL_L3_TO_L2:
     261                 :            :         case MLX5DR_ACTION_TYP_REFORMAT_L2_TO_TNL_L3:
     262                 :            :                 return mlx5_multi_pattern_reformat_to_index(type);
     263                 :            :         default:
     264                 :            :                 break;
     265                 :            :         }
     266                 :            :         return -1;
     267                 :            : }
     268                 :            : 
     269                 :            : static __rte_always_inline enum mlx5dr_action_type
     270                 :            : mlx5_multi_pattern_reformat_index_to_type(uint32_t ix)
     271                 :            : {
     272                 :            :         switch (ix) {
     273                 :            :         case 0:
     274                 :            :                 return MLX5DR_ACTION_TYP_REFORMAT_TNL_L2_TO_L2;
     275                 :            :         case 1:
     276                 :            :                 return MLX5DR_ACTION_TYP_REFORMAT_L2_TO_TNL_L2;
     277                 :            :         case 2:
     278                 :            :                 return MLX5DR_ACTION_TYP_REFORMAT_TNL_L3_TO_L2;
     279                 :            :         case 3:
     280                 :            :                 return MLX5DR_ACTION_TYP_REFORMAT_L2_TO_TNL_L3;
     281                 :            :         default:
     282                 :            :                 break;
     283                 :            :         }
     284                 :            :         return MLX5DR_ACTION_TYP_MAX;
     285                 :            : }
     286                 :            : 
     287                 :            : static inline enum mlx5dr_table_type
     288                 :            : get_mlx5dr_table_type(const struct rte_flow_attr *attr)
     289                 :            : {
     290                 :            :         enum mlx5dr_table_type type;
     291                 :            : 
     292         [ #  # ]:          0 :         if (attr->transfer)
     293                 :            :                 type = MLX5DR_TABLE_TYPE_FDB;
     294   [ #  #  #  #  :          0 :         else if (attr->egress)
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     295                 :            :                 type = MLX5DR_TABLE_TYPE_NIC_TX;
     296                 :            :         else
     297                 :            :                 type = MLX5DR_TABLE_TYPE_NIC_RX;
     298                 :            :         return type;
     299                 :            : }
     300                 :            : 
     301                 :            : /* Non template default queue size used for inner ctrl queue. */
     302                 :            : #define MLX5_NT_DEFAULT_QUEUE_SIZE 32
     303                 :            : 
     304                 :            : struct mlx5_mirror_clone {
     305                 :            :         enum rte_flow_action_type type;
     306                 :            :         void *action_ctx;
     307                 :            : };
     308                 :            : 
     309                 :            : struct mlx5_mirror {
     310                 :            :         struct mlx5_indirect_list indirect;
     311                 :            :         uint32_t clones_num;
     312                 :            :         struct mlx5dr_action *mirror_action;
     313                 :            :         struct mlx5_mirror_clone clone[MLX5_MIRROR_MAX_CLONES_NUM];
     314                 :            : };
     315                 :            : 
     316                 :            : static int flow_hw_flush_all_ctrl_flows(struct rte_eth_dev *dev);
     317                 :            : static int flow_hw_translate_group(struct rte_eth_dev *dev,
     318                 :            :                                    const struct mlx5_flow_template_table_cfg *cfg,
     319                 :            :                                    uint32_t group,
     320                 :            :                                    uint32_t *table_group,
     321                 :            :                                    struct rte_flow_error *error);
     322                 :            : static __rte_always_inline int
     323                 :            : flow_hw_set_vlan_vid_construct(struct rte_eth_dev *dev,
     324                 :            :                                struct mlx5_modification_cmd *mhdr_cmd,
     325                 :            :                                struct mlx5_action_construct_data *act_data,
     326                 :            :                                const struct mlx5_hw_actions *hw_acts,
     327                 :            :                                const struct rte_flow_action *action);
     328                 :            : static void
     329                 :            : flow_hw_construct_quota(struct mlx5_priv *priv,
     330                 :            :                         struct mlx5dr_rule_action *rule_act, uint32_t qid);
     331                 :            : 
     332                 :            : static int
     333                 :            : mlx5_flow_ct_init(struct rte_eth_dev *dev,
     334                 :            :                   uint32_t nb_conn_tracks,
     335                 :            :                   uint16_t nb_queue);
     336                 :            : 
     337                 :            : static __rte_always_inline uint32_t flow_hw_tx_tag_regc_mask(struct rte_eth_dev *dev);
     338                 :            : static __rte_always_inline uint32_t flow_hw_tx_tag_regc_value(struct rte_eth_dev *dev);
     339                 :            : 
     340                 :            : static int flow_hw_async_create_validate(struct rte_eth_dev *dev,
     341                 :            :                                          const uint32_t queue,
     342                 :            :                                          const struct rte_flow_template_table *table,
     343                 :            :                                          enum rte_flow_table_insertion_type insertion_type,
     344                 :            :                                          const uint32_t rule_index,
     345                 :            :                                          const struct rte_flow_item items[],
     346                 :            :                                          const uint8_t pattern_template_index,
     347                 :            :                                          const struct rte_flow_action actions[],
     348                 :            :                                          const uint8_t action_template_index,
     349                 :            :                                          struct rte_flow_error *error);
     350                 :            : static int flow_hw_async_update_validate(struct rte_eth_dev *dev,
     351                 :            :                                          const uint32_t queue,
     352                 :            :                                          const struct rte_flow_hw *flow,
     353                 :            :                                          const struct rte_flow_action actions[],
     354                 :            :                                          const uint8_t action_template_index,
     355                 :            :                                          struct rte_flow_error *error);
     356                 :            : static int flow_hw_async_destroy_validate(struct rte_eth_dev *dev,
     357                 :            :                                           const uint32_t queue,
     358                 :            :                                           const struct rte_flow_hw *flow,
     359                 :            :                                           struct rte_flow_error *error);
     360                 :            : 
     361                 :            : const struct mlx5_flow_driver_ops mlx5_flow_hw_drv_ops;
     362                 :            : 
     363                 :            : /* DR action flags with different table. */
     364                 :            : static uint32_t mlx5_hw_act_flag[MLX5_HW_ACTION_FLAG_MAX]
     365                 :            :                                 [MLX5DR_TABLE_TYPE_MAX] = {
     366                 :            :         {
     367                 :            :                 MLX5DR_ACTION_FLAG_ROOT_RX,
     368                 :            :                 MLX5DR_ACTION_FLAG_ROOT_TX,
     369                 :            :                 MLX5DR_ACTION_FLAG_ROOT_FDB,
     370                 :            :         },
     371                 :            :         {
     372                 :            :                 MLX5DR_ACTION_FLAG_HWS_RX,
     373                 :            :                 MLX5DR_ACTION_FLAG_HWS_TX,
     374                 :            :                 MLX5DR_ACTION_FLAG_HWS_FDB,
     375                 :            :         },
     376                 :            : };
     377                 :            : 
     378                 :            : /* Ethernet item spec for promiscuous mode. */
     379                 :            : static const struct rte_flow_item_eth ctrl_rx_eth_promisc_spec = {
     380                 :            :         .hdr.dst_addr.addr_bytes = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
     381                 :            :         .hdr.src_addr.addr_bytes = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
     382                 :            :         .hdr.ether_type = 0,
     383                 :            : };
     384                 :            : /* Ethernet item mask for promiscuous mode. */
     385                 :            : static const struct rte_flow_item_eth ctrl_rx_eth_promisc_mask = {
     386                 :            :         .hdr.dst_addr.addr_bytes = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
     387                 :            :         .hdr.src_addr.addr_bytes = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
     388                 :            :         .hdr.ether_type = 0,
     389                 :            : };
     390                 :            : 
     391                 :            : /* Ethernet item spec for all multicast mode. */
     392                 :            : static const struct rte_flow_item_eth ctrl_rx_eth_mcast_spec = {
     393                 :            :         .hdr.dst_addr.addr_bytes = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 },
     394                 :            :         .hdr.src_addr.addr_bytes = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
     395                 :            :         .hdr.ether_type = 0,
     396                 :            : };
     397                 :            : /* Ethernet item mask for all multicast mode. */
     398                 :            : static const struct rte_flow_item_eth ctrl_rx_eth_mcast_mask = {
     399                 :            :         .hdr.dst_addr.addr_bytes = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 },
     400                 :            :         .hdr.src_addr.addr_bytes = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
     401                 :            :         .hdr.ether_type = 0,
     402                 :            : };
     403                 :            : 
     404                 :            : /* Ethernet item spec for IPv4 multicast traffic. */
     405                 :            : static const struct rte_flow_item_eth ctrl_rx_eth_ipv4_mcast_spec = {
     406                 :            :         .hdr.dst_addr.addr_bytes = { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 },
     407                 :            :         .hdr.src_addr.addr_bytes = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
     408                 :            :         .hdr.ether_type = 0,
     409                 :            : };
     410                 :            : /* Ethernet item mask for IPv4 multicast traffic. */
     411                 :            : static const struct rte_flow_item_eth ctrl_rx_eth_ipv4_mcast_mask = {
     412                 :            :         .hdr.dst_addr.addr_bytes = { 0xff, 0xff, 0xff, 0x00, 0x00, 0x00 },
     413                 :            :         .hdr.src_addr.addr_bytes = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
     414                 :            :         .hdr.ether_type = 0,
     415                 :            : };
     416                 :            : 
     417                 :            : /* Ethernet item spec for IPv6 multicast traffic. */
     418                 :            : static const struct rte_flow_item_eth ctrl_rx_eth_ipv6_mcast_spec = {
     419                 :            :         .hdr.dst_addr.addr_bytes = { 0x33, 0x33, 0x00, 0x00, 0x00, 0x00 },
     420                 :            :         .hdr.src_addr.addr_bytes = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
     421                 :            :         .hdr.ether_type = 0,
     422                 :            : };
     423                 :            : /* Ethernet item mask for IPv6 multicast traffic. */
     424                 :            : static const struct rte_flow_item_eth ctrl_rx_eth_ipv6_mcast_mask = {
     425                 :            :         .hdr.dst_addr.addr_bytes = { 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 },
     426                 :            :         .hdr.src_addr.addr_bytes = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
     427                 :            :         .hdr.ether_type = 0,
     428                 :            : };
     429                 :            : 
     430                 :            : /* Ethernet item mask for unicast traffic. */
     431                 :            : static const struct rte_flow_item_eth ctrl_rx_eth_dmac_mask = {
     432                 :            :         .hdr.dst_addr.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
     433                 :            :         .hdr.src_addr.addr_bytes = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
     434                 :            :         .hdr.ether_type = 0,
     435                 :            : };
     436                 :            : 
     437                 :            : /* Ethernet item spec for broadcast. */
     438                 :            : static const struct rte_flow_item_eth ctrl_rx_eth_bcast_spec = {
     439                 :            :         .hdr.dst_addr.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
     440                 :            :         .hdr.src_addr.addr_bytes = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
     441                 :            :         .hdr.ether_type = 0,
     442                 :            : };
     443                 :            : 
     444                 :            : static inline uint32_t
     445                 :            : flow_hw_q_pending(struct mlx5_priv *priv, uint32_t queue)
     446                 :            : {
     447                 :          0 :         struct mlx5_hw_q *q = &priv->hw_q[queue];
     448                 :            : 
     449                 :            :         MLX5_ASSERT(q->size >= q->job_idx);
     450                 :          0 :         return (q->size - q->job_idx) + q->ongoing_flow_ops;
     451                 :            : }
     452                 :            : 
     453                 :            : static inline void
     454                 :          0 : flow_hw_q_inc_flow_ops(struct mlx5_priv *priv, uint32_t queue)
     455                 :            : {
     456                 :          0 :         struct mlx5_hw_q *q = &priv->hw_q[queue];
     457                 :            : 
     458                 :          0 :         q->ongoing_flow_ops++;
     459                 :          0 : }
     460                 :            : 
     461                 :            : static inline void
     462                 :            : flow_hw_q_dec_flow_ops(struct mlx5_priv *priv, uint32_t queue)
     463                 :            : {
     464                 :          0 :         struct mlx5_hw_q *q = &priv->hw_q[queue];
     465                 :            : 
     466                 :          0 :         q->ongoing_flow_ops--;
     467                 :            : }
     468                 :            : 
     469                 :            : static inline enum mlx5dr_matcher_insert_mode
     470                 :            : flow_hw_matcher_insert_mode_get(enum rte_flow_table_insertion_type insert_type)
     471                 :            : {
     472                 :          0 :         if (insert_type == RTE_FLOW_TABLE_INSERTION_TYPE_PATTERN)
     473                 :            :                 return MLX5DR_MATCHER_INSERT_BY_HASH;
     474                 :            :         else
     475                 :          0 :                 return MLX5DR_MATCHER_INSERT_BY_INDEX;
     476                 :            : }
     477                 :            : 
     478                 :            : static inline enum mlx5dr_matcher_distribute_mode
     479                 :            : flow_hw_matcher_distribute_mode_get(enum rte_flow_table_hash_func hash_func)
     480                 :            : {
     481         [ #  # ]:          0 :         if (hash_func == RTE_FLOW_TABLE_HASH_FUNC_LINEAR)
     482                 :            :                 return MLX5DR_MATCHER_DISTRIBUTE_BY_LINEAR;
     483                 :            :         else
     484                 :          0 :                 return MLX5DR_MATCHER_DISTRIBUTE_BY_HASH;
     485                 :            : }
     486                 :            : 
     487                 :            : /**
     488                 :            :  * Set the hash fields according to the @p rss_desc information.
     489                 :            :  *
     490                 :            :  * @param[in] rss_desc
     491                 :            :  *   Pointer to the mlx5_flow_rss_desc.
     492                 :            :  * @param[out] hash_fields
     493                 :            :  *   Pointer to the RSS hash fields.
     494                 :            :  */
     495                 :            : static void
     496                 :          0 : flow_hw_hashfields_set(struct mlx5_flow_rss_desc *rss_desc,
     497                 :            :                        uint64_t *hash_fields)
     498                 :            : {
     499                 :            :         uint64_t fields = 0;
     500                 :            :         int rss_inner = 0;
     501         [ #  # ]:          0 :         uint64_t rss_types = rte_eth_rss_hf_refine(rss_desc->types);
     502                 :            : 
     503                 :            : #ifdef HAVE_IBV_DEVICE_TUNNEL_SUPPORT
     504         [ #  # ]:          0 :         if (rss_desc->level >= 2)
     505                 :            :                 rss_inner = 1;
     506                 :            : #endif
     507         [ #  # ]:          0 :         if (rss_types & MLX5_IPV4_LAYER_TYPES) {
     508         [ #  # ]:          0 :                 if (rss_types & RTE_ETH_RSS_L3_SRC_ONLY)
     509                 :            :                         fields |= IBV_RX_HASH_SRC_IPV4;
     510         [ #  # ]:          0 :                 else if (rss_types & RTE_ETH_RSS_L3_DST_ONLY)
     511                 :            :                         fields |= IBV_RX_HASH_DST_IPV4;
     512                 :            :                 else
     513                 :            :                         fields |= MLX5_IPV4_IBV_RX_HASH;
     514         [ #  # ]:          0 :         } else if (rss_types & MLX5_IPV6_LAYER_TYPES) {
     515         [ #  # ]:          0 :                 if (rss_types & RTE_ETH_RSS_L3_SRC_ONLY)
     516                 :            :                         fields |= IBV_RX_HASH_SRC_IPV6;
     517         [ #  # ]:          0 :                 else if (rss_types & RTE_ETH_RSS_L3_DST_ONLY)
     518                 :            :                         fields |= IBV_RX_HASH_DST_IPV6;
     519                 :            :                 else
     520                 :            :                         fields |= MLX5_IPV6_IBV_RX_HASH;
     521                 :            :         }
     522         [ #  # ]:          0 :         if (rss_types & RTE_ETH_RSS_UDP) {
     523         [ #  # ]:          0 :                 if (rss_types & RTE_ETH_RSS_L4_SRC_ONLY)
     524                 :          0 :                         fields |= IBV_RX_HASH_SRC_PORT_UDP;
     525         [ #  # ]:          0 :                 else if (rss_types & RTE_ETH_RSS_L4_DST_ONLY)
     526                 :          0 :                         fields |= IBV_RX_HASH_DST_PORT_UDP;
     527                 :            :                 else
     528                 :          0 :                         fields |= MLX5_UDP_IBV_RX_HASH;
     529         [ #  # ]:          0 :         } else if (rss_types & RTE_ETH_RSS_TCP) {
     530         [ #  # ]:          0 :                 if (rss_types & RTE_ETH_RSS_L4_SRC_ONLY)
     531                 :          0 :                         fields |= IBV_RX_HASH_SRC_PORT_TCP;
     532         [ #  # ]:          0 :                 else if (rss_types & RTE_ETH_RSS_L4_DST_ONLY)
     533                 :          0 :                         fields |= IBV_RX_HASH_DST_PORT_TCP;
     534                 :            :                 else
     535                 :          0 :                         fields |= MLX5_TCP_IBV_RX_HASH;
     536                 :            :         }
     537         [ #  # ]:          0 :         if (rss_types & RTE_ETH_RSS_ESP)
     538                 :          0 :                 fields |= IBV_RX_HASH_IPSEC_SPI;
     539         [ #  # ]:          0 :         if (rss_inner)
     540                 :          0 :                 fields |= IBV_RX_HASH_INNER;
     541                 :          0 :         *hash_fields |= fields;
     542                 :          0 : }
     543                 :            : 
     544                 :            : /**
     545                 :            :  * Generate the matching pattern item flags.
     546                 :            :  *
     547                 :            :  * @param[in] items
     548                 :            :  *   Pointer to the list of items.
     549                 :            :  *
     550                 :            :  * @return
     551                 :            :  *   Matching item flags. RSS hash field function
     552                 :            :  *   silently ignores the flags which are unsupported.
     553                 :            :  */
     554                 :            : static uint64_t
     555                 :          0 : flow_hw_matching_item_flags_get(const struct rte_flow_item items[])
     556                 :            : {
     557                 :            :         uint64_t item_flags = 0;
     558                 :            :         uint64_t last_item = 0;
     559                 :            : 
     560         [ #  # ]:          0 :         for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {
     561                 :          0 :                 enum rte_flow_item_flex_tunnel_mode tunnel_mode = FLEX_TUNNEL_MODE_SINGLE;
     562                 :          0 :                 int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL);
     563                 :            :                 int item_type = items->type;
     564                 :            : 
     565   [ #  #  #  #  :          0 :                 switch (item_type) {
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
     566                 :          0 :                 case RTE_FLOW_ITEM_TYPE_IPV4:
     567         [ #  # ]:          0 :                         last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV4 :
     568                 :            :                                              MLX5_FLOW_LAYER_OUTER_L3_IPV4;
     569                 :            :                         break;
     570                 :          0 :                 case RTE_FLOW_ITEM_TYPE_IPV6:
     571         [ #  # ]:          0 :                         last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV6 :
     572                 :            :                                              MLX5_FLOW_LAYER_OUTER_L3_IPV6;
     573                 :            :                         break;
     574                 :          0 :                 case RTE_FLOW_ITEM_TYPE_TCP:
     575         [ #  # ]:          0 :                         last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L4_TCP :
     576                 :            :                                              MLX5_FLOW_LAYER_OUTER_L4_TCP;
     577                 :            :                         break;
     578                 :          0 :                 case RTE_FLOW_ITEM_TYPE_UDP:
     579         [ #  # ]:          0 :                         last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L4_UDP :
     580                 :            :                                              MLX5_FLOW_LAYER_OUTER_L4_UDP;
     581                 :            :                         break;
     582                 :          0 :                 case RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT:
     583         [ #  # ]:          0 :                         last_item = tunnel ? MLX5_FLOW_ITEM_INNER_IPV6_ROUTING_EXT :
     584                 :            :                                              MLX5_FLOW_ITEM_OUTER_IPV6_ROUTING_EXT;
     585                 :            :                         break;
     586                 :          0 :                 case RTE_FLOW_ITEM_TYPE_GRE:
     587                 :            :                         last_item = MLX5_FLOW_LAYER_GRE;
     588                 :          0 :                         break;
     589                 :          0 :                 case RTE_FLOW_ITEM_TYPE_NVGRE:
     590                 :            :                         last_item = MLX5_FLOW_LAYER_GRE;
     591                 :          0 :                         break;
     592                 :          0 :                 case RTE_FLOW_ITEM_TYPE_VXLAN:
     593                 :            :                         last_item = MLX5_FLOW_LAYER_VXLAN;
     594                 :          0 :                         break;
     595                 :          0 :                 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
     596                 :            :                         last_item = MLX5_FLOW_LAYER_VXLAN_GPE;
     597                 :          0 :                         break;
     598                 :          0 :                 case RTE_FLOW_ITEM_TYPE_GENEVE:
     599                 :            :                         last_item = MLX5_FLOW_LAYER_GENEVE;
     600                 :          0 :                         break;
     601                 :          0 :                 case RTE_FLOW_ITEM_TYPE_MPLS:
     602                 :            :                         last_item = MLX5_FLOW_LAYER_MPLS;
     603                 :          0 :                         break;
     604                 :          0 :                 case RTE_FLOW_ITEM_TYPE_GTP:
     605                 :            :                         last_item = MLX5_FLOW_LAYER_GTP;
     606                 :          0 :                         break;
     607                 :          0 :                 case RTE_FLOW_ITEM_TYPE_COMPARE:
     608                 :            :                         last_item = MLX5_FLOW_ITEM_COMPARE;
     609                 :          0 :                         break;
     610                 :          0 :                 case RTE_FLOW_ITEM_TYPE_FLEX:
     611                 :          0 :                         mlx5_flex_get_tunnel_mode(items, &tunnel_mode);
     612                 :          0 :                         last_item = tunnel_mode == FLEX_TUNNEL_MODE_TUNNEL ?
     613         [ #  # ]:          0 :                                         MLX5_FLOW_ITEM_FLEX_TUNNEL :
     614         [ #  # ]:          0 :                                         tunnel ? MLX5_FLOW_ITEM_INNER_FLEX :
     615                 :            :                                                 MLX5_FLOW_ITEM_OUTER_FLEX;
     616                 :            :                         break;
     617                 :            :                 default:
     618                 :            :                         break;
     619                 :            :                 }
     620                 :          0 :                 item_flags |= last_item;
     621                 :            :         }
     622                 :          0 :         return item_flags;
     623                 :            : }
     624                 :            : 
     625                 :            : static uint64_t
     626                 :          0 : flow_hw_action_flags_get(const struct rte_flow_action actions[],
     627                 :            :                          const struct rte_flow_action **qrss,
     628                 :            :                          const struct rte_flow_action **mark,
     629                 :            :                          int *encap_idx,
     630                 :            :                          int *act_cnt,
     631                 :            :                          struct rte_flow_error *error)
     632                 :            : {
     633                 :            :         uint64_t action_flags = 0;
     634                 :            :         const struct rte_flow_action *action;
     635                 :            :         const struct rte_flow_action_raw_encap *raw_encap;
     636                 :            :         int raw_decap_idx = -1;
     637                 :            :         int action_idx;
     638                 :            : 
     639                 :          0 :         *encap_idx = -1;
     640                 :            :         action_idx = 0;
     641         [ #  # ]:          0 :         for (action = actions; action->type != RTE_FLOW_ACTION_TYPE_END; action++) {
     642                 :          0 :                 int type = (int)action->type;
     643   [ #  #  #  #  :          0 :                 switch (type) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     644                 :          0 :                 case RTE_FLOW_ACTION_TYPE_INDIRECT:
     645   [ #  #  #  #  :          0 :                         switch (MLX5_INDIRECT_ACTION_TYPE_GET(action->conf)) {
                   #  # ]
     646                 :          0 :                         case MLX5_INDIRECT_ACTION_TYPE_RSS:
     647                 :          0 :                                 goto rss;
     648                 :          0 :                         case MLX5_INDIRECT_ACTION_TYPE_AGE:
     649                 :          0 :                                 goto age;
     650                 :          0 :                         case MLX5_INDIRECT_ACTION_TYPE_COUNT:
     651                 :          0 :                                 goto count;
     652                 :          0 :                         case MLX5_INDIRECT_ACTION_TYPE_CT:
     653                 :          0 :                                 goto ct;
     654                 :          0 :                         case MLX5_INDIRECT_ACTION_TYPE_METER_MARK:
     655                 :          0 :                                 goto meter;
     656                 :          0 :                         default:
     657                 :          0 :                                 goto error;
     658                 :            :                         }
     659                 :            :                         break;
     660                 :          0 :                 case RTE_FLOW_ACTION_TYPE_DROP:
     661                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_DROP;
     662                 :          0 :                         break;
     663                 :          0 :                 case RTE_FLOW_ACTION_TYPE_FLAG:
     664                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_FLAG;
     665                 :          0 :                         break;
     666                 :          0 :                 case RTE_FLOW_ACTION_TYPE_MARK:
     667                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_MARK;
     668                 :          0 :                         *mark = action;
     669                 :          0 :                         break;
     670                 :          0 :                 case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
     671                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_OF_PUSH_VLAN;
     672                 :          0 :                         break;
     673                 :          0 :                 case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:
     674                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_OF_POP_VLAN;
     675                 :          0 :                         break;
     676                 :          0 :                 case RTE_FLOW_ACTION_TYPE_JUMP:
     677                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_JUMP;
     678                 :          0 :                         break;
     679                 :          0 :                 case RTE_FLOW_ACTION_TYPE_QUEUE:
     680                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_QUEUE;
     681                 :          0 :                         *qrss = action;
     682                 :          0 :                         break;
     683                 :            :                 case RTE_FLOW_ACTION_TYPE_RSS:
     684                 :          0 : rss:
     685                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_RSS;
     686                 :          0 :                         *qrss = action;
     687                 :          0 :                         break;
     688                 :          0 :                 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
     689                 :            :                 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
     690                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_ENCAP;
     691                 :          0 :                         *encap_idx = action_idx;
     692                 :          0 :                         break;
     693                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
     694                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_ENCAP;
     695                 :          0 :                         raw_encap = action->conf;
     696         [ #  # ]:          0 :                         if (raw_encap->size > MLX5_ENCAPSULATION_DECISION_SIZE)
     697                 :          0 :                                 *encap_idx = raw_decap_idx != -1 ?
     698         [ #  # ]:          0 :                                              raw_decap_idx : action_idx;
     699                 :            :                         break;
     700                 :          0 :                 case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
     701                 :            :                 case RTE_FLOW_ACTION_TYPE_NVGRE_DECAP:
     702                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_DECAP;
     703                 :          0 :                         break;
     704                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
     705                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_DECAP;
     706                 :            :                         raw_decap_idx = action_idx;
     707                 :          0 :                         break;
     708                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SEND_TO_KERNEL:
     709                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SEND_TO_KERNEL;
     710                 :          0 :                         break;
     711                 :          0 :                 case RTE_FLOW_ACTION_TYPE_MODIFY_FIELD:
     712                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_MODIFY_FIELD;
     713                 :          0 :                         break;
     714                 :          0 :                 case RTE_FLOW_ACTION_TYPE_PORT_ID:
     715                 :            :                 case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
     716                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_PORT_ID;
     717                 :          0 :                         break;
     718                 :            :                 case RTE_FLOW_ACTION_TYPE_AGE:
     719                 :          0 : age:
     720                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_AGE;
     721                 :          0 :                         break;
     722                 :            :                 case RTE_FLOW_ACTION_TYPE_COUNT:
     723                 :          0 : count:
     724                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_COUNT;
     725                 :          0 :                         break;
     726                 :            :                 case RTE_FLOW_ACTION_TYPE_CONNTRACK:
     727                 :          0 : ct:
     728                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_CT;
     729                 :          0 :                         break;
     730                 :            :                 case RTE_FLOW_ACTION_TYPE_METER_MARK:
     731                 :          0 : meter:
     732                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_METER;
     733                 :          0 :                         break;
     734                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_DEFAULT_MISS:
     735                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_DEFAULT_MISS;
     736                 :          0 :                         break;
     737                 :          0 :                 case RTE_FLOW_ACTION_TYPE_JUMP_TO_TABLE_INDEX:
     738                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_JUMP_TO_TABLE_INDEX;
     739                 :          0 :                         break;
     740                 :            :                 case RTE_FLOW_ACTION_TYPE_VOID:
     741                 :            :                 case RTE_FLOW_ACTION_TYPE_END:
     742                 :            :                         break;
     743                 :          0 :                 default:
     744                 :          0 :                         goto error;
     745                 :            :                 }
     746                 :          0 :                 action_idx++;
     747                 :            :         }
     748         [ #  # ]:          0 :         if (*encap_idx == -1)
     749                 :          0 :                 *encap_idx = action_idx;
     750                 :          0 :         action_idx++; /* The END action. */
     751                 :          0 :         *act_cnt = action_idx;
     752                 :          0 :         return action_flags;
     753                 :          0 : error:
     754                 :          0 :         rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
     755                 :            :                            action, "invalid flow action");
     756                 :          0 :         return 0;
     757                 :            : }
     758                 :            : 
     759                 :            : /**
     760                 :            :  * Register destination table DR jump action.
     761                 :            :  *
     762                 :            :  * @param[in] dev
     763                 :            :  *   Pointer to the rte_eth_dev structure.
     764                 :            :  * @param[in] table_attr
     765                 :            :  *   Pointer to the flow attributes.
     766                 :            :  * @param[in] dest_group
     767                 :            :  *   The destination group ID.
     768                 :            :  * @param[out] error
     769                 :            :  *   Pointer to error structure.
     770                 :            :  *
     771                 :            :  * @return
     772                 :            :  *    Table on success, NULL otherwise and rte_errno is set.
     773                 :            :  */
     774                 :            : static struct mlx5_hw_jump_action *
     775                 :          0 : flow_hw_jump_action_register(struct rte_eth_dev *dev,
     776                 :            :                              const struct mlx5_flow_template_table_cfg *cfg,
     777                 :            :                              uint32_t dest_group,
     778                 :            :                              struct rte_flow_error *error)
     779                 :            : {
     780                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
     781                 :          0 :         struct rte_flow_attr jattr = cfg->attr.flow_attr;
     782                 :            :         struct mlx5_flow_group *grp;
     783                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
     784                 :            :                 .dev = dev,
     785                 :            :                 .error = error,
     786                 :            :                 .data = &jattr,
     787                 :            :         };
     788                 :            :         struct mlx5_list_entry *ge;
     789                 :            :         uint32_t target_group;
     790                 :            : 
     791                 :          0 :         target_group = dest_group;
     792         [ #  # ]:          0 :         if (flow_hw_translate_group(dev, cfg, dest_group, &target_group, error))
     793                 :            :                 return NULL;
     794                 :          0 :         jattr.group = target_group;
     795                 :          0 :         ge = mlx5_hlist_register(priv->sh->flow_tbls, target_group, &ctx);
     796         [ #  # ]:          0 :         if (!ge)
     797                 :            :                 return NULL;
     798                 :            :         grp = container_of(ge, struct mlx5_flow_group, entry);
     799                 :          0 :         return &grp->jump;
     800                 :            : }
     801                 :            : 
     802                 :            : /**
     803                 :            :  * Release jump action.
     804                 :            :  *
     805                 :            :  * @param[in] dev
     806                 :            :  *   Pointer to the rte_eth_dev structure.
     807                 :            :  * @param[in] jump
     808                 :            :  *   Pointer to the jump action.
     809                 :            :  */
     810                 :            : 
     811                 :            : static void
     812                 :            : flow_hw_jump_release(struct rte_eth_dev *dev, struct mlx5_hw_jump_action *jump)
     813                 :            : {
     814                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
     815                 :            :         struct mlx5_flow_group *grp;
     816                 :            : 
     817                 :          0 :         grp = container_of(jump, struct mlx5_flow_group, jump);
     818                 :          0 :         mlx5_hlist_unregister(priv->sh->flow_tbls, &grp->entry);
     819                 :          0 : }
     820                 :            : 
     821                 :            : /**
     822                 :            :  * Register queue/RSS action.
     823                 :            :  *
     824                 :            :  * @param[in] dev
     825                 :            :  *   Pointer to the rte_eth_dev structure.
     826                 :            :  * @param[in] hws_flags
     827                 :            :  *   DR action flags.
     828                 :            :  * @param[in] action
     829                 :            :  *   rte flow action.
     830                 :            :  * @param[in] item_flags
     831                 :            :  *   Item flags for non template rule.
     832                 :            :  * @param[in] is_template
     833                 :            :  *   True if it is a template rule.
     834                 :            :  *
     835                 :            :  * @return
     836                 :            :  *    Table on success, NULL otherwise and rte_errno is set.
     837                 :            :  */
     838                 :            : static inline struct mlx5_hrxq*
     839                 :          0 : flow_hw_tir_action_register(struct rte_eth_dev *dev,
     840                 :            :                             uint32_t hws_flags,
     841                 :            :                             const struct rte_flow_action *action)
     842                 :            : {
     843                 :          0 :         struct mlx5_flow_rss_desc rss_desc = {
     844                 :            :                 .hws_flags = hws_flags,
     845                 :            :         };
     846                 :            :         struct mlx5_hrxq *hrxq;
     847                 :            : 
     848         [ #  # ]:          0 :         if (action->type == RTE_FLOW_ACTION_TYPE_QUEUE) {
     849                 :          0 :                 const struct rte_flow_action_queue *queue = action->conf;
     850                 :            : 
     851                 :          0 :                 rss_desc.const_q = &queue->index;
     852                 :          0 :                 rss_desc.queue_num = 1;
     853                 :            :         } else {
     854                 :          0 :                 const struct rte_flow_action_rss *rss = action->conf;
     855                 :            : 
     856                 :          0 :                 rss_desc.queue_num = rss->queue_num;
     857                 :          0 :                 rss_desc.const_q = rss->queue;
     858                 :          0 :                 memcpy(rss_desc.key,
     859         [ #  # ]:          0 :                        !rss->key ? rss_hash_default_key : rss->key,
     860                 :            :                        MLX5_RSS_HASH_KEY_LEN);
     861                 :          0 :                 rss_desc.key_len = MLX5_RSS_HASH_KEY_LEN;
     862         [ #  # ]:          0 :                 rss_desc.types = !rss->types ? RTE_ETH_RSS_IP : rss->types;
     863                 :          0 :                 rss_desc.symmetric_hash_function = MLX5_RSS_IS_SYMM(rss->func);
     864                 :          0 :                 flow_hw_hashfields_set(&rss_desc, &rss_desc.hash_fields);
     865                 :          0 :                 flow_dv_action_rss_l34_hash_adjust(rss->types,
     866                 :            :                                                    &rss_desc.hash_fields);
     867         [ #  # ]:          0 :                 if (rss->level > 1) {
     868                 :          0 :                         rss_desc.hash_fields |= IBV_RX_HASH_INNER;
     869                 :          0 :                         rss_desc.tunnel = 1;
     870                 :            :                 }
     871                 :            :         }
     872                 :          0 :         hrxq = mlx5_hrxq_get(dev, &rss_desc);
     873                 :          0 :         return hrxq;
     874                 :            : }
     875                 :            : 
     876                 :            : static __rte_always_inline int
     877                 :            : flow_hw_ct_compile(struct rte_eth_dev *dev,
     878                 :            :                    uint32_t queue, uint32_t idx,
     879                 :            :                    struct mlx5dr_rule_action *rule_act)
     880                 :            : {
     881                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
     882                 :            :         struct mlx5_aso_ct_action *ct;
     883                 :            : 
     884                 :          0 :         ct = mlx5_ipool_get(priv->hws_ctpool->cts, idx);
     885   [ #  #  #  #  :          0 :         if (!ct || (!priv->shared_host && mlx5_aso_ct_available(priv->sh, queue, ct)))
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
     886                 :            :                 return -1;
     887                 :          0 :         rule_act->action = priv->hws_ctpool->dr_action;
     888                 :          0 :         rule_act->aso_ct.offset = ct->offset;
     889                 :          0 :         rule_act->aso_ct.direction = ct->is_original ?
     890                 :          0 :                 MLX5DR_ACTION_ASO_CT_DIRECTION_INITIATOR :
     891                 :            :                 MLX5DR_ACTION_ASO_CT_DIRECTION_RESPONDER;
     892                 :            :         return 0;
     893                 :            : }
     894                 :            : 
     895                 :            : static void
     896                 :            : flow_hw_template_destroy_reformat_action(struct mlx5_hw_encap_decap_action *encap_decap)
     897                 :            : {
     898   [ #  #  #  # ]:          0 :         if (encap_decap->action && !encap_decap->multi_pattern)
     899                 :          0 :                 mlx5dr_action_destroy(encap_decap->action);
     900                 :            : }
     901                 :            : 
     902                 :            : static void
     903                 :            : flow_hw_template_destroy_mhdr_action(struct mlx5_hw_modify_header_action *mhdr)
     904                 :            : {
     905   [ #  #  #  # ]:          0 :         if (mhdr->action && !mhdr->multi_pattern)
     906                 :          0 :                 mlx5dr_action_destroy(mhdr->action);
     907                 :            : }
     908                 :            : 
     909                 :            : /**
     910                 :            :  * Destroy DR actions created by action template.
     911                 :            :  *
     912                 :            :  * For DR actions created during table creation's action translate.
     913                 :            :  * Need to destroy the DR action when destroying the table.
     914                 :            :  *
     915                 :            :  * @param[in] dev
     916                 :            :  *   Pointer to the rte_eth_dev structure.
     917                 :            :  * @param[in] acts
     918                 :            :  *   Pointer to the template HW steering DR actions.
     919                 :            :  */
     920                 :            : static void
     921                 :          0 : __flow_hw_actions_release(struct rte_eth_dev *dev, struct mlx5_hw_actions *acts)
     922                 :            : {
     923                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
     924                 :            : 
     925         [ #  # ]:          0 :         if (acts->mark)
     926         [ #  # ]:          0 :                 if (!(rte_atomic_fetch_sub_explicit(&priv->hws_mark_refcnt, 1,
     927                 :            :                                 rte_memory_order_relaxed) - 1))
     928                 :          0 :                         flow_hw_rxq_flag_set(dev, false);
     929                 :            : 
     930         [ #  # ]:          0 :         if (acts->jump) {
     931                 :            :                 struct mlx5_flow_group *grp;
     932                 :            : 
     933                 :          0 :                 grp = container_of
     934                 :            :                         (acts->jump, struct mlx5_flow_group, jump);
     935                 :          0 :                 mlx5_hlist_unregister(priv->sh->flow_tbls, &grp->entry);
     936                 :          0 :                 acts->jump = NULL;
     937                 :            :         }
     938         [ #  # ]:          0 :         if (acts->tir) {
     939                 :          0 :                 mlx5_hrxq_release(dev, acts->tir->idx);
     940                 :          0 :                 acts->tir = NULL;
     941                 :            :         }
     942         [ #  # ]:          0 :         if (acts->encap_decap) {
     943                 :            :                 flow_hw_template_destroy_reformat_action(acts->encap_decap);
     944                 :          0 :                 mlx5_free(acts->encap_decap);
     945                 :          0 :                 acts->encap_decap = NULL;
     946                 :            :         }
     947         [ #  # ]:          0 :         if (acts->push_remove) {
     948         [ #  # ]:          0 :                 if (acts->push_remove->action)
     949                 :          0 :                         mlx5dr_action_destroy(acts->push_remove->action);
     950                 :          0 :                 mlx5_free(acts->push_remove);
     951                 :          0 :                 acts->push_remove = NULL;
     952                 :            :         }
     953         [ #  # ]:          0 :         if (acts->mhdr) {
     954                 :            :                 flow_hw_template_destroy_mhdr_action(acts->mhdr);
     955                 :          0 :                 mlx5_free(acts->mhdr);
     956                 :          0 :                 acts->mhdr = NULL;
     957                 :            :         }
     958         [ #  # ]:          0 :         if (mlx5_hws_cnt_id_valid(acts->cnt_id)) {
     959         [ #  # ]:          0 :                 mlx5_hws_cnt_shared_put(priv->hws_cpool, &acts->cnt_id);
     960                 :          0 :                 acts->cnt_id = 0;
     961                 :            :         }
     962         [ #  # ]:          0 :         if (acts->mtr_id) {
     963                 :          0 :                 mlx5_ipool_free(priv->hws_mpool->idx_pool, acts->mtr_id);
     964                 :          0 :                 acts->mtr_id = 0;
     965                 :            :         }
     966                 :          0 : }
     967                 :            : 
     968                 :            : /**
     969                 :            :  * Release the action data back into the pool without destroy any action.
     970                 :            :  *
     971                 :            :  * @param[in] dev
     972                 :            :  *   Pointer to the rte_eth_dev structure.
     973                 :            :  * @param[in] acts
     974                 :            :  *   Pointer to the template HW steering DR actions.
     975                 :            :  */
     976                 :            : static inline void
     977                 :          0 : __flow_hw_act_data_flush(struct rte_eth_dev *dev, struct mlx5_hw_actions *acts)
     978                 :            : {
     979                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
     980                 :            :         struct mlx5_action_construct_data *data;
     981                 :            : 
     982         [ #  # ]:          0 :         while (!LIST_EMPTY(&acts->act_list)) {
     983                 :            :                 data = LIST_FIRST(&acts->act_list);
     984         [ #  # ]:          0 :                 LIST_REMOVE(data, next);
     985                 :          0 :                 mlx5_ipool_free(priv->acts_ipool, data->idx);
     986                 :            :         }
     987                 :          0 : }
     988                 :            : 
     989                 :            : /*
     990                 :            :  * Destroy DR actions created by action template.
     991                 :            :  *
     992                 :            :  * For DR actions created during table creation's action translate.
     993                 :            :  * Need to destroy the DR action when destroying the table.
     994                 :            :  *
     995                 :            :  * @param[in] dev
     996                 :            :  *   Pointer to the rte_eth_dev structure.
     997                 :            :  * @param[in] acts
     998                 :            :  *   Pointer to the template HW steering DR actions.
     999                 :            :  */
    1000                 :            : static void
    1001                 :          0 : __flow_hw_action_template_destroy(struct rte_eth_dev *dev, struct mlx5_hw_actions *acts)
    1002                 :            : {
    1003                 :          0 :         __flow_hw_act_data_flush(dev, acts);
    1004                 :          0 :         __flow_hw_actions_release(dev, acts);
    1005                 :          0 : }
    1006                 :            : 
    1007                 :            : /**
    1008                 :            :  * Append dynamic action to the dynamic action list.
    1009                 :            :  *
    1010                 :            :  * @param[in] priv
    1011                 :            :  *   Pointer to the port private data structure.
    1012                 :            :  * @param[in] acts
    1013                 :            :  *   Pointer to the template HW steering DR actions.
    1014                 :            :  * @param[in] type
    1015                 :            :  *   Action type.
    1016                 :            :  * @param[in] action_src
    1017                 :            :  *   Offset of source rte flow action.
    1018                 :            :  * @param[in] action_dst
    1019                 :            :  *   Offset of destination DR action.
    1020                 :            :  *
    1021                 :            :  * @return
    1022                 :            :  *    0 on success, negative value otherwise and rte_errno is set.
    1023                 :            :  */
    1024                 :            : static __rte_always_inline struct mlx5_action_construct_data *
    1025                 :            : __flow_hw_act_data_alloc(struct mlx5_priv *priv,
    1026                 :            :                          enum rte_flow_action_type type,
    1027                 :            :                          uint16_t action_src,
    1028                 :            :                          uint16_t action_dst)
    1029                 :            : {
    1030                 :            :         struct mlx5_action_construct_data *act_data;
    1031                 :          0 :         uint32_t idx = 0;
    1032                 :            : 
    1033                 :          0 :         act_data = mlx5_ipool_zmalloc(priv->acts_ipool, &idx);
    1034   [ #  #  #  #  :          0 :         if (!act_data)
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    1035                 :            :                 return NULL;
    1036                 :          0 :         act_data->idx = idx;
    1037                 :          0 :         act_data->type = type;
    1038                 :          0 :         act_data->action_src = action_src;
    1039                 :          0 :         act_data->action_dst = action_dst;
    1040                 :            :         return act_data;
    1041                 :            : }
    1042                 :            : 
    1043                 :            : /**
    1044                 :            :  * Append dynamic action to the dynamic action list.
    1045                 :            :  *
    1046                 :            :  * @param[in] priv
    1047                 :            :  *   Pointer to the port private data structure.
    1048                 :            :  * @param[in] acts
    1049                 :            :  *   Pointer to the template HW steering DR actions.
    1050                 :            :  * @param[in] type
    1051                 :            :  *   Action type.
    1052                 :            :  * @param[in] action_src
    1053                 :            :  *   Offset of source rte flow action.
    1054                 :            :  * @param[in] action_dst
    1055                 :            :  *   Offset of destination DR action.
    1056                 :            :  *
    1057                 :            :  * @return
    1058                 :            :  *    0 on success, negative value otherwise and rte_errno is set.
    1059                 :            :  */
    1060                 :            : static __rte_always_inline int
    1061                 :            : __flow_hw_act_data_general_append(struct mlx5_priv *priv,
    1062                 :            :                                   struct mlx5_hw_actions *acts,
    1063                 :            :                                   enum rte_flow_action_type type,
    1064                 :            :                                   uint16_t action_src,
    1065                 :            :                                   uint16_t action_dst)
    1066                 :            : {
    1067                 :            :         struct mlx5_action_construct_data *act_data;
    1068                 :            : 
    1069                 :            :         act_data = __flow_hw_act_data_alloc(priv, type, action_src, action_dst);
    1070                 :            :         if (!act_data)
    1071                 :            :                 return -1;
    1072   [ #  #  #  #  :          0 :         LIST_INSERT_HEAD(&acts->act_list, act_data, next);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    1073                 :            :         return 0;
    1074                 :            : }
    1075                 :            : 
    1076                 :            : static __rte_always_inline int
    1077                 :            : __flow_hw_act_data_indirect_append(struct mlx5_priv *priv,
    1078                 :            :                                    struct mlx5_hw_actions *acts,
    1079                 :            :                                    enum rte_flow_action_type type,
    1080                 :            :                                    enum rte_flow_action_type mask_type,
    1081                 :            :                                    uint16_t action_src,
    1082                 :            :                                    uint16_t action_dst)
    1083                 :            : {
    1084                 :            :         struct mlx5_action_construct_data *act_data;
    1085                 :            : 
    1086                 :            :         act_data = __flow_hw_act_data_alloc(priv, type, action_src, action_dst);
    1087                 :            :         if (!act_data)
    1088                 :            :                 return -1;
    1089                 :          0 :         act_data->indirect.expected_type = mask_type;
    1090         [ #  # ]:          0 :         LIST_INSERT_HEAD(&acts->act_list, act_data, next);
    1091                 :            :         return 0;
    1092                 :            : }
    1093                 :            : 
    1094                 :            : static __rte_always_inline int
    1095                 :            : flow_hw_act_data_indirect_list_append(struct mlx5_priv *priv,
    1096                 :            :                                       struct mlx5_hw_actions *acts,
    1097                 :            :                                       enum rte_flow_action_type type,
    1098                 :            :                                       uint16_t action_src, uint16_t action_dst,
    1099                 :            :                                       indirect_list_callback_t cb)
    1100                 :            : {
    1101                 :            :         struct mlx5_action_construct_data *act_data;
    1102                 :            : 
    1103                 :            :         act_data = __flow_hw_act_data_alloc(priv, type, action_src, action_dst);
    1104                 :            :         if (!act_data)
    1105                 :          0 :                 return -1;
    1106                 :          0 :         act_data->indirect_list_cb = cb;
    1107   [ #  #  #  #  :          0 :         LIST_INSERT_HEAD(&acts->act_list, act_data, next);
                   #  # ]
    1108                 :          0 :         return 0;
    1109                 :            : }
    1110                 :            : /**
    1111                 :            :  * Append dynamic encap action to the dynamic action list.
    1112                 :            :  *
    1113                 :            :  * @param[in] priv
    1114                 :            :  *   Pointer to the port private data structure.
    1115                 :            :  * @param[in] acts
    1116                 :            :  *   Pointer to the template HW steering DR actions.
    1117                 :            :  * @param[in] type
    1118                 :            :  *   Action type.
    1119                 :            :  * @param[in] action_src
    1120                 :            :  *   Offset of source rte flow action.
    1121                 :            :  * @param[in] action_dst
    1122                 :            :  *   Offset of destination DR action.
    1123                 :            :  * @param[in] len
    1124                 :            :  *   Length of the data to be updated.
    1125                 :            :  *
    1126                 :            :  * @return
    1127                 :            :  *    0 on success, negative value otherwise and rte_errno is set.
    1128                 :            :  */
    1129                 :            : static __rte_always_inline int
    1130                 :            : __flow_hw_act_data_encap_append(struct mlx5_priv *priv,
    1131                 :            :                                 struct mlx5_hw_actions *acts,
    1132                 :            :                                 enum rte_flow_action_type type,
    1133                 :            :                                 uint16_t action_src,
    1134                 :            :                                 uint16_t action_dst,
    1135                 :            :                                 uint16_t len)
    1136                 :            : {
    1137                 :            :         struct mlx5_action_construct_data *act_data;
    1138                 :            : 
    1139                 :            :         act_data = __flow_hw_act_data_alloc(priv, type, action_src, action_dst);
    1140                 :            :         if (!act_data)
    1141                 :            :                 return -1;
    1142                 :          0 :         act_data->encap.len = len;
    1143         [ #  # ]:          0 :         LIST_INSERT_HEAD(&acts->act_list, act_data, next);
    1144                 :            :         return 0;
    1145                 :            : }
    1146                 :            : 
    1147                 :            : /**
    1148                 :            :  * Append dynamic push action to the dynamic action list.
    1149                 :            :  *
    1150                 :            :  * @param[in] dev
    1151                 :            :  *   Pointer to the port.
    1152                 :            :  * @param[in] acts
    1153                 :            :  *   Pointer to the template HW steering DR actions.
    1154                 :            :  * @param[in] type
    1155                 :            :  *   Action type.
    1156                 :            :  * @param[in] action_src
    1157                 :            :  *   Offset of source rte flow action.
    1158                 :            :  * @param[in] action_dst
    1159                 :            :  *   Offset of destination DR action.
    1160                 :            :  * @param[in] len
    1161                 :            :  *   Length of the data to be updated.
    1162                 :            :  *
    1163                 :            :  * @return
    1164                 :            :  *    Data pointer on success, NULL otherwise and rte_errno is set.
    1165                 :            :  */
    1166                 :            : static __rte_always_inline void *
    1167                 :            : __flow_hw_act_data_push_append(struct rte_eth_dev *dev,
    1168                 :            :                                struct mlx5_hw_actions *acts,
    1169                 :            :                                enum rte_flow_action_type type,
    1170                 :            :                                uint16_t action_src,
    1171                 :            :                                uint16_t action_dst,
    1172                 :            :                                uint16_t len)
    1173                 :            : {
    1174                 :            :         struct mlx5_action_construct_data *act_data;
    1175                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    1176                 :            : 
    1177                 :            :         act_data = __flow_hw_act_data_alloc(priv, type, action_src, action_dst);
    1178                 :            :         if (!act_data)
    1179                 :            :                 return NULL;
    1180                 :          0 :         act_data->ipv6_ext.len = len;
    1181         [ #  # ]:          0 :         LIST_INSERT_HEAD(&acts->act_list, act_data, next);
    1182                 :            :         return act_data;
    1183                 :            : }
    1184                 :            : 
    1185                 :            : static __rte_always_inline int
    1186                 :            : __flow_hw_act_data_hdr_modify_append(struct mlx5_priv *priv,
    1187                 :            :                                      struct mlx5_hw_actions *acts,
    1188                 :            :                                      enum rte_flow_action_type type,
    1189                 :            :                                      uint16_t action_src,
    1190                 :            :                                      uint16_t action_dst,
    1191                 :            :                                      const struct rte_flow_action_modify_field *mf,
    1192                 :            :                                      uint16_t mhdr_cmds_off,
    1193                 :            :                                      uint16_t mhdr_cmds_end,
    1194                 :            :                                      bool shared,
    1195                 :            :                                      struct field_modify_info *field,
    1196                 :            :                                      struct field_modify_info *dcopy,
    1197                 :            :                                      uint32_t *mask)
    1198                 :            : {
    1199                 :            :         struct mlx5_action_construct_data *act_data;
    1200                 :            : 
    1201                 :            :         act_data = __flow_hw_act_data_alloc(priv, type, action_src, action_dst);
    1202                 :            :         if (!act_data)
    1203                 :            :                 return -1;
    1204                 :          0 :         act_data->modify_header.action = *mf;
    1205                 :          0 :         act_data->modify_header.mhdr_cmds_off = mhdr_cmds_off;
    1206                 :          0 :         act_data->modify_header.mhdr_cmds_end = mhdr_cmds_end;
    1207                 :          0 :         act_data->modify_header.shared = shared;
    1208         [ #  # ]:          0 :         rte_memcpy(act_data->modify_header.field, field,
    1209                 :            :                    sizeof(*field) * MLX5_ACT_MAX_MOD_FIELDS);
    1210         [ #  # ]:          0 :         rte_memcpy(act_data->modify_header.dcopy, dcopy,
    1211                 :            :                    sizeof(*dcopy) * MLX5_ACT_MAX_MOD_FIELDS);
    1212         [ #  # ]:          0 :         rte_memcpy(act_data->modify_header.mask, mask,
    1213                 :            :                    sizeof(*mask) * MLX5_ACT_MAX_MOD_FIELDS);
    1214         [ #  # ]:          0 :         LIST_INSERT_HEAD(&acts->act_list, act_data, next);
    1215                 :            :         return 0;
    1216                 :            : }
    1217                 :            : 
    1218                 :            : /**
    1219                 :            :  * Append shared RSS action to the dynamic action list.
    1220                 :            :  *
    1221                 :            :  * @param[in] priv
    1222                 :            :  *   Pointer to the port private data structure.
    1223                 :            :  * @param[in] acts
    1224                 :            :  *   Pointer to the template HW steering DR actions.
    1225                 :            :  * @param[in] type
    1226                 :            :  *   Action type.
    1227                 :            :  * @param[in] action_src
    1228                 :            :  *   Offset of source rte flow action.
    1229                 :            :  * @param[in] action_dst
    1230                 :            :  *   Offset of destination DR action.
    1231                 :            :  * @param[in] idx
    1232                 :            :  *   Shared RSS index.
    1233                 :            :  * @param[in] rss
    1234                 :            :  *   Pointer to the shared RSS info.
    1235                 :            :  *
    1236                 :            :  * @return
    1237                 :            :  *    0 on success, negative value otherwise and rte_errno is set.
    1238                 :            :  */
    1239                 :            : static __rte_always_inline int
    1240                 :            : __flow_hw_act_data_shared_rss_append(struct mlx5_priv *priv,
    1241                 :            :                                      struct mlx5_hw_actions *acts,
    1242                 :            :                                      enum rte_flow_action_type type,
    1243                 :            :                                      uint16_t action_src,
    1244                 :            :                                      uint16_t action_dst,
    1245                 :            :                                      uint32_t idx,
    1246                 :            :                                      struct mlx5_shared_action_rss *rss)
    1247                 :            : {
    1248                 :            :         struct mlx5_action_construct_data *act_data;
    1249                 :            : 
    1250                 :            :         act_data = __flow_hw_act_data_alloc(priv, type, action_src, action_dst);
    1251                 :            :         if (!act_data)
    1252                 :            :                 return -1;
    1253                 :          0 :         act_data->shared_rss.level = rss->origin.level;
    1254         [ #  # ]:          0 :         act_data->shared_rss.types = !rss->origin.types ? RTE_ETH_RSS_IP :
    1255                 :            :                                      rss->origin.types;
    1256                 :          0 :         act_data->shared_rss.idx = idx;
    1257                 :          0 :         act_data->shared_rss.symmetric_hash_function =
    1258                 :          0 :                 MLX5_RSS_IS_SYMM(rss->origin.func);
    1259         [ #  # ]:          0 :         LIST_INSERT_HEAD(&acts->act_list, act_data, next);
    1260                 :            :         return 0;
    1261                 :            : }
    1262                 :            : 
    1263                 :            : /**
    1264                 :            :  * Append shared counter action to the dynamic action list.
    1265                 :            :  *
    1266                 :            :  * @param[in] priv
    1267                 :            :  *   Pointer to the port private data structure.
    1268                 :            :  * @param[in] acts
    1269                 :            :  *   Pointer to the template HW steering DR actions.
    1270                 :            :  * @param[in] type
    1271                 :            :  *   Action type.
    1272                 :            :  * @param[in] action_src
    1273                 :            :  *   Offset of source rte flow action.
    1274                 :            :  * @param[in] action_dst
    1275                 :            :  *   Offset of destination DR action.
    1276                 :            :  * @param[in] cnt_id
    1277                 :            :  *   Shared counter id.
    1278                 :            :  *
    1279                 :            :  * @return
    1280                 :            :  *    0 on success, negative value otherwise and rte_errno is set.
    1281                 :            :  */
    1282                 :            : static __rte_always_inline int
    1283                 :            : __flow_hw_act_data_shared_cnt_append(struct mlx5_priv *priv,
    1284                 :            :                                      struct mlx5_hw_actions *acts,
    1285                 :            :                                      enum rte_flow_action_type type,
    1286                 :            :                                      uint16_t action_src,
    1287                 :            :                                      uint16_t action_dst,
    1288                 :            :                                      cnt_id_t cnt_id)
    1289                 :            : {
    1290                 :            :         struct mlx5_action_construct_data *act_data;
    1291                 :            : 
    1292                 :            :         act_data = __flow_hw_act_data_alloc(priv, type, action_src, action_dst);
    1293                 :            :         if (!act_data)
    1294                 :            :                 return -1;
    1295                 :            :         act_data->type = type;
    1296                 :          0 :         act_data->shared_counter.id = cnt_id;
    1297         [ #  # ]:          0 :         LIST_INSERT_HEAD(&acts->act_list, act_data, next);
    1298                 :            :         return 0;
    1299                 :            : }
    1300                 :            : 
    1301                 :            : /**
    1302                 :            :  * Append shared meter_mark action to the dynamic action list.
    1303                 :            :  *
    1304                 :            :  * @param[in] priv
    1305                 :            :  *   Pointer to the port private data structure.
    1306                 :            :  * @param[in] acts
    1307                 :            :  *   Pointer to the template HW steering DR actions.
    1308                 :            :  * @param[in] type
    1309                 :            :  *   Action type.
    1310                 :            :  * @param[in] action_src
    1311                 :            :  *   Offset of source rte flow action.
    1312                 :            :  * @param[in] action_dst
    1313                 :            :  *   Offset of destination DR action.
    1314                 :            :  * @param[in] mtr_id
    1315                 :            :  *   Shared meter id.
    1316                 :            :  *
    1317                 :            :  * @return
    1318                 :            :  *    0 on success, negative value otherwise and rte_errno is set.
    1319                 :            :  */
    1320                 :            : static __rte_always_inline int
    1321                 :            : __flow_hw_act_data_shared_mtr_append(struct mlx5_priv *priv,
    1322                 :            :                                      struct mlx5_hw_actions *acts,
    1323                 :            :                                      enum rte_flow_action_type type,
    1324                 :            :                                      uint16_t action_src,
    1325                 :            :                                      uint16_t action_dst,
    1326                 :            :                                      cnt_id_t mtr_id)
    1327                 :            : {       struct mlx5_action_construct_data *act_data;
    1328                 :            : 
    1329                 :            :         act_data = __flow_hw_act_data_alloc(priv, type, action_src, action_dst);
    1330                 :            :         if (!act_data)
    1331                 :            :                 return -1;
    1332                 :            :         act_data->type = type;
    1333                 :          0 :         act_data->shared_meter.id = mtr_id;
    1334         [ #  # ]:          0 :         LIST_INSERT_HEAD(&acts->act_list, act_data, next);
    1335                 :            :         return 0;
    1336                 :            : }
    1337                 :            : 
    1338                 :            : /**
    1339                 :            :  * Translate shared indirect action.
    1340                 :            :  *
    1341                 :            :  * @param[in] dev
    1342                 :            :  *   Pointer to the rte_eth_dev data structure.
    1343                 :            :  * @param[in] action
    1344                 :            :  *   Pointer to the shared indirect rte_flow action.
    1345                 :            :  * @param[in] acts
    1346                 :            :  *   Pointer to the template HW steering DR actions.
    1347                 :            :  * @param[in] action_src
    1348                 :            :  *   Offset of source rte flow action.
    1349                 :            :  * @param[in] action_dst
    1350                 :            :  *   Offset of destination DR action.
    1351                 :            :  *
    1352                 :            :  * @return
    1353                 :            :  *    0 on success, negative value otherwise and rte_errno is set.
    1354                 :            :  */
    1355                 :            : static __rte_always_inline int
    1356                 :            : flow_hw_shared_action_translate(struct rte_eth_dev *dev,
    1357                 :            :                                 const struct rte_flow_action *action,
    1358                 :            :                                 struct mlx5_hw_actions *acts,
    1359                 :            :                                 uint16_t action_src,
    1360                 :            :                                 uint16_t action_dst)
    1361                 :            : {
    1362                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    1363                 :            :         struct mlx5_shared_action_rss *shared_rss;
    1364                 :          0 :         uint32_t act_idx = (uint32_t)(uintptr_t)action->conf;
    1365                 :          0 :         uint32_t type = act_idx >> MLX5_INDIRECT_ACTION_TYPE_OFFSET;
    1366                 :          0 :         uint32_t idx = act_idx &
    1367                 :            :                        ((1u << MLX5_INDIRECT_ACTION_TYPE_OFFSET) - 1);
    1368                 :            : 
    1369                 :          0 :         switch (type) {
    1370                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_RSS:
    1371                 :          0 :                 shared_rss = mlx5_ipool_get
    1372                 :          0 :                   (priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], idx);
    1373         [ #  # ]:          0 :                 if (!shared_rss || __flow_hw_act_data_shared_rss_append
    1374                 :            :                     (priv, acts,
    1375                 :            :                     (enum rte_flow_action_type)MLX5_RTE_FLOW_ACTION_TYPE_RSS,
    1376                 :            :                     action_src, action_dst, idx, shared_rss)) {
    1377                 :          0 :                         DRV_LOG(WARNING, "Indirect RSS action index %d translate failed", act_idx);
    1378                 :            :                         return -1;
    1379                 :            :                 }
    1380                 :            :                 break;
    1381                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_COUNT:
    1382                 :            :                 if (__flow_hw_act_data_shared_cnt_append(priv, acts,
    1383                 :            :                         (enum rte_flow_action_type)
    1384                 :            :                         MLX5_RTE_FLOW_ACTION_TYPE_COUNT,
    1385                 :            :                         action_src, action_dst, act_idx)) {
    1386                 :          0 :                         DRV_LOG(WARNING, "Indirect count action translate failed");
    1387                 :            :                         return -1;
    1388                 :            :                 }
    1389                 :            :                 break;
    1390                 :            :         case MLX5_INDIRECT_ACTION_TYPE_AGE:
    1391                 :            :                 /* Not supported, prevent by validate function. */
    1392                 :            :                 MLX5_ASSERT(0);
    1393                 :            :                 break;
    1394                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_CT:
    1395                 :            :                 if (flow_hw_ct_compile(dev, MLX5_HW_INV_QUEUE,
    1396                 :            :                                        idx, &acts->rule_acts[action_dst])) {
    1397                 :          0 :                         DRV_LOG(WARNING, "Indirect CT action translate failed");
    1398                 :            :                         return -1;
    1399                 :            :                 }
    1400                 :            :                 break;
    1401                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_METER_MARK:
    1402                 :            :                 if (__flow_hw_act_data_shared_mtr_append(priv, acts,
    1403                 :            :                         (enum rte_flow_action_type)
    1404                 :            :                         MLX5_RTE_FLOW_ACTION_TYPE_METER_MARK,
    1405                 :            :                         action_src, action_dst, idx)) {
    1406                 :          0 :                         DRV_LOG(WARNING, "Indirect meter mark action translate failed");
    1407                 :            :                         return -1;
    1408                 :            :                 }
    1409                 :            :                 break;
    1410                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_QUOTA:
    1411                 :            :                 flow_hw_construct_quota(priv, &acts->rule_acts[action_dst], idx);
    1412                 :            :                 break;
    1413                 :          0 :         default:
    1414                 :          0 :                 DRV_LOG(WARNING, "Unsupported shared action type:%d", type);
    1415                 :            :                 break;
    1416                 :            :         }
    1417                 :            :         return 0;
    1418                 :            : }
    1419                 :            : 
    1420                 :            : static __rte_always_inline bool
    1421                 :            : flow_hw_action_modify_field_is_shared(const struct rte_flow_action *action,
    1422                 :            :                                       const struct rte_flow_action *mask)
    1423                 :            : {
    1424                 :            :         const struct rte_flow_action_modify_field *v = action->conf;
    1425                 :          0 :         const struct rte_flow_action_modify_field *m = mask->conf;
    1426                 :            : 
    1427                 :          0 :         if (v->src.field == RTE_FLOW_FIELD_VALUE) {
    1428                 :            :                 uint32_t j;
    1429                 :            : 
    1430         [ #  # ]:          0 :                 for (j = 0; j < RTE_DIM(m->src.value); ++j) {
    1431                 :            :                         /*
    1432                 :            :                          * Immediate value is considered to be masked
    1433                 :            :                          * (and thus shared by all flow rules), if mask
    1434                 :            :                          * is non-zero. Partial mask over immediate value
    1435                 :            :                          * is not allowed.
    1436                 :            :                          */
    1437         [ #  # ]:          0 :                         if (m->src.value[j])
    1438                 :            :                                 return true;
    1439                 :            :                 }
    1440                 :            :                 return false;
    1441                 :            :         }
    1442         [ #  # ]:          0 :         if (v->src.field == RTE_FLOW_FIELD_POINTER)
    1443                 :          0 :                 return m->src.pvalue != NULL;
    1444                 :            :         /*
    1445                 :            :          * Source field types other than VALUE and
    1446                 :            :          * POINTER are always shared.
    1447                 :            :          */
    1448                 :            :         return true;
    1449                 :            : }
    1450                 :            : 
    1451                 :            : static __rte_always_inline bool
    1452                 :            : flow_hw_should_insert_nop(const struct mlx5_hw_modify_header_action *mhdr,
    1453                 :            :                           const struct mlx5_modification_cmd *cmd)
    1454                 :            : {
    1455                 :            :         struct mlx5_modification_cmd last_cmd = { { 0 } };
    1456                 :            :         struct mlx5_modification_cmd new_cmd = { { 0 } };
    1457                 :          0 :         const uint32_t cmds_num = mhdr->mhdr_cmds_num;
    1458                 :            :         unsigned int last_type;
    1459                 :            :         bool should_insert = false;
    1460                 :            : 
    1461   [ #  #  #  # ]:          0 :         if (cmds_num == 0)
    1462                 :            :                 return false;
    1463                 :          0 :         last_cmd = *(&mhdr->mhdr_cmds[cmds_num - 1]);
    1464   [ #  #  #  # ]:          0 :         last_cmd.data0 = rte_be_to_cpu_32(last_cmd.data0);
    1465   [ #  #  #  # ]:          0 :         last_cmd.data1 = rte_be_to_cpu_32(last_cmd.data1);
    1466                 :          0 :         last_type = last_cmd.action_type;
    1467                 :          0 :         new_cmd = *cmd;
    1468   [ #  #  #  # ]:          0 :         new_cmd.data0 = rte_be_to_cpu_32(new_cmd.data0);
    1469   [ #  #  #  # ]:          0 :         new_cmd.data1 = rte_be_to_cpu_32(new_cmd.data1);
    1470   [ #  #  #  #  :          0 :         switch (new_cmd.action_type) {
                   #  # ]
    1471                 :          0 :         case MLX5_MODIFICATION_TYPE_SET:
    1472                 :            :         case MLX5_MODIFICATION_TYPE_ADD:
    1473   [ #  #  #  # ]:          0 :                 if (last_type == MLX5_MODIFICATION_TYPE_SET ||
    1474                 :            :                     last_type == MLX5_MODIFICATION_TYPE_ADD)
    1475                 :          0 :                         should_insert = new_cmd.field == last_cmd.field;
    1476                 :          0 :                 else if (last_type == MLX5_MODIFICATION_TYPE_COPY ||
    1477   [ #  #  #  # ]:          0 :                          last_type == MLX5_MODIFICATION_TYPE_ADD_FIELD)
    1478                 :          0 :                         should_insert = new_cmd.field == last_cmd.dst_field;
    1479                 :            :                 else if (last_type == MLX5_MODIFICATION_TYPE_NOP)
    1480                 :            :                         should_insert = false;
    1481                 :            :                 else
    1482                 :            :                         MLX5_ASSERT(false); /* Other types are not supported. */
    1483                 :            :                 break;
    1484                 :          0 :         case MLX5_MODIFICATION_TYPE_COPY:
    1485                 :            :         case MLX5_MODIFICATION_TYPE_ADD_FIELD:
    1486   [ #  #  #  # ]:          0 :                 if (last_type == MLX5_MODIFICATION_TYPE_SET ||
    1487                 :            :                     last_type == MLX5_MODIFICATION_TYPE_ADD)
    1488   [ #  #  #  # ]:          0 :                         should_insert = (new_cmd.field == last_cmd.field ||
    1489   [ #  #  #  # ]:          0 :                                          new_cmd.dst_field == last_cmd.field);
    1490                 :          0 :                 else if (last_type == MLX5_MODIFICATION_TYPE_COPY ||
    1491   [ #  #  #  # ]:          0 :                          last_type == MLX5_MODIFICATION_TYPE_ADD_FIELD)
    1492   [ #  #  #  # ]:          0 :                         should_insert = (new_cmd.field == last_cmd.dst_field ||
    1493   [ #  #  #  # ]:          0 :                                          new_cmd.dst_field == last_cmd.dst_field);
    1494                 :            :                 else if (last_type == MLX5_MODIFICATION_TYPE_NOP)
    1495                 :            :                         should_insert = false;
    1496                 :            :                 else
    1497                 :            :                         MLX5_ASSERT(false); /* Other types are not supported. */
    1498                 :            :                 break;
    1499                 :            :         default:
    1500                 :            :                 /* Other action types should be rejected on AT validation. */
    1501                 :            :                 MLX5_ASSERT(false);
    1502                 :            :                 break;
    1503                 :            :         }
    1504                 :            :         return should_insert;
    1505                 :            : }
    1506                 :            : 
    1507                 :            : static __rte_always_inline int
    1508                 :            : flow_hw_mhdr_cmd_nop_append(struct mlx5_hw_modify_header_action *mhdr)
    1509                 :            : {
    1510                 :            :         struct mlx5_modification_cmd *nop;
    1511                 :            :         uint32_t num = mhdr->mhdr_cmds_num;
    1512                 :            : 
    1513   [ #  #  #  # ]:          0 :         if (num + 1 >= MLX5_MHDR_MAX_CMD)
    1514                 :            :                 return -ENOMEM;
    1515                 :          0 :         nop = mhdr->mhdr_cmds + num;
    1516                 :            :         nop->data0 = 0;
    1517                 :            :         nop->action_type = MLX5_MODIFICATION_TYPE_NOP;
    1518                 :          0 :         nop->data0 = rte_cpu_to_be_32(nop->data0);
    1519                 :          0 :         nop->data1 = 0;
    1520                 :          0 :         mhdr->mhdr_cmds_num = num + 1;
    1521                 :            :         return 0;
    1522                 :            : }
    1523                 :            : 
    1524                 :            : static __rte_always_inline int
    1525                 :            : flow_hw_mhdr_cmd_append(struct mlx5_hw_modify_header_action *mhdr,
    1526                 :            :                         struct mlx5_modification_cmd *cmd)
    1527                 :            : {
    1528                 :          0 :         uint32_t num = mhdr->mhdr_cmds_num;
    1529                 :            : 
    1530         [ #  # ]:          0 :         if (num + 1 >= MLX5_MHDR_MAX_CMD)
    1531                 :            :                 return -ENOMEM;
    1532                 :          0 :         mhdr->mhdr_cmds[num] = *cmd;
    1533                 :          0 :         mhdr->mhdr_cmds_num = num + 1;
    1534                 :            :         return 0;
    1535                 :            : }
    1536                 :            : 
    1537                 :            : static __rte_always_inline int
    1538                 :            : flow_hw_converted_mhdr_cmds_append(struct mlx5_hw_modify_header_action *mhdr,
    1539                 :            :                                    struct mlx5_flow_dv_modify_hdr_resource *resource)
    1540                 :            : {
    1541                 :            :         uint32_t idx;
    1542                 :            :         int ret;
    1543                 :            : 
    1544         [ #  # ]:          0 :         for (idx = 0; idx < resource->actions_num; ++idx) {
    1545                 :            :                 struct mlx5_modification_cmd *src = &resource->actions[idx];
    1546                 :            : 
    1547         [ #  # ]:          0 :                 if (flow_hw_should_insert_nop(mhdr, src)) {
    1548                 :            :                         ret = flow_hw_mhdr_cmd_nop_append(mhdr);
    1549                 :            :                         if (ret)
    1550                 :            :                                 return ret;
    1551                 :            :                 }
    1552                 :            :                 ret = flow_hw_mhdr_cmd_append(mhdr, src);
    1553                 :            :                 if (ret)
    1554                 :            :                         return ret;
    1555                 :            :         }
    1556                 :            :         return 0;
    1557                 :            : }
    1558                 :            : 
    1559                 :            : static __rte_always_inline void
    1560                 :            : flow_hw_modify_field_init(struct mlx5_hw_modify_header_action *mhdr,
    1561                 :            :                           struct rte_flow_actions_template *at)
    1562                 :            : {
    1563                 :            :         memset(mhdr, 0, sizeof(*mhdr));
    1564                 :            :         /* Modify header action without any commands is shared by default. */
    1565                 :          0 :         mhdr->shared = true;
    1566                 :          0 :         mhdr->pos = at->mhdr_off;
    1567                 :            : }
    1568                 :            : 
    1569                 :            : static __rte_always_inline int
    1570                 :            : flow_hw_modify_field_compile(struct rte_eth_dev *dev,
    1571                 :            :                              const struct rte_flow_attr *attr,
    1572                 :            :                              const struct rte_flow_action *action, /* Current action from AT. */
    1573                 :            :                              const struct rte_flow_action *action_mask, /* Current mask from AT. */
    1574                 :            :                              struct mlx5_hw_actions *acts,
    1575                 :            :                              struct mlx5_hw_modify_header_action *mhdr,
    1576                 :            :                              uint16_t src_pos,
    1577                 :            :                              struct rte_flow_error *error)
    1578                 :            : {
    1579                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    1580                 :          0 :         const struct rte_flow_action_modify_field *conf = action->conf;
    1581                 :            :         union {
    1582                 :            :                 struct mlx5_flow_dv_modify_hdr_resource resource;
    1583                 :            :                 uint8_t data[sizeof(struct mlx5_flow_dv_modify_hdr_resource) +
    1584                 :            :                              sizeof(struct mlx5_modification_cmd) * MLX5_MHDR_MAX_CMD];
    1585                 :            :         } dummy;
    1586                 :            :         struct mlx5_flow_dv_modify_hdr_resource *resource;
    1587                 :          0 :         struct rte_flow_item item = {
    1588                 :            :                 .spec = NULL,
    1589                 :            :                 .mask = NULL
    1590                 :            :         };
    1591                 :          0 :         struct field_modify_info field[MLX5_ACT_MAX_MOD_FIELDS] = {
    1592                 :            :                                                 {0, 0, MLX5_MODI_OUT_NONE} };
    1593                 :          0 :         struct field_modify_info dcopy[MLX5_ACT_MAX_MOD_FIELDS] = {
    1594                 :            :                                                 {0, 0, MLX5_MODI_OUT_NONE} };
    1595                 :          0 :         uint32_t mask[MLX5_ACT_MAX_MOD_FIELDS] = { 0 };
    1596                 :          0 :         uint32_t type, value = 0;
    1597                 :            :         uint16_t cmds_start, cmds_end;
    1598                 :            :         bool shared;
    1599                 :            :         int ret;
    1600                 :            : 
    1601                 :            :         /*
    1602                 :            :          * Modify header action is shared if previous modify_field actions
    1603                 :            :          * are shared and currently compiled action is shared.
    1604                 :            :          */
    1605                 :            :         shared = flow_hw_action_modify_field_is_shared(action, action_mask);
    1606                 :          0 :         mhdr->shared &= shared;
    1607         [ #  # ]:          0 :         if (conf->src.field == RTE_FLOW_FIELD_POINTER ||
    1608                 :            :             conf->src.field == RTE_FLOW_FIELD_VALUE) {
    1609         [ #  # ]:          0 :                 type = conf->operation == RTE_FLOW_MODIFY_SET ? MLX5_MODIFICATION_TYPE_SET :
    1610                 :            :                                                                 MLX5_MODIFICATION_TYPE_ADD;
    1611                 :            :                 /* For SET/ADD fill the destination field (field) first. */
    1612                 :          0 :                 mlx5_flow_field_id_to_modify_info(&conf->dst, field, mask,
    1613                 :          0 :                                                   conf->width, dev,
    1614                 :            :                                                   attr, error);
    1615                 :          0 :                 item.spec = conf->src.field == RTE_FLOW_FIELD_POINTER ?
    1616         [ #  # ]:          0 :                                 (void *)(uintptr_t)conf->src.pvalue :
    1617                 :            :                                 (void *)(uintptr_t)&conf->src.value;
    1618         [ #  # ]:          0 :                 if (conf->dst.field == RTE_FLOW_FIELD_META ||
    1619         [ #  # ]:          0 :                     conf->dst.field == RTE_FLOW_FIELD_TAG ||
    1620         [ #  # ]:          0 :                     conf->dst.field == RTE_FLOW_FIELD_METER_COLOR ||
    1621                 :          0 :                     conf->dst.field == (enum rte_flow_field_id)MLX5_RTE_FLOW_FIELD_META_REG) {
    1622                 :            :                         uint8_t tag_index = flow_tag_index_get(&conf->dst);
    1623                 :            : 
    1624                 :          0 :                         value = *(const unaligned_uint32_t *)item.spec;
    1625   [ #  #  #  # ]:          0 :                         if (conf->dst.field == RTE_FLOW_FIELD_TAG &&
    1626                 :            :                             tag_index == RTE_PMD_MLX5_LINEAR_HASH_TAG_INDEX)
    1627         [ #  # ]:          0 :                                 value = rte_cpu_to_be_32(value << 16);
    1628                 :            :                         else
    1629         [ #  # ]:          0 :                                 value = rte_cpu_to_be_32(value);
    1630                 :          0 :                         item.spec = &value;
    1631         [ #  # ]:          0 :                 } else if (conf->dst.field == RTE_FLOW_FIELD_GTP_PSC_QFI ||
    1632                 :            :                            conf->dst.field == RTE_FLOW_FIELD_GENEVE_OPT_TYPE) {
    1633                 :            :                         /*
    1634                 :            :                          * Both QFI and Geneve option type are passed as an uint8_t integer,
    1635                 :            :                          * but it is accessed through a 2nd least significant byte of a 32-bit
    1636                 :            :                          * field in modify header command.
    1637                 :            :                          */
    1638                 :          0 :                         value = *(const uint8_t *)item.spec;
    1639         [ #  # ]:          0 :                         value = rte_cpu_to_be_32(value << 8);
    1640                 :          0 :                         item.spec = &value;
    1641         [ #  # ]:          0 :                 } else if (conf->dst.field == RTE_FLOW_FIELD_VXLAN_LAST_RSVD) {
    1642                 :          0 :                         value = *(const uint8_t *)item.spec << 24;
    1643         [ #  # ]:          0 :                         value = rte_cpu_to_be_32(value);
    1644                 :          0 :                         item.spec = &value;
    1645                 :            :                 }
    1646                 :            :         } else {
    1647                 :          0 :                 type = conf->operation == RTE_FLOW_MODIFY_SET ?
    1648         [ #  # ]:          0 :                        MLX5_MODIFICATION_TYPE_COPY : MLX5_MODIFICATION_TYPE_ADD_FIELD;
    1649                 :            :                 /* For COPY fill the destination field (dcopy) without mask. */
    1650                 :          0 :                 mlx5_flow_field_id_to_modify_info(&conf->dst, dcopy, NULL,
    1651                 :          0 :                                                   conf->width, dev,
    1652                 :            :                                                   attr, error);
    1653                 :            :                 /* Then construct the source field (field) with mask. */
    1654                 :          0 :                 mlx5_flow_field_id_to_modify_info(&conf->src, field, mask,
    1655                 :          0 :                                                   conf->width, dev,
    1656                 :            :                                                   attr, error);
    1657                 :            :         }
    1658                 :          0 :         item.mask = &mask;
    1659                 :            :         memset(&dummy, 0, sizeof(dummy));
    1660                 :            :         resource = &dummy.resource;
    1661                 :          0 :         ret = flow_dv_convert_modify_action(&item, field, dcopy, resource, type, error);
    1662         [ #  # ]:          0 :         if (ret)
    1663                 :            :                 return ret;
    1664                 :            :         MLX5_ASSERT(resource->actions_num > 0);
    1665                 :            :         /*
    1666                 :            :          * If previous modify field action collide with this one, then insert NOP command.
    1667                 :            :          * This NOP command will not be a part of action's command range used to update commands
    1668                 :            :          * on rule creation.
    1669                 :            :          */
    1670         [ #  # ]:          0 :         if (flow_hw_should_insert_nop(mhdr, &resource->actions[0])) {
    1671                 :            :                 ret = flow_hw_mhdr_cmd_nop_append(mhdr);
    1672                 :            :                 if (ret)
    1673                 :          0 :                         return rte_flow_error_set(error, ret, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    1674                 :            :                                                   NULL, "too many modify field operations specified");
    1675                 :            :         }
    1676                 :          0 :         cmds_start = mhdr->mhdr_cmds_num;
    1677                 :            :         ret = flow_hw_converted_mhdr_cmds_append(mhdr, resource);
    1678         [ #  # ]:          0 :         if (ret)
    1679                 :          0 :                 return rte_flow_error_set(error, ret, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    1680                 :            :                                           NULL, "too many modify field operations specified");
    1681                 :            : 
    1682                 :          0 :         cmds_end = mhdr->mhdr_cmds_num;
    1683         [ #  # ]:          0 :         if (shared)
    1684                 :            :                 return 0;
    1685                 :            :         ret = __flow_hw_act_data_hdr_modify_append(priv, acts, RTE_FLOW_ACTION_TYPE_MODIFY_FIELD,
    1686                 :          0 :                                                    src_pos, mhdr->pos, conf,
    1687                 :            :                                                    cmds_start, cmds_end, shared,
    1688                 :            :                                                    field, dcopy, mask);
    1689                 :            :         if (ret)
    1690                 :          0 :                 return rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    1691                 :            :                                           NULL, "not enough memory to store modify field metadata");
    1692                 :            :         return 0;
    1693                 :            : }
    1694                 :            : 
    1695                 :            : static uint32_t
    1696                 :          0 : flow_hw_count_nop_modify_field(struct mlx5_hw_modify_header_action *mhdr)
    1697                 :            : {
    1698                 :            :         uint32_t i;
    1699                 :            :         uint32_t nops = 0;
    1700                 :            : 
    1701         [ #  # ]:          0 :         for (i = 0; i < mhdr->mhdr_cmds_num; ++i) {
    1702                 :          0 :                 struct mlx5_modification_cmd cmd = mhdr->mhdr_cmds[i];
    1703                 :            : 
    1704         [ #  # ]:          0 :                 cmd.data0 = rte_be_to_cpu_32(cmd.data0);
    1705         [ #  # ]:          0 :                 if (cmd.action_type == MLX5_MODIFICATION_TYPE_NOP)
    1706                 :          0 :                         ++nops;
    1707                 :            :         }
    1708                 :          0 :         return nops;
    1709                 :            : }
    1710                 :            : 
    1711                 :            : static int
    1712                 :          0 : flow_hw_validate_compiled_modify_field(struct rte_eth_dev *dev,
    1713                 :            :                                        const struct mlx5_flow_template_table_cfg *cfg,
    1714                 :            :                                        struct mlx5_hw_modify_header_action *mhdr,
    1715                 :            :                                        struct rte_flow_error *error)
    1716                 :            : {
    1717                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    1718                 :          0 :         struct mlx5_hca_attr *hca_attr = &priv->sh->cdev->config.hca_attr;
    1719                 :            : 
    1720                 :            :         /*
    1721                 :            :          * Header modify pattern length limitation is only valid for HWS groups, i.e. groups > 0.
    1722                 :            :          * In group 0, MODIFY_FIELD actions are handled with header modify actions
    1723                 :            :          * managed by rdma-core.
    1724                 :            :          */
    1725         [ #  # ]:          0 :         if (cfg->attr.flow_attr.group != 0 &&
    1726         [ #  # ]:          0 :             mhdr->mhdr_cmds_num > hca_attr->max_header_modify_pattern_length) {
    1727                 :          0 :                 uint32_t nops = flow_hw_count_nop_modify_field(mhdr);
    1728                 :            : 
    1729                 :          0 :                 DRV_LOG(ERR, "Too many modify header commands generated from "
    1730                 :            :                              "MODIFY_FIELD actions. "
    1731                 :            :                              "Generated HW commands = %u (amount of NOP commands = %u). "
    1732                 :            :                              "Maximum supported = %u.",
    1733                 :            :                              mhdr->mhdr_cmds_num, nops,
    1734                 :            :                              hca_attr->max_header_modify_pattern_length);
    1735                 :          0 :                 return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    1736                 :            :                                           "Number of MODIFY_FIELD actions exceeds maximum "
    1737                 :            :                                           "supported limit of actions");
    1738                 :            :         }
    1739                 :            :         return 0;
    1740                 :            : }
    1741                 :            : 
    1742                 :            : static int
    1743                 :          0 : flow_hw_represented_port_compile(struct rte_eth_dev *dev,
    1744                 :            :                                  const struct rte_flow_attr *attr,
    1745                 :            :                                  const struct rte_flow_action *action,
    1746                 :            :                                  const struct rte_flow_action *action_mask,
    1747                 :            :                                  struct mlx5_hw_actions *acts,
    1748                 :            :                                  uint16_t action_src, uint16_t action_dst,
    1749                 :            :                                  struct rte_flow_error *error)
    1750                 :            : {
    1751                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    1752                 :          0 :         const struct rte_flow_action_ethdev *v = action->conf;
    1753                 :          0 :         const struct rte_flow_action_ethdev *m = action_mask->conf;
    1754                 :            :         int ret;
    1755                 :            : 
    1756         [ #  # ]:          0 :         if (!attr->group)
    1757                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    1758                 :            :                                           RTE_FLOW_ERROR_TYPE_ATTR, NULL,
    1759                 :            :                                           "represented_port action cannot"
    1760                 :            :                                           " be used on group 0");
    1761         [ #  # ]:          0 :         if (!attr->transfer)
    1762                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    1763                 :            :                                           RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER,
    1764                 :            :                                           NULL,
    1765                 :            :                                           "represented_port action requires"
    1766                 :            :                                           " transfer attribute");
    1767         [ #  # ]:          0 :         if (attr->ingress || attr->egress)
    1768                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    1769                 :            :                                           RTE_FLOW_ERROR_TYPE_ATTR, NULL,
    1770                 :            :                                           "represented_port action cannot"
    1771                 :            :                                           " be used with direction attributes");
    1772         [ #  # ]:          0 :         if (!priv->master)
    1773                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    1774                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    1775                 :            :                                           "represented_port action must"
    1776                 :            :                                           " be used on proxy port");
    1777   [ #  #  #  # ]:          0 :         if (m && !!m->port_id) {
    1778                 :            :                 struct mlx5_priv *port_priv;
    1779                 :            : 
    1780         [ #  # ]:          0 :                 if (!v)
    1781                 :          0 :                         return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
    1782                 :            :                                                   action, "port index was not provided");
    1783                 :          0 :                 port_priv = mlx5_port_to_eswitch_info(v->port_id, false);
    1784         [ #  # ]:          0 :                 if (port_priv == NULL)
    1785                 :          0 :                         return rte_flow_error_set
    1786                 :            :                                         (error, EINVAL,
    1787                 :            :                                          RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    1788                 :            :                                          "port does not exist or unable to"
    1789                 :            :                                          " obtain E-Switch info for port");
    1790                 :            :                 MLX5_ASSERT(priv->hw_vport != NULL);
    1791         [ #  # ]:          0 :                 if (priv->hw_vport[v->port_id]) {
    1792                 :          0 :                         acts->rule_acts[action_dst].action =
    1793                 :            :                                         priv->hw_vport[v->port_id];
    1794                 :            :                 } else {
    1795                 :          0 :                         return rte_flow_error_set
    1796                 :            :                                         (error, EINVAL,
    1797                 :            :                                          RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    1798                 :            :                                          "cannot use represented_port action"
    1799                 :            :                                          " with this port");
    1800                 :            :                 }
    1801                 :            :         } else {
    1802                 :            :                 ret = __flow_hw_act_data_general_append
    1803                 :          0 :                                 (priv, acts, action->type,
    1804                 :            :                                  action_src, action_dst);
    1805                 :            :                 if (ret)
    1806                 :          0 :                         return rte_flow_error_set
    1807                 :            :                                         (error, ENOMEM,
    1808                 :            :                                          RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    1809                 :            :                                          "not enough memory to store"
    1810                 :            :                                          " vport action");
    1811                 :            :         }
    1812                 :            :         return 0;
    1813                 :            : }
    1814                 :            : 
    1815                 :            : static __rte_always_inline int
    1816                 :            : flow_hw_meter_compile(struct rte_eth_dev *dev,
    1817                 :            :                       const struct mlx5_flow_template_table_cfg *cfg,
    1818                 :            :                       uint16_t aso_mtr_pos,
    1819                 :            :                       uint16_t jump_pos,
    1820                 :            :                       const struct rte_flow_action *action,
    1821                 :            :                       struct mlx5_hw_actions *acts,
    1822                 :            :                       struct rte_flow_error *error)
    1823                 :            : {
    1824                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    1825                 :            :         struct mlx5_aso_mtr *aso_mtr;
    1826                 :            :         const struct rte_flow_action_meter *meter = action->conf;
    1827                 :          0 :         uint32_t group = cfg->attr.flow_attr.group;
    1828                 :            : 
    1829                 :          0 :         aso_mtr = mlx5_aso_meter_by_idx(priv, meter->mtr_id);
    1830                 :          0 :         acts->rule_acts[aso_mtr_pos].action = priv->mtr_bulk.action;
    1831                 :          0 :         acts->rule_acts[aso_mtr_pos].aso_meter.offset = aso_mtr->offset;
    1832                 :          0 :         acts->jump = flow_hw_jump_action_register
    1833                 :          0 :                 (dev, cfg, aso_mtr->fm.group, error);
    1834         [ #  # ]:          0 :         if (!acts->jump)
    1835                 :            :                 return -ENOMEM;
    1836                 :          0 :         acts->rule_acts[jump_pos].action = (!!group) ?
    1837         [ #  # ]:          0 :                                     acts->jump->hws_action :
    1838                 :            :                                     acts->jump->root_action;
    1839         [ #  # ]:          0 :         if (mlx5_aso_mtr_wait(priv, aso_mtr, true))
    1840                 :            :                 return -ENOMEM;
    1841                 :            :         return 0;
    1842                 :            : }
    1843                 :            : 
    1844                 :            : static __rte_always_inline int
    1845                 :            : flow_hw_cnt_compile(struct rte_eth_dev *dev, uint32_t  start_pos,
    1846                 :            :                       struct mlx5_hw_actions *acts)
    1847                 :            : {
    1848                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    1849                 :            :         uint32_t pos = start_pos;
    1850                 :            :         cnt_id_t cnt_id;
    1851                 :            :         int ret;
    1852                 :            : 
    1853                 :          0 :         ret = mlx5_hws_cnt_shared_get(priv->hws_cpool, &cnt_id, 0);
    1854                 :            :         if (ret != 0)
    1855                 :            :                 return ret;
    1856                 :          0 :         ret = mlx5_hws_cnt_pool_get_action_offset
    1857                 :            :                                 (priv->hws_cpool,
    1858                 :            :                                  cnt_id,
    1859                 :            :                                  &acts->rule_acts[pos].action,
    1860                 :            :                                  &acts->rule_acts[pos].counter.offset);
    1861                 :            :         if (ret != 0)
    1862                 :            :                 return ret;
    1863                 :          0 :         acts->cnt_id = cnt_id;
    1864                 :            :         return 0;
    1865                 :            : }
    1866                 :            : 
    1867                 :            : static __rte_always_inline bool
    1868                 :            : is_of_vlan_pcp_present(const struct rte_flow_action *actions)
    1869                 :            : {
    1870                 :            :         /*
    1871                 :            :          * Order of RTE VLAN push actions is
    1872                 :            :          * OF_PUSH_VLAN / OF_SET_VLAN_VID [ / OF_SET_VLAN_PCP ]
    1873                 :            :          */
    1874                 :          0 :         return actions[MLX5_HW_VLAN_PUSH_PCP_IDX].type ==
    1875                 :            :                 RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP;
    1876                 :            : }
    1877                 :            : 
    1878                 :            : static __rte_always_inline bool
    1879                 :            : is_template_masked_push_vlan(const struct rte_flow_action_of_push_vlan *mask)
    1880                 :            : {
    1881                 :            :         /*
    1882                 :            :          * In masked push VLAN template all RTE push actions are masked.
    1883                 :            :          */
    1884         [ #  # ]:          0 :         return mask && mask->ethertype != 0;
    1885                 :            : }
    1886                 :            : 
    1887                 :          0 : static rte_be32_t vlan_hdr_to_be32(const struct rte_flow_action *actions)
    1888                 :            : {
    1889                 :            : /*
    1890                 :            :  * OpenFlow Switch Specification defines 801.1q VID as 12+1 bits.
    1891                 :            :  */
    1892                 :            :         rte_be32_t type, vid, pcp;
    1893                 :            : #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
    1894                 :            :         rte_be32_t vid_lo, vid_hi;
    1895                 :            : #endif
    1896                 :            : 
    1897                 :          0 :         type = ((const struct rte_flow_action_of_push_vlan *)
    1898                 :          0 :                 actions[MLX5_HW_VLAN_PUSH_TYPE_IDX].conf)->ethertype;
    1899                 :          0 :         vid = ((const struct rte_flow_action_of_set_vlan_vid *)
    1900                 :          0 :                 actions[MLX5_HW_VLAN_PUSH_VID_IDX].conf)->vlan_vid;
    1901                 :            :         pcp = is_of_vlan_pcp_present(actions) ?
    1902                 :            :               ((const struct rte_flow_action_of_set_vlan_pcp *)
    1903   [ #  #  #  # ]:          0 :                       actions[MLX5_HW_VLAN_PUSH_PCP_IDX].conf)->vlan_pcp : 0;
    1904                 :            : #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
    1905                 :          0 :         vid_hi = vid & 0xff;
    1906                 :            :         vid_lo = vid >> 8;
    1907                 :          0 :         return (((vid_lo << 8) | (pcp << 5) | vid_hi) << 16) | type;
    1908                 :            : #else
    1909                 :            :         return (type << 16) | (pcp << 13) | vid;
    1910                 :            : #endif
    1911                 :            : }
    1912                 :            : 
    1913                 :            : static __rte_always_inline struct mlx5_aso_mtr *
    1914                 :            : flow_hw_meter_mark_alloc(struct rte_eth_dev *dev, uint32_t queue,
    1915                 :            :                          const struct rte_flow_action *action,
    1916                 :            :                          struct mlx5_hw_q_job *job, bool push,
    1917                 :            :                          struct rte_flow_error *error)
    1918                 :            : {
    1919                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    1920                 :          0 :         struct mlx5_aso_mtr_pool *pool = priv->hws_mpool;
    1921                 :          0 :         const struct rte_flow_action_meter_mark *meter_mark = action->conf;
    1922                 :            :         struct mlx5_aso_mtr *aso_mtr;
    1923                 :            :         struct mlx5_flow_meter_info *fm;
    1924                 :          0 :         uint32_t mtr_id = 0;
    1925                 :            :         uintptr_t handle = (uintptr_t)MLX5_INDIRECT_ACTION_TYPE_METER_MARK <<
    1926                 :            :                                         MLX5_INDIRECT_ACTION_TYPE_OFFSET;
    1927                 :            : 
    1928                 :          0 :         if (priv->shared_host) {
    1929                 :          0 :                 rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    1930                 :            :                                    "Meter mark actions can only be created on the host port");
    1931                 :            :                 return NULL;
    1932                 :            :         }
    1933   [ #  #  #  #  :          0 :         if (meter_mark->profile == NULL)
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    1934                 :            :                 return NULL;
    1935                 :          0 :         aso_mtr = mlx5_ipool_malloc(pool->idx_pool, &mtr_id);
    1936   [ #  #  #  #  :          0 :         if (!aso_mtr) {
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    1937                 :          0 :                 rte_flow_error_set(error, ENOMEM,
    1938                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    1939                 :            :                                    NULL,
    1940                 :            :                                    "failed to allocate aso meter entry");
    1941   [ #  #  #  #  :          0 :                 if (mtr_id)
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    1942                 :          0 :                         mlx5_ipool_free(pool->idx_pool, mtr_id);
    1943                 :            :                 return NULL;
    1944                 :            :         }
    1945                 :            :         /* Fill the flow meter parameters. */
    1946                 :          0 :         aso_mtr->type = ASO_METER_INDIRECT;
    1947                 :            :         fm = &aso_mtr->fm;
    1948                 :          0 :         fm->meter_id = mtr_id;
    1949                 :          0 :         fm->profile = (struct mlx5_flow_meter_profile *)(meter_mark->profile);
    1950                 :          0 :         fm->is_enable = meter_mark->state;
    1951                 :          0 :         fm->color_aware = meter_mark->color_mode;
    1952                 :          0 :         aso_mtr->pool = pool;
    1953         [ #  # ]:          0 :         aso_mtr->state = (queue == MLX5_HW_INV_QUEUE) ?
    1954                 :            :                           ASO_METER_WAIT : ASO_METER_WAIT_ASYNC;
    1955                 :          0 :         aso_mtr->offset = mtr_id - 1;
    1956   [ #  #  #  #  :          0 :         aso_mtr->init_color = fm->color_aware ? RTE_COLORS : RTE_COLOR_GREEN;
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    1957                 :          0 :         job->action = (void *)(handle | mtr_id);
    1958                 :            :         /* Update ASO flow meter by wqe. */
    1959   [ #  #  #  #  :          0 :         if (mlx5_aso_meter_update_by_wqe(priv, queue, aso_mtr,
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    1960                 :            :                                          &priv->mtr_bulk, job, push)) {
    1961                 :          0 :                 mlx5_ipool_free(pool->idx_pool, mtr_id);
    1962                 :            :                 return NULL;
    1963                 :            :         }
    1964                 :            :         /* Wait for ASO object completion. */
    1965   [ #  #  #  #  :          0 :         if (queue == MLX5_HW_INV_QUEUE &&
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    1966                 :          0 :             mlx5_aso_mtr_wait(priv, aso_mtr, true)) {
    1967                 :          0 :                 mlx5_ipool_free(pool->idx_pool, mtr_id);
    1968                 :            :                 return NULL;
    1969                 :            :         }
    1970                 :            :         return aso_mtr;
    1971                 :            : }
    1972                 :            : 
    1973                 :            : static __rte_always_inline int
    1974                 :            : flow_hw_meter_mark_compile(struct rte_eth_dev *dev,
    1975                 :            :                            uint16_t aso_mtr_pos,
    1976                 :            :                            const struct rte_flow_action *action,
    1977                 :            :                            struct mlx5dr_rule_action *acts,
    1978                 :            :                            uint32_t *index,
    1979                 :            :                            uint32_t queue,
    1980                 :            :                            struct rte_flow_error *error)
    1981                 :            : {
    1982                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    1983                 :          0 :         struct mlx5_aso_mtr_pool *pool = priv->hws_mpool;
    1984                 :            :         struct mlx5_aso_mtr *aso_mtr;
    1985                 :            :         struct mlx5_hw_q_job *job =
    1986                 :            :                 flow_hw_action_job_init(priv, queue, NULL, NULL, NULL,
    1987                 :            :                                         MLX5_HW_Q_JOB_TYPE_CREATE,
    1988                 :            :                                         MLX5_HW_INDIRECT_TYPE_LEGACY, NULL);
    1989                 :            : 
    1990                 :            :         if (!job)
    1991                 :            :                 return -1;
    1992                 :            :         aso_mtr = flow_hw_meter_mark_alloc(dev, queue, action, job,
    1993                 :            :                                            true, error);
    1994                 :            :         if (!aso_mtr) {
    1995                 :            :                 flow_hw_job_put(priv, job, queue);
    1996                 :            :                 return -1;
    1997                 :            :         }
    1998                 :            : 
    1999                 :            :         /* Compile METER_MARK action */
    2000                 :          0 :         acts[aso_mtr_pos].action = pool->action;
    2001                 :          0 :         acts[aso_mtr_pos].aso_meter.offset = aso_mtr->offset;
    2002                 :          0 :         *index = aso_mtr->fm.meter_id;
    2003                 :            :         return 0;
    2004                 :            : }
    2005                 :            : 
    2006                 :            : static int
    2007                 :          0 : flow_hw_translate_indirect_mirror(__rte_unused struct rte_eth_dev *dev,
    2008                 :            :                                   __rte_unused const struct mlx5_action_construct_data *act_data,
    2009                 :            :                                   const struct rte_flow_action *action,
    2010                 :            :                                   struct mlx5dr_rule_action *dr_rule)
    2011                 :            : {
    2012                 :          0 :         const struct rte_flow_action_indirect_list *list_conf = action->conf;
    2013                 :          0 :         const struct mlx5_mirror *mirror = (typeof(mirror))list_conf->handle;
    2014                 :            : 
    2015                 :          0 :         dr_rule->action = mirror->mirror_action;
    2016                 :          0 :         return 0;
    2017                 :            : }
    2018                 :            : 
    2019                 :            : /**
    2020                 :            :  * HWS mirror implemented as FW island.
    2021                 :            :  * The action does not support indirect list flow configuration.
    2022                 :            :  * If template handle was masked, use handle mirror action in flow rules.
    2023                 :            :  * Otherwise let flow rule specify mirror handle.
    2024                 :            :  */
    2025                 :            : static int
    2026                 :          0 : hws_table_tmpl_translate_indirect_mirror(struct rte_eth_dev *dev,
    2027                 :            :                                          const struct rte_flow_action *action,
    2028                 :            :                                          const struct rte_flow_action *mask,
    2029                 :            :                                          struct mlx5_hw_actions *acts,
    2030                 :            :                                          uint16_t action_src, uint16_t action_dst)
    2031                 :            : {
    2032                 :            :         int ret = 0;
    2033                 :          0 :         const struct rte_flow_action_indirect_list *mask_conf = mask->conf;
    2034                 :            : 
    2035   [ #  #  #  # ]:          0 :         if (mask_conf && mask_conf->handle) {
    2036                 :            :                 /**
    2037                 :            :                  * If mirror handle was masked, assign fixed DR5 mirror action.
    2038                 :            :                  */
    2039                 :            :                 flow_hw_translate_indirect_mirror(dev, NULL, action,
    2040                 :          0 :                                                   &acts->rule_acts[action_dst]);
    2041                 :            :         } else {
    2042                 :          0 :                 struct mlx5_priv *priv = dev->data->dev_private;
    2043                 :            :                 ret = flow_hw_act_data_indirect_list_append
    2044                 :            :                         (priv, acts, RTE_FLOW_ACTION_TYPE_INDIRECT_LIST,
    2045                 :            :                          action_src, action_dst,
    2046                 :            :                          flow_hw_translate_indirect_mirror);
    2047                 :            :         }
    2048                 :          0 :         return ret;
    2049                 :            : }
    2050                 :            : 
    2051                 :            : static int
    2052                 :          0 : flow_hw_reformat_action(__rte_unused struct rte_eth_dev *dev,
    2053                 :            :                         __rte_unused const struct mlx5_action_construct_data *data,
    2054                 :            :                         const struct rte_flow_action *action,
    2055                 :            :                         struct mlx5dr_rule_action *dr_rule)
    2056                 :            : {
    2057                 :          0 :         const struct rte_flow_action_indirect_list *indlst_conf = action->conf;
    2058                 :            : 
    2059                 :          0 :         dr_rule->action = ((struct mlx5_hw_encap_decap_action *)
    2060                 :          0 :                            (indlst_conf->handle))->action;
    2061         [ #  # ]:          0 :         if (!dr_rule->action)
    2062                 :          0 :                 return -EINVAL;
    2063                 :            :         return 0;
    2064                 :            : }
    2065                 :            : 
    2066                 :            : /**
    2067                 :            :  * Template conf must not be masked. If handle is masked, use the one in template,
    2068                 :            :  * otherwise update per flow rule.
    2069                 :            :  */
    2070                 :            : static int
    2071                 :          0 : hws_table_tmpl_translate_indirect_reformat(struct rte_eth_dev *dev,
    2072                 :            :                                            const struct rte_flow_action *action,
    2073                 :            :                                            const struct rte_flow_action *mask,
    2074                 :            :                                            struct mlx5_hw_actions *acts,
    2075                 :            :                                            uint16_t action_src, uint16_t action_dst)
    2076                 :            : {
    2077                 :            :         int ret = -1;
    2078                 :          0 :         const struct rte_flow_action_indirect_list *mask_conf = mask->conf;
    2079                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    2080                 :            : 
    2081   [ #  #  #  #  :          0 :         if (mask_conf && mask_conf->handle && !mask_conf->conf)
                   #  # ]
    2082                 :            :                 /**
    2083                 :            :                  * If handle was masked, assign fixed DR action.
    2084                 :            :                  */
    2085                 :            :                 ret = flow_hw_reformat_action(dev, NULL, action,
    2086         [ #  # ]:          0 :                                               &acts->rule_acts[action_dst]);
    2087   [ #  #  #  #  :          0 :         else if (mask_conf && !mask_conf->handle && !mask_conf->conf)
                   #  # ]
    2088                 :            :                 ret = flow_hw_act_data_indirect_list_append
    2089                 :            :                         (priv, acts, RTE_FLOW_ACTION_TYPE_INDIRECT_LIST,
    2090                 :            :                          action_src, action_dst, flow_hw_reformat_action);
    2091                 :          0 :         return ret;
    2092                 :            : }
    2093                 :            : 
    2094                 :            : static int
    2095                 :          0 : flow_dr_set_meter(struct mlx5_priv *priv,
    2096                 :            :                   struct mlx5dr_rule_action *dr_rule,
    2097                 :            :                   const struct rte_flow_action_indirect_list *action_conf)
    2098                 :            : {
    2099                 :          0 :         const struct mlx5_indlst_legacy *legacy_obj =
    2100                 :            :                 (typeof(legacy_obj))action_conf->handle;
    2101                 :          0 :         struct mlx5_aso_mtr_pool *mtr_pool = priv->hws_mpool;
    2102                 :          0 :         uint32_t act_idx = (uint32_t)(uintptr_t)legacy_obj->handle;
    2103                 :          0 :         uint32_t mtr_id = act_idx & (RTE_BIT32(MLX5_INDIRECT_ACTION_TYPE_OFFSET) - 1);
    2104                 :          0 :         struct mlx5_aso_mtr *aso_mtr = mlx5_ipool_get(mtr_pool->idx_pool, mtr_id);
    2105                 :            : 
    2106         [ #  # ]:          0 :         if (!aso_mtr)
    2107                 :            :                 return -EINVAL;
    2108                 :          0 :         dr_rule->action = mtr_pool->action;
    2109                 :          0 :         dr_rule->aso_meter.offset = aso_mtr->offset;
    2110                 :          0 :         return 0;
    2111                 :            : }
    2112                 :            : 
    2113                 :            : __rte_always_inline static void
    2114                 :            : flow_dr_mtr_flow_color(struct mlx5dr_rule_action *dr_rule, enum rte_color init_color)
    2115                 :            : {
    2116                 :          0 :         dr_rule->aso_meter.init_color =
    2117                 :          0 :                 (enum mlx5dr_action_aso_meter_color)rte_col_2_mlx5_col(init_color);
    2118                 :          0 : }
    2119                 :            : 
    2120                 :            : static int
    2121                 :          0 : flow_hw_translate_indirect_meter(struct rte_eth_dev *dev,
    2122                 :            :                                  const struct mlx5_action_construct_data *act_data,
    2123                 :            :                                  const struct rte_flow_action *action,
    2124                 :            :                                  struct mlx5dr_rule_action *dr_rule)
    2125                 :            : {
    2126                 :            :         int ret;
    2127                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    2128                 :          0 :         const struct rte_flow_action_indirect_list *action_conf = action->conf;
    2129                 :          0 :         const struct rte_flow_indirect_update_flow_meter_mark **flow_conf =
    2130                 :            :                 (typeof(flow_conf))action_conf->conf;
    2131                 :            : 
    2132                 :          0 :         ret = flow_dr_set_meter(priv, dr_rule, action_conf);
    2133         [ #  # ]:          0 :         if (ret)
    2134                 :            :                 return ret;
    2135         [ #  # ]:          0 :         if (!act_data->shared_meter.conf_masked) {
    2136   [ #  #  #  #  :          0 :                 if (flow_conf && flow_conf[0] && flow_conf[0]->init_color < RTE_COLORS)
                   #  # ]
    2137                 :            :                         flow_dr_mtr_flow_color(dr_rule, flow_conf[0]->init_color);
    2138                 :            :         }
    2139                 :            :         return 0;
    2140                 :            : }
    2141                 :            : 
    2142                 :            : static int
    2143                 :          0 : hws_table_tmpl_translate_indirect_meter(struct rte_eth_dev *dev,
    2144                 :            :                                         const struct rte_flow_action *action,
    2145                 :            :                                         const struct rte_flow_action *mask,
    2146                 :            :                                         struct mlx5_hw_actions *acts,
    2147                 :            :                                         uint16_t action_src, uint16_t action_dst)
    2148                 :            : {
    2149                 :            :         int ret;
    2150                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    2151                 :          0 :         const struct rte_flow_action_indirect_list *action_conf = action->conf;
    2152                 :          0 :         const struct rte_flow_action_indirect_list *mask_conf = mask->conf;
    2153   [ #  #  #  # ]:          0 :         bool is_handle_masked = mask_conf && mask_conf->handle;
    2154   [ #  #  #  #  :          0 :         bool is_conf_masked = mask_conf && mask_conf->conf && mask_conf->conf[0];
                   #  # ]
    2155                 :          0 :         struct mlx5dr_rule_action *dr_rule = &acts->rule_acts[action_dst];
    2156                 :            : 
    2157         [ #  # ]:          0 :         if (is_handle_masked) {
    2158                 :          0 :                 ret = flow_dr_set_meter(priv, dr_rule, action->conf);
    2159         [ #  # ]:          0 :                 if (ret)
    2160                 :            :                         return ret;
    2161                 :            :         }
    2162         [ #  # ]:          0 :         if (is_conf_masked) {
    2163                 :            :                 const struct
    2164                 :          0 :                         rte_flow_indirect_update_flow_meter_mark **flow_conf =
    2165                 :            :                         (typeof(flow_conf))action_conf->conf;
    2166                 :            :                 flow_dr_mtr_flow_color(dr_rule,
    2167         [ #  # ]:          0 :                                        flow_conf[0]->init_color);
    2168                 :            :         }
    2169         [ #  # ]:          0 :         if (!is_handle_masked || !is_conf_masked) {
    2170                 :            :                 struct mlx5_action_construct_data *act_data;
    2171                 :            : 
    2172                 :            :                 ret = flow_hw_act_data_indirect_list_append
    2173                 :            :                         (priv, acts, RTE_FLOW_ACTION_TYPE_INDIRECT_LIST,
    2174                 :            :                          action_src, action_dst, flow_hw_translate_indirect_meter);
    2175                 :            :                 if (ret)
    2176                 :          0 :                         return ret;
    2177                 :            :                 act_data = LIST_FIRST(&acts->act_list);
    2178                 :          0 :                 act_data->shared_meter.conf_masked = is_conf_masked;
    2179                 :            :         }
    2180                 :            :         return 0;
    2181                 :            : }
    2182                 :            : 
    2183                 :            : static int
    2184                 :            : hws_table_tmpl_translate_indirect_legacy(struct rte_eth_dev *dev,
    2185                 :            :                                          const struct rte_flow_action *action,
    2186                 :            :                                          const struct rte_flow_action *mask,
    2187                 :            :                                          struct mlx5_hw_actions *acts,
    2188                 :            :                                          uint16_t action_src, uint16_t action_dst)
    2189                 :            : {
    2190                 :            :         int ret;
    2191                 :            :         const struct rte_flow_action_indirect_list *indlst_conf = action->conf;
    2192                 :            :         struct mlx5_indlst_legacy *indlst_obj = (typeof(indlst_obj))indlst_conf->handle;
    2193                 :          0 :         uint32_t act_idx = (uint32_t)(uintptr_t)indlst_obj->handle;
    2194                 :          0 :         uint32_t type = act_idx >> MLX5_INDIRECT_ACTION_TYPE_OFFSET;
    2195                 :            : 
    2196                 :          0 :         switch (type) {
    2197                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_METER_MARK:
    2198                 :          0 :                 ret = hws_table_tmpl_translate_indirect_meter(dev, action, mask,
    2199                 :            :                                                               acts, action_src,
    2200                 :            :                                                               action_dst);
    2201                 :          0 :                 break;
    2202                 :            :         default:
    2203                 :            :                 ret = -EINVAL;
    2204                 :            :                 break;
    2205                 :            :         }
    2206                 :            :         return ret;
    2207                 :            : }
    2208                 :            : 
    2209                 :            : /*
    2210                 :            :  * template .. indirect_list handle Ht conf Ct ..
    2211                 :            :  * mask     .. indirect_list handle Hm conf Cm ..
    2212                 :            :  *
    2213                 :            :  * PMD requires Ht != 0 to resolve handle type.
    2214                 :            :  * If Ht was masked (Hm != 0) DR5 action will be set according to Ht and will
    2215                 :            :  * not change. Otherwise, DR5 action will be resolved during flow rule build.
    2216                 :            :  * If Ct was masked (Cm != 0), table template processing updates base
    2217                 :            :  * indirect action configuration with Ct parameters.
    2218                 :            :  */
    2219                 :            : static int
    2220                 :          0 : table_template_translate_indirect_list(struct rte_eth_dev *dev,
    2221                 :            :                                        const struct rte_flow_action *action,
    2222                 :            :                                        const struct rte_flow_action *mask,
    2223                 :            :                                        struct mlx5_hw_actions *acts,
    2224                 :            :                                        uint16_t action_src, uint16_t action_dst)
    2225                 :            : {
    2226                 :            :         int ret = 0;
    2227                 :            :         enum mlx5_indirect_list_type type;
    2228                 :          0 :         const struct rte_flow_action_indirect_list *list_conf = action->conf;
    2229                 :            : 
    2230   [ #  #  #  # ]:          0 :         if (!list_conf || !list_conf->handle)
    2231                 :            :                 return -EINVAL;
    2232                 :            :         type = mlx5_get_indirect_list_type(list_conf->handle);
    2233   [ #  #  #  # ]:          0 :         switch (type) {
    2234                 :          0 :         case MLX5_INDIRECT_ACTION_LIST_TYPE_LEGACY:
    2235         [ #  # ]:          0 :                 ret = hws_table_tmpl_translate_indirect_legacy(dev, action, mask,
    2236                 :            :                                                                acts, action_src,
    2237                 :            :                                                                action_dst);
    2238                 :            :                 break;
    2239                 :          0 :         case MLX5_INDIRECT_ACTION_LIST_TYPE_MIRROR:
    2240                 :          0 :                 ret = hws_table_tmpl_translate_indirect_mirror(dev, action, mask,
    2241                 :            :                                                                acts, action_src,
    2242                 :            :                                                                action_dst);
    2243                 :          0 :                 break;
    2244                 :          0 :         case MLX5_INDIRECT_ACTION_LIST_TYPE_REFORMAT:
    2245         [ #  # ]:          0 :                 if (list_conf->conf)
    2246                 :            :                         return -EINVAL;
    2247                 :          0 :                 ret = hws_table_tmpl_translate_indirect_reformat(dev, action, mask,
    2248                 :            :                                                                  acts, action_src,
    2249                 :            :                                                                  action_dst);
    2250                 :          0 :                 break;
    2251                 :            :         default:
    2252                 :            :                 return -EINVAL;
    2253                 :            :         }
    2254                 :            :         return ret;
    2255                 :            : }
    2256                 :            : 
    2257                 :            : static void
    2258                 :            : mlx5_set_reformat_header(struct mlx5dr_action_reformat_header *hdr,
    2259                 :            :                          uint8_t *encap_data,
    2260                 :            :                          size_t data_size)
    2261                 :            : {
    2262                 :          0 :         hdr->sz = data_size;
    2263                 :          0 :         hdr->data = encap_data;
    2264                 :            : }
    2265                 :            : 
    2266                 :            : static int
    2267         [ #  # ]:          0 : mlx5_tbl_translate_reformat(struct mlx5_priv *priv,
    2268                 :            :                             struct mlx5_hw_actions *acts,
    2269                 :            :                             struct rte_flow_actions_template *at,
    2270                 :            :                             const struct rte_flow_item *enc_item,
    2271                 :            :                             const struct rte_flow_item *enc_item_m,
    2272                 :            :                             uint8_t *encap_data, uint8_t *encap_data_m,
    2273                 :            :                             struct mlx5_tbl_multi_pattern_ctx *mp_ctx,
    2274                 :            :                             size_t data_size, uint16_t reformat_src,
    2275                 :            :                             enum mlx5dr_action_type refmt_type,
    2276                 :            :                             struct rte_flow_error *error)
    2277                 :            : {
    2278                 :            :         int mp_reformat_ix = mlx5_multi_pattern_reformat_to_index(refmt_type);
    2279                 :            :         struct mlx5dr_action_reformat_header hdr;
    2280                 :            :         uint8_t buf[MLX5_ENCAP_MAX_LEN];
    2281                 :            :         bool shared_rfmt = false;
    2282                 :            :         int ret;
    2283                 :            : 
    2284                 :            :         MLX5_ASSERT(at->reformat_off != UINT16_MAX);
    2285         [ #  # ]:          0 :         if (enc_item) {
    2286                 :            :                 MLX5_ASSERT(!encap_data);
    2287                 :          0 :                 ret = flow_dv_convert_encap_data(enc_item, buf, &data_size, error);
    2288         [ #  # ]:          0 :                 if (ret)
    2289                 :            :                         return ret;
    2290                 :            :                 encap_data = buf;
    2291         [ #  # ]:          0 :                 if (enc_item_m)
    2292                 :            :                         shared_rfmt = true;
    2293         [ #  # ]:          0 :         } else if (encap_data && encap_data_m) {
    2294                 :            :                 shared_rfmt = true;
    2295                 :            :         }
    2296                 :          0 :         acts->encap_decap = mlx5_malloc(MLX5_MEM_ZERO,
    2297                 :            :                                         sizeof(*acts->encap_decap) + data_size,
    2298                 :            :                                         0, SOCKET_ID_ANY);
    2299         [ #  # ]:          0 :         if (!acts->encap_decap)
    2300                 :          0 :                 return rte_flow_error_set(error, ENOMEM,
    2301                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    2302                 :            :                                           NULL, "no memory for reformat context");
    2303                 :          0 :         acts->encap_decap_pos = at->reformat_off;
    2304                 :          0 :         acts->encap_decap->data_size = data_size;
    2305                 :          0 :         acts->encap_decap->action_type = refmt_type;
    2306         [ #  # ]:          0 :         if (shared_rfmt || mp_reformat_ix < 0) {
    2307                 :            :                 uint16_t reformat_ix = at->reformat_off;
    2308                 :            :                 /*
    2309                 :            :                  * This copy is only needed in non template mode.
    2310                 :            :                  * In order to create the action later.
    2311                 :            :                  */
    2312                 :          0 :                 memcpy(acts->encap_decap->data, encap_data, data_size);
    2313                 :          0 :                 acts->rule_acts[reformat_ix].reformat.data = acts->encap_decap->data;
    2314                 :          0 :                 acts->rule_acts[reformat_ix].reformat.offset = 0;
    2315                 :          0 :                 acts->encap_decap->shared = true;
    2316                 :            :         } else {
    2317                 :            :                 uint32_t ix;
    2318                 :          0 :                 typeof(mp_ctx->reformat[0]) *reformat = mp_ctx->reformat +
    2319                 :            :                                                         mp_reformat_ix;
    2320                 :            :                 mlx5_set_reformat_header(&hdr, encap_data, data_size);
    2321                 :          0 :                 ix = reformat->elements_num++;
    2322                 :          0 :                 reformat->reformat_hdr[ix] = hdr;
    2323                 :          0 :                 acts->rule_acts[at->reformat_off].reformat.hdr_idx = ix;
    2324                 :          0 :                 acts->encap_decap->multi_pattern = 1;
    2325                 :          0 :                 ret = __flow_hw_act_data_encap_append
    2326                 :          0 :                         (priv, acts, (at->actions + reformat_src)->type,
    2327                 :            :                          reformat_src, at->reformat_off, data_size);
    2328                 :            :                 if (ret)
    2329                 :          0 :                         return -rte_errno;
    2330                 :            :                 mlx5_multi_pattern_activate(mp_ctx);
    2331                 :            :         }
    2332                 :            :         return 0;
    2333                 :            : }
    2334                 :            : 
    2335                 :            : static int
    2336         [ #  # ]:          0 : mlx5_tbl_create_reformat_action(struct mlx5_priv *priv,
    2337                 :            :                                 const struct rte_flow_template_table_attr *table_attr,
    2338                 :            :                                 struct mlx5_hw_actions *acts,
    2339                 :            :                                 struct rte_flow_actions_template *at,
    2340                 :            :                                 uint8_t *encap_data,
    2341                 :            :                                 size_t data_size,
    2342                 :            :                                 enum mlx5dr_action_type refmt_type)
    2343                 :            : {
    2344                 :            :         const struct rte_flow_attr *attr = &table_attr->flow_attr;
    2345                 :            :         enum mlx5dr_table_type tbl_type = get_mlx5dr_table_type(attr);
    2346                 :            :         struct mlx5dr_action_reformat_header hdr;
    2347                 :            : 
    2348                 :            :         mlx5_set_reformat_header(&hdr, encap_data, data_size);
    2349                 :          0 :         uint16_t reformat_ix = at->reformat_off;
    2350                 :          0 :         uint32_t flags = mlx5_hw_act_flag[!!attr->group][tbl_type] |
    2351                 :            :                                 MLX5DR_ACTION_FLAG_SHARED;
    2352                 :            : 
    2353                 :          0 :         acts->encap_decap->action = mlx5dr_action_create_reformat(priv->dr_ctx, refmt_type,
    2354                 :            :                                                            1, &hdr, 0, flags);
    2355         [ #  # ]:          0 :         if (!acts->encap_decap->action)
    2356                 :          0 :                 return -rte_errno;
    2357                 :          0 :         acts->rule_acts[reformat_ix].action = acts->encap_decap->action;
    2358                 :          0 :         return 0;
    2359                 :            : }
    2360                 :            : 
    2361                 :            : static int
    2362                 :          0 : mlx5_tbl_translate_modify_header(struct rte_eth_dev *dev,
    2363                 :            :                                  const struct mlx5_flow_template_table_cfg *cfg,
    2364                 :            :                                  struct mlx5_hw_actions *acts,
    2365                 :            :                                  struct mlx5_tbl_multi_pattern_ctx *mp_ctx,
    2366                 :            :                                  struct mlx5_hw_modify_header_action *mhdr,
    2367                 :            :                                  struct rte_flow_error *error)
    2368                 :            : {
    2369                 :          0 :         uint16_t mhdr_ix = mhdr->pos;
    2370                 :            :         struct mlx5dr_action_mh_pattern pattern = {
    2371                 :          0 :                 .sz = sizeof(struct mlx5_modification_cmd) * mhdr->mhdr_cmds_num
    2372                 :            :         };
    2373                 :            : 
    2374         [ #  # ]:          0 :         if (flow_hw_validate_compiled_modify_field(dev, cfg, mhdr, error)) {
    2375                 :            :                 __flow_hw_action_template_destroy(dev, acts);
    2376                 :          0 :                 return -rte_errno;
    2377                 :            :         }
    2378                 :          0 :         acts->mhdr = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*acts->mhdr),
    2379                 :            :                                  0, SOCKET_ID_ANY);
    2380         [ #  # ]:          0 :         if (!acts->mhdr)
    2381                 :          0 :                 return rte_flow_error_set(error, ENOMEM,
    2382                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    2383                 :            :                                           NULL, "translate modify_header: no memory for modify header context");
    2384                 :            :         rte_memcpy(acts->mhdr, mhdr, sizeof(*mhdr));
    2385         [ #  # ]:          0 :         if (!mhdr->shared) {
    2386                 :          0 :                 pattern.data = (__be64 *)acts->mhdr->mhdr_cmds;
    2387                 :            :                 typeof(mp_ctx->mh) *mh = &mp_ctx->mh;
    2388                 :          0 :                 uint32_t idx = mh->elements_num;
    2389                 :          0 :                 mh->pattern[mh->elements_num++] = pattern;
    2390                 :          0 :                 acts->mhdr->multi_pattern = 1;
    2391                 :          0 :                 acts->rule_acts[mhdr_ix].modify_header.pattern_idx = idx;
    2392                 :            :                 mlx5_multi_pattern_activate(mp_ctx);
    2393                 :            :         }
    2394                 :            :         return 0;
    2395                 :            : }
    2396                 :            : 
    2397                 :            : static int
    2398                 :          0 : mlx5_tbl_ensure_shared_modify_header(struct rte_eth_dev *dev,
    2399                 :            :                                      const struct mlx5_flow_template_table_cfg *cfg,
    2400                 :            :                                      struct mlx5_hw_actions *acts,
    2401                 :            :                                      struct rte_flow_error *error)
    2402                 :            : {
    2403         [ #  # ]:          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    2404                 :            :         const struct rte_flow_template_table_attr *table_attr = &cfg->attr;
    2405                 :            :         const struct rte_flow_attr *attr = &table_attr->flow_attr;
    2406                 :            :         enum mlx5dr_table_type tbl_type = get_mlx5dr_table_type(attr);
    2407                 :          0 :         struct mlx5dr_action_mh_pattern pattern = {
    2408                 :          0 :                 .sz = sizeof(struct mlx5_modification_cmd) * acts->mhdr->mhdr_cmds_num
    2409                 :            :         };
    2410                 :          0 :         uint16_t mhdr_ix = acts->mhdr->pos;
    2411                 :          0 :         uint32_t flags = mlx5_hw_act_flag[!!attr->group][tbl_type] | MLX5DR_ACTION_FLAG_SHARED;
    2412                 :            : 
    2413                 :          0 :         pattern.data = (__be64 *)acts->mhdr->mhdr_cmds;
    2414                 :          0 :         acts->mhdr->action = mlx5dr_action_create_modify_header(priv->dr_ctx, 1,
    2415                 :            :                                                                 &pattern, 0, flags);
    2416         [ #  # ]:          0 :         if (!acts->mhdr->action)
    2417                 :          0 :                 return rte_flow_error_set(error, rte_errno,
    2418                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    2419                 :            :                                           "translate modify_header: failed to create DR action");
    2420                 :          0 :         acts->rule_acts[mhdr_ix].action = acts->mhdr->action;
    2421                 :          0 :         return 0;
    2422                 :            : }
    2423                 :            : 
    2424                 :            : static int
    2425                 :          0 : mlx5_create_ipv6_ext_reformat(struct rte_eth_dev *dev,
    2426                 :            :                               const struct mlx5_flow_template_table_cfg *cfg,
    2427                 :            :                               struct mlx5_hw_actions *acts,
    2428                 :            :                               struct rte_flow_actions_template *at,
    2429                 :            :                               uint8_t *push_data, uint8_t *push_data_m,
    2430                 :            :                               size_t push_size, uint16_t recom_src,
    2431                 :            :                               enum mlx5dr_action_type recom_type)
    2432                 :            : {
    2433         [ #  # ]:          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    2434                 :            :         const struct rte_flow_template_table_attr *table_attr = &cfg->attr;
    2435                 :            :         const struct rte_flow_attr *attr = &table_attr->flow_attr;
    2436                 :            :         enum mlx5dr_table_type type = get_mlx5dr_table_type(attr);
    2437                 :            :         struct mlx5_action_construct_data *act_data;
    2438                 :          0 :         struct mlx5dr_action_reformat_header hdr = {0};
    2439                 :            :         uint32_t flag, bulk = 0;
    2440                 :            : 
    2441                 :          0 :         flag = mlx5_hw_act_flag[!!attr->group][type];
    2442                 :          0 :         acts->push_remove = mlx5_malloc(MLX5_MEM_ZERO,
    2443                 :            :                                         sizeof(*acts->push_remove) + push_size,
    2444                 :            :                                         0, SOCKET_ID_ANY);
    2445         [ #  # ]:          0 :         if (!acts->push_remove)
    2446                 :            :                 return -ENOMEM;
    2447                 :            : 
    2448      [ #  #  # ]:          0 :         switch (recom_type) {
    2449                 :          0 :         case MLX5DR_ACTION_TYP_PUSH_IPV6_ROUTE_EXT:
    2450         [ #  # ]:          0 :                 if (!push_data || !push_size)
    2451                 :          0 :                         goto err1;
    2452         [ #  # ]:          0 :                 if (!push_data_m) {
    2453         [ #  # ]:          0 :                         bulk = rte_log2_u32(table_attr->nb_flows);
    2454                 :            :                 } else {
    2455                 :          0 :                         flag |= MLX5DR_ACTION_FLAG_SHARED;
    2456                 :          0 :                         acts->push_remove->shared = 1;
    2457                 :            :                 }
    2458                 :          0 :                 acts->push_remove->data_size = push_size;
    2459                 :          0 :                 memcpy(acts->push_remove->data, push_data, push_size);
    2460                 :          0 :                 hdr.data = push_data;
    2461                 :          0 :                 hdr.sz = push_size;
    2462                 :          0 :                 break;
    2463                 :          0 :         case MLX5DR_ACTION_TYP_POP_IPV6_ROUTE_EXT:
    2464                 :          0 :                 flag |= MLX5DR_ACTION_FLAG_SHARED;
    2465                 :          0 :                 acts->push_remove->shared = 1;
    2466                 :          0 :                 break;
    2467                 :            :         default:
    2468                 :            :                 break;
    2469                 :            :         }
    2470                 :            : 
    2471                 :          0 :         acts->push_remove->action =
    2472                 :          0 :                 mlx5dr_action_create_reformat_ipv6_ext(priv->dr_ctx,
    2473                 :            :                                 recom_type, &hdr, bulk, flag);
    2474         [ #  # ]:          0 :         if (!acts->push_remove->action)
    2475                 :          0 :                 goto err1;
    2476                 :          0 :         acts->rule_acts[at->recom_off].action = acts->push_remove->action;
    2477                 :          0 :         acts->rule_acts[at->recom_off].ipv6_ext.header = acts->push_remove->data;
    2478                 :          0 :         acts->rule_acts[at->recom_off].ipv6_ext.offset = 0;
    2479                 :          0 :         acts->push_remove_pos = at->recom_off;
    2480         [ #  # ]:          0 :         if (!acts->push_remove->shared) {
    2481                 :          0 :                 act_data = __flow_hw_act_data_push_append(dev, acts,
    2482                 :            :                                 RTE_FLOW_ACTION_TYPE_IPV6_EXT_PUSH,
    2483                 :            :                                 recom_src, at->recom_off, push_size);
    2484                 :            :                 if (!act_data)
    2485                 :          0 :                         goto err;
    2486                 :            :         }
    2487                 :            :         return 0;
    2488                 :            : err:
    2489         [ #  # ]:          0 :         if (acts->push_remove->action)
    2490                 :          0 :                 mlx5dr_action_destroy(acts->push_remove->action);
    2491                 :          0 : err1:
    2492         [ #  # ]:          0 :         if (acts->push_remove) {
    2493                 :          0 :                 mlx5_free(acts->push_remove);
    2494                 :          0 :                 acts->push_remove = NULL;
    2495                 :            :         }
    2496                 :            :         return -EINVAL;
    2497                 :            : }
    2498                 :            : 
    2499                 :            : /**
    2500                 :            :  * Translate rte_flow actions to DR action.
    2501                 :            :  *
    2502                 :            :  * As the action template has already indicated the actions. Translate
    2503                 :            :  * the rte_flow actions to DR action if possbile. So in flow create
    2504                 :            :  * stage we will save cycles from handing the actions' organizing.
    2505                 :            :  * For the actions with limited information, need to add these to a
    2506                 :            :  * list.
    2507                 :            :  *
    2508                 :            :  * @param[in] dev
    2509                 :            :  *   Pointer to the rte_eth_dev structure.
    2510                 :            :  * @param[in] cfg
    2511                 :            :  *   Pointer to the table configuration.
    2512                 :            :  * @param[in/out] acts
    2513                 :            :  *   Pointer to the template HW steering DR actions.
    2514                 :            :  * @param[in] at
    2515                 :            :  *   Action template.
    2516                 :            :  * @param[in] nt_mode
    2517                 :            :  *   Non template rule translate.
    2518                 :            :  * @param[out] error
    2519                 :            :  *   Pointer to error structure.
    2520                 :            :  *
    2521                 :            :  * @return
    2522                 :            :  *   0 on success, a negative errno otherwise and rte_errno is set.
    2523                 :            :  */
    2524                 :            : static int
    2525                 :          0 : __flow_hw_translate_actions_template(struct rte_eth_dev *dev,
    2526                 :            :                                      const struct mlx5_flow_template_table_cfg *cfg,
    2527                 :            :                                      struct mlx5_hw_actions *acts,
    2528                 :            :                                      struct rte_flow_actions_template *at,
    2529                 :            :                                      struct mlx5_tbl_multi_pattern_ctx *mp_ctx,
    2530                 :            :                                      bool nt_mode,
    2531                 :            :                                      struct rte_flow_error *error)
    2532                 :            : {
    2533                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    2534                 :          0 :         const struct rte_flow_template_table_attr *table_attr = &cfg->attr;
    2535                 :          0 :         struct mlx5_hca_flex_attr *hca_attr = &priv->sh->cdev->config.hca_attr.flex;
    2536                 :          0 :         const struct rte_flow_attr *attr = &table_attr->flow_attr;
    2537                 :          0 :         struct rte_flow_action *actions = at->actions;
    2538                 :          0 :         struct rte_flow_action *masks = at->masks;
    2539                 :            :         enum mlx5dr_action_type refmt_type = MLX5DR_ACTION_TYP_LAST;
    2540                 :            :         enum mlx5dr_action_type recom_type = MLX5DR_ACTION_TYP_LAST;
    2541                 :            :         const struct rte_flow_action_raw_encap *raw_encap_data;
    2542                 :            :         const struct rte_flow_action_ipv6_ext_push *ipv6_ext_data;
    2543                 :            :         const struct rte_flow_item *enc_item = NULL, *enc_item_m = NULL;
    2544                 :            :         uint16_t reformat_src = 0, recom_src = 0;
    2545                 :            :         uint8_t *encap_data = NULL, *encap_data_m = NULL;
    2546                 :            :         uint8_t *push_data = NULL, *push_data_m = NULL;
    2547                 :            :         size_t data_size = 0, push_size = 0;
    2548                 :            :         struct mlx5_hw_modify_header_action mhdr = { 0 };
    2549                 :            :         bool actions_end = false;
    2550                 :            :         uint32_t type;
    2551                 :            :         bool reformat_used = false;
    2552                 :            :         bool recom_used = false;
    2553                 :            :         unsigned int of_vlan_offset;
    2554                 :            :         uint16_t jump_pos;
    2555                 :            :         uint32_t ct_idx;
    2556                 :            :         int ret, err;
    2557         [ #  # ]:          0 :         uint32_t target_grp = 0;
    2558                 :            :         int table_type;
    2559                 :            : 
    2560                 :            :         flow_hw_modify_field_init(&mhdr, at);
    2561         [ #  # ]:          0 :         if (attr->transfer)
    2562                 :            :                 type = MLX5DR_TABLE_TYPE_FDB;
    2563         [ #  # ]:          0 :         else if (attr->egress)
    2564                 :            :                 type = MLX5DR_TABLE_TYPE_NIC_TX;
    2565                 :            :         else
    2566                 :            :                 type = MLX5DR_TABLE_TYPE_NIC_RX;
    2567         [ #  # ]:          0 :         for (; !actions_end; actions++, masks++) {
    2568                 :          0 :                 uint64_t pos = actions - at->actions;
    2569                 :          0 :                 uint16_t src_pos = pos - at->src_off[pos];
    2570                 :          0 :                 uint16_t dr_pos = at->dr_off[pos];
    2571                 :            : 
    2572   [ #  #  #  #  :          0 :                 switch ((int)actions->type) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    2573                 :          0 :                 case RTE_FLOW_ACTION_TYPE_INDIRECT_LIST:
    2574         [ #  # ]:          0 :                         if (!attr->group) {
    2575                 :          0 :                                 DRV_LOG(ERR, "Indirect action is not supported in root table.");
    2576                 :          0 :                                 goto err;
    2577                 :            :                         }
    2578                 :          0 :                         ret = table_template_translate_indirect_list
    2579                 :            :                                 (dev, actions, masks, acts, src_pos, dr_pos);
    2580         [ #  # ]:          0 :                         if (ret)
    2581                 :          0 :                                 goto err;
    2582                 :            :                         break;
    2583                 :          0 :                 case RTE_FLOW_ACTION_TYPE_INDIRECT:
    2584         [ #  # ]:          0 :                         if (!attr->group) {
    2585                 :          0 :                                 DRV_LOG(ERR, "Indirect action is not supported in root table.");
    2586                 :          0 :                                 goto err;
    2587                 :            :                         }
    2588   [ #  #  #  # ]:          0 :                         if (actions->conf && masks->conf) {
    2589   [ #  #  #  #  :          0 :                                 if (flow_hw_shared_action_translate
                #  #  # ]
    2590                 :            :                                 (dev, actions, acts, src_pos, dr_pos))
    2591                 :          0 :                                         goto err;
    2592                 :          0 :                         } else if (__flow_hw_act_data_indirect_append
    2593                 :            :                                         (priv, acts, RTE_FLOW_ACTION_TYPE_INDIRECT,
    2594                 :            :                                          masks->type, src_pos, dr_pos)){
    2595                 :          0 :                                 goto err;
    2596                 :            :                         }
    2597                 :            :                         break;
    2598                 :            :                 case RTE_FLOW_ACTION_TYPE_VOID:
    2599                 :            :                         break;
    2600                 :          0 :                 case RTE_FLOW_ACTION_TYPE_DROP:
    2601                 :          0 :                         acts->rule_acts[dr_pos].action =
    2602                 :          0 :                                 priv->hw_drop[!!attr->group];
    2603                 :          0 :                         break;
    2604                 :          0 :                 case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR:
    2605         [ #  # ]:          0 :                         if (!attr->group) {
    2606                 :          0 :                                 DRV_LOG(ERR, "Port representor is not supported in root table.");
    2607                 :          0 :                                 goto err;
    2608                 :            :                         }
    2609                 :          0 :                         acts->rule_acts[dr_pos].action = priv->hw_def_miss;
    2610                 :          0 :                         break;
    2611                 :          0 :                 case RTE_FLOW_ACTION_TYPE_FLAG:
    2612                 :          0 :                         acts->mark = true;
    2613                 :          0 :                         acts->rule_acts[dr_pos].tag.value =
    2614                 :            :                                 mlx5_flow_mark_set(MLX5_FLOW_MARK_DEFAULT);
    2615                 :          0 :                         acts->rule_acts[dr_pos].action =
    2616                 :          0 :                                 priv->hw_tag[!!attr->group];
    2617                 :          0 :                         rte_atomic_fetch_add_explicit(&priv->hws_mark_refcnt, 1,
    2618                 :            :                                         rte_memory_order_relaxed);
    2619                 :          0 :                         flow_hw_rxq_flag_set(dev, true);
    2620                 :          0 :                         break;
    2621                 :          0 :                 case RTE_FLOW_ACTION_TYPE_MARK:
    2622                 :          0 :                         acts->mark = true;
    2623         [ #  # ]:          0 :                         if (masks->conf &&
    2624                 :            :                             ((const struct rte_flow_action_mark *)
    2625         [ #  # ]:          0 :                              masks->conf)->id)
    2626                 :          0 :                                 acts->rule_acts[dr_pos].tag.value =
    2627                 :            :                                         mlx5_flow_mark_set
    2628                 :            :                                         (((const struct rte_flow_action_mark *)
    2629         [ #  # ]:          0 :                                         (actions->conf))->id);
    2630                 :            :                         else if (__flow_hw_act_data_general_append(priv, acts,
    2631                 :            :                                                                    actions->type,
    2632                 :            :                                                                    src_pos, dr_pos))
    2633                 :          0 :                                 goto err;
    2634                 :          0 :                         acts->rule_acts[dr_pos].action =
    2635                 :          0 :                                 priv->hw_tag[!!attr->group];
    2636                 :          0 :                         rte_atomic_fetch_add_explicit(&priv->hws_mark_refcnt, 1,
    2637                 :            :                                         rte_memory_order_relaxed);
    2638                 :          0 :                         flow_hw_rxq_flag_set(dev, true);
    2639                 :          0 :                         break;
    2640                 :          0 :                 case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
    2641                 :          0 :                         acts->rule_acts[dr_pos].action =
    2642                 :          0 :                                 priv->hw_push_vlan[type];
    2643   [ #  #  #  # ]:          0 :                         if (is_template_masked_push_vlan(masks->conf))
    2644                 :          0 :                                 acts->rule_acts[dr_pos].push_vlan.vlan_hdr =
    2645                 :            :                                         vlan_hdr_to_be32(actions);
    2646                 :            :                         else if (__flow_hw_act_data_general_append
    2647                 :            :                                         (priv, acts, actions->type,
    2648                 :            :                                          src_pos, dr_pos))
    2649                 :          0 :                                 goto err;
    2650                 :            :                         of_vlan_offset = is_of_vlan_pcp_present(actions) ?
    2651         [ #  # ]:          0 :                                         MLX5_HW_VLAN_PUSH_PCP_IDX :
    2652                 :            :                                         MLX5_HW_VLAN_PUSH_VID_IDX;
    2653                 :          0 :                         actions += of_vlan_offset;
    2654                 :          0 :                         masks += of_vlan_offset;
    2655                 :          0 :                         break;
    2656                 :          0 :                 case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:
    2657                 :          0 :                         acts->rule_acts[dr_pos].action =
    2658                 :          0 :                                 priv->hw_pop_vlan[type];
    2659                 :          0 :                         break;
    2660                 :          0 :                 case RTE_FLOW_ACTION_TYPE_JUMP:
    2661         [ #  # ]:          0 :                         if (masks->conf &&
    2662                 :            :                             ((const struct rte_flow_action_jump *)
    2663         [ #  # ]:          0 :                              masks->conf)->group) {
    2664                 :          0 :                                 uint32_t jump_group =
    2665                 :            :                                         ((const struct rte_flow_action_jump *)
    2666                 :          0 :                                         actions->conf)->group;
    2667                 :          0 :                                 acts->jump = flow_hw_jump_action_register
    2668                 :            :                                                 (dev, cfg, jump_group, error);
    2669         [ #  # ]:          0 :                                 if (!acts->jump)
    2670                 :          0 :                                         goto err;
    2671                 :          0 :                                 acts->rule_acts[dr_pos].action = (!!attr->group) ?
    2672         [ #  # ]:          0 :                                                                  acts->jump->hws_action :
    2673                 :            :                                                                  acts->jump->root_action;
    2674                 :            :                         } else if (__flow_hw_act_data_general_append
    2675                 :            :                                         (priv, acts, actions->type,
    2676                 :            :                                          src_pos, dr_pos)){
    2677                 :          0 :                                 goto err;
    2678                 :            :                         }
    2679                 :            :                         break;
    2680                 :          0 :                 case RTE_FLOW_ACTION_TYPE_QUEUE:
    2681         [ #  # ]:          0 :                         if (masks->conf &&
    2682                 :            :                             ((const struct rte_flow_action_queue *)
    2683         [ #  # ]:          0 :                              masks->conf)->index) {
    2684                 :          0 :                                 acts->tir = flow_hw_tir_action_register
    2685                 :          0 :                                 (dev, mlx5_hw_act_flag[!!attr->group][type],
    2686                 :            :                                  actions);
    2687         [ #  # ]:          0 :                                 if (!acts->tir)
    2688                 :          0 :                                         goto err;
    2689                 :          0 :                                 acts->rule_acts[dr_pos].action =
    2690                 :          0 :                                         acts->tir->action;
    2691                 :            :                         } else if (__flow_hw_act_data_general_append
    2692                 :            :                                         (priv, acts, actions->type,
    2693                 :            :                                          src_pos, dr_pos)) {
    2694                 :          0 :                                 goto err;
    2695                 :            :                         }
    2696                 :            :                         break;
    2697                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RSS:
    2698   [ #  #  #  # ]:          0 :                         if (actions->conf && masks->conf) {
    2699                 :          0 :                                 acts->tir = flow_hw_tir_action_register
    2700                 :          0 :                                 (dev, mlx5_hw_act_flag[!!attr->group][type],
    2701                 :            :                                  actions);
    2702         [ #  # ]:          0 :                                 if (!acts->tir)
    2703                 :          0 :                                         goto err;
    2704                 :          0 :                                 acts->rule_acts[dr_pos].action =
    2705                 :          0 :                                         acts->tir->action;
    2706                 :            :                         } else if (__flow_hw_act_data_general_append
    2707                 :            :                                         (priv, acts, actions->type,
    2708                 :            :                                          src_pos, dr_pos)) {
    2709                 :          0 :                                 goto err;
    2710                 :            :                         }
    2711                 :            :                         break;
    2712                 :          0 :                 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
    2713                 :            :                         MLX5_ASSERT(!reformat_used);
    2714                 :          0 :                         enc_item = MLX5_CONST_ENCAP_ITEM(rte_flow_action_vxlan_encap,
    2715                 :            :                                                          actions->conf);
    2716         [ #  # ]:          0 :                         if (masks->conf)
    2717                 :          0 :                                 enc_item_m = MLX5_CONST_ENCAP_ITEM(rte_flow_action_vxlan_encap,
    2718                 :            :                                                                    masks->conf);
    2719                 :            :                         reformat_used = true;
    2720                 :            :                         reformat_src = src_pos;
    2721                 :            :                         refmt_type = MLX5DR_ACTION_TYP_REFORMAT_L2_TO_TNL_L2;
    2722                 :            :                         break;
    2723                 :          0 :                 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
    2724                 :            :                         MLX5_ASSERT(!reformat_used);
    2725                 :          0 :                         enc_item = MLX5_CONST_ENCAP_ITEM(rte_flow_action_nvgre_encap,
    2726                 :            :                                                          actions->conf);
    2727         [ #  # ]:          0 :                         if (masks->conf)
    2728                 :          0 :                                 enc_item_m = MLX5_CONST_ENCAP_ITEM(rte_flow_action_nvgre_encap,
    2729                 :            :                                                                    masks->conf);
    2730                 :            :                         reformat_used = true;
    2731                 :            :                         reformat_src = src_pos;
    2732                 :            :                         refmt_type = MLX5DR_ACTION_TYP_REFORMAT_L2_TO_TNL_L2;
    2733                 :            :                         break;
    2734                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
    2735                 :          0 :                         raw_encap_data =
    2736                 :            :                                 (const struct rte_flow_action_raw_encap *)
    2737                 :            :                                  masks->conf;
    2738         [ #  # ]:          0 :                         if (raw_encap_data)
    2739                 :          0 :                                 encap_data_m = raw_encap_data->data;
    2740                 :          0 :                         raw_encap_data =
    2741                 :            :                                 (const struct rte_flow_action_raw_encap *)
    2742                 :            :                                  actions->conf;
    2743                 :          0 :                         encap_data = raw_encap_data->data;
    2744                 :          0 :                         data_size = raw_encap_data->size;
    2745         [ #  # ]:          0 :                         if (reformat_used) {
    2746                 :            :                                 refmt_type = data_size <
    2747                 :            :                                 MLX5_ENCAPSULATION_DECISION_SIZE ?
    2748         [ #  # ]:          0 :                                 MLX5DR_ACTION_TYP_REFORMAT_TNL_L3_TO_L2 :
    2749                 :            :                                 MLX5DR_ACTION_TYP_REFORMAT_L2_TO_TNL_L3;
    2750                 :            :                         } else {
    2751                 :            :                                 reformat_used = true;
    2752                 :            :                                 refmt_type =
    2753                 :            :                                 MLX5DR_ACTION_TYP_REFORMAT_L2_TO_TNL_L2;
    2754                 :            :                         }
    2755                 :            :                         reformat_src = src_pos;
    2756                 :            :                         break;
    2757                 :          0 :                 case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
    2758                 :            :                 case RTE_FLOW_ACTION_TYPE_NVGRE_DECAP:
    2759                 :            :                         MLX5_ASSERT(!reformat_used);
    2760                 :            :                         reformat_used = true;
    2761                 :            :                         refmt_type = MLX5DR_ACTION_TYP_REFORMAT_TNL_L2_TO_L2;
    2762                 :          0 :                         break;
    2763                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
    2764                 :            :                         reformat_used = true;
    2765                 :            :                         refmt_type = MLX5DR_ACTION_TYP_REFORMAT_TNL_L2_TO_L2;
    2766                 :          0 :                         break;
    2767                 :          0 :                 case RTE_FLOW_ACTION_TYPE_IPV6_EXT_PUSH:
    2768         [ #  # ]:          0 :                         if (!hca_attr->query_match_sample_info || !hca_attr->parse_graph_anchor ||
    2769         [ #  # ]:          0 :                             !priv->sh->srh_flex_parser.flex.mapnum) {
    2770                 :          0 :                                 DRV_LOG(ERR, "SRv6 anchor is not supported.");
    2771                 :          0 :                                 goto err;
    2772                 :            :                         }
    2773                 :            :                         MLX5_ASSERT(!recom_used && !recom_type);
    2774                 :            :                         recom_used = true;
    2775                 :            :                         recom_type = MLX5DR_ACTION_TYP_PUSH_IPV6_ROUTE_EXT;
    2776                 :          0 :                         ipv6_ext_data =
    2777                 :            :                                 (const struct rte_flow_action_ipv6_ext_push *)masks->conf;
    2778         [ #  # ]:          0 :                         if (ipv6_ext_data)
    2779                 :          0 :                                 push_data_m = ipv6_ext_data->data;
    2780                 :          0 :                         ipv6_ext_data =
    2781                 :            :                                 (const struct rte_flow_action_ipv6_ext_push *)actions->conf;
    2782         [ #  # ]:          0 :                         if (ipv6_ext_data) {
    2783                 :          0 :                                 push_data = ipv6_ext_data->data;
    2784                 :          0 :                                 push_size = ipv6_ext_data->size;
    2785                 :            :                         }
    2786                 :            :                         recom_src = src_pos;
    2787                 :            :                         break;
    2788                 :          0 :                 case RTE_FLOW_ACTION_TYPE_IPV6_EXT_REMOVE:
    2789         [ #  # ]:          0 :                         if (!hca_attr->query_match_sample_info || !hca_attr->parse_graph_anchor ||
    2790         [ #  # ]:          0 :                             !priv->sh->srh_flex_parser.flex.mapnum) {
    2791                 :          0 :                                 DRV_LOG(ERR, "SRv6 anchor is not supported.");
    2792                 :          0 :                                 goto err;
    2793                 :            :                         }
    2794                 :            :                         recom_used = true;
    2795                 :            :                         recom_type = MLX5DR_ACTION_TYP_POP_IPV6_ROUTE_EXT;
    2796                 :            :                         break;
    2797                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SEND_TO_KERNEL:
    2798                 :          0 :                         ret = flow_hw_translate_group(dev, cfg, attr->group,
    2799                 :            :                                                 &target_grp, error);
    2800         [ #  # ]:          0 :                         if (ret)
    2801                 :          0 :                                 return ret;
    2802         [ #  # ]:          0 :                         if (target_grp == 0) {
    2803                 :            :                                 __flow_hw_action_template_destroy(dev, acts);
    2804                 :          0 :                                 return rte_flow_error_set(error, ENOTSUP,
    2805                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
    2806                 :            :                                                 NULL,
    2807                 :            :                                                 "Send to kernel action on root table is not supported in HW steering mode");
    2808                 :            :                         }
    2809         [ #  # ]:          0 :                         table_type = attr->ingress ? MLX5DR_TABLE_TYPE_NIC_RX :
    2810         [ #  # ]:          0 :                                      ((attr->egress) ? MLX5DR_TABLE_TYPE_NIC_TX :
    2811                 :            :                                       MLX5DR_TABLE_TYPE_FDB);
    2812                 :          0 :                         acts->rule_acts[dr_pos].action = priv->hw_send_to_kernel[table_type];
    2813                 :          0 :                         break;
    2814         [ #  # ]:          0 :                 case RTE_FLOW_ACTION_TYPE_MODIFY_FIELD:
    2815                 :            :                         err = flow_hw_modify_field_compile(dev, attr, actions,
    2816                 :            :                                                            masks, acts, &mhdr,
    2817                 :            :                                                            src_pos, error);
    2818         [ #  # ]:          0 :                         if (err)
    2819                 :          0 :                                 goto err;
    2820                 :            :                         break;
    2821                 :          0 :                 case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
    2822         [ #  # ]:          0 :                         if (flow_hw_represented_port_compile
    2823                 :            :                                         (dev, attr, actions,
    2824                 :            :                                          masks, acts, src_pos, dr_pos, error))
    2825                 :          0 :                                 goto err;
    2826                 :            :                         break;
    2827                 :          0 :                 case RTE_FLOW_ACTION_TYPE_METER:
    2828                 :            :                         /*
    2829                 :            :                          * METER action is compiled to 2 DR actions - ASO_METER and FT.
    2830                 :            :                          * Calculated DR offset is stored only for ASO_METER and FT
    2831                 :            :                          * is assumed to be the next action.
    2832                 :            :                          */
    2833                 :          0 :                         jump_pos = dr_pos + 1;
    2834   [ #  #  #  # ]:          0 :                         if (actions->conf && masks->conf &&
    2835                 :            :                             ((const struct rte_flow_action_meter *)
    2836         [ #  # ]:          0 :                              masks->conf)->mtr_id) {
    2837                 :          0 :                                 err = flow_hw_meter_compile(dev, cfg,
    2838                 :            :                                                             dr_pos, jump_pos, actions, acts, error);
    2839                 :            :                                 if (err)
    2840                 :          0 :                                         goto err;
    2841                 :            :                         } else if (__flow_hw_act_data_general_append(priv, acts,
    2842                 :            :                                                                      actions->type,
    2843                 :            :                                                                      src_pos,
    2844                 :            :                                                                      dr_pos))
    2845                 :          0 :                                 goto err;
    2846                 :            :                         break;
    2847                 :          0 :                 case RTE_FLOW_ACTION_TYPE_AGE:
    2848                 :          0 :                         ret = flow_hw_translate_group(dev, cfg, attr->group,
    2849                 :            :                                                 &target_grp, error);
    2850         [ #  # ]:          0 :                         if (ret)
    2851                 :          0 :                                 return ret;
    2852         [ #  # ]:          0 :                         if (target_grp == 0) {
    2853                 :            :                                 __flow_hw_action_template_destroy(dev, acts);
    2854                 :          0 :                                 return rte_flow_error_set(error, ENOTSUP,
    2855                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
    2856                 :            :                                                 NULL,
    2857                 :            :                                                 "Age action on root table is not supported in HW steering mode");
    2858                 :            :                         }
    2859                 :          0 :                         if (__flow_hw_act_data_general_append(priv, acts,
    2860                 :            :                                                               actions->type,
    2861                 :            :                                                               src_pos,
    2862                 :            :                                                               dr_pos))
    2863                 :          0 :                                 goto err;
    2864                 :            :                         break;
    2865                 :          0 :                 case RTE_FLOW_ACTION_TYPE_COUNT:
    2866                 :          0 :                         ret = flow_hw_translate_group(dev, cfg, attr->group,
    2867                 :            :                                                 &target_grp, error);
    2868         [ #  # ]:          0 :                         if (ret)
    2869                 :          0 :                                 return ret;
    2870         [ #  # ]:          0 :                         if (target_grp == 0) {
    2871                 :            :                                 __flow_hw_action_template_destroy(dev, acts);
    2872                 :          0 :                                 return rte_flow_error_set(error, ENOTSUP,
    2873                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
    2874                 :            :                                                 NULL,
    2875                 :            :                                                 "Counter action on root table is not supported in HW steering mode");
    2876                 :            :                         }
    2877         [ #  # ]:          0 :                         if ((at->action_flags & MLX5_FLOW_ACTION_AGE) ||
    2878                 :            :                             (at->action_flags & MLX5_FLOW_ACTION_INDIRECT_AGE))
    2879                 :            :                                 /*
    2880                 :            :                                  * When both COUNT and AGE are requested, it is
    2881                 :            :                                  * saved as AGE action which creates also the
    2882                 :            :                                  * counter.
    2883                 :            :                                  */
    2884                 :            :                                 break;
    2885         [ #  # ]:          0 :                         if (masks->conf &&
    2886                 :            :                             ((const struct rte_flow_action_count *)
    2887         [ #  # ]:          0 :                              masks->conf)->id) {
    2888         [ #  # ]:          0 :                                 err = flow_hw_cnt_compile(dev, dr_pos, acts);
    2889                 :            :                                 if (err)
    2890                 :          0 :                                         goto err;
    2891                 :          0 :                         } else if (__flow_hw_act_data_general_append
    2892                 :            :                                         (priv, acts, actions->type,
    2893                 :            :                                          src_pos, dr_pos)) {
    2894                 :          0 :                                 goto err;
    2895                 :            :                         }
    2896                 :            :                         break;
    2897                 :          0 :                 case RTE_FLOW_ACTION_TYPE_CONNTRACK:
    2898         [ #  # ]:          0 :                         if (masks->conf) {
    2899                 :          0 :                                 ct_idx = MLX5_INDIRECT_ACTION_IDX_GET(actions->conf);
    2900                 :            :                                 if (flow_hw_ct_compile(dev, MLX5_HW_INV_QUEUE, ct_idx,
    2901                 :          0 :                                                        &acts->rule_acts[dr_pos]))
    2902                 :          0 :                                         goto err;
    2903                 :            :                         } else if (__flow_hw_act_data_general_append
    2904                 :            :                                         (priv, acts, actions->type,
    2905                 :            :                                          src_pos, dr_pos)) {
    2906                 :          0 :                                 goto err;
    2907                 :            :                         }
    2908                 :            :                         break;
    2909                 :          0 :                 case RTE_FLOW_ACTION_TYPE_METER_MARK:
    2910   [ #  #  #  # ]:          0 :                         if (actions->conf && masks->conf &&
    2911                 :            :                             ((const struct rte_flow_action_meter_mark *)
    2912         [ #  # ]:          0 :                              masks->conf)->profile) {
    2913                 :            :                                 err = flow_hw_meter_mark_compile(dev,
    2914                 :            :                                                                  dr_pos, actions,
    2915                 :          0 :                                                                  acts->rule_acts,
    2916                 :            :                                                                  &acts->mtr_id,
    2917                 :            :                                                                  MLX5_HW_INV_QUEUE,
    2918                 :            :                                                                  error);
    2919                 :            :                                 if (err)
    2920                 :          0 :                                         goto err;
    2921                 :            :                         } else if (__flow_hw_act_data_general_append(priv, acts,
    2922                 :            :                                                                      actions->type,
    2923                 :            :                                                                      src_pos,
    2924                 :            :                                                                      dr_pos))
    2925                 :          0 :                                 goto err;
    2926                 :            :                         break;
    2927                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_DEFAULT_MISS:
    2928                 :            :                         /* Internal, can be skipped. */
    2929         [ #  # ]:          0 :                         if (!!attr->group) {
    2930                 :          0 :                                 DRV_LOG(ERR, "DEFAULT MISS action is only"
    2931                 :            :                                         " supported in root table.");
    2932                 :          0 :                                 goto err;
    2933                 :            :                         }
    2934                 :          0 :                         acts->rule_acts[dr_pos].action = priv->hw_def_miss;
    2935                 :          0 :                         break;
    2936                 :          0 :                 case RTE_FLOW_ACTION_TYPE_NAT64:
    2937         [ #  # ]:          0 :                         if (masks->conf &&
    2938         [ #  # ]:          0 :                             ((const struct rte_flow_action_nat64 *)masks->conf)->type) {
    2939                 :          0 :                                 const struct rte_flow_action_nat64 *nat64_c =
    2940                 :            :                                         (const struct rte_flow_action_nat64 *)actions->conf;
    2941                 :            : 
    2942                 :          0 :                                 acts->rule_acts[dr_pos].action =
    2943                 :          0 :                                         priv->action_nat64[type][nat64_c->type];
    2944                 :            :                         } else if (__flow_hw_act_data_general_append(priv, acts,
    2945                 :            :                                                                      actions->type,
    2946                 :            :                                                                      src_pos, dr_pos))
    2947                 :          0 :                                 goto err;
    2948                 :            :                         break;
    2949                 :          0 :                 case RTE_FLOW_ACTION_TYPE_JUMP_TO_TABLE_INDEX:
    2950         [ #  # ]:          0 :                         if (masks->conf &&
    2951                 :            :                             ((const struct rte_flow_action_jump_to_table_index *)
    2952         [ #  # ]:          0 :                              masks->conf)->table) {
    2953                 :          0 :                                 struct rte_flow_template_table *jump_table =
    2954                 :            :                                         ((const struct rte_flow_action_jump_to_table_index *)
    2955                 :          0 :                                         actions->conf)->table;
    2956                 :          0 :                                 acts->rule_acts[dr_pos].jump_to_matcher.offset =
    2957                 :            :                                         ((const struct rte_flow_action_jump_to_table_index *)
    2958                 :          0 :                                         actions->conf)->index;
    2959         [ #  # ]:          0 :                                 if (likely(!rte_flow_template_table_resizable(dev->data->port_id,
    2960                 :            :                                                                         &jump_table->cfg.attr))) {
    2961                 :          0 :                                         acts->rule_acts[dr_pos].action =
    2962                 :          0 :                                                 jump_table->matcher_info[0].jump;
    2963                 :            :                                 } else {
    2964                 :            :                                         uint32_t selector;
    2965                 :          0 :                                         rte_rwlock_read_lock(&jump_table->matcher_replace_rwlk);
    2966                 :          0 :                                         selector = jump_table->matcher_selector;
    2967                 :          0 :                                         acts->rule_acts[dr_pos].action =
    2968                 :          0 :                                                 jump_table->matcher_info[selector].jump;
    2969                 :            :                                         rte_rwlock_read_unlock(&jump_table->matcher_replace_rwlk);
    2970                 :            :                                 }
    2971                 :            :                         } else if (__flow_hw_act_data_general_append
    2972                 :            :                                         (priv, acts, actions->type,
    2973                 :            :                                          src_pos, dr_pos)){
    2974                 :          0 :                                 goto err;
    2975                 :            :                         }
    2976                 :            :                         break;
    2977                 :          0 :                 case RTE_FLOW_ACTION_TYPE_END:
    2978                 :            :                         actions_end = true;
    2979                 :          0 :                         break;
    2980                 :            :                 default:
    2981                 :            :                         break;
    2982                 :            :                 }
    2983                 :            :         }
    2984         [ #  # ]:          0 :         if (mhdr.pos != UINT16_MAX) {
    2985                 :          0 :                 ret = mlx5_tbl_translate_modify_header(dev, cfg, acts, mp_ctx, &mhdr, error);
    2986         [ #  # ]:          0 :                 if (ret)
    2987                 :          0 :                         goto err;
    2988   [ #  #  #  # ]:          0 :                 if (!nt_mode && mhdr.shared) {
    2989                 :          0 :                         ret = mlx5_tbl_ensure_shared_modify_header(dev, cfg, acts, error);
    2990         [ #  # ]:          0 :                         if (ret)
    2991                 :          0 :                                 goto err;
    2992                 :            :                 }
    2993                 :            :         }
    2994         [ #  # ]:          0 :         if (reformat_used) {
    2995                 :          0 :                 ret = mlx5_tbl_translate_reformat(priv, acts, at,
    2996                 :            :                                                   enc_item, enc_item_m,
    2997                 :            :                                                   encap_data, encap_data_m,
    2998                 :            :                                                   mp_ctx, data_size,
    2999                 :            :                                                   reformat_src,
    3000                 :            :                                                   refmt_type, error);
    3001         [ #  # ]:          0 :                 if (ret)
    3002                 :          0 :                         goto err;
    3003   [ #  #  #  # ]:          0 :                 if (!nt_mode && acts->encap_decap->shared) {
    3004                 :          0 :                         ret = mlx5_tbl_create_reformat_action(priv, table_attr, acts, at,
    3005                 :            :                                                               encap_data, data_size,
    3006                 :            :                                                               refmt_type);
    3007         [ #  # ]:          0 :                         if (ret)
    3008                 :          0 :                                 goto err;
    3009                 :            :                 }
    3010                 :            :         }
    3011         [ #  # ]:          0 :         if (recom_used) {
    3012                 :            :                 MLX5_ASSERT(at->recom_off != UINT16_MAX);
    3013                 :          0 :                 ret = mlx5_create_ipv6_ext_reformat(dev, cfg, acts, at, push_data,
    3014                 :            :                                                     push_data_m, push_size, recom_src,
    3015                 :            :                                                     recom_type);
    3016         [ #  # ]:          0 :                 if (ret)
    3017                 :          0 :                         goto err;
    3018                 :            :         }
    3019                 :            :         return 0;
    3020                 :          0 : err:
    3021                 :            :         /* If rte_errno was not initialized and reached error state. */
    3022         [ #  # ]:          0 :         if (!rte_errno)
    3023                 :          0 :                 rte_errno = EINVAL;
    3024                 :          0 :         err = rte_errno;
    3025                 :            :         __flow_hw_action_template_destroy(dev, acts);
    3026                 :          0 :         return rte_flow_error_set(error, err,
    3027                 :            :                                   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    3028                 :            :                                   "fail to create rte table");
    3029                 :            : }
    3030                 :            : 
    3031                 :            : /**
    3032                 :            :  * Translate rte_flow actions to DR action.
    3033                 :            :  *
    3034                 :            :  * As the action template has already indicated the actions. Translate
    3035                 :            :  * the rte_flow actions to DR action if possible. So in flow create
    3036                 :            :  * stage we will save cycles from handing the actions' organizing.
    3037                 :            :  * For the actions with limited information, need to add these to a
    3038                 :            :  * list.
    3039                 :            :  *
    3040                 :            :  * @param[in] dev
    3041                 :            :  *   Pointer to the rte_eth_dev structure.
    3042                 :            :  * @param[in] cfg
    3043                 :            :  *   Pointer to the table configuration.
    3044                 :            :  * @param[in/out] acts
    3045                 :            :  *   Pointer to the template HW steering DR actions.
    3046                 :            :  * @param[in] at
    3047                 :            :  *   Action template.
    3048                 :            :  * @param[out] error
    3049                 :            :  *   Pointer to error structure.
    3050                 :            :  *
    3051                 :            :  * @return
    3052                 :            :  *   0 on success, a negative errno otherwise and rte_errno is set.
    3053                 :            :  */
    3054                 :            : static int
    3055                 :            : flow_hw_translate_actions_template(struct rte_eth_dev *dev,
    3056                 :            :                             const struct mlx5_flow_template_table_cfg *cfg,
    3057                 :            :                             struct mlx5_hw_actions *acts,
    3058                 :            :                             struct rte_flow_actions_template *at,
    3059                 :            :                             struct mlx5_tbl_multi_pattern_ctx *mp_ctx,
    3060                 :            :                             struct rte_flow_error *error)
    3061                 :            : {
    3062                 :          0 :         return __flow_hw_translate_actions_template(dev, cfg, acts, at, mp_ctx, false, error);
    3063                 :            : }
    3064                 :            : 
    3065                 :            : static __rte_always_inline struct mlx5dr_rule_action *
    3066                 :            : flow_hw_get_dr_action_buffer(struct mlx5_priv *priv,
    3067                 :            :                              struct rte_flow_template_table *table,
    3068                 :            :                              uint8_t action_template_index,
    3069                 :            :                              uint32_t queue)
    3070                 :            : {
    3071                 :          0 :         uint32_t offset = action_template_index * priv->nb_queue + queue;
    3072                 :            : 
    3073                 :          0 :         return &table->rule_acts[offset].acts[0];
    3074                 :            : }
    3075                 :            : 
    3076                 :            : static void
    3077                 :          0 : flow_hw_populate_rule_acts_caches(struct rte_eth_dev *dev,
    3078                 :            :                                   struct rte_flow_template_table *table,
    3079                 :            :                                   uint8_t at_idx)
    3080                 :            : {
    3081                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    3082                 :            :         uint32_t q;
    3083                 :            : 
    3084         [ #  # ]:          0 :         for (q = 0; q < priv->nb_queue; ++q) {
    3085                 :            :                 struct mlx5dr_rule_action *rule_acts =
    3086                 :          0 :                                 flow_hw_get_dr_action_buffer(priv, table, at_idx, q);
    3087                 :            : 
    3088         [ #  # ]:          0 :                 rte_memcpy(rule_acts, table->ats[at_idx].acts.rule_acts,
    3089                 :            :                            sizeof(table->ats[at_idx].acts.rule_acts));
    3090                 :            :         }
    3091                 :          0 : }
    3092                 :            : 
    3093                 :            : /**
    3094                 :            :  * Translate rte_flow actions to DR action.
    3095                 :            :  *
    3096                 :            :  * @param[in] dev
    3097                 :            :  *   Pointer to the rte_eth_dev structure.
    3098                 :            :  * @param[in] tbl
    3099                 :            :  *   Pointer to the flow template table.
    3100                 :            :  * @param[out] error
    3101                 :            :  *   Pointer to error structure.
    3102                 :            :  *
    3103                 :            :  * @return
    3104                 :            :  *    0 on success, negative value otherwise and rte_errno is set.
    3105                 :            :  */
    3106                 :            : static int
    3107                 :          0 : flow_hw_translate_all_actions_templates(struct rte_eth_dev *dev,
    3108                 :            :                           struct rte_flow_template_table *tbl,
    3109                 :            :                           struct rte_flow_error *error)
    3110                 :            : {
    3111                 :            :         int ret;
    3112                 :            :         uint32_t i;
    3113                 :            : 
    3114         [ #  # ]:          0 :         for (i = 0; i < tbl->nb_action_templates; i++) {
    3115         [ #  # ]:          0 :                 if (flow_hw_translate_actions_template(dev, &tbl->cfg,
    3116                 :            :                                                 &tbl->ats[i].acts,
    3117                 :            :                                                 tbl->ats[i].action_template,
    3118                 :            :                                                 &tbl->mpctx, error))
    3119                 :          0 :                         goto err;
    3120                 :          0 :                 flow_hw_populate_rule_acts_caches(dev, tbl, i);
    3121                 :            :         }
    3122         [ #  # ]:          0 :         ret = mlx5_tbl_multi_pattern_process(dev, tbl, &tbl->mpctx.segments[0],
    3123                 :            :                                              rte_log2_u32(tbl->cfg.attr.nb_flows),
    3124                 :            :                                              error);
    3125         [ #  # ]:          0 :         if (ret)
    3126                 :          0 :                 goto err;
    3127                 :            :         return 0;
    3128                 :            : err:
    3129         [ #  # ]:          0 :         while (i--)
    3130                 :          0 :                 __flow_hw_action_template_destroy(dev, &tbl->ats[i].acts);
    3131                 :            :         return -1;
    3132                 :            : }
    3133                 :            : 
    3134                 :            : /**
    3135                 :            :  * Get shared indirect action.
    3136                 :            :  *
    3137                 :            :  * @param[in] dev
    3138                 :            :  *   Pointer to the rte_eth_dev data structure.
    3139                 :            :  * @param[in] act_data
    3140                 :            :  *   Pointer to the recorded action construct data.
    3141                 :            :  * @param[in] item_flags
    3142                 :            :  *   The matcher itme_flags used for RSS lookup.
    3143                 :            :  * @param[in] rule_act
    3144                 :            :  *   Pointer to the shared action's destination rule DR action.
    3145                 :            :  *
    3146                 :            :  * @return
    3147                 :            :  *    0 on success, negative value otherwise and rte_errno is set.
    3148                 :            :  */
    3149                 :            : static __rte_always_inline int
    3150                 :            : flow_hw_shared_action_get(struct rte_eth_dev *dev,
    3151                 :            :                           struct mlx5_action_construct_data *act_data,
    3152                 :            :                           const uint64_t item_flags,
    3153                 :            :                           struct mlx5dr_rule_action *rule_act)
    3154                 :            : {
    3155                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    3156                 :          0 :         struct mlx5_flow_rss_desc rss_desc = { 0 };
    3157                 :          0 :         uint64_t hash_fields = 0;
    3158                 :            :         uint32_t hrxq_idx = 0;
    3159                 :            :         struct mlx5_hrxq *hrxq = NULL;
    3160                 :            :         int act_type = act_data->type;
    3161                 :            : 
    3162                 :            :         switch (act_type) {
    3163                 :            :         case MLX5_RTE_FLOW_ACTION_TYPE_RSS:
    3164                 :          0 :                 rss_desc.level = act_data->shared_rss.level;
    3165                 :          0 :                 rss_desc.types = act_data->shared_rss.types;
    3166                 :          0 :                 rss_desc.symmetric_hash_function = act_data->shared_rss.symmetric_hash_function;
    3167                 :          0 :                 flow_dv_hashfields_set(item_flags, &rss_desc, &hash_fields);
    3168                 :          0 :                 hrxq_idx = flow_dv_action_rss_hrxq_lookup
    3169                 :            :                         (dev, act_data->shared_rss.idx, hash_fields);
    3170   [ #  #  #  #  :          0 :                 if (hrxq_idx)
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
    3171                 :          0 :                         hrxq = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_HRXQ],
    3172                 :            :                                               hrxq_idx);
    3173   [ #  #  #  #  :          0 :                 if (hrxq) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
    3174                 :          0 :                         rule_act->action = hrxq->action;
    3175                 :            :                         return 0;
    3176                 :            :                 }
    3177                 :            :                 break;
    3178                 :            :         default:
    3179                 :            :                 DRV_LOG(WARNING, "Unsupported shared action type:%d",
    3180                 :            :                         act_data->type);
    3181                 :            :                 break;
    3182                 :            :         }
    3183                 :            :         return -1;
    3184                 :            : }
    3185                 :            : 
    3186                 :            : static void
    3187                 :          0 : flow_hw_construct_quota(struct mlx5_priv *priv,
    3188                 :            :                         struct mlx5dr_rule_action *rule_act, uint32_t qid)
    3189                 :            : {
    3190                 :          0 :         rule_act->action = priv->quota_ctx.dr_action;
    3191                 :          0 :         rule_act->aso_meter.offset = qid - 1;
    3192                 :          0 :         rule_act->aso_meter.init_color =
    3193                 :            :                 MLX5DR_ACTION_ASO_METER_COLOR_GREEN;
    3194                 :          0 : }
    3195                 :            : 
    3196                 :            : /**
    3197                 :            :  * Construct shared indirect action.
    3198                 :            :  *
    3199                 :            :  * @param[in] dev
    3200                 :            :  *   Pointer to the rte_eth_dev data structure.
    3201                 :            :  * @param[in] queue
    3202                 :            :  *   The flow creation queue index.
    3203                 :            :  * @param[in] action
    3204                 :            :  *   Pointer to the shared indirect rte_flow action.
    3205                 :            :   * @param[in] table
    3206                 :            :  *   Pointer to the flow table.
    3207                 :            :  * @param[in] item_flags
    3208                 :            :  *   Item flags.
    3209                 :            :  * @param[in] action_flags
    3210                 :            :  *   Actions bit-map detected in this template.
    3211                 :            :  * @param[in, out] flow
    3212                 :            :  *   Pointer to the flow containing the counter.
    3213                 :            :  * @param[in] rule_act
    3214                 :            :  *   Pointer to the shared action's destination rule DR action.
    3215                 :            :  *
    3216                 :            :  * @return
    3217                 :            :  *    0 on success, negative value otherwise and rte_errno is set.
    3218                 :            :  */
    3219                 :            : static __rte_always_inline int
    3220                 :            : flow_hw_shared_action_construct(struct rte_eth_dev *dev, uint32_t queue,
    3221                 :            :                                 const struct rte_flow_action *action,
    3222                 :            :                                 struct rte_flow_template_table *table __rte_unused,
    3223                 :            :                                 const uint64_t item_flags, uint64_t action_flags,
    3224                 :            :                                 struct rte_flow_hw *flow,
    3225                 :            :                                 struct mlx5dr_rule_action *rule_act)
    3226                 :            : {
    3227                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    3228                 :          0 :         struct mlx5_aso_mtr_pool *pool = priv->hws_mpool;
    3229                 :            :         struct mlx5_action_construct_data act_data;
    3230                 :            :         struct mlx5_shared_action_rss *shared_rss;
    3231                 :            :         struct mlx5_aso_mtr *aso_mtr;
    3232                 :            :         struct mlx5_age_info *age_info;
    3233                 :            :         struct mlx5_hws_age_param *param;
    3234                 :            :         struct rte_flow_hw_aux *aux;
    3235                 :          0 :         uint32_t act_idx = (uint32_t)(uintptr_t)action->conf;
    3236                 :          0 :         uint32_t type = act_idx >> MLX5_INDIRECT_ACTION_TYPE_OFFSET;
    3237                 :          0 :         uint32_t idx = act_idx &
    3238                 :            :                        ((1u << MLX5_INDIRECT_ACTION_TYPE_OFFSET) - 1);
    3239                 :            :         cnt_id_t age_cnt;
    3240                 :            : 
    3241                 :            :         memset(&act_data, 0, sizeof(act_data));
    3242   [ #  #  #  #  :          0 :         switch (type) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
    3243                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_RSS:
    3244                 :          0 :                 act_data.type = MLX5_RTE_FLOW_ACTION_TYPE_RSS;
    3245                 :          0 :                 shared_rss = mlx5_ipool_get
    3246                 :          0 :                         (priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], idx);
    3247   [ #  #  #  #  :          0 :                 if (!shared_rss)
          #  #  #  #  #  
                      # ]
    3248                 :            :                         return -1;
    3249                 :          0 :                 act_data.shared_rss.idx = idx;
    3250                 :          0 :                 act_data.shared_rss.level = shared_rss->origin.level;
    3251                 :          0 :                 act_data.shared_rss.types = !shared_rss->origin.types ?
    3252   [ #  #  #  #  :          0 :                                             RTE_ETH_RSS_IP :
          #  #  #  #  #  
                      # ]
    3253                 :            :                                             shared_rss->origin.types;
    3254                 :          0 :                 act_data.shared_rss.symmetric_hash_function =
    3255                 :          0 :                         MLX5_RSS_IS_SYMM(shared_rss->origin.func);
    3256                 :            : 
    3257                 :            :                 if (flow_hw_shared_action_get
    3258                 :            :                                 (dev, &act_data, item_flags, rule_act))
    3259                 :            :                         return -1;
    3260                 :            :                 break;
    3261                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_COUNT:
    3262                 :          0 :                 if (mlx5_hws_cnt_pool_get_action_offset(priv->hws_cpool,
    3263                 :            :                                 act_idx,
    3264                 :            :                                 &rule_act->action,
    3265                 :            :                                 &rule_act->counter.offset))
    3266                 :            :                         return -1;
    3267                 :          0 :                 flow->flags |= MLX5_FLOW_HW_FLOW_FLAG_CNT_ID;
    3268                 :          0 :                 flow->cnt_id = act_idx;
    3269                 :            :                 break;
    3270                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_AGE:
    3271                 :          0 :                 aux = mlx5_flow_hw_aux(dev->data->port_id, flow);
    3272                 :            :                 /*
    3273                 :            :                  * Save the index with the indirect type, to recognize
    3274                 :            :                  * it in flow destroy.
    3275                 :            :                  */
    3276                 :            :                 mlx5_flow_hw_aux_set_age_idx(flow, aux, act_idx);
    3277                 :          0 :                 flow->flags |= MLX5_FLOW_HW_FLOW_FLAG_AGE_IDX;
    3278   [ #  #  #  #  :          0 :                 if (action_flags & MLX5_FLOW_ACTION_INDIRECT_COUNT)
          #  #  #  #  #  
                      # ]
    3279                 :            :                         /*
    3280                 :            :                          * The mutual update for idirect AGE & COUNT will be
    3281                 :            :                          * performed later after we have ID for both of them.
    3282                 :            :                          */
    3283                 :            :                         break;
    3284                 :          0 :                 age_info = GET_PORT_AGE_INFO(priv);
    3285                 :          0 :                 param = mlx5_ipool_get(age_info->ages_ipool, idx);
    3286   [ #  #  #  #  :          0 :                 if (param == NULL)
          #  #  #  #  #  
                      # ]
    3287                 :            :                         return -1;
    3288   [ #  #  #  #  :          0 :                 if (action_flags & MLX5_FLOW_ACTION_COUNT) {
          #  #  #  #  #  
                      # ]
    3289   [ #  #  #  #  :          0 :                         if (mlx5_hws_cnt_pool_get(priv->hws_cpool,
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
    3290                 :            :                                                   &param->queue_id, &age_cnt,
    3291                 :            :                                                   idx) < 0)
    3292                 :            :                                 return -1;
    3293                 :          0 :                         flow->flags |= MLX5_FLOW_HW_FLOW_FLAG_CNT_ID;
    3294                 :          0 :                         flow->cnt_id = age_cnt;
    3295                 :          0 :                         param->nb_cnts++;
    3296                 :            :                 } else {
    3297                 :            :                         /*
    3298                 :            :                          * Get the counter of this indirect AGE or create one
    3299                 :            :                          * if doesn't exist.
    3300                 :            :                          */
    3301                 :            :                         age_cnt = mlx5_hws_age_cnt_get(priv, param, idx);
    3302   [ #  #  #  #  :          0 :                         if (age_cnt == 0)
          #  #  #  #  #  
                      # ]
    3303                 :            :                                 return -1;
    3304                 :            :                 }
    3305                 :          0 :                 if (mlx5_hws_cnt_pool_get_action_offset(priv->hws_cpool,
    3306                 :            :                                                      age_cnt, &rule_act->action,
    3307                 :            :                                                      &rule_act->counter.offset))
    3308                 :            :                         return -1;
    3309                 :            :                 break;
    3310                 :            :         case MLX5_INDIRECT_ACTION_TYPE_CT:
    3311                 :            :                 if (flow_hw_ct_compile(dev, queue, idx, rule_act))
    3312                 :            :                         return -1;
    3313                 :            :                 break;
    3314                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_METER_MARK:
    3315                 :            :                 /* Find ASO object. */
    3316                 :          0 :                 aso_mtr = mlx5_ipool_get(pool->idx_pool, idx);
    3317   [ #  #  #  #  :          0 :                 if (!aso_mtr)
          #  #  #  #  #  
                      # ]
    3318                 :            :                         return -1;
    3319                 :          0 :                 rule_act->action = pool->action;
    3320                 :          0 :                 rule_act->aso_meter.offset = aso_mtr->offset;
    3321                 :            :                 break;
    3322                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_QUOTA:
    3323                 :          0 :                 flow_hw_construct_quota(priv, rule_act, idx);
    3324                 :            :                 break;
    3325                 :          0 :         default:
    3326                 :          0 :                 DRV_LOG(WARNING, "Unsupported shared action type:%d", type);
    3327                 :            :                 break;
    3328                 :            :         }
    3329                 :            :         return 0;
    3330                 :            : }
    3331                 :            : 
    3332                 :            : static __rte_always_inline int
    3333                 :            : flow_hw_mhdr_cmd_is_nop(const struct mlx5_modification_cmd *cmd)
    3334                 :            : {
    3335                 :            :         struct mlx5_modification_cmd cmd_he = {
    3336                 :          0 :                 .data0 = rte_be_to_cpu_32(cmd->data0),
    3337                 :            :                 .data1 = 0,
    3338                 :            :         };
    3339                 :            : 
    3340                 :          0 :         return cmd_he.action_type == MLX5_MODIFICATION_TYPE_NOP;
    3341                 :            : }
    3342                 :            : 
    3343                 :            : /**
    3344                 :            :  * Construct flow action array.
    3345                 :            :  *
    3346                 :            :  * For action template contains dynamic actions, these actions need to
    3347                 :            :  * be updated according to the rte_flow action during flow creation.
    3348                 :            :  *
    3349                 :            :  * @param[in] dev
    3350                 :            :  *   Pointer to the rte_eth_dev structure.
    3351                 :            :  * @param[in] job
    3352                 :            :  *   Pointer to job descriptor.
    3353                 :            :  * @param[in] hw_acts
    3354                 :            :  *   Pointer to translated actions from template.
    3355                 :            :  * @param[in] it_idx
    3356                 :            :  *   Item template index the action template refer to.
    3357                 :            :  * @param[in] actions
    3358                 :            :  *   Array of rte_flow action need to be checked.
    3359                 :            :  * @param[in] rule_acts
    3360                 :            :  *   Array of DR rule actions to be used during flow creation..
    3361                 :            :  * @param[in] acts_num
    3362                 :            :  *   Pointer to the real acts_num flow has.
    3363                 :            :  *
    3364                 :            :  * @return
    3365                 :            :  *    0 on success, negative value otherwise and rte_errno is set.
    3366                 :            :  */
    3367                 :            : static __rte_always_inline int
    3368                 :            : flow_hw_modify_field_construct(struct mlx5_modification_cmd *mhdr_cmd,
    3369                 :            :                                struct mlx5_action_construct_data *act_data,
    3370                 :            :                                const struct mlx5_hw_actions *hw_acts,
    3371                 :            :                                const struct rte_flow_action *action)
    3372                 :            : {
    3373                 :          0 :         const struct rte_flow_action_modify_field *mhdr_action = action->conf;
    3374                 :          0 :         uint8_t values[16] = { 0 };
    3375                 :            :         unaligned_uint32_t *value_p;
    3376                 :            :         uint32_t i;
    3377                 :            :         struct field_modify_info *field;
    3378                 :            : 
    3379   [ #  #  #  #  :          0 :         if (!hw_acts->mhdr)
          #  #  #  #  #  
                      # ]
    3380                 :            :                 return -1;
    3381   [ #  #  #  #  :          0 :         if (hw_acts->mhdr->shared || act_data->modify_header.shared)
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
    3382                 :            :                 return 0;
    3383                 :            :         MLX5_ASSERT(mhdr_action->operation == RTE_FLOW_MODIFY_SET ||
    3384                 :            :                     mhdr_action->operation == RTE_FLOW_MODIFY_ADD);
    3385   [ #  #  #  #  :          0 :         if (mhdr_action->src.field != RTE_FLOW_FIELD_VALUE &&
          #  #  #  #  #  
                      # ]
    3386                 :            :             mhdr_action->src.field != RTE_FLOW_FIELD_POINTER)
    3387                 :            :                 return 0;
    3388   [ #  #  #  #  :          0 :         if (mhdr_action->src.field == RTE_FLOW_FIELD_VALUE)
          #  #  #  #  #  
                      # ]
    3389   [ #  #  #  #  :          0 :                 rte_memcpy(values, &mhdr_action->src.value, sizeof(values));
          #  #  #  #  #  
                      # ]
    3390                 :            :         else
    3391   [ #  #  #  #  :          0 :                 rte_memcpy(values, mhdr_action->src.pvalue, sizeof(values));
          #  #  #  #  #  
                      # ]
    3392   [ #  #  #  #  :          0 :         if (mhdr_action->dst.field == RTE_FLOW_FIELD_META ||
          #  #  #  #  #  
                      # ]
    3393   [ #  #  #  #  :          0 :             mhdr_action->dst.field == RTE_FLOW_FIELD_TAG ||
          #  #  #  #  #  
                      # ]
    3394   [ #  #  #  #  :          0 :             mhdr_action->dst.field == RTE_FLOW_FIELD_METER_COLOR ||
          #  #  #  #  #  
                      # ]
    3395                 :            :             mhdr_action->dst.field == (enum rte_flow_field_id)MLX5_RTE_FLOW_FIELD_META_REG) {
    3396                 :          0 :                 uint8_t tag_index = flow_tag_index_get(&mhdr_action->dst);
    3397                 :            : 
    3398                 :            :                 value_p = (unaligned_uint32_t *)values;
    3399   [ #  #  #  #  :          0 :                 if (mhdr_action->dst.field == RTE_FLOW_FIELD_TAG &&
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
    3400                 :            :                     tag_index == RTE_PMD_MLX5_LINEAR_HASH_TAG_INDEX)
    3401   [ #  #  #  #  :          0 :                         *value_p = rte_cpu_to_be_32(*value_p << 16);
          #  #  #  #  #  
                      # ]
    3402                 :            :                 else
    3403   [ #  #  #  #  :          0 :                         *value_p = rte_cpu_to_be_32(*value_p);
          #  #  #  #  #  
                      # ]
    3404   [ #  #  #  #  :          0 :         } else if (mhdr_action->dst.field == RTE_FLOW_FIELD_GTP_PSC_QFI ||
          #  #  #  #  #  
                      # ]
    3405                 :            :                    mhdr_action->dst.field == RTE_FLOW_FIELD_GENEVE_OPT_TYPE) {
    3406                 :            :                 uint32_t tmp;
    3407                 :            : 
    3408                 :            :                 /*
    3409                 :            :                  * Both QFI and Geneve option type are passed as an uint8_t integer,
    3410                 :            :                  * but it is accessed through a 2nd least significant byte of a 32-bit
    3411                 :            :                  * field in modify header command.
    3412                 :            :                  */
    3413                 :          0 :                 tmp = values[0];
    3414                 :            :                 value_p = (unaligned_uint32_t *)values;
    3415   [ #  #  #  #  :          0 :                 *value_p = rte_cpu_to_be_32(tmp << 8);
          #  #  #  #  #  
                      # ]
    3416                 :            :         }
    3417                 :          0 :         i = act_data->modify_header.mhdr_cmds_off;
    3418                 :          0 :         field = act_data->modify_header.field;
    3419                 :            :         do {
    3420                 :            :                 uint32_t off_b;
    3421                 :            :                 uint32_t mask;
    3422                 :            :                 uint32_t data;
    3423                 :            :                 const uint8_t *mask_src;
    3424                 :            : 
    3425   [ #  #  #  #  :          0 :                 if (i >= act_data->modify_header.mhdr_cmds_end)
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
    3426                 :            :                         return -1;
    3427   [ #  #  #  #  :          0 :                 if (flow_hw_mhdr_cmd_is_nop(&mhdr_cmd[i])) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
    3428                 :          0 :                         ++i;
    3429                 :          0 :                         continue;
    3430                 :            :                 }
    3431                 :          0 :                 mask_src = (const uint8_t *)act_data->modify_header.mask;
    3432                 :          0 :                 mask = flow_dv_fetch_field(mask_src + field->offset, field->size);
    3433   [ #  #  #  #  :          0 :                 if (!mask) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
    3434                 :          0 :                         ++field;
    3435                 :          0 :                         continue;
    3436                 :            :                 }
    3437                 :          0 :                 off_b = rte_bsf32(mask);
    3438                 :          0 :                 data = flow_dv_fetch_field(values + field->offset, field->size);
    3439                 :            :                 /*
    3440                 :            :                  * IPv6 DSCP uses OUT_IPV6_TRAFFIC_CLASS as ID but it starts from 2
    3441                 :            :                  * bits left. Shift the data left for IPv6 DSCP
    3442                 :            :                  */
    3443   [ #  #  #  #  :          0 :                 if (field->id == MLX5_MODI_OUT_IPV6_TRAFFIC_CLASS &&
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    3444   [ #  #  #  #  :          0 :                     mhdr_action->dst.field == RTE_FLOW_FIELD_IPV6_DSCP)
                   #  # ]
    3445                 :          0 :                         data <<= MLX5_IPV6_HDR_DSCP_SHIFT;
    3446                 :          0 :                 data = (data & mask) >> off_b;
    3447   [ #  #  #  #  :          0 :                 mhdr_cmd[i++].data1 = rte_cpu_to_be_32(data);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
    3448                 :          0 :                 ++field;
    3449   [ #  #  #  #  :          0 :         } while (field->size);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
    3450                 :            :         return 0;
    3451                 :            : }
    3452                 :            : 
    3453                 :            : /**
    3454                 :            :  * Release any actions allocated for the flow rule during actions construction.
    3455                 :            :  *
    3456                 :            :  * @param[in] flow
    3457                 :            :  *   Pointer to flow structure.
    3458                 :            :  */
    3459                 :            : static void
    3460                 :          0 : flow_hw_release_actions(struct rte_eth_dev *dev,
    3461                 :            :                         uint32_t queue,
    3462                 :            :                         struct rte_flow_hw *flow)
    3463                 :            : {
    3464                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    3465                 :          0 :         struct mlx5_aso_mtr_pool *pool = priv->hws_mpool;
    3466                 :          0 :         struct rte_flow_hw_aux *aux = mlx5_flow_hw_aux(dev->data->port_id, flow);
    3467                 :            : 
    3468         [ #  # ]:          0 :         if (flow->flags & MLX5_FLOW_HW_FLOW_FLAG_FATE_JUMP)
    3469                 :          0 :                 flow_hw_jump_release(dev, flow->jump);
    3470         [ #  # ]:          0 :         else if (flow->flags & MLX5_FLOW_HW_FLOW_FLAG_FATE_HRXQ)
    3471                 :          0 :                 mlx5_hrxq_obj_release(dev, flow->hrxq);
    3472         [ #  # ]:          0 :         if (flow->flags & MLX5_FLOW_HW_FLOW_FLAG_CNT_ID)
    3473                 :          0 :                 flow_hw_age_count_release(priv, queue, flow, NULL);
    3474         [ #  # ]:          0 :         if (flow->flags & MLX5_FLOW_HW_FLOW_FLAG_MTR_ID)
    3475                 :          0 :                 mlx5_ipool_free(pool->idx_pool, mlx5_flow_hw_aux_get_mtr_id(flow, aux));
    3476                 :          0 : }
    3477                 :            : 
    3478                 :            : /**
    3479                 :            :  * Construct flow action array.
    3480                 :            :  *
    3481                 :            :  * For action template contains dynamic actions, these actions need to
    3482                 :            :  * be updated according to the rte_flow action during flow creation.
    3483                 :            :  *
    3484                 :            :  * @param[in] dev
    3485                 :            :  *   Pointer to the rte_eth_dev structure.
    3486                 :            :  * @param[in] flow
    3487                 :            :  *   Pointer to flow structure.
    3488                 :            :  * @param[in] ap
    3489                 :            :  *   Pointer to container for temporarily constructed actions' parameters.
    3490                 :            :  * @param[in] hw_acts
    3491                 :            :  *   Pointer to translated actions from template.
    3492                 :            :  * @param[in] items_flags
    3493                 :            :  *   Item flags.
    3494                 :            :  * @param[in] table
    3495                 :            :  *   Pointer to the template table.
    3496                 :            :  * @param[in] actions
    3497                 :            :  *   Array of rte_flow action need to be checked.
    3498                 :            :  * @param[in] rule_acts
    3499                 :            :  *   Array of DR rule actions to be used during flow creation..
    3500                 :            :  * @param[in] acts_num
    3501                 :            :  *   Pointer to the real acts_num flow has.
    3502                 :            :  *
    3503                 :            :  * @return
    3504                 :            :  *    0 on success, negative value otherwise and rte_errno is set.
    3505                 :            :  */
    3506                 :            : static __rte_always_inline int
    3507                 :            : flow_hw_actions_construct(struct rte_eth_dev *dev,
    3508                 :            :                           struct rte_flow_hw *flow,
    3509                 :            :                           struct mlx5_flow_hw_action_params *ap,
    3510                 :            :                           const struct mlx5_hw_action_template *hw_at,
    3511                 :            :                           uint64_t item_flags,
    3512                 :            :                           struct rte_flow_template_table *table,
    3513                 :            :                           const struct rte_flow_action actions[],
    3514                 :            :                           struct mlx5dr_rule_action *rule_acts,
    3515                 :            :                           uint32_t queue,
    3516                 :            :                           struct rte_flow_error *error)
    3517                 :            : {
    3518                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    3519                 :          0 :         struct mlx5_aso_mtr_pool *pool = priv->hws_mpool;
    3520                 :            :         struct mlx5_action_construct_data *act_data;
    3521                 :          0 :         const struct rte_flow_actions_template *at = hw_at->action_template;
    3522                 :            :         const struct mlx5_hw_actions *hw_acts = &hw_at->acts;
    3523                 :            :         const struct rte_flow_action *action;
    3524                 :            :         const struct rte_flow_action_raw_encap *raw_encap_data;
    3525                 :            :         const struct rte_flow_action_ipv6_ext_push *ipv6_push;
    3526                 :            :         const struct rte_flow_item *enc_item = NULL;
    3527                 :            :         const struct rte_flow_action_ethdev *port_action = NULL;
    3528                 :            :         const struct rte_flow_action_meter *meter = NULL;
    3529                 :            :         const struct rte_flow_action_age *age = NULL;
    3530                 :            :         const struct rte_flow_action_nat64 *nat64_c = NULL;
    3531                 :          0 :         struct rte_flow_attr attr = {
    3532                 :            :                 .ingress = 1,
    3533                 :            :         };
    3534                 :            :         uint32_t ft_flag;
    3535                 :            :         int ret;
    3536                 :          0 :         size_t encap_len = 0;
    3537                 :            :         uint32_t age_idx = 0;
    3538                 :            :         uint32_t mtr_idx = 0;
    3539                 :            :         struct mlx5_aso_mtr *aso_mtr;
    3540                 :            :         struct mlx5_multi_pattern_segment *mp_segment = NULL;
    3541                 :            :         struct rte_flow_hw_aux *aux;
    3542                 :            : 
    3543                 :          0 :         attr.group = table->grp->group_id;
    3544                 :          0 :         ft_flag = mlx5_hw_act_flag[!!table->grp->group_id][table->type];
    3545                 :          0 :         if (table->type == MLX5DR_TABLE_TYPE_FDB) {
    3546                 :          0 :                 attr.transfer = 1;
    3547                 :            :                 attr.ingress = 1;
    3548   [ #  #  #  #  :          0 :         } else if (table->type == MLX5DR_TABLE_TYPE_NIC_TX) {
          #  #  #  #  #  
                      # ]
    3549                 :          0 :                 attr.egress = 1;
    3550                 :          0 :                 attr.ingress = 0;
    3551                 :            :         } else {
    3552                 :            :                 attr.ingress = 1;
    3553                 :            :         }
    3554   [ #  #  #  #  :          0 :         if (hw_acts->mhdr && hw_acts->mhdr->mhdr_cmds_num > 0 && !hw_acts->mhdr->shared) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
    3555                 :          0 :                 uint16_t pos = hw_acts->mhdr->pos;
    3556                 :            : 
    3557                 :          0 :                 mp_segment = mlx5_multi_pattern_segment_find(table, flow->res_idx);
    3558   [ #  #  #  #  :          0 :                 if (!mp_segment || !mp_segment->mhdr_action)
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
    3559                 :            :                         return -1;
    3560                 :          0 :                 rule_acts[pos].action = mp_segment->mhdr_action;
    3561                 :            :                 /* offset is relative to DR action */
    3562                 :          0 :                 rule_acts[pos].modify_header.offset =
    3563                 :          0 :                                         flow->res_idx - mp_segment->head_index;
    3564                 :          0 :                 rule_acts[pos].modify_header.data =
    3565                 :          0 :                                         (uint8_t *)ap->mhdr_cmd;
    3566                 :            :                 MLX5_ASSERT(hw_acts->mhdr->mhdr_cmds_num <= MLX5_MHDR_MAX_CMD);
    3567                 :          0 :                 rte_memcpy(ap->mhdr_cmd, hw_acts->mhdr->mhdr_cmds,
    3568   [ #  #  #  #  :          0 :                            sizeof(*ap->mhdr_cmd) * hw_acts->mhdr->mhdr_cmds_num);
          #  #  #  #  #  
                      # ]
    3569                 :            :         }
    3570   [ #  #  #  #  :          0 :         LIST_FOREACH(act_data, &hw_acts->act_list, next) {
          #  #  #  #  #  
                      # ]
    3571                 :            :                 uint32_t jump_group;
    3572                 :            :                 uint32_t tag;
    3573                 :            :                 struct mlx5_hw_jump_action *jump;
    3574                 :            :                 struct mlx5_hrxq *hrxq;
    3575                 :            :                 uint32_t ct_idx;
    3576                 :            :                 cnt_id_t cnt_id;
    3577                 :            :                 uint32_t *cnt_queue;
    3578                 :            :                 uint32_t mtr_id;
    3579                 :            :                 struct rte_flow_template_table *jump_table;
    3580                 :            : 
    3581                 :          0 :                 action = &actions[act_data->action_src];
    3582                 :            :                 /*
    3583                 :            :                  * action template construction replaces
    3584                 :            :                  * OF_SET_VLAN_VID with MODIFY_FIELD
    3585                 :            :                  */
    3586                 :          0 :                 if (action->type == RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID)
    3587                 :            :                         MLX5_ASSERT(act_data->type ==
    3588                 :            :                                     RTE_FLOW_ACTION_TYPE_MODIFY_FIELD);
    3589                 :            :                 else
    3590                 :            :                         MLX5_ASSERT(action->type ==
    3591                 :            :                                     RTE_FLOW_ACTION_TYPE_INDIRECT ||
    3592                 :            :                                     (int)action->type == act_data->type);
    3593   [ #  #  #  #  :          0 :                 switch ((int)act_data->type) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
    3594                 :          0 :                 case RTE_FLOW_ACTION_TYPE_INDIRECT_LIST:
    3595                 :          0 :                         act_data->indirect_list_cb(dev, act_data, action,
    3596                 :          0 :                                                    &rule_acts[act_data->action_dst]);
    3597                 :          0 :                         break;
    3598                 :          0 :                 case RTE_FLOW_ACTION_TYPE_INDIRECT:
    3599                 :          0 :                         if (flow_hw_shared_action_construct
    3600                 :            :                                         (dev, queue, action, table,
    3601                 :          0 :                                          item_flags, at->action_flags, flow,
    3602   [ #  #  #  #  :          0 :                                          &rule_acts[act_data->action_dst]))
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
    3603                 :          0 :                                 goto error;
    3604                 :            :                         break;
    3605                 :            :                 case RTE_FLOW_ACTION_TYPE_VOID:
    3606                 :            :                         break;
    3607                 :          0 :                 case RTE_FLOW_ACTION_TYPE_MARK:
    3608                 :          0 :                         tag = mlx5_flow_mark_set
    3609                 :            :                               (((const struct rte_flow_action_mark *)
    3610                 :          0 :                               (action->conf))->id);
    3611                 :          0 :                         rule_acts[act_data->action_dst].tag.value = tag;
    3612                 :          0 :                         break;
    3613                 :          0 :                 case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
    3614                 :          0 :                         rule_acts[act_data->action_dst].push_vlan.vlan_hdr =
    3615                 :          0 :                                 vlan_hdr_to_be32(action);
    3616                 :          0 :                         break;
    3617                 :          0 :                 case RTE_FLOW_ACTION_TYPE_JUMP:
    3618                 :          0 :                         jump_group = ((const struct rte_flow_action_jump *)
    3619                 :          0 :                                                 action->conf)->group;
    3620                 :          0 :                         jump = flow_hw_jump_action_register
    3621                 :          0 :                                 (dev, &table->cfg, jump_group, NULL);
    3622   [ #  #  #  #  :          0 :                         if (!jump)
          #  #  #  #  #  
                      # ]
    3623                 :          0 :                                 goto error;
    3624                 :          0 :                         rule_acts[act_data->action_dst].action =
    3625   [ #  #  #  #  :          0 :                         (!!attr.group) ? jump->hws_action : jump->root_action;
          #  #  #  #  #  
                      # ]
    3626                 :          0 :                         flow->jump = jump;
    3627                 :          0 :                         flow->flags |= MLX5_FLOW_HW_FLOW_FLAG_FATE_JUMP;
    3628                 :          0 :                         break;
    3629                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RSS:
    3630                 :            :                 case RTE_FLOW_ACTION_TYPE_QUEUE:
    3631                 :          0 :                         hrxq = flow_hw_tir_action_register(dev, ft_flag, action);
    3632   [ #  #  #  #  :          0 :                         if (!hrxq)
          #  #  #  #  #  
                      # ]
    3633                 :          0 :                                 goto error;
    3634                 :          0 :                         rule_acts[act_data->action_dst].action = hrxq->action;
    3635                 :          0 :                         flow->hrxq = hrxq;
    3636                 :          0 :                         flow->flags |= MLX5_FLOW_HW_FLOW_FLAG_FATE_HRXQ;
    3637                 :          0 :                         break;
    3638                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_RSS:
    3639                 :          0 :                         if (flow_hw_shared_action_get
    3640                 :            :                                 (dev, act_data, item_flags,
    3641                 :          0 :                                  &rule_acts[act_data->action_dst]))
    3642                 :          0 :                                 goto error;
    3643                 :            :                         break;
    3644                 :          0 :                 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
    3645                 :          0 :                         enc_item = ((const struct rte_flow_action_vxlan_encap *)
    3646                 :          0 :                                    action->conf)->definition;
    3647   [ #  #  #  #  :          0 :                         if (flow_dv_convert_encap_data(enc_item, ap->encap_data, &encap_len, NULL))
          #  #  #  #  #  
                      # ]
    3648                 :          0 :                                 goto error;
    3649                 :            :                         break;
    3650                 :          0 :                 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
    3651                 :          0 :                         enc_item = ((const struct rte_flow_action_nvgre_encap *)
    3652                 :          0 :                                    action->conf)->definition;
    3653   [ #  #  #  #  :          0 :                         if (flow_dv_convert_encap_data(enc_item, ap->encap_data, &encap_len, NULL))
          #  #  #  #  #  
                      # ]
    3654                 :          0 :                                 goto error;
    3655                 :            :                         break;
    3656                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
    3657                 :          0 :                         raw_encap_data =
    3658                 :            :                                 (const struct rte_flow_action_raw_encap *)
    3659                 :            :                                  action->conf;
    3660                 :            :                         MLX5_ASSERT(raw_encap_data->size == act_data->encap.len);
    3661   [ #  #  #  #  :          0 :                         if (unlikely(act_data->encap.len > MLX5_ENCAP_MAX_LEN))
          #  #  #  #  #  
                      # ]
    3662                 :            :                                 return -1;
    3663   [ #  #  #  #  :          0 :                         rte_memcpy(ap->encap_data, raw_encap_data->data, act_data->encap.len);
          #  #  #  #  #  
                      # ]
    3664                 :            :                         break;
    3665                 :          0 :                 case RTE_FLOW_ACTION_TYPE_IPV6_EXT_PUSH:
    3666                 :          0 :                         ipv6_push =
    3667                 :            :                                 (const struct rte_flow_action_ipv6_ext_push *)action->conf;
    3668                 :            :                         MLX5_ASSERT(ipv6_push->size == act_data->ipv6_ext.len);
    3669   [ #  #  #  #  :          0 :                         if (unlikely(act_data->ipv6_ext.len > MLX5_PUSH_MAX_LEN))
          #  #  #  #  #  
                      # ]
    3670                 :            :                                 return -1;
    3671   [ #  #  #  #  :          0 :                         rte_memcpy(ap->ipv6_push_data, ipv6_push->data,
          #  #  #  #  #  
                      # ]
    3672                 :            :                                    act_data->ipv6_ext.len);
    3673                 :            :                         break;
    3674                 :          0 :                 case RTE_FLOW_ACTION_TYPE_MODIFY_FIELD:
    3675   [ #  #  #  #  :          0 :                         if (action->type == RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID)
          #  #  #  #  #  
                      # ]
    3676                 :          0 :                                 ret = flow_hw_set_vlan_vid_construct(dev, ap->mhdr_cmd,
    3677                 :            :                                                                      act_data,
    3678                 :            :                                                                      hw_acts,
    3679                 :            :                                                                      action);
    3680                 :            :                         else
    3681   [ #  #  #  #  :          0 :                                 ret = flow_hw_modify_field_construct(ap->mhdr_cmd,
          #  #  #  #  #  
                      # ]
    3682                 :            :                                                                      act_data,
    3683                 :            :                                                                      hw_acts,
    3684                 :            :                                                                      action);
    3685   [ #  #  #  #  :          0 :                         if (ret)
          #  #  #  #  #  
                      # ]
    3686                 :          0 :                                 goto error;
    3687                 :            :                         break;
    3688                 :          0 :                 case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
    3689                 :          0 :                         port_action = action->conf;
    3690   [ #  #  #  #  :          0 :                         if (!priv->hw_vport[port_action->port_id])
          #  #  #  #  #  
                      # ]
    3691                 :          0 :                                 goto error;
    3692                 :          0 :                         rule_acts[act_data->action_dst].action =
    3693                 :            :                                         priv->hw_vport[port_action->port_id];
    3694                 :          0 :                         break;
    3695                 :          0 :                 case RTE_FLOW_ACTION_TYPE_QUOTA:
    3696                 :          0 :                         flow_hw_construct_quota(priv,
    3697                 :          0 :                                                 rule_acts + act_data->action_dst,
    3698                 :            :                                                 act_data->shared_meter.id);
    3699                 :          0 :                         break;
    3700                 :          0 :                 case RTE_FLOW_ACTION_TYPE_METER:
    3701                 :          0 :                         meter = action->conf;
    3702                 :          0 :                         mtr_id = meter->mtr_id;
    3703                 :          0 :                         aso_mtr = mlx5_aso_meter_by_idx(priv, mtr_id);
    3704                 :          0 :                         rule_acts[act_data->action_dst].action =
    3705                 :          0 :                                 priv->mtr_bulk.action;
    3706                 :          0 :                         rule_acts[act_data->action_dst].aso_meter.offset =
    3707                 :          0 :                                                                 aso_mtr->offset;
    3708                 :          0 :                         jump = flow_hw_jump_action_register
    3709                 :          0 :                                 (dev, &table->cfg, aso_mtr->fm.group, NULL);
    3710   [ #  #  #  #  :          0 :                         if (!jump)
          #  #  #  #  #  
                      # ]
    3711                 :          0 :                                 goto error;
    3712                 :            :                         MLX5_ASSERT
    3713                 :            :                                 (!rule_acts[act_data->action_dst + 1].action);
    3714                 :          0 :                         rule_acts[act_data->action_dst + 1].action =
    3715   [ #  #  #  #  :          0 :                                         (!!attr.group) ? jump->hws_action :
          #  #  #  #  #  
                      # ]
    3716                 :            :                                                          jump->root_action;
    3717                 :          0 :                         flow->jump = jump;
    3718                 :          0 :                         flow->flags |= MLX5_FLOW_HW_FLOW_FLAG_FATE_JUMP;
    3719   [ #  #  #  #  :          0 :                         if (mlx5_aso_mtr_wait(priv, aso_mtr, true))
          #  #  #  #  #  
                      # ]
    3720                 :          0 :                                 goto error;
    3721                 :            :                         break;
    3722                 :          0 :                 case RTE_FLOW_ACTION_TYPE_AGE:
    3723                 :          0 :                         aux = mlx5_flow_hw_aux(dev->data->port_id, flow);
    3724                 :          0 :                         age = action->conf;
    3725                 :            :                         /*
    3726                 :            :                          * First, create the AGE parameter, then create its
    3727                 :            :                          * counter later:
    3728                 :            :                          * Regular counter - in next case.
    3729                 :            :                          * Indirect counter - update it after the loop.
    3730                 :            :                          */
    3731                 :          0 :                         age_idx = mlx5_hws_age_action_create(priv, queue, 0,
    3732                 :            :                                                              age,
    3733                 :            :                                                              flow->res_idx,
    3734                 :            :                                                              error);
    3735   [ #  #  #  #  :          0 :                         if (age_idx == 0)
          #  #  #  #  #  
                      # ]
    3736                 :          0 :                                 goto error;
    3737                 :            :                         mlx5_flow_hw_aux_set_age_idx(flow, aux, age_idx);
    3738                 :          0 :                         flow->flags |= MLX5_FLOW_HW_FLOW_FLAG_AGE_IDX;
    3739   [ #  #  #  #  :          0 :                         if (at->action_flags & MLX5_FLOW_ACTION_INDIRECT_COUNT)
          #  #  #  #  #  
                      # ]
    3740                 :            :                                 /*
    3741                 :            :                                  * When AGE uses indirect counter, no need to
    3742                 :            :                                  * create counter but need to update it with the
    3743                 :            :                                  * AGE parameter, will be done after the loop.
    3744                 :            :                                  */
    3745                 :            :                                 break;
    3746                 :            :                         /* Fall-through. */
    3747                 :            :                 case RTE_FLOW_ACTION_TYPE_COUNT:
    3748                 :            :                         cnt_queue = mlx5_hws_cnt_get_queue(priv, &queue);
    3749                 :            :                         ret = mlx5_hws_cnt_pool_get(priv->hws_cpool, cnt_queue, &cnt_id, age_idx);
    3750   [ #  #  #  #  :          0 :                         if (ret != 0) {
          #  #  #  #  #  
                      # ]
    3751                 :          0 :                                 rte_flow_error_set(error, -ret, RTE_FLOW_ERROR_TYPE_ACTION,
    3752                 :            :                                                 action, "Failed to allocate flow counter");
    3753                 :          0 :                                 goto error;
    3754                 :            :                         }
    3755                 :          0 :                         ret = mlx5_hws_cnt_pool_get_action_offset
    3756                 :            :                                 (priv->hws_cpool,
    3757                 :            :                                  cnt_id,
    3758                 :            :                                  &rule_acts[act_data->action_dst].action,
    3759                 :          0 :                                  &rule_acts[act_data->action_dst].counter.offset
    3760                 :            :                                  );
    3761                 :            :                         if (ret != 0)
    3762                 :            :                                 goto error;
    3763                 :          0 :                         flow->flags |= MLX5_FLOW_HW_FLOW_FLAG_CNT_ID;
    3764                 :          0 :                         flow->cnt_id = cnt_id;
    3765                 :          0 :                         break;
    3766                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_COUNT:
    3767                 :          0 :                         ret = mlx5_hws_cnt_pool_get_action_offset
    3768                 :            :                                 (priv->hws_cpool,
    3769                 :            :                                  act_data->shared_counter.id,
    3770                 :            :                                  &rule_acts[act_data->action_dst].action,
    3771                 :          0 :                                  &rule_acts[act_data->action_dst].counter.offset
    3772                 :            :                                  );
    3773                 :            :                         if (ret != 0)
    3774                 :            :                                 goto error;
    3775                 :          0 :                         flow->flags |= MLX5_FLOW_HW_FLOW_FLAG_CNT_ID;
    3776                 :          0 :                         flow->cnt_id = act_data->shared_counter.id;
    3777                 :          0 :                         break;
    3778                 :          0 :                 case RTE_FLOW_ACTION_TYPE_CONNTRACK:
    3779                 :          0 :                         ct_idx = MLX5_INDIRECT_ACTION_IDX_GET(action->conf);
    3780                 :          0 :                         if (flow_hw_ct_compile(dev, queue, ct_idx,
    3781                 :          0 :                                                &rule_acts[act_data->action_dst]))
    3782                 :          0 :                                 goto error;
    3783                 :            :                         break;
    3784                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_METER_MARK:
    3785                 :          0 :                         mtr_id = act_data->shared_meter.id &
    3786                 :            :                                 ((1u << MLX5_INDIRECT_ACTION_TYPE_OFFSET) - 1);
    3787                 :            :                         /* Find ASO object. */
    3788                 :          0 :                         aso_mtr = mlx5_ipool_get(pool->idx_pool, mtr_id);
    3789   [ #  #  #  #  :          0 :                         if (!aso_mtr)
          #  #  #  #  #  
                      # ]
    3790                 :          0 :                                 goto error;
    3791                 :          0 :                         rule_acts[act_data->action_dst].action =
    3792                 :          0 :                                                         pool->action;
    3793                 :          0 :                         rule_acts[act_data->action_dst].aso_meter.offset =
    3794                 :          0 :                                                         aso_mtr->offset;
    3795                 :          0 :                         break;
    3796                 :          0 :                 case RTE_FLOW_ACTION_TYPE_METER_MARK:
    3797                 :            :                         /*
    3798                 :            :                          * Allocate meter directly will slow down flow
    3799                 :            :                          * insertion rate.
    3800                 :            :                          */
    3801                 :            :                         ret = flow_hw_meter_mark_compile(dev,
    3802                 :          0 :                                 act_data->action_dst, action,
    3803                 :            :                                 rule_acts, &mtr_idx, MLX5_HW_INV_QUEUE, error);
    3804                 :            :                         if (ret != 0)
    3805                 :          0 :                                 goto error;
    3806                 :          0 :                         aux = mlx5_flow_hw_aux(dev->data->port_id, flow);
    3807                 :            :                         mlx5_flow_hw_aux_set_mtr_id(flow, aux, mtr_idx);
    3808                 :          0 :                         flow->flags |= MLX5_FLOW_HW_FLOW_FLAG_MTR_ID;
    3809                 :          0 :                         break;
    3810                 :          0 :                 case RTE_FLOW_ACTION_TYPE_NAT64:
    3811                 :          0 :                         nat64_c = action->conf;
    3812                 :          0 :                         rule_acts[act_data->action_dst].action =
    3813                 :          0 :                                 priv->action_nat64[table->type][nat64_c->type];
    3814                 :          0 :                         break;
    3815                 :          0 :                 case RTE_FLOW_ACTION_TYPE_JUMP_TO_TABLE_INDEX:
    3816                 :          0 :                         jump_table = ((const struct rte_flow_action_jump_to_table_index *)
    3817                 :          0 :                                                 action->conf)->table;
    3818   [ #  #  #  #  :          0 :                         if (likely(!rte_flow_template_table_resizable(dev->data->port_id,
          #  #  #  #  #  
                      # ]
    3819                 :            :                                                                       &table->cfg.attr))) {
    3820                 :          0 :                                 rule_acts[act_data->action_dst].action =
    3821                 :          0 :                                         jump_table->matcher_info[0].jump;
    3822                 :            :                         } else {
    3823                 :            :                                 uint32_t selector;
    3824                 :          0 :                                 rte_rwlock_read_lock(&table->matcher_replace_rwlk);
    3825                 :          0 :                                 selector = table->matcher_selector;
    3826                 :          0 :                                 rule_acts[act_data->action_dst].action =
    3827                 :          0 :                                         jump_table->matcher_info[selector].jump;
    3828                 :          0 :                                 rte_rwlock_read_unlock(&table->matcher_replace_rwlk);
    3829                 :            :                         }
    3830                 :          0 :                         rule_acts[act_data->action_dst].jump_to_matcher.offset =
    3831                 :            :                                 ((const struct rte_flow_action_jump_to_table_index *)
    3832                 :          0 :                                 action->conf)->index;
    3833                 :          0 :                         break;
    3834                 :            :                 default:
    3835                 :            :                         break;
    3836                 :            :                 }
    3837                 :            :         }
    3838   [ #  #  #  #  :          0 :         if (at->action_flags & MLX5_FLOW_ACTION_INDIRECT_COUNT) {
          #  #  #  #  #  
                      # ]
    3839                 :            :                 /* If indirect count is used, then CNT_ID flag should be set. */
    3840                 :            :                 MLX5_ASSERT(flow->flags & MLX5_FLOW_HW_FLOW_FLAG_CNT_ID);
    3841   [ #  #  #  #  :          0 :                 if (at->action_flags & MLX5_FLOW_ACTION_INDIRECT_AGE) {
          #  #  #  #  #  
                      # ]
    3842                 :            :                         /* If indirect AGE is used, then AGE_IDX flag should be set. */
    3843                 :            :                         MLX5_ASSERT(flow->flags & MLX5_FLOW_HW_FLOW_FLAG_AGE_IDX);
    3844                 :          0 :                         aux = mlx5_flow_hw_aux(dev->data->port_id, flow);
    3845                 :          0 :                         age_idx = mlx5_flow_hw_aux_get_age_idx(flow, aux) &
    3846                 :            :                                   MLX5_HWS_AGE_IDX_MASK;
    3847   [ #  #  #  #  :          0 :                         if (mlx5_hws_cnt_age_get(priv->hws_cpool, flow->cnt_id) != age_idx)
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
    3848                 :            :                                 /*
    3849                 :            :                                  * This is first use of this indirect counter
    3850                 :            :                                  * for this indirect AGE, need to increase the
    3851                 :            :                                  * number of counters.
    3852                 :            :                                  */
    3853                 :            :                                 mlx5_hws_age_nb_cnt_increase(priv, age_idx);
    3854                 :            :                 }
    3855                 :            :                 /*
    3856                 :            :                  * Update this indirect counter the indirect/direct AGE in which
    3857                 :            :                  * using it.
    3858                 :            :                  */
    3859   [ #  #  #  #  :          0 :                 mlx5_hws_cnt_age_set(priv->hws_cpool, flow->cnt_id, age_idx);
          #  #  #  #  #  
                      # ]
    3860                 :            :         }
    3861   [ #  #  #  #  :          0 :         if (hw_acts->encap_decap && !hw_acts->encap_decap->shared) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
    3862   [ #  #  #  #  :          0 :                 int ix = mlx5_multi_pattern_reformat_to_index(hw_acts->encap_decap->action_type);
          #  #  #  #  #  
                      # ]
    3863                 :          0 :                 struct mlx5dr_rule_action *ra = &rule_acts[hw_acts->encap_decap_pos];
    3864                 :            : 
    3865   [ #  #  #  #  :          0 :                 if (ix < 0)
          #  #  #  #  #  
                      # ]
    3866                 :          0 :                         goto error;
    3867   [ #  #  #  #  :          0 :                 if (!mp_segment)
          #  #  #  #  #  
                      # ]
    3868                 :          0 :                         mp_segment = mlx5_multi_pattern_segment_find(table, flow->res_idx);
    3869   [ #  #  #  #  :          0 :                 if (!mp_segment || !mp_segment->reformat_action[ix])
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
    3870                 :          0 :                         goto error;
    3871                 :          0 :                 ra->action = mp_segment->reformat_action[ix];
    3872                 :            :                 /* reformat offset is relative to selected DR action */
    3873                 :          0 :                 ra->reformat.offset = flow->res_idx - mp_segment->head_index;
    3874                 :          0 :                 ra->reformat.data = ap->encap_data;
    3875                 :            :         }
    3876   [ #  #  #  #  :          0 :         if (hw_acts->push_remove && !hw_acts->push_remove->shared) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
    3877                 :          0 :                 rule_acts[hw_acts->push_remove_pos].ipv6_ext.offset =
    3878                 :          0 :                                 flow->res_idx - 1;
    3879                 :          0 :                 rule_acts[hw_acts->push_remove_pos].ipv6_ext.header = ap->ipv6_push_data;
    3880                 :            :         }
    3881   [ #  #  #  #  :          0 :         if (mlx5_hws_cnt_id_valid(hw_acts->cnt_id)) {
          #  #  #  #  #  
                      # ]
    3882                 :          0 :                 flow->flags |= MLX5_FLOW_HW_FLOW_FLAG_CNT_ID;
    3883                 :          0 :                 flow->cnt_id = hw_acts->cnt_id;
    3884                 :            :         }
    3885                 :            :         return 0;
    3886                 :            : 
    3887                 :          0 : error:
    3888                 :          0 :         flow_hw_release_actions(dev, queue, flow);
    3889                 :          0 :         rte_errno = EINVAL;
    3890                 :            :         return -rte_errno;
    3891                 :            : }
    3892                 :            : 
    3893                 :            : static const struct rte_flow_item *
    3894                 :          0 : flow_hw_get_rule_items(struct rte_eth_dev *dev,
    3895                 :            :                        const struct rte_flow_template_table *table,
    3896                 :            :                        const struct rte_flow_item items[],
    3897                 :            :                        uint8_t pattern_template_index,
    3898                 :            :                        struct mlx5_flow_hw_pattern_params *pp)
    3899                 :            : {
    3900                 :          0 :         struct rte_flow_pattern_template *pt = table->its[pattern_template_index];
    3901                 :            : 
    3902                 :            :         /* Only one implicit item can be added to flow rule pattern. */
    3903                 :            :         MLX5_ASSERT(!pt->implicit_port || !pt->implicit_tag);
    3904                 :            :         /* At least one item was allocated in pattern params for items. */
    3905                 :            :         MLX5_ASSERT(MLX5_HW_MAX_ITEMS >= 1);
    3906         [ #  # ]:          0 :         if (pt->implicit_port) {
    3907         [ #  # ]:          0 :                 if (pt->orig_item_nb + 1 > MLX5_HW_MAX_ITEMS) {
    3908                 :          0 :                         rte_errno = ENOMEM;
    3909                 :          0 :                         return NULL;
    3910                 :            :                 }
    3911                 :            :                 /* Set up represented port item in pattern params. */
    3912                 :          0 :                 pp->port_spec = (struct rte_flow_item_ethdev){
    3913                 :          0 :                         .port_id = dev->data->port_id,
    3914                 :            :                 };
    3915                 :          0 :                 pp->items[0] = (struct rte_flow_item){
    3916                 :            :                         .type = RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT,
    3917                 :          0 :                         .spec = &pp->port_spec,
    3918                 :            :                 };
    3919         [ #  # ]:          0 :                 rte_memcpy(&pp->items[1], items, sizeof(*items) * pt->orig_item_nb);
    3920                 :          0 :                 return pp->items;
    3921         [ #  # ]:          0 :         } else if (pt->implicit_tag) {
    3922         [ #  # ]:          0 :                 if (pt->orig_item_nb + 1 > MLX5_HW_MAX_ITEMS) {
    3923                 :          0 :                         rte_errno = ENOMEM;
    3924                 :          0 :                         return NULL;
    3925                 :            :                 }
    3926                 :            :                 /* Set up tag item in pattern params. */
    3927                 :          0 :                 pp->tag_spec = (struct rte_flow_item_tag){
    3928                 :            :                         .data = flow_hw_tx_tag_regc_value(dev),
    3929                 :            :                 };
    3930                 :          0 :                 pp->items[0] = (struct rte_flow_item){
    3931                 :            :                         .type = (enum rte_flow_item_type)MLX5_RTE_FLOW_ITEM_TYPE_TAG,
    3932                 :          0 :                         .spec = &pp->tag_spec,
    3933                 :            :                 };
    3934                 :          0 :                 rte_memcpy(&pp->items[1], items, sizeof(*items) * pt->orig_item_nb);
    3935                 :          0 :                 return pp->items;
    3936                 :            :         } else {
    3937                 :            :                 return items;
    3938                 :            :         }
    3939                 :            : }
    3940                 :            : 
    3941                 :            : /**
    3942                 :            :  * Enqueue HW steering flow creation.
    3943                 :            :  *
    3944                 :            :  * The flow will be applied to the HW only if the postpone bit is not set or
    3945                 :            :  * the extra push function is called.
    3946                 :            :  * The flow creation status should be checked from dequeue result.
    3947                 :            :  *
    3948                 :            :  * @param[in] dev
    3949                 :            :  *   Pointer to the rte_eth_dev structure.
    3950                 :            :  * @param[in] queue
    3951                 :            :  *   The queue to create the flow.
    3952                 :            :  * @param[in] attr
    3953                 :            :  *   Pointer to the flow operation attributes.
    3954                 :            :  * @param[in] table
    3955                 :            :  *   Pointer to the template table.
    3956                 :            :  * @param[in] insertion_type
    3957                 :            :  *   Insertion type for flow rules.
    3958                 :            :  * @param[in] rule_index
    3959                 :            :  *   The item pattern flow follows from the table.
    3960                 :            :  * @param[in] items
    3961                 :            :  *   Items with flow spec value.
    3962                 :            :  * @param[in] pattern_template_index
    3963                 :            :  *   The item pattern flow follows from the table.
    3964                 :            :  * @param[in] actions
    3965                 :            :  *   Action with flow spec value.
    3966                 :            :  * @param[in] action_template_index
    3967                 :            :  *   The action pattern flow follows from the table.
    3968                 :            :  * @param[in] user_data
    3969                 :            :  *   Pointer to the user_data.
    3970                 :            :  * @param[out] error
    3971                 :            :  *   Pointer to error structure.
    3972                 :            :  *
    3973                 :            :  * @return
    3974                 :            :  *    Flow pointer on success, NULL otherwise and rte_errno is set.
    3975                 :            :  */
    3976                 :            : static __rte_always_inline struct rte_flow *
    3977                 :            : flow_hw_async_flow_create_generic(struct rte_eth_dev *dev,
    3978                 :            :                                   uint32_t queue,
    3979                 :            :                                   const struct rte_flow_op_attr *attr,
    3980                 :            :                                   struct rte_flow_template_table *table,
    3981                 :            :                                   enum rte_flow_table_insertion_type insertion_type,
    3982                 :            :                                   uint32_t rule_index,
    3983                 :            :                                   const struct rte_flow_item items[],
    3984                 :            :                                   uint8_t pattern_template_index,
    3985                 :            :                                   const struct rte_flow_action actions[],
    3986                 :            :                                   uint8_t action_template_index,
    3987                 :            :                                   void *user_data,
    3988                 :            :                                   struct rte_flow_error *error)
    3989                 :            : {
    3990                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    3991                 :          0 :         struct mlx5dr_rule_attr rule_attr = {
    3992                 :            :                 .queue_id = queue,
    3993                 :            :                 .user_data = user_data,
    3994                 :          0 :                 .burst = attr->postpone,
    3995                 :            :         };
    3996                 :            :         struct mlx5dr_rule_action *rule_acts;
    3997                 :            :         struct rte_flow_hw *flow = NULL;
    3998                 :            :         const struct rte_flow_item *rule_items;
    3999                 :          0 :         struct rte_flow_error sub_error = { 0 };
    4000                 :          0 :         uint32_t flow_idx = 0;
    4001                 :          0 :         uint32_t res_idx = 0;
    4002                 :            :         int ret;
    4003                 :            : 
    4004                 :          0 :         if (mlx5_fp_debug_enabled()) {
    4005   [ #  #  #  #  :          0 :                 if (flow_hw_async_create_validate(dev, queue, table, insertion_type, rule_index,
                   #  # ]
    4006                 :            :                         items, pattern_template_index, actions, action_template_index, error))
    4007                 :            :                         return NULL;
    4008                 :            :         }
    4009                 :          0 :         flow = mlx5_ipool_malloc(table->flow, &flow_idx);
    4010   [ #  #  #  #  :          0 :         if (!flow) {
                   #  # ]
    4011                 :          0 :                 rte_errno = ENOMEM;
    4012                 :          0 :                 goto error;
    4013                 :            :         }
    4014                 :            :         rule_acts = flow_hw_get_dr_action_buffer(priv, table, action_template_index, queue);
    4015                 :            :         /*
    4016                 :            :          * Set the table here in order to know the destination table
    4017                 :            :          * when free the flow afterward.
    4018                 :            :          */
    4019                 :          0 :         flow->table = table;
    4020                 :          0 :         flow->mt_idx = pattern_template_index;
    4021                 :          0 :         flow->idx = flow_idx;
    4022   [ #  #  #  #  :          0 :         if (table->resource) {
                   #  # ]
    4023                 :          0 :                 mlx5_ipool_malloc(table->resource, &res_idx);
    4024   [ #  #  #  #  :          0 :                 if (!res_idx) {
                   #  # ]
    4025                 :          0 :                         rte_errno = ENOMEM;
    4026                 :          0 :                         goto error;
    4027                 :            :                 }
    4028                 :          0 :                 flow->res_idx = res_idx;
    4029                 :            :         } else {
    4030                 :          0 :                 flow->res_idx = flow_idx;
    4031                 :            :         }
    4032                 :          0 :         flow->flags = 0;
    4033                 :            :         /*
    4034                 :            :          * Set the flow operation type here in order to know if the flow memory
    4035                 :            :          * should be freed or not when get the result from dequeue.
    4036                 :            :          */
    4037                 :          0 :         flow->operation_type = MLX5_FLOW_HW_FLOW_OP_TYPE_CREATE;
    4038                 :          0 :         flow->user_data = user_data;
    4039                 :          0 :         rule_attr.user_data = flow;
    4040                 :            :         /*
    4041                 :            :          * Indexed pool returns 1-based indices, but mlx5dr expects 0-based indices
    4042                 :            :          * for rule insertion hints.
    4043                 :            :          */
    4044   [ #  #  #  # ]:          0 :         flow->rule_idx = (rule_index == UINT32_MAX) ? flow->res_idx - 1 : rule_index;
    4045                 :          0 :         rule_attr.rule_idx = flow->rule_idx;
    4046                 :            :         /*
    4047                 :            :          * Construct the flow actions based on the input actions.
    4048                 :            :          * The implicitly appended action is always fixed, like metadata
    4049                 :            :          * copy action from FDB to NIC Rx.
    4050                 :            :          * No need to copy and contrust a new "actions" list based on the
    4051                 :            :          * user's input, in order to save the cost.
    4052                 :            :          */
    4053                 :          0 :         if (flow_hw_actions_construct(dev, flow, &priv->hw_q[queue].ap,
    4054                 :          0 :                                       &table->ats[action_template_index],
    4055   [ #  #  #  #  :          0 :                                       table->its[pattern_template_index]->item_flags,
                   #  # ]
    4056                 :            :                                       flow->table, actions,
    4057                 :            :                                       rule_acts, queue, &sub_error))
    4058                 :          0 :                 goto error;
    4059                 :          0 :         rule_items = flow_hw_get_rule_items(dev, table, items,
    4060                 :          0 :                                             pattern_template_index, &priv->hw_q[queue].pp);
    4061   [ #  #  #  #  :          0 :         if (!rule_items)
                   #  # ]
    4062                 :          0 :                 goto error;
    4063   [ #  #  #  #  :          0 :         if (likely(!rte_flow_template_table_resizable(dev->data->port_id, &table->cfg.attr))) {
                   #  # ]
    4064                 :          0 :                 ret = mlx5dr_rule_create(table->matcher_info[0].matcher,
    4065                 :            :                                          pattern_template_index, rule_items,
    4066                 :            :                                          action_template_index, rule_acts,
    4067                 :            :                                          &rule_attr,
    4068                 :          0 :                                          (struct mlx5dr_rule *)flow->rule);
    4069                 :            :         } else {
    4070                 :          0 :                 struct rte_flow_hw_aux *aux = mlx5_flow_hw_aux(dev->data->port_id, flow);
    4071                 :            :                 uint32_t selector;
    4072                 :            : 
    4073                 :          0 :                 flow->operation_type = MLX5_FLOW_HW_FLOW_OP_TYPE_RSZ_TBL_CREATE;
    4074                 :          0 :                 rte_rwlock_read_lock(&table->matcher_replace_rwlk);
    4075                 :          0 :                 selector = table->matcher_selector;
    4076                 :          0 :                 ret = mlx5dr_rule_create(table->matcher_info[selector].matcher,
    4077                 :            :                                          pattern_template_index, rule_items,
    4078                 :            :                                          action_template_index, rule_acts,
    4079                 :            :                                          &rule_attr,
    4080                 :          0 :                                          (struct mlx5dr_rule *)flow->rule);
    4081                 :          0 :                 rte_rwlock_read_unlock(&table->matcher_replace_rwlk);
    4082                 :          0 :                 aux->matcher_selector = selector;
    4083                 :          0 :                 flow->flags |= MLX5_FLOW_HW_FLOW_FLAG_MATCHER_SELECTOR;
    4084                 :            :         }
    4085   [ #  #  #  #  :          0 :         if (likely(!ret)) {
                   #  # ]
    4086                 :          0 :                 flow_hw_q_inc_flow_ops(priv, queue);
    4087                 :          0 :                 return (struct rte_flow *)flow;
    4088                 :            :         }
    4089                 :          0 : error:
    4090   [ #  #  #  #  :          0 :         if (table->resource && res_idx)
          #  #  #  #  #  
                #  #  # ]
    4091                 :          0 :                 mlx5_ipool_free(table->resource, res_idx);
    4092   [ #  #  #  #  :          0 :         if (flow_idx)
                   #  # ]
    4093                 :          0 :                 mlx5_ipool_free(table->flow, flow_idx);
    4094   [ #  #  #  #  :          0 :         if (sub_error.cause != RTE_FLOW_ERROR_TYPE_NONE && error != NULL)
          #  #  #  #  #  
                #  #  # ]
    4095                 :          0 :                 *error = sub_error;
    4096                 :            :         else
    4097                 :          0 :                 rte_flow_error_set(error, rte_errno,
    4098                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    4099                 :            :                                    "fail to create rte flow");
    4100                 :            :         return NULL;
    4101                 :            : }
    4102                 :            : 
    4103                 :            : static struct rte_flow *
    4104                 :          0 : flow_hw_async_flow_create(struct rte_eth_dev *dev,
    4105                 :            :                           uint32_t queue,
    4106                 :            :                           const struct rte_flow_op_attr *attr,
    4107                 :            :                           struct rte_flow_template_table *table,
    4108                 :            :                           const struct rte_flow_item items[],
    4109                 :            :                           uint8_t pattern_template_index,
    4110                 :            :                           const struct rte_flow_action actions[],
    4111                 :            :                           uint8_t action_template_index,
    4112                 :            :                           void *user_data,
    4113                 :            :                           struct rte_flow_error *error)
    4114                 :            : {
    4115                 :            :         uint32_t rule_index = UINT32_MAX;
    4116                 :            : 
    4117         [ #  # ]:          0 :         return flow_hw_async_flow_create_generic(dev, queue, attr, table,
    4118                 :            :                 RTE_FLOW_TABLE_INSERTION_TYPE_PATTERN, rule_index,
    4119                 :            :                 items, pattern_template_index, actions, action_template_index,
    4120                 :            :                 user_data, error);
    4121                 :            : }
    4122                 :            : 
    4123                 :            : static struct rte_flow *
    4124                 :          0 : flow_hw_async_flow_create_by_index(struct rte_eth_dev *dev,
    4125                 :            :                           uint32_t queue,
    4126                 :            :                           const struct rte_flow_op_attr *attr,
    4127                 :            :                           struct rte_flow_template_table *table,
    4128                 :            :                           uint32_t rule_index,
    4129                 :            :                           const struct rte_flow_action actions[],
    4130                 :            :                           uint8_t action_template_index,
    4131                 :            :                           void *user_data,
    4132                 :            :                           struct rte_flow_error *error)
    4133                 :            : {
    4134                 :          0 :         struct rte_flow_item items[] = {{.type = RTE_FLOW_ITEM_TYPE_END,}};
    4135                 :            :         uint8_t pattern_template_index = 0;
    4136                 :            : 
    4137         [ #  # ]:          0 :         return flow_hw_async_flow_create_generic(dev, queue, attr, table,
    4138                 :            :                 RTE_FLOW_TABLE_INSERTION_TYPE_INDEX, rule_index,
    4139                 :            :                 items, pattern_template_index, actions, action_template_index,
    4140                 :            :                 user_data, error);
    4141                 :            : }
    4142                 :            : 
    4143                 :            : static struct rte_flow *
    4144                 :          0 : flow_hw_async_flow_create_by_index_with_pattern(struct rte_eth_dev *dev,
    4145                 :            :                                                 uint32_t queue,
    4146                 :            :                                                 const struct rte_flow_op_attr *attr,
    4147                 :            :                                                 struct rte_flow_template_table *table,
    4148                 :            :                                                 uint32_t rule_index,
    4149                 :            :                                                 const struct rte_flow_item items[],
    4150                 :            :                                                 uint8_t pattern_template_index,
    4151                 :            :                                                 const struct rte_flow_action actions[],
    4152                 :            :                                                 uint8_t action_template_index,
    4153                 :            :                                                 void *user_data,
    4154                 :            :                                                 struct rte_flow_error *error)
    4155                 :            : {
    4156         [ #  # ]:          0 :         return flow_hw_async_flow_create_generic(dev, queue, attr, table,
    4157                 :            :                 RTE_FLOW_TABLE_INSERTION_TYPE_INDEX_WITH_PATTERN, rule_index,
    4158                 :            :                 items, pattern_template_index, actions, action_template_index,
    4159                 :            :                 user_data, error);
    4160                 :            : }
    4161                 :            : 
    4162                 :            : /**
    4163                 :            :  * Enqueue HW steering flow update.
    4164                 :            :  *
    4165                 :            :  * The flow will be applied to the HW only if the postpone bit is not set or
    4166                 :            :  * the extra push function is called.
    4167                 :            :  * The flow destruction status should be checked from dequeue result.
    4168                 :            :  *
    4169                 :            :  * @param[in] dev
    4170                 :            :  *   Pointer to the rte_eth_dev structure.
    4171                 :            :  * @param[in] queue
    4172                 :            :  *   The queue to destroy the flow.
    4173                 :            :  * @param[in] attr
    4174                 :            :  *   Pointer to the flow operation attributes.
    4175                 :            :  * @param[in] flow
    4176                 :            :  *   Pointer to the flow to be destroyed.
    4177                 :            :  * @param[in] actions
    4178                 :            :  *   Action with flow spec value.
    4179                 :            :  * @param[in] action_template_index
    4180                 :            :  *   The action pattern flow follows from the table.
    4181                 :            :  * @param[in] user_data
    4182                 :            :  *   Pointer to the user_data.
    4183                 :            :  * @param[out] error
    4184                 :            :  *   Pointer to error structure.
    4185                 :            :  *
    4186                 :            :  * @return
    4187                 :            :  *    0 on success, negative value otherwise and rte_errno is set.
    4188                 :            :  */
    4189                 :            : static int
    4190                 :          0 : flow_hw_async_flow_update(struct rte_eth_dev *dev,
    4191                 :            :                            uint32_t queue,
    4192                 :            :                            const struct rte_flow_op_attr *attr,
    4193                 :            :                            struct rte_flow *flow,
    4194                 :            :                            const struct rte_flow_action actions[],
    4195                 :            :                            uint8_t action_template_index,
    4196                 :            :                            void *user_data,
    4197                 :            :                            struct rte_flow_error *error)
    4198                 :            : {
    4199                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    4200                 :          0 :         struct mlx5dr_rule_attr rule_attr = {
    4201                 :            :                 .queue_id = queue,
    4202                 :            :                 .user_data = user_data,
    4203                 :          0 :                 .burst = attr->postpone,
    4204                 :            :         };
    4205                 :            :         struct mlx5dr_rule_action *rule_acts;
    4206                 :            :         struct rte_flow_hw *of = (struct rte_flow_hw *)flow;
    4207                 :            :         struct rte_flow_hw *nf;
    4208                 :            :         struct rte_flow_hw_aux *aux;
    4209                 :          0 :         struct rte_flow_template_table *table = of->table;
    4210                 :          0 :         uint32_t res_idx = 0;
    4211                 :            :         int ret;
    4212                 :            : 
    4213         [ #  # ]:          0 :         if (mlx5_fp_debug_enabled()) {
    4214         [ #  # ]:          0 :                 if (flow_hw_async_update_validate(dev, queue, of, actions, action_template_index,
    4215                 :            :                                                   error))
    4216                 :          0 :                         return -rte_errno;
    4217                 :            :         }
    4218                 :          0 :         aux = mlx5_flow_hw_aux(dev->data->port_id, of);
    4219         [ #  # ]:          0 :         nf = &aux->upd_flow;
    4220                 :            :         memset(nf, 0, sizeof(struct rte_flow_hw));
    4221                 :          0 :         rule_acts = flow_hw_get_dr_action_buffer(priv, table, action_template_index, queue);
    4222                 :            :         /*
    4223                 :            :          * Set the table here in order to know the destination table
    4224                 :            :          * when free the flow afterwards.
    4225                 :            :          */
    4226                 :          0 :         nf->table = table;
    4227                 :          0 :         nf->mt_idx = of->mt_idx;
    4228                 :          0 :         nf->idx = of->idx;
    4229         [ #  # ]:          0 :         if (table->resource) {
    4230                 :          0 :                 mlx5_ipool_malloc(table->resource, &res_idx);
    4231         [ #  # ]:          0 :                 if (!res_idx) {
    4232                 :          0 :                         rte_errno = ENOMEM;
    4233                 :          0 :                         goto error;
    4234                 :            :                 }
    4235                 :          0 :                 nf->res_idx = res_idx;
    4236                 :            :         } else {
    4237                 :          0 :                 nf->res_idx = of->res_idx;
    4238                 :            :         }
    4239                 :          0 :         nf->flags = 0;
    4240                 :            :         /* Indicate the construction function to set the proper fields. */
    4241                 :          0 :         nf->operation_type = MLX5_FLOW_HW_FLOW_OP_TYPE_UPDATE;
    4242                 :            :         /*
    4243                 :            :          * Indexed pool returns 1-based indices, but mlx5dr expects 0-based indices
    4244                 :            :          * for rule insertion hints.
    4245                 :            :          * If there is only one STE, the update will be atomic by nature.
    4246                 :            :          */
    4247                 :          0 :         nf->rule_idx = nf->res_idx - 1;
    4248                 :          0 :         rule_attr.rule_idx = nf->rule_idx;
    4249                 :            :         /*
    4250                 :            :          * Construct the flow actions based on the input actions.
    4251                 :            :          * The implicitly appended action is always fixed, like metadata
    4252                 :            :          * copy action from FDB to NIC Rx.
    4253                 :            :          * No need to copy and contrust a new "actions" list based on the
    4254                 :            :          * user's input, in order to save the cost.
    4255                 :            :          */
    4256                 :          0 :         if (flow_hw_actions_construct(dev, nf, &priv->hw_q[queue].ap,
    4257                 :          0 :                                       &table->ats[action_template_index],
    4258         [ #  # ]:          0 :                                       table->its[nf->mt_idx]->item_flags,
    4259                 :            :                                       table, actions,
    4260                 :            :                                       rule_acts, queue, error)) {
    4261                 :          0 :                 rte_errno = EINVAL;
    4262                 :          0 :                 goto error;
    4263                 :            :         }
    4264                 :            :         /*
    4265                 :            :          * Set the flow operation type here in order to know if the flow memory
    4266                 :            :          * should be freed or not when get the result from dequeue.
    4267                 :            :          */
    4268                 :          0 :         of->operation_type = MLX5_FLOW_HW_FLOW_OP_TYPE_UPDATE;
    4269                 :          0 :         of->user_data = user_data;
    4270                 :          0 :         of->flags |= MLX5_FLOW_HW_FLOW_FLAG_UPD_FLOW;
    4271                 :          0 :         rule_attr.user_data = of;
    4272                 :          0 :         ret = mlx5dr_rule_action_update((struct mlx5dr_rule *)of->rule,
    4273                 :            :                                         action_template_index, rule_acts, &rule_attr);
    4274         [ #  # ]:          0 :         if (likely(!ret)) {
    4275                 :          0 :                 flow_hw_q_inc_flow_ops(priv, queue);
    4276                 :          0 :                 return 0;
    4277                 :            :         }
    4278                 :          0 : error:
    4279   [ #  #  #  # ]:          0 :         if (table->resource && res_idx)
    4280                 :          0 :                 mlx5_ipool_free(table->resource, res_idx);
    4281                 :          0 :         return rte_flow_error_set(error, rte_errno,
    4282                 :            :                                   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    4283                 :            :                                   "fail to update rte flow");
    4284                 :            : }
    4285                 :            : 
    4286                 :            : /**
    4287                 :            :  * Enqueue HW steering flow destruction.
    4288                 :            :  *
    4289                 :            :  * The flow will be applied to the HW only if the postpone bit is not set or
    4290                 :            :  * the extra push function is called.
    4291                 :            :  * The flow destruction status should be checked from dequeue result.
    4292                 :            :  *
    4293                 :            :  * @param[in] dev
    4294                 :            :  *   Pointer to the rte_eth_dev structure.
    4295                 :            :  * @param[in] queue
    4296                 :            :  *   The queue to destroy the flow.
    4297                 :            :  * @param[in] attr
    4298                 :            :  *   Pointer to the flow operation attributes.
    4299                 :            :  * @param[in] flow
    4300                 :            :  *   Pointer to the flow to be destroyed.
    4301                 :            :  * @param[in] user_data
    4302                 :            :  *   Pointer to the user_data.
    4303                 :            :  * @param[out] error
    4304                 :            :  *   Pointer to error structure.
    4305                 :            :  *
    4306                 :            :  * @return
    4307                 :            :  *    0 on success, negative value otherwise and rte_errno is set.
    4308                 :            :  */
    4309                 :            : static int
    4310                 :          0 : flow_hw_async_flow_destroy(struct rte_eth_dev *dev,
    4311                 :            :                            uint32_t queue,
    4312                 :            :                            const struct rte_flow_op_attr *attr,
    4313                 :            :                            struct rte_flow *flow,
    4314                 :            :                            void *user_data,
    4315                 :            :                            struct rte_flow_error *error)
    4316                 :            : {
    4317                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    4318                 :          0 :         struct mlx5dr_rule_attr rule_attr = {
    4319                 :            :                 .queue_id = queue,
    4320                 :            :                 .user_data = user_data,
    4321                 :          0 :                 .burst = attr->postpone,
    4322                 :            :         };
    4323                 :            :         struct rte_flow_hw *fh = (struct rte_flow_hw *)flow;
    4324                 :          0 :         bool resizable = rte_flow_template_table_resizable(dev->data->port_id,
    4325                 :          0 :                                                            &fh->table->cfg.attr);
    4326                 :            :         int ret;
    4327                 :            : 
    4328                 :            :         if (mlx5_fp_debug_enabled()) {
    4329                 :            :                 if (flow_hw_async_destroy_validate(dev, queue, fh, error))
    4330                 :            :                         return -rte_errno;
    4331                 :            :         }
    4332         [ #  # ]:          0 :         fh->operation_type = !resizable ?
    4333                 :            :                              MLX5_FLOW_HW_FLOW_OP_TYPE_DESTROY :
    4334                 :            :                              MLX5_FLOW_HW_FLOW_OP_TYPE_RSZ_TBL_DESTROY;
    4335                 :          0 :         fh->user_data = user_data;
    4336                 :          0 :         rule_attr.user_data = fh;
    4337                 :          0 :         rule_attr.rule_idx = fh->rule_idx;
    4338                 :          0 :         ret = mlx5dr_rule_destroy((struct mlx5dr_rule *)fh->rule, &rule_attr);
    4339         [ #  # ]:          0 :         if (ret) {
    4340                 :          0 :                 return rte_flow_error_set(error, rte_errno,
    4341                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    4342                 :            :                                           "fail to destroy rte flow");
    4343                 :            :         }
    4344                 :            :         flow_hw_q_inc_flow_ops(priv, queue);
    4345                 :          0 :         return 0;
    4346                 :            : }
    4347                 :            : 
    4348                 :            : /**
    4349                 :            :  * Release the AGE and counter for given flow.
    4350                 :            :  *
    4351                 :            :  * @param[in] priv
    4352                 :            :  *   Pointer to the port private data structure.
    4353                 :            :  * @param[in] queue
    4354                 :            :  *   The queue to release the counter.
    4355                 :            :  * @param[in, out] flow
    4356                 :            :  *   Pointer to the flow containing the counter.
    4357                 :            :  * @param[out] error
    4358                 :            :  *   Pointer to error structure.
    4359                 :            :  */
    4360                 :            : static void
    4361                 :          0 : flow_hw_age_count_release(struct mlx5_priv *priv, uint32_t queue,
    4362                 :            :                           struct rte_flow_hw *flow,
    4363                 :            :                           struct rte_flow_error *error)
    4364                 :            : {
    4365                 :          0 :         struct rte_flow_hw_aux *aux = mlx5_flow_hw_aux(priv->dev_data->port_id, flow);
    4366                 :            :         uint32_t *cnt_queue;
    4367                 :          0 :         uint32_t age_idx = aux->orig.age_idx;
    4368                 :            : 
    4369                 :            :         MLX5_ASSERT(flow->flags & MLX5_FLOW_HW_FLOW_FLAG_CNT_ID);
    4370   [ #  #  #  # ]:          0 :         if (mlx5_hws_cnt_is_shared(priv->hws_cpool, flow->cnt_id)) {
    4371   [ #  #  #  # ]:          0 :                 if ((flow->flags & MLX5_FLOW_HW_FLOW_FLAG_AGE_IDX) &&
    4372                 :            :                     !mlx5_hws_age_is_indirect(age_idx)) {
    4373                 :            :                         /* Remove this AGE parameter from indirect counter. */
    4374                 :            :                         mlx5_hws_cnt_age_set(priv->hws_cpool, flow->cnt_id, 0);
    4375                 :            :                         /* Release the AGE parameter. */
    4376                 :          0 :                         mlx5_hws_age_action_destroy(priv, age_idx, error);
    4377                 :            :                 }
    4378                 :          0 :                 return;
    4379                 :            :         }
    4380                 :            :         cnt_queue = mlx5_hws_cnt_get_queue(priv, &queue);
    4381                 :            :         /* Put the counter first to reduce the race risk in BG thread. */
    4382         [ #  # ]:          0 :         mlx5_hws_cnt_pool_put(priv->hws_cpool, cnt_queue, &flow->cnt_id);
    4383         [ #  # ]:          0 :         if (flow->flags & MLX5_FLOW_HW_FLOW_FLAG_AGE_IDX) {
    4384         [ #  # ]:          0 :                 if (mlx5_hws_age_is_indirect(age_idx)) {
    4385                 :          0 :                         uint32_t idx = age_idx & MLX5_HWS_AGE_IDX_MASK;
    4386                 :            : 
    4387                 :            :                         mlx5_hws_age_nb_cnt_decrease(priv, idx);
    4388                 :            :                 } else {
    4389                 :            :                         /* Release the AGE parameter. */
    4390                 :          0 :                         mlx5_hws_age_action_destroy(priv, age_idx, error);
    4391                 :            :                 }
    4392                 :            :         }
    4393                 :            : }
    4394                 :            : 
    4395                 :            : static __rte_always_inline void
    4396                 :            : flow_hw_pull_legacy_indirect_comp(struct rte_eth_dev *dev, struct mlx5_hw_q_job *job,
    4397                 :            :                                   uint32_t queue)
    4398                 :            : {
    4399                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    4400                 :            :         struct mlx5_aso_ct_action *aso_ct;
    4401                 :            :         struct mlx5_aso_mtr *aso_mtr;
    4402                 :            :         uint32_t type, idx;
    4403                 :            : 
    4404         [ #  # ]:          0 :         if (MLX5_INDIRECT_ACTION_TYPE_GET(job->action) ==
    4405                 :            :             MLX5_INDIRECT_ACTION_TYPE_QUOTA) {
    4406                 :          0 :                 mlx5_quota_async_completion(dev, queue, job);
    4407         [ #  # ]:          0 :         } else if (job->type == MLX5_HW_Q_JOB_TYPE_DESTROY) {
    4408                 :            :                 type = MLX5_INDIRECT_ACTION_TYPE_GET(job->action);
    4409         [ #  # ]:          0 :                 if (type == MLX5_INDIRECT_ACTION_TYPE_METER_MARK) {
    4410                 :          0 :                         idx = MLX5_INDIRECT_ACTION_IDX_GET(job->action);
    4411                 :          0 :                         mlx5_ipool_free(priv->hws_mpool->idx_pool, idx);
    4412                 :            :                 }
    4413         [ #  # ]:          0 :         } else if (job->type == MLX5_HW_Q_JOB_TYPE_CREATE) {
    4414                 :            :                 type = MLX5_INDIRECT_ACTION_TYPE_GET(job->action);
    4415         [ #  # ]:          0 :                 if (type == MLX5_INDIRECT_ACTION_TYPE_METER_MARK) {
    4416                 :          0 :                         idx = MLX5_INDIRECT_ACTION_IDX_GET(job->action);
    4417                 :          0 :                         aso_mtr = mlx5_ipool_get(priv->hws_mpool->idx_pool, idx);
    4418                 :          0 :                         aso_mtr->state = ASO_METER_READY;
    4419         [ #  # ]:          0 :                 } else if (type == MLX5_INDIRECT_ACTION_TYPE_CT) {
    4420                 :          0 :                         idx = MLX5_INDIRECT_ACTION_IDX_GET(job->action);
    4421                 :          0 :                         aso_ct = mlx5_ipool_get(priv->hws_ctpool->cts, idx);
    4422                 :          0 :                         aso_ct->state = ASO_CONNTRACK_READY;
    4423                 :            :                 }
    4424         [ #  # ]:          0 :         } else if (job->type == MLX5_HW_Q_JOB_TYPE_QUERY) {
    4425                 :            :                 type = MLX5_INDIRECT_ACTION_TYPE_GET(job->action);
    4426         [ #  # ]:          0 :                 if (type == MLX5_INDIRECT_ACTION_TYPE_CT) {
    4427                 :          0 :                         idx = MLX5_INDIRECT_ACTION_IDX_GET(job->action);
    4428                 :          0 :                         aso_ct = mlx5_ipool_get(priv->hws_ctpool->cts, idx);
    4429                 :          0 :                         mlx5_aso_ct_obj_analyze(job->query.user,
    4430                 :          0 :                                                 job->query.hw);
    4431                 :          0 :                         aso_ct->state = ASO_CONNTRACK_READY;
    4432                 :            :                 }
    4433                 :            :         }
    4434                 :            : }
    4435                 :            : 
    4436                 :            : static __rte_always_inline int
    4437                 :            : mlx5_hw_pull_flow_transfer_comp(struct rte_eth_dev *dev,
    4438                 :            :                                 uint32_t queue, struct rte_flow_op_result res[],
    4439                 :            :                                 uint16_t n_res)
    4440                 :            : {
    4441                 :            :         uint32_t size, i;
    4442                 :          0 :         struct rte_flow_hw *flow = NULL;
    4443                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    4444                 :          0 :         struct rte_ring *ring = priv->hw_q[queue].flow_transfer_completed;
    4445                 :            : 
    4446                 :          0 :         size = RTE_MIN(rte_ring_count(ring), n_res);
    4447         [ #  # ]:          0 :         for (i = 0; i < size; i++) {
    4448   [ #  #  #  #  :          0 :                 res[i].status = RTE_FLOW_OP_SUCCESS;
                      # ]
    4449                 :            :                 rte_ring_dequeue(ring, (void **)&flow);
    4450                 :          0 :                 res[i].user_data = flow->user_data;
    4451                 :            :                 flow_hw_q_dec_flow_ops(priv, queue);
    4452                 :            :         }
    4453                 :          0 :         return (int)size;
    4454                 :            : }
    4455                 :            : 
    4456                 :            : static inline int
    4457                 :          0 : __flow_hw_pull_indir_action_comp(struct rte_eth_dev *dev,
    4458                 :            :                                  uint32_t queue,
    4459                 :            :                                  struct rte_flow_op_result res[],
    4460                 :            :                                  uint16_t n_res)
    4461                 :            : 
    4462                 :            : {
    4463                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    4464                 :          0 :         struct rte_ring *r = priv->hw_q[queue].indir_cq;
    4465                 :          0 :         void *user_data = NULL;
    4466                 :            :         int ret_comp, i;
    4467                 :            : 
    4468                 :          0 :         ret_comp = (int)rte_ring_count(r);
    4469                 :          0 :         if (ret_comp > n_res)
    4470                 :            :                 ret_comp = n_res;
    4471         [ #  # ]:          0 :         for (i = 0; i < ret_comp; i++) {
    4472                 :            :                 rte_ring_dequeue(r, &user_data);
    4473                 :          0 :                 res[i].user_data = user_data;
    4474                 :          0 :                 res[i].status = RTE_FLOW_OP_SUCCESS;
    4475                 :            :         }
    4476         [ #  # ]:          0 :         if (!priv->shared_host) {
    4477   [ #  #  #  # ]:          0 :                 if (ret_comp < n_res && priv->hws_mpool)
    4478                 :          0 :                         ret_comp += mlx5_aso_pull_completion(&priv->hws_mpool->sq[queue],
    4479                 :          0 :                                         &res[ret_comp], n_res - ret_comp);
    4480   [ #  #  #  # ]:          0 :                 if (ret_comp < n_res && priv->hws_ctpool)
    4481                 :          0 :                         ret_comp += mlx5_aso_pull_completion(&priv->ct_mng->aso_sqs[queue],
    4482                 :          0 :                                         &res[ret_comp], n_res - ret_comp);
    4483                 :            :         }
    4484   [ #  #  #  # ]:          0 :         if (ret_comp < n_res && priv->quota_ctx.sq)
    4485                 :          0 :                 ret_comp += mlx5_aso_pull_completion(&priv->quota_ctx.sq[queue],
    4486                 :          0 :                                                      &res[ret_comp],
    4487                 :          0 :                                                      n_res - ret_comp);
    4488         [ #  # ]:          0 :         for (i = 0; i <  ret_comp; i++) {
    4489                 :          0 :                 struct mlx5_hw_q_job *job = (struct mlx5_hw_q_job *)res[i].user_data;
    4490                 :            : 
    4491                 :            :                 /* Restore user data. */
    4492                 :          0 :                 res[i].user_data = job->user_data;
    4493         [ #  # ]:          0 :                 if (job->indirect_type == MLX5_HW_INDIRECT_TYPE_LEGACY)
    4494                 :            :                         flow_hw_pull_legacy_indirect_comp(dev, job, queue);
    4495                 :            :                 /*
    4496                 :            :                  * Current PMD supports 2 indirect action list types - MIRROR and REFORMAT.
    4497                 :            :                  * These indirect list types do not post WQE to create action.
    4498                 :            :                  * Future indirect list types that do post WQE will add
    4499                 :            :                  * completion handlers here.
    4500                 :            :                  */
    4501                 :            :                 flow_hw_job_put(priv, job, queue);
    4502                 :            :         }
    4503                 :          0 :         return ret_comp;
    4504                 :            : }
    4505                 :            : 
    4506                 :            : static __rte_always_inline void
    4507                 :            : hw_cmpl_flow_update_or_destroy(struct rte_eth_dev *dev,
    4508                 :            :                                struct rte_flow_hw *flow,
    4509                 :            :                                uint32_t queue, struct rte_flow_error *error)
    4510                 :            : {
    4511                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    4512                 :          0 :         struct mlx5_aso_mtr_pool *pool = priv->hws_mpool;
    4513                 :          0 :         struct rte_flow_template_table *table = flow->table;
    4514                 :            :         /* Release the original resource index in case of update. */
    4515                 :          0 :         uint32_t res_idx = flow->res_idx;
    4516                 :            : 
    4517         [ #  # ]:          0 :         if (flow->flags & MLX5_FLOW_HW_FLOW_FLAGS_ALL) {
    4518                 :          0 :                 struct rte_flow_hw_aux *aux = mlx5_flow_hw_aux(dev->data->port_id, flow);
    4519                 :            : 
    4520   [ #  #  #  #  :          0 :                 if (flow->flags & MLX5_FLOW_HW_FLOW_FLAG_FATE_JUMP)
                   #  # ]
    4521                 :          0 :                         flow_hw_jump_release(dev, flow->jump);
    4522   [ #  #  #  #  :          0 :                 else if (flow->flags & MLX5_FLOW_HW_FLOW_FLAG_FATE_HRXQ)
                   #  # ]
    4523                 :          0 :                         mlx5_hrxq_obj_release(dev, flow->hrxq);
    4524   [ #  #  #  #  :          0 :                 if (flow->flags & MLX5_FLOW_HW_FLOW_FLAG_CNT_ID)
                   #  # ]
    4525                 :          0 :                         flow_hw_age_count_release(priv, queue, flow, error);
    4526   [ #  #  #  #  :          0 :                 if (flow->flags & MLX5_FLOW_HW_FLOW_FLAG_MTR_ID)
                   #  # ]
    4527                 :          0 :                         mlx5_ipool_free(pool->idx_pool, aux->orig.mtr_id);
    4528   [ #  #  #  #  :          0 :                 if (flow->flags & MLX5_FLOW_HW_FLOW_FLAG_UPD_FLOW) {
                   #  # ]
    4529   [ #  #  #  #  :          0 :                         struct rte_flow_hw *upd_flow = &aux->upd_flow;
                   #  # ]
    4530                 :            : 
    4531                 :            :                         rte_memcpy(flow, upd_flow, offsetof(struct rte_flow_hw, rule));
    4532                 :          0 :                         aux->orig = aux->upd;
    4533                 :          0 :                         flow->operation_type = MLX5_FLOW_HW_FLOW_OP_TYPE_CREATE;
    4534   [ #  #  #  #  :          0 :                         if (!flow->nt_rule && table->resource)
          #  #  #  #  #  
                #  #  # ]
    4535                 :          0 :                                 mlx5_ipool_free(table->resource, res_idx);
    4536                 :            :                 }
    4537                 :            :         }
    4538   [ #  #  #  #  :          0 :         if (flow->operation_type == MLX5_FLOW_HW_FLOW_OP_TYPE_DESTROY ||
                   #  # ]
    4539                 :            :             flow->operation_type == MLX5_FLOW_HW_FLOW_OP_TYPE_RSZ_TBL_DESTROY) {
    4540   [ #  #  #  #  :          0 :                 if (!flow->nt_rule) {
                   #  # ]
    4541   [ #  #  #  #  :          0 :                         if (table->resource)
                   #  # ]
    4542                 :          0 :                                 mlx5_ipool_free(table->resource, res_idx);
    4543                 :          0 :                         mlx5_ipool_free(table->flow, flow->idx);
    4544                 :            :                 }
    4545                 :            :         }
    4546                 :            : }
    4547                 :            : 
    4548                 :            : static __rte_always_inline void
    4549                 :            : hw_cmpl_resizable_tbl(struct rte_eth_dev *dev,
    4550                 :            :                       struct rte_flow_hw *flow,
    4551                 :            :                       uint32_t queue, enum rte_flow_op_status status,
    4552                 :            :                       struct rte_flow_error *error)
    4553                 :            : {
    4554                 :          0 :         struct rte_flow_template_table *table = flow->table;
    4555                 :          0 :         struct rte_flow_hw_aux *aux = mlx5_flow_hw_aux(dev->data->port_id, flow);
    4556                 :          0 :         uint32_t selector = aux->matcher_selector;
    4557                 :          0 :         uint32_t other_selector = (selector + 1) & 1;
    4558                 :            : 
    4559                 :            :         MLX5_ASSERT(flow->flags & MLX5_FLOW_HW_FLOW_FLAG_MATCHER_SELECTOR);
    4560   [ #  #  #  # ]:          0 :         switch (flow->operation_type) {
    4561                 :          0 :         case MLX5_FLOW_HW_FLOW_OP_TYPE_RSZ_TBL_CREATE:
    4562                 :          0 :                 rte_atomic_fetch_add_explicit
    4563                 :            :                         (&table->matcher_info[selector].refcnt, 1,
    4564                 :            :                          rte_memory_order_relaxed);
    4565                 :          0 :                 break;
    4566                 :          0 :         case MLX5_FLOW_HW_FLOW_OP_TYPE_RSZ_TBL_DESTROY:
    4567         [ #  # ]:          0 :                 rte_atomic_fetch_sub_explicit
    4568                 :            :                         (&table->matcher_info[selector].refcnt, 1,
    4569                 :            :                          rte_memory_order_relaxed);
    4570                 :            :                 hw_cmpl_flow_update_or_destroy(dev, flow, queue, error);
    4571                 :            :                 break;
    4572                 :          0 :         case MLX5_FLOW_HW_FLOW_OP_TYPE_RSZ_TBL_MOVE:
    4573         [ #  # ]:          0 :                 if (status == RTE_FLOW_OP_SUCCESS) {
    4574                 :          0 :                         rte_atomic_fetch_sub_explicit
    4575                 :            :                                 (&table->matcher_info[selector].refcnt, 1,
    4576                 :            :                                  rte_memory_order_relaxed);
    4577                 :          0 :                         rte_atomic_fetch_add_explicit
    4578                 :            :                                 (&table->matcher_info[other_selector].refcnt, 1,
    4579                 :            :                                  rte_memory_order_relaxed);
    4580                 :          0 :                         aux->matcher_selector = other_selector;
    4581                 :            :                 }
    4582                 :            :                 break;
    4583                 :            :         default:
    4584                 :            :                 break;
    4585                 :            :         }
    4586                 :            : }
    4587                 :            : 
    4588                 :            : /**
    4589                 :            :  * Pull the enqueued flows.
    4590                 :            :  *
    4591                 :            :  * For flows enqueued from creation/destruction, the status should be
    4592                 :            :  * checked from the dequeue result.
    4593                 :            :  *
    4594                 :            :  * @param[in] dev
    4595                 :            :  *   Pointer to the rte_eth_dev structure.
    4596                 :            :  * @param[in] queue
    4597                 :            :  *   The queue to pull the result.
    4598                 :            :  * @param[in/out] res
    4599                 :            :  *   Array to save the results.
    4600                 :            :  * @param[in] n_res
    4601                 :            :  *   Available result with the array.
    4602                 :            :  * @param[out] error
    4603                 :            :  *   Pointer to error structure.
    4604                 :            :  *
    4605                 :            :  * @return
    4606                 :            :  *    Result number on success, negative value otherwise and rte_errno is set.
    4607                 :            :  */
    4608                 :            : static int
    4609                 :          0 : flow_hw_pull(struct rte_eth_dev *dev,
    4610                 :            :              uint32_t queue,
    4611                 :            :              struct rte_flow_op_result res[],
    4612                 :            :              uint16_t n_res,
    4613                 :            :              struct rte_flow_error *error)
    4614                 :            : {
    4615                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    4616                 :            :         int ret, i;
    4617                 :            : 
    4618                 :            :         /* 1. Pull the flow completion. */
    4619                 :          0 :         ret = mlx5dr_send_queue_poll(priv->dr_ctx, queue, res, n_res);
    4620         [ #  # ]:          0 :         if (ret < 0)
    4621                 :          0 :                 return rte_flow_error_set(error, rte_errno,
    4622                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    4623                 :            :                                 "fail to query flow queue");
    4624         [ #  # ]:          0 :         for (i = 0; i <  ret; i++) {
    4625                 :          0 :                 struct rte_flow_hw *flow = res[i].user_data;
    4626                 :            : 
    4627                 :            :                 /* Restore user data. */
    4628                 :          0 :                 res[i].user_data = flow->user_data;
    4629      [ #  #  # ]:          0 :                 switch (flow->operation_type) {
    4630                 :            :                 case MLX5_FLOW_HW_FLOW_OP_TYPE_DESTROY:
    4631                 :            :                 case MLX5_FLOW_HW_FLOW_OP_TYPE_UPDATE:
    4632                 :            :                         hw_cmpl_flow_update_or_destroy(dev, flow, queue, error);
    4633                 :            :                         break;
    4634                 :          0 :                 case MLX5_FLOW_HW_FLOW_OP_TYPE_RSZ_TBL_CREATE:
    4635                 :            :                 case MLX5_FLOW_HW_FLOW_OP_TYPE_RSZ_TBL_DESTROY:
    4636                 :            :                 case MLX5_FLOW_HW_FLOW_OP_TYPE_RSZ_TBL_MOVE:
    4637                 :          0 :                         hw_cmpl_resizable_tbl(dev, flow, queue, res[i].status, error);
    4638                 :            :                         break;
    4639                 :            :                 default:
    4640                 :            :                         break;
    4641                 :            :                 }
    4642                 :            :                 flow_hw_q_dec_flow_ops(priv, queue);
    4643                 :            :         }
    4644                 :            :         /* 2. Pull indirect action comp. */
    4645         [ #  # ]:          0 :         if (ret < n_res)
    4646                 :          0 :                 ret += __flow_hw_pull_indir_action_comp(dev, queue, &res[ret],
    4647                 :          0 :                                                         n_res - ret);
    4648         [ #  # ]:          0 :         if (ret < n_res)
    4649                 :          0 :                 ret += mlx5_hw_pull_flow_transfer_comp(dev, queue, &res[ret],
    4650                 :          0 :                                                        n_res - ret);
    4651                 :            : 
    4652                 :            :         return ret;
    4653                 :            : }
    4654                 :            : 
    4655                 :            : static uint32_t
    4656                 :          0 : mlx5_hw_push_queue(struct rte_ring *pending_q, struct rte_ring *cmpl_q)
    4657                 :            : {
    4658                 :          0 :         void *job = NULL;
    4659                 :            :         uint32_t i, size = rte_ring_count(pending_q);
    4660                 :            : 
    4661         [ #  # ]:          0 :         for (i = 0; i < size; i++) {
    4662                 :            :                 rte_ring_dequeue(pending_q, &job);
    4663   [ #  #  #  #  :          0 :                 rte_ring_enqueue(cmpl_q, job);
                      # ]
    4664                 :            :         }
    4665                 :          0 :         return size;
    4666                 :            : }
    4667                 :            : 
    4668                 :            : static inline uint32_t
    4669                 :          0 : __flow_hw_push_action(struct rte_eth_dev *dev,
    4670                 :            :                     uint32_t queue)
    4671                 :            : {
    4672                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    4673                 :          0 :         struct mlx5_hw_q *hw_q = &priv->hw_q[queue];
    4674                 :            : 
    4675                 :          0 :         mlx5_hw_push_queue(hw_q->indir_iq, hw_q->indir_cq);
    4676                 :          0 :         mlx5_hw_push_queue(hw_q->flow_transfer_pending,
    4677                 :            :                            hw_q->flow_transfer_completed);
    4678         [ #  # ]:          0 :         if (!priv->shared_host) {
    4679         [ #  # ]:          0 :                 if (priv->hws_ctpool)
    4680                 :          0 :                         mlx5_aso_push_wqe(priv->sh,
    4681                 :          0 :                                           &priv->ct_mng->aso_sqs[queue]);
    4682         [ #  # ]:          0 :                 if (priv->hws_mpool)
    4683                 :          0 :                         mlx5_aso_push_wqe(priv->sh,
    4684                 :          0 :                                           &priv->hws_mpool->sq[queue]);
    4685                 :            :         }
    4686                 :          0 :         return flow_hw_q_pending(priv, queue);
    4687                 :            : }
    4688                 :            : 
    4689                 :            : static int
    4690                 :          0 : __flow_hw_push(struct rte_eth_dev *dev,
    4691                 :            :                uint32_t queue,
    4692                 :            :                struct rte_flow_error *error)
    4693                 :            : {
    4694                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    4695                 :            :         int ret, num;
    4696                 :            : 
    4697                 :          0 :         num = __flow_hw_push_action(dev, queue);
    4698                 :          0 :         ret = mlx5dr_send_queue_action(priv->dr_ctx, queue,
    4699                 :            :                                        MLX5DR_SEND_QUEUE_ACTION_DRAIN_ASYNC);
    4700         [ #  # ]:          0 :         if (ret) {
    4701                 :          0 :                 rte_flow_error_set(error, rte_errno,
    4702                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    4703                 :            :                                    "fail to push flows");
    4704                 :          0 :                 return ret;
    4705                 :            :         }
    4706                 :            :         return num;
    4707                 :            : }
    4708                 :            : 
    4709                 :            : /**
    4710                 :            :  * Push the enqueued flows to HW.
    4711                 :            :  *
    4712                 :            :  * Force apply all the enqueued flows to the HW.
    4713                 :            :  *
    4714                 :            :  * @param[in] dev
    4715                 :            :  *   Pointer to the rte_eth_dev structure.
    4716                 :            :  * @param[in] queue
    4717                 :            :  *   The queue to push the flow.
    4718                 :            :  * @param[out] error
    4719                 :            :  *   Pointer to error structure.
    4720                 :            :  *
    4721                 :            :  * @return
    4722                 :            :  *    0 on success, negative value otherwise and rte_errno is set.
    4723                 :            :  */
    4724                 :            : static int
    4725                 :          0 : flow_hw_push(struct rte_eth_dev *dev,
    4726                 :            :              uint32_t queue, struct rte_flow_error *error)
    4727                 :            : {
    4728                 :          0 :         int ret = __flow_hw_push(dev, queue, error);
    4729                 :            : 
    4730                 :          0 :         return ret >= 0 ? 0 : ret;
    4731                 :            : }
    4732                 :            : 
    4733                 :            : /**
    4734                 :            :  * Drain the enqueued flows' completion.
    4735                 :            :  *
    4736                 :            :  * @param[in] dev
    4737                 :            :  *   Pointer to the rte_eth_dev structure.
    4738                 :            :  * @param[in] queue
    4739                 :            :  *   The queue to pull the flow.
    4740                 :            :  * @param[out] error
    4741                 :            :  *   Pointer to error structure.
    4742                 :            :  *
    4743                 :            :  * @return
    4744                 :            :  *    0 on success, negative value otherwise and rte_errno is set.
    4745                 :            :  */
    4746                 :            : static int
    4747                 :          0 : __flow_hw_pull_comp(struct rte_eth_dev *dev,
    4748                 :            :                     uint32_t queue, struct rte_flow_error *error)
    4749                 :            : {
    4750                 :            :         struct rte_flow_op_result comp[BURST_THR];
    4751                 :            :         int ret, i, empty_loop = 0;
    4752                 :            :         uint32_t pending_rules;
    4753                 :            : 
    4754                 :          0 :         ret = __flow_hw_push(dev, queue, error);
    4755         [ #  # ]:          0 :         if (ret < 0)
    4756                 :            :                 return ret;
    4757                 :          0 :         pending_rules = ret;
    4758         [ #  # ]:          0 :         while (pending_rules) {
    4759                 :          0 :                 ret = flow_hw_pull(dev, queue, comp, BURST_THR, error);
    4760         [ #  # ]:          0 :                 if (ret < 0)
    4761                 :            :                         return -1;
    4762         [ #  # ]:          0 :                 if (!ret) {
    4763                 :          0 :                         rte_delay_us_sleep(MLX5_ASO_WQE_CQE_RESPONSE_DELAY);
    4764         [ #  # ]:          0 :                         if (++empty_loop > 5) {
    4765                 :          0 :                                 DRV_LOG(WARNING, "No available dequeue %u, quit.", pending_rules);
    4766                 :          0 :                                 break;
    4767                 :            :                         }
    4768                 :          0 :                         continue;
    4769                 :            :                 }
    4770         [ #  # ]:          0 :                 for (i = 0; i < ret; i++) {
    4771         [ #  # ]:          0 :                         if (comp[i].status == RTE_FLOW_OP_ERROR)
    4772                 :          0 :                                 DRV_LOG(WARNING, "Flow flush get error CQE.");
    4773                 :            :                 }
    4774                 :            :                 /*
    4775                 :            :                  * Indirect **SYNC** METER_MARK and CT actions do not
    4776                 :            :                  * remove completion after WQE post.
    4777                 :            :                  * That implementation avoids HW timeout.
    4778                 :            :                  * The completion is removed before the following WQE post.
    4779                 :            :                  * However, HWS queue updates do not reflect that behaviour.
    4780                 :            :                  * Therefore, during port destruction sync queue may have
    4781                 :            :                  * pending completions.
    4782                 :            :                  */
    4783                 :          0 :                 pending_rules -= RTE_MIN(pending_rules, (uint32_t)ret);
    4784                 :            :                 empty_loop = 0;
    4785                 :            :         }
    4786                 :            :         return 0;
    4787                 :            : }
    4788                 :            : 
    4789                 :            : /**
    4790                 :            :  * Flush created flows.
    4791                 :            :  *
    4792                 :            :  * @param[in] dev
    4793                 :            :  *   Pointer to the rte_eth_dev structure.
    4794                 :            :  * @param[out] error
    4795                 :            :  *   Pointer to error structure.
    4796                 :            :  *
    4797                 :            :  * @return
    4798                 :            :  *    0 on success, negative value otherwise and rte_errno is set.
    4799                 :            :  */
    4800                 :            : int
    4801                 :          0 : flow_hw_q_flow_flush(struct rte_eth_dev *dev,
    4802                 :            :                      struct rte_flow_error *error)
    4803                 :            : {
    4804                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    4805                 :          0 :         struct mlx5_hw_q *hw_q = &priv->hw_q[MLX5_DEFAULT_FLUSH_QUEUE];
    4806                 :            :         struct rte_flow_template_table *tbl;
    4807                 :            :         struct rte_flow_hw *flow;
    4808                 :          0 :         struct rte_flow_op_attr attr = {
    4809                 :            :                 .postpone = 0,
    4810                 :            :         };
    4811                 :            :         uint32_t pending_rules = 0;
    4812                 :            :         uint32_t queue;
    4813                 :            :         uint32_t fidx;
    4814                 :            : 
    4815                 :            :         /*
    4816                 :            :          * Ensure to push and dequeue all the enqueued flow
    4817                 :            :          * creation/destruction jobs in case user forgot to
    4818                 :            :          * dequeue. Or the enqueued created flows will be
    4819                 :            :          * leaked. The forgotten dequeues would also cause
    4820                 :            :          * flow flush get extra CQEs as expected and pending_rules
    4821                 :            :          * be minus value.
    4822                 :            :          */
    4823         [ #  # ]:          0 :         for (queue = 0; queue < priv->nb_queue; queue++) {
    4824         [ #  # ]:          0 :                 if (__flow_hw_pull_comp(dev, queue, error))
    4825                 :            :                         return -1;
    4826                 :            :         }
    4827                 :            :         /* Flush flow per-table from MLX5_DEFAULT_FLUSH_QUEUE. */
    4828         [ #  # ]:          0 :         LIST_FOREACH(tbl, &priv->flow_hw_tbl, next) {
    4829         [ #  # ]:          0 :                 if (!tbl->cfg.external)
    4830                 :          0 :                         continue;
    4831         [ #  # ]:          0 :                 MLX5_IPOOL_FOREACH(tbl->flow, fidx, flow) {
    4832         [ #  # ]:          0 :                         if (flow_hw_async_flow_destroy(dev,
    4833                 :            :                                                 MLX5_DEFAULT_FLUSH_QUEUE,
    4834                 :            :                                                 &attr,
    4835                 :            :                                                 (struct rte_flow *)flow,
    4836                 :            :                                                 NULL,
    4837                 :            :                                                 error))
    4838                 :            :                                 return -1;
    4839                 :          0 :                         pending_rules++;
    4840                 :            :                         /* Drain completion with queue size. */
    4841         [ #  # ]:          0 :                         if (pending_rules >= hw_q->size) {
    4842         [ #  # ]:          0 :                                 if (__flow_hw_pull_comp(dev,
    4843                 :            :                                                         MLX5_DEFAULT_FLUSH_QUEUE,
    4844                 :            :                                                         error))
    4845                 :            :                                         return -1;
    4846                 :            :                                 pending_rules = 0;
    4847                 :            :                         }
    4848                 :            :                 }
    4849                 :            :         }
    4850                 :            :         /* Drain left completion. */
    4851   [ #  #  #  # ]:          0 :         if (pending_rules &&
    4852                 :          0 :             __flow_hw_pull_comp(dev, MLX5_DEFAULT_FLUSH_QUEUE, error))
    4853                 :          0 :                 return -1;
    4854                 :            :         return 0;
    4855                 :            : }
    4856                 :            : 
    4857                 :            : static int
    4858                 :          0 : mlx5_tbl_multi_pattern_process(struct rte_eth_dev *dev,
    4859                 :            :                                struct rte_flow_template_table *tbl,
    4860                 :            :                                struct mlx5_multi_pattern_segment *segment,
    4861                 :            :                                uint32_t bulk_size,
    4862                 :            :                                struct rte_flow_error *error)
    4863                 :            : {
    4864                 :            :         int ret = 0;
    4865                 :            :         uint32_t i;
    4866         [ #  # ]:          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    4867                 :            :         struct mlx5_tbl_multi_pattern_ctx *mpctx = &tbl->mpctx;
    4868                 :            :         const struct rte_flow_template_table_attr *table_attr = &tbl->cfg.attr;
    4869                 :            :         const struct rte_flow_attr *attr = &table_attr->flow_attr;
    4870                 :            :         enum mlx5dr_table_type type = get_mlx5dr_table_type(attr);
    4871                 :          0 :         uint32_t flags = mlx5_hw_act_flag[!!attr->group][type];
    4872                 :            :         struct mlx5dr_action *dr_action = NULL;
    4873                 :            : 
    4874         [ #  # ]:          0 :         for (i = 0; i < MLX5_MULTIPATTERN_ENCAP_NUM; i++) {
    4875         [ #  # ]:          0 :                 typeof(mpctx->reformat[0]) *reformat = mpctx->reformat + i;
    4876                 :            :                 enum mlx5dr_action_type reformat_type =
    4877                 :            :                         mlx5_multi_pattern_reformat_index_to_type(i);
    4878                 :            : 
    4879         [ #  # ]:          0 :                 if (!reformat->elements_num)
    4880                 :          0 :                         continue;
    4881                 :            :                 dr_action = reformat_type == MLX5DR_ACTION_TYP_INSERT_HEADER ?
    4882                 :            :                         mlx5dr_action_create_insert_header
    4883                 :            :                         (priv->dr_ctx, reformat->elements_num,
    4884                 :            :                          reformat->insert_hdr, bulk_size, flags) :
    4885                 :          0 :                         mlx5dr_action_create_reformat
    4886                 :            :                         (priv->dr_ctx, reformat_type, reformat->elements_num,
    4887                 :          0 :                          reformat->reformat_hdr, bulk_size, flags);
    4888         [ #  # ]:          0 :                 if (!dr_action) {
    4889                 :          0 :                         ret = rte_flow_error_set(error, rte_errno,
    4890                 :            :                                                  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    4891                 :            :                                                  NULL,
    4892                 :            :                                                  "failed to create multi-pattern encap action");
    4893                 :          0 :                         goto error;
    4894                 :            :                 }
    4895                 :          0 :                 segment->reformat_action[i] = dr_action;
    4896                 :            :         }
    4897         [ #  # ]:          0 :         if (mpctx->mh.elements_num) {
    4898                 :            :                 typeof(mpctx->mh) *mh = &mpctx->mh;
    4899                 :          0 :                 dr_action = mlx5dr_action_create_modify_header
    4900                 :          0 :                         (priv->dr_ctx, mpctx->mh.elements_num, mh->pattern,
    4901                 :            :                          bulk_size, flags);
    4902         [ #  # ]:          0 :                 if (!dr_action) {
    4903                 :          0 :                         ret = rte_flow_error_set(error, rte_errno,
    4904                 :            :                                                   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    4905                 :            :                                                   NULL, "failed to create multi-pattern header modify action");
    4906                 :          0 :                         goto error;
    4907                 :            :                 }
    4908                 :          0 :                 segment->mhdr_action = dr_action;
    4909                 :            :         }
    4910         [ #  # ]:          0 :         if (dr_action) {
    4911                 :          0 :                 segment->capacity = RTE_BIT32(bulk_size);
    4912         [ #  # ]:          0 :                 if (segment != &mpctx->segments[MLX5_MAX_TABLE_RESIZE_NUM - 1])
    4913                 :          0 :                         segment[1].head_index = segment->head_index + segment->capacity;
    4914                 :            :         }
    4915                 :            :         return 0;
    4916                 :          0 : error:
    4917                 :          0 :         mlx5_destroy_multi_pattern_segment(segment);
    4918                 :          0 :         return ret;
    4919                 :            : }
    4920                 :            : 
    4921                 :            : static int
    4922                 :          0 : mlx5_hw_build_template_table(struct rte_eth_dev *dev,
    4923                 :            :                              uint8_t nb_action_templates,
    4924                 :            :                              struct rte_flow_actions_template *action_templates[],
    4925                 :            :                              struct mlx5dr_action_template *at[],
    4926                 :            :                              struct rte_flow_template_table *tbl,
    4927                 :            :                              struct rte_flow_error *error)
    4928                 :            : {
    4929                 :            :         int ret;
    4930                 :            :         uint8_t i;
    4931                 :            : 
    4932         [ #  # ]:          0 :         for (i = 0; i < nb_action_templates; i++) {
    4933                 :          0 :                 uint32_t refcnt = rte_atomic_fetch_add_explicit(&action_templates[i]->refcnt, 1,
    4934                 :            :                                                      rte_memory_order_relaxed) + 1;
    4935                 :            : 
    4936         [ #  # ]:          0 :                 if (refcnt <= 1) {
    4937                 :          0 :                         rte_flow_error_set(error, EINVAL,
    4938                 :            :                                            RTE_FLOW_ERROR_TYPE_ACTION,
    4939                 :            :                                            &action_templates[i], "invalid AT refcount");
    4940                 :          0 :                         goto at_error;
    4941                 :            :                 }
    4942                 :          0 :                 at[i] = action_templates[i]->tmpl;
    4943                 :          0 :                 tbl->ats[i].action_template = action_templates[i];
    4944                 :          0 :                 LIST_INIT(&tbl->ats[i].acts.act_list);
    4945                 :            :                 /* do NOT translate table action if `dev` was not started */
    4946         [ #  # ]:          0 :                 if (!dev->data->dev_started)
    4947                 :          0 :                         continue;
    4948                 :          0 :                 ret = flow_hw_translate_actions_template(dev, &tbl->cfg,
    4949                 :            :                                                   &tbl->ats[i].acts,
    4950                 :            :                                                   action_templates[i],
    4951                 :            :                                                   &tbl->mpctx, error);
    4952         [ #  # ]:          0 :                 if (ret) {
    4953                 :          0 :                         i++;
    4954                 :          0 :                         goto at_error;
    4955                 :            :                 }
    4956                 :          0 :                 flow_hw_populate_rule_acts_caches(dev, tbl, i);
    4957                 :            :         }
    4958         [ #  # ]:          0 :         tbl->nb_action_templates = nb_action_templates;
    4959         [ #  # ]:          0 :         if (mlx5_is_multi_pattern_active(&tbl->mpctx)) {
    4960         [ #  # ]:          0 :                 ret = mlx5_tbl_multi_pattern_process(dev, tbl,
    4961                 :            :                                                      &tbl->mpctx.segments[0],
    4962                 :            :                                                      rte_log2_u32(tbl->cfg.attr.nb_flows),
    4963                 :            :                                                      error);
    4964         [ #  # ]:          0 :                 if (ret)
    4965                 :          0 :                         goto at_error;
    4966                 :            :         }
    4967                 :            :         return 0;
    4968                 :            : 
    4969                 :            : at_error:
    4970         [ #  # ]:          0 :         while (i--) {
    4971                 :          0 :                 __flow_hw_action_template_destroy(dev, &tbl->ats[i].acts);
    4972                 :          0 :                 rte_atomic_fetch_sub_explicit(&action_templates[i]->refcnt,
    4973                 :            :                                    1, rte_memory_order_relaxed);
    4974                 :            :         }
    4975                 :          0 :         return rte_errno;
    4976                 :            : }
    4977                 :            : 
    4978                 :            : static bool
    4979                 :            : flow_hw_validate_template_domain(const struct rte_flow_attr *table_attr,
    4980                 :            :                                  uint32_t ingress, uint32_t egress, uint32_t transfer)
    4981                 :            : {
    4982                 :          0 :         if (table_attr->ingress)
    4983                 :            :                 return ingress != 0;
    4984   [ #  #  #  # ]:          0 :         else if (table_attr->egress)
    4985                 :            :                 return egress != 0;
    4986                 :            :         else
    4987                 :          0 :                 return transfer;
    4988                 :            : }
    4989                 :            : 
    4990                 :            : static bool
    4991                 :            : flow_hw_validate_table_domain(const struct rte_flow_attr *table_attr)
    4992                 :            : {
    4993                 :          0 :         return table_attr->ingress + table_attr->egress + table_attr->transfer
    4994                 :            :                 == 1;
    4995                 :            : }
    4996                 :            : 
    4997                 :            : /**
    4998                 :            :  * Create flow table.
    4999                 :            :  *
    5000                 :            :  * The input item and action templates will be binded to the table.
    5001                 :            :  * Flow memory will also be allocated. Matcher will be created based
    5002                 :            :  * on the item template. Action will be translated to the dedicated
    5003                 :            :  * DR action if possible.
    5004                 :            :  *
    5005                 :            :  * @param[in] dev
    5006                 :            :  *   Pointer to the rte_eth_dev structure.
    5007                 :            :  * @param[in] table_cfg
    5008                 :            :  *   Pointer to the table configuration.
    5009                 :            :  * @param[in] item_templates
    5010                 :            :  *   Item template array to be binded to the table.
    5011                 :            :  * @param[in] nb_item_templates
    5012                 :            :  *   Number of item template.
    5013                 :            :  * @param[in] action_templates
    5014                 :            :  *   Action template array to be binded to the table.
    5015                 :            :  * @param[in] nb_action_templates
    5016                 :            :  *   Number of action template.
    5017                 :            :  * @param[out] error
    5018                 :            :  *   Pointer to error structure.
    5019                 :            :  *
    5020                 :            :  * @return
    5021                 :            :  *    Table on success, NULL otherwise and rte_errno is set.
    5022                 :            :  */
    5023                 :            : static struct rte_flow_template_table *
    5024                 :          0 : flow_hw_table_create(struct rte_eth_dev *dev,
    5025                 :            :                      const struct mlx5_flow_template_table_cfg *table_cfg,
    5026                 :            :                      struct rte_flow_pattern_template *item_templates[],
    5027                 :            :                      uint8_t nb_item_templates,
    5028                 :            :                      struct rte_flow_actions_template *action_templates[],
    5029                 :            :                      uint8_t nb_action_templates,
    5030                 :            :                      struct rte_flow_error *error)
    5031                 :            : {
    5032                 :          0 :         struct rte_flow_error sub_error = {
    5033                 :            :                 .type = RTE_FLOW_ERROR_TYPE_NONE,
    5034                 :            :                 .cause = NULL,
    5035                 :            :                 .message = NULL,
    5036                 :            :         };
    5037                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    5038                 :          0 :         struct mlx5dr_matcher_attr matcher_attr = {0};
    5039                 :          0 :         struct mlx5dr_action_jump_to_matcher_attr jump_attr = {
    5040                 :            :                 .type = MLX5DR_ACTION_JUMP_TO_MATCHER_BY_INDEX,
    5041                 :            :                 .matcher = NULL,
    5042                 :            :         };
    5043                 :            :         struct rte_flow_template_table *tbl = NULL;
    5044                 :            :         struct mlx5_flow_group *grp;
    5045                 :            :         struct mlx5dr_match_template *mt[MLX5_HW_TBL_MAX_ITEM_TEMPLATE];
    5046                 :            :         struct mlx5dr_action_template *at[MLX5_HW_TBL_MAX_ACTION_TEMPLATE];
    5047                 :          0 :         const struct rte_flow_template_table_attr *attr = &table_cfg->attr;
    5048                 :          0 :         struct rte_flow_attr flow_attr = attr->flow_attr;
    5049                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
    5050                 :            :                 .dev = dev,
    5051                 :            :                 .error = &sub_error,
    5052                 :            :                 .data = &flow_attr,
    5053                 :            :         };
    5054                 :          0 :         struct mlx5_indexed_pool_config cfg = {
    5055                 :            :                 .trunk_size = 1 << 12,
    5056                 :            :                 .per_core_cache = 1 << 13,
    5057                 :            :                 .need_lock = 1,
    5058                 :          0 :                 .release_mem_en = !!priv->sh->config.reclaim_mode,
    5059                 :            :                 .malloc = mlx5_malloc,
    5060                 :            :                 .free = mlx5_free,
    5061                 :            :                 .type = "mlx5_hw_table_flow",
    5062                 :            :         };
    5063                 :            :         struct mlx5_list_entry *ge;
    5064                 :            :         uint32_t i = 0, max_tpl = MLX5_HW_TBL_MAX_ITEM_TEMPLATE;
    5065         [ #  # ]:          0 :         uint32_t nb_flows = rte_align32pow2(attr->nb_flows);
    5066                 :          0 :         bool port_started = !!dev->data->dev_started;
    5067                 :            :         bool rpool_needed;
    5068                 :            :         size_t tbl_mem_size;
    5069                 :            :         int err;
    5070                 :            : 
    5071         [ #  # ]:          0 :         if (!flow_hw_validate_table_domain(&attr->flow_attr)) {
    5072                 :          0 :                 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ATTR,
    5073                 :            :                                    NULL, "invalid table domain attributes");
    5074                 :          0 :                 return NULL;
    5075                 :            :         }
    5076         [ #  # ]:          0 :         for (i = 0; i < nb_item_templates; i++) {
    5077                 :            :                 const struct rte_flow_pattern_template_attr *pt_attr =
    5078                 :          0 :                         &item_templates[i]->attr;
    5079                 :            :                 bool match = flow_hw_validate_template_domain(&attr->flow_attr,
    5080                 :          0 :                                                               pt_attr->ingress,
    5081                 :          0 :                                                               pt_attr->egress,
    5082         [ #  # ]:          0 :                                                               pt_attr->transfer);
    5083         [ #  # ]:          0 :                 if (!match) {
    5084                 :          0 :                         rte_flow_error_set(error, EINVAL,
    5085                 :            :                                            RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    5086                 :            :                                            NULL, "pattern template domain does not match table");
    5087                 :          0 :                         return NULL;
    5088                 :            :                 }
    5089                 :            :         }
    5090         [ #  # ]:          0 :         for (i = 0; i < nb_action_templates; i++) {
    5091                 :          0 :                 const struct rte_flow_actions_template *at = action_templates[i];
    5092                 :            :                 bool match = flow_hw_validate_template_domain(&attr->flow_attr,
    5093                 :          0 :                                                               at->attr.ingress,
    5094                 :          0 :                                                               at->attr.egress,
    5095         [ #  # ]:          0 :                                                               at->attr.transfer);
    5096         [ #  # ]:          0 :                 if (!match) {
    5097                 :          0 :                         rte_flow_error_set(error, EINVAL,
    5098                 :            :                                            RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    5099                 :            :                                            NULL, "action template domain does not match table");
    5100                 :          0 :                         return NULL;
    5101                 :            :                 }
    5102                 :            :         }
    5103                 :            :         /* HWS layer accepts only 1 item template with root table. */
    5104         [ #  # ]:          0 :         if (!attr->flow_attr.group)
    5105                 :            :                 max_tpl = 1;
    5106                 :          0 :         cfg.max_idx = nb_flows;
    5107         [ #  # ]:          0 :         cfg.size = !rte_flow_template_table_resizable(dev->data->port_id, attr) ?
    5108                 :            :                    mlx5_flow_hw_entry_size() :
    5109                 :            :                    mlx5_flow_hw_auxed_entry_size();
    5110                 :            :         /* For table has very limited flows, disable cache. */
    5111         [ #  # ]:          0 :         if (nb_flows < cfg.trunk_size) {
    5112                 :          0 :                 cfg.per_core_cache = 0;
    5113                 :          0 :                 cfg.trunk_size = nb_flows;
    5114         [ #  # ]:          0 :         } else if (nb_flows <= MLX5_HW_IPOOL_SIZE_THRESHOLD) {
    5115                 :          0 :                 cfg.per_core_cache = MLX5_HW_IPOOL_CACHE_MIN;
    5116                 :            :         }
    5117                 :            :         /* Check if we requires too many templates. */
    5118   [ #  #  #  # ]:          0 :         if (nb_item_templates > max_tpl ||
    5119                 :            :             nb_action_templates > MLX5_HW_TBL_MAX_ACTION_TEMPLATE) {
    5120                 :          0 :                 rte_errno = EINVAL;
    5121                 :          0 :                 goto error;
    5122                 :            :         }
    5123                 :            :         /*
    5124                 :            :          * Amount of memory required for rte_flow_template_table struct:
    5125                 :            :          * - Size of the struct itself.
    5126                 :            :          * - VLA of DR rule action containers at the end =
    5127                 :            :          *     number of actions templates * number of queues * size of DR rule actions container.
    5128                 :            :          */
    5129                 :            :         tbl_mem_size = sizeof(*tbl);
    5130                 :          0 :         tbl_mem_size += nb_action_templates * priv->nb_queue * sizeof(tbl->rule_acts[0]);
    5131                 :            :         /* Allocate the table memory. */
    5132                 :          0 :         tbl = mlx5_malloc(MLX5_MEM_ZERO, tbl_mem_size, RTE_CACHE_LINE_SIZE, rte_socket_id());
    5133         [ #  # ]:          0 :         if (!tbl)
    5134                 :          0 :                 goto error;
    5135                 :          0 :         tbl->cfg = *table_cfg;
    5136                 :            :         /* Allocate flow indexed pool. */
    5137                 :          0 :         tbl->flow = mlx5_ipool_create(&cfg);
    5138         [ #  # ]:          0 :         if (!tbl->flow)
    5139                 :          0 :                 goto error;
    5140                 :            :         /* Allocate table of auxiliary flow rule structs. */
    5141                 :          0 :         tbl->flow_aux = mlx5_malloc(MLX5_MEM_ZERO, sizeof(struct rte_flow_hw_aux) * nb_flows,
    5142                 :          0 :                                     RTE_CACHE_LINE_SIZE, rte_dev_numa_node(dev->device));
    5143         [ #  # ]:          0 :         if (!tbl->flow_aux)
    5144                 :          0 :                 goto error;
    5145                 :            :         /* Register the flow group. */
    5146                 :          0 :         ge = mlx5_hlist_register(priv->sh->groups, attr->flow_attr.group, &ctx);
    5147         [ #  # ]:          0 :         if (!ge)
    5148                 :          0 :                 goto error;
    5149                 :            :         grp = container_of(ge, struct mlx5_flow_group, entry);
    5150                 :          0 :         tbl->grp = grp;
    5151                 :            :         /* Prepare matcher information. */
    5152                 :          0 :         matcher_attr.resizable = !!rte_flow_template_table_resizable
    5153                 :          0 :                                         (dev->data->port_id, &table_cfg->attr);
    5154                 :          0 :         matcher_attr.optimize_flow_src = MLX5DR_MATCHER_FLOW_SRC_ANY;
    5155                 :          0 :         matcher_attr.priority = attr->flow_attr.priority;
    5156                 :          0 :         matcher_attr.optimize_using_rule_idx = true;
    5157                 :          0 :         matcher_attr.mode = MLX5DR_MATCHER_RESOURCE_MODE_RULE;
    5158         [ #  # ]:          0 :         matcher_attr.insert_mode = flow_hw_matcher_insert_mode_get(attr->insertion_type);
    5159         [ #  # ]:          0 :         if (matcher_attr.insert_mode == MLX5DR_MATCHER_INSERT_BY_INDEX) {
    5160         [ #  # ]:          0 :                 if (attr->insertion_type == RTE_FLOW_TABLE_INSERTION_TYPE_INDEX_WITH_PATTERN) {
    5161                 :          0 :                         matcher_attr.isolated = true;
    5162                 :          0 :                         matcher_attr.match_mode = MLX5DR_MATCHER_MATCH_MODE_DEFAULT;
    5163                 :            :                 } else {
    5164                 :          0 :                         matcher_attr.isolated = false;
    5165                 :          0 :                         matcher_attr.match_mode = MLX5DR_MATCHER_MATCH_MODE_ALWAYS_HIT;
    5166                 :            :                 }
    5167                 :            :         }
    5168         [ #  # ]:          0 :         if (attr->hash_func == RTE_FLOW_TABLE_HASH_FUNC_CRC16) {
    5169                 :          0 :                 DRV_LOG(ERR, "16-bit checksum hash type is not supported");
    5170                 :          0 :                 rte_errno = ENOTSUP;
    5171                 :          0 :                 goto it_error;
    5172                 :            :         }
    5173         [ #  # ]:          0 :         matcher_attr.distribute_mode = flow_hw_matcher_distribute_mode_get(attr->hash_func);
    5174                 :          0 :         matcher_attr.rule.num_log = rte_log2_u32(nb_flows);
    5175                 :            :         /* Parse hints information. */
    5176         [ #  # ]:          0 :         if (attr->specialize) {
    5177                 :            :                 uint32_t val = RTE_FLOW_TABLE_SPECIALIZE_TRANSFER_WIRE_ORIG |
    5178                 :            :                                RTE_FLOW_TABLE_SPECIALIZE_TRANSFER_VPORT_ORIG;
    5179                 :            : 
    5180         [ #  # ]:          0 :                 if ((attr->specialize & val) == val) {
    5181                 :          0 :                         DRV_LOG(ERR, "Invalid hint value %x",
    5182                 :            :                                 attr->specialize);
    5183                 :          0 :                         rte_errno = EINVAL;
    5184                 :          0 :                         goto it_error;
    5185                 :            :                 }
    5186         [ #  # ]:          0 :                 if (attr->specialize &
    5187                 :            :                     RTE_FLOW_TABLE_SPECIALIZE_TRANSFER_WIRE_ORIG)
    5188                 :          0 :                         matcher_attr.optimize_flow_src =
    5189                 :            :                                 MLX5DR_MATCHER_FLOW_SRC_WIRE;
    5190         [ #  # ]:          0 :                 else if (attr->specialize &
    5191                 :            :                          RTE_FLOW_TABLE_SPECIALIZE_TRANSFER_VPORT_ORIG)
    5192                 :          0 :                         matcher_attr.optimize_flow_src =
    5193                 :            :                                 MLX5DR_MATCHER_FLOW_SRC_VPORT;
    5194                 :            :         }
    5195                 :            :         /* Build the item template. */
    5196         [ #  # ]:          0 :         for (i = 0; i < nb_item_templates; i++) {
    5197                 :            :                 uint32_t ret;
    5198                 :            : 
    5199   [ #  #  #  # ]:          0 :                 if ((flow_attr.ingress && !item_templates[i]->attr.ingress) ||
    5200   [ #  #  #  # ]:          0 :                     (flow_attr.egress && !item_templates[i]->attr.egress) ||
    5201   [ #  #  #  # ]:          0 :                     (flow_attr.transfer && !item_templates[i]->attr.transfer)) {
    5202                 :          0 :                         DRV_LOG(ERR, "pattern template and template table attribute mismatch");
    5203                 :          0 :                         rte_errno = EINVAL;
    5204                 :          0 :                         goto it_error;
    5205                 :            :                 }
    5206         [ #  # ]:          0 :                 if (item_templates[i]->item_flags & MLX5_FLOW_ITEM_COMPARE)
    5207                 :          0 :                         matcher_attr.mode = MLX5DR_MATCHER_RESOURCE_MODE_HTABLE;
    5208                 :          0 :                 ret = rte_atomic_fetch_add_explicit(&item_templates[i]->refcnt, 1,
    5209                 :            :                                          rte_memory_order_relaxed) + 1;
    5210         [ #  # ]:          0 :                 if (ret <= 1) {
    5211                 :          0 :                         rte_errno = EINVAL;
    5212                 :          0 :                         goto it_error;
    5213                 :            :                 }
    5214                 :          0 :                 mt[i] = item_templates[i]->mt;
    5215                 :          0 :                 tbl->its[i] = item_templates[i];
    5216                 :            :         }
    5217                 :          0 :         tbl->nb_item_templates = nb_item_templates;
    5218                 :            :         /* Build the action template. */
    5219                 :          0 :         err = mlx5_hw_build_template_table(dev, nb_action_templates,
    5220                 :            :                                            action_templates, at, tbl, &sub_error);
    5221         [ #  # ]:          0 :         if (err) {
    5222                 :            :                 i = nb_item_templates;
    5223                 :          0 :                 goto it_error;
    5224                 :            :         }
    5225                 :          0 :         tbl->matcher_info[0].matcher = mlx5dr_matcher_create
    5226                 :          0 :                 (tbl->grp->tbl, mt, nb_item_templates, at, nb_action_templates, &matcher_attr);
    5227         [ #  # ]:          0 :         if (!tbl->matcher_info[0].matcher)
    5228                 :          0 :                 goto at_error;
    5229                 :          0 :         tbl->matcher_attr = matcher_attr;
    5230         [ #  # ]:          0 :         tbl->type = attr->flow_attr.transfer ? MLX5DR_TABLE_TYPE_FDB :
    5231                 :          0 :                     (attr->flow_attr.egress ? MLX5DR_TABLE_TYPE_NIC_TX :
    5232                 :            :                     MLX5DR_TABLE_TYPE_NIC_RX);
    5233         [ #  # ]:          0 :         if (matcher_attr.isolated) {
    5234                 :          0 :                 jump_attr.matcher = tbl->matcher_info[0].matcher;
    5235                 :          0 :                 tbl->matcher_info[0].jump = mlx5dr_action_create_jump_to_matcher(priv->dr_ctx,
    5236                 :          0 :                                 &jump_attr, mlx5_hw_act_flag[!!attr->flow_attr.group][tbl->type]);
    5237         [ #  # ]:          0 :                 if (!tbl->matcher_info[0].jump)
    5238                 :          0 :                         goto jtm_error;
    5239                 :            :         }
    5240                 :            :         /*
    5241                 :            :          * Only the matcher supports update and needs more than 1 WQE, an additional
    5242                 :            :          * index is needed. Or else the flow index can be reused.
    5243                 :            :          */
    5244   [ #  #  #  # ]:          0 :         rpool_needed = mlx5dr_matcher_is_updatable(tbl->matcher_info[0].matcher) &&
    5245                 :          0 :                        mlx5dr_matcher_is_dependent(tbl->matcher_info[0].matcher);
    5246         [ #  # ]:          0 :         if (rpool_needed) {
    5247                 :            :                 /* Allocate rule indexed pool. */
    5248                 :          0 :                 cfg.size = 0;
    5249                 :          0 :                 cfg.type = "mlx5_hw_table_rule";
    5250                 :          0 :                 cfg.max_idx += priv->hw_q[0].size;
    5251                 :          0 :                 tbl->resource = mlx5_ipool_create(&cfg);
    5252         [ #  # ]:          0 :                 if (!tbl->resource)
    5253                 :          0 :                         goto res_error;
    5254                 :            :         }
    5255         [ #  # ]:          0 :         if (port_started)
    5256         [ #  # ]:          0 :                 LIST_INSERT_HEAD(&priv->flow_hw_tbl, tbl, next);
    5257                 :            :         else
    5258         [ #  # ]:          0 :                 LIST_INSERT_HEAD(&priv->flow_hw_tbl_ongo, tbl, next);
    5259                 :            :         rte_rwlock_init(&tbl->matcher_replace_rwlk);
    5260                 :          0 :         return tbl;
    5261                 :            : res_error:
    5262         [ #  # ]:          0 :         if (tbl->matcher_info[0].jump)
    5263                 :          0 :                 mlx5dr_action_destroy(tbl->matcher_info[0].jump);
    5264                 :          0 : jtm_error:
    5265         [ #  # ]:          0 :         if (tbl->matcher_info[0].matcher)
    5266                 :          0 :                 (void)mlx5dr_matcher_destroy(tbl->matcher_info[0].matcher);
    5267                 :          0 : at_error:
    5268         [ #  # ]:          0 :         for (i = 0; i < nb_action_templates; i++) {
    5269                 :          0 :                 __flow_hw_action_template_destroy(dev, &tbl->ats[i].acts);
    5270                 :          0 :                 rte_atomic_fetch_sub_explicit(&action_templates[i]->refcnt,
    5271                 :            :                                    1, rte_memory_order_relaxed);
    5272                 :            :         }
    5273                 :            :         i = nb_item_templates;
    5274                 :            : it_error:
    5275         [ #  # ]:          0 :         while (i--)
    5276                 :          0 :                 rte_atomic_fetch_sub_explicit(&item_templates[i]->refcnt,
    5277                 :            :                                    1, rte_memory_order_relaxed);
    5278                 :          0 : error:
    5279                 :          0 :         err = rte_errno;
    5280         [ #  # ]:          0 :         if (tbl) {
    5281         [ #  # ]:          0 :                 if (tbl->grp)
    5282                 :          0 :                         mlx5_hlist_unregister(priv->sh->groups,
    5283                 :            :                                               &tbl->grp->entry);
    5284         [ #  # ]:          0 :                 if (tbl->flow_aux)
    5285                 :          0 :                         mlx5_free(tbl->flow_aux);
    5286         [ #  # ]:          0 :                 if (tbl->flow)
    5287                 :          0 :                         mlx5_ipool_destroy(tbl->flow);
    5288                 :          0 :                 mlx5_free(tbl);
    5289                 :            :         }
    5290         [ #  # ]:          0 :         if (error != NULL) {
    5291         [ #  # ]:          0 :                 if (sub_error.type == RTE_FLOW_ERROR_TYPE_NONE)
    5292                 :          0 :                         rte_flow_error_set(error, err, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    5293                 :            :                                            "Failed to create template table");
    5294                 :            :                 else
    5295                 :            :                         rte_memcpy(error, &sub_error, sizeof(sub_error));
    5296                 :            :         }
    5297                 :            :         return NULL;
    5298                 :            : }
    5299                 :            : 
    5300                 :            : /**
    5301                 :            :  * Update flow template table.
    5302                 :            :  *
    5303                 :            :  * @param[in] dev
    5304                 :            :  *   Pointer to the rte_eth_dev structure.
    5305                 :            :  * @param[out] error
    5306                 :            :  *   Pointer to error structure.
    5307                 :            :  *
    5308                 :            :  * @return
    5309                 :            :  *    0 on success, negative value otherwise and rte_errno is set.
    5310                 :            :  */
    5311                 :            : int
    5312                 :          0 : flow_hw_table_update(struct rte_eth_dev *dev,
    5313                 :            :                      struct rte_flow_error *error)
    5314                 :            : {
    5315                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    5316                 :            :         struct rte_flow_template_table *tbl;
    5317                 :            : 
    5318         [ #  # ]:          0 :         while ((tbl = LIST_FIRST(&priv->flow_hw_tbl_ongo)) != NULL) {
    5319         [ #  # ]:          0 :                 if (flow_hw_translate_all_actions_templates(dev, tbl, error))
    5320                 :            :                         return -1;
    5321         [ #  # ]:          0 :                 LIST_REMOVE(tbl, next);
    5322         [ #  # ]:          0 :                 LIST_INSERT_HEAD(&priv->flow_hw_tbl, tbl, next);
    5323                 :            :         }
    5324                 :            :         return 0;
    5325                 :            : }
    5326                 :            : 
    5327                 :            : static inline int
    5328                 :          0 : __translate_group(struct rte_eth_dev *dev,
    5329                 :            :                         const struct rte_flow_attr *flow_attr,
    5330                 :            :                         bool external,
    5331                 :            :                         uint32_t group,
    5332                 :            :                         uint32_t *table_group,
    5333                 :            :                         struct rte_flow_error *error)
    5334                 :            : {
    5335                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    5336                 :          0 :         struct mlx5_sh_config *config = &priv->sh->config;
    5337                 :            : 
    5338         [ #  # ]:          0 :         if (config->dv_esw_en &&
    5339   [ #  #  #  # ]:          0 :             priv->fdb_def_rule &&
    5340         [ #  # ]:          0 :             external &&
    5341                 :            :             flow_attr->transfer) {
    5342         [ #  # ]:          0 :                 if (group > MLX5_HW_MAX_TRANSFER_GROUP)
    5343                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5344                 :            :                                                   RTE_FLOW_ERROR_TYPE_ATTR_GROUP,
    5345                 :            :                                                   NULL,
    5346                 :            :                                                   "group index not supported");
    5347                 :          0 :                 *table_group = group + 1;
    5348         [ #  # ]:          0 :         } else if (config->dv_esw_en &&
    5349   [ #  #  #  #  :          0 :                    (config->repr_matching || config->dv_xmeta_en == MLX5_XMETA_MODE_META32_HWS) &&
                   #  # ]
    5350         [ #  # ]:          0 :                    external &&
    5351                 :            :                    flow_attr->egress) {
    5352                 :            :                 /*
    5353                 :            :                  * On E-Switch setups, default egress flow rules are inserted to allow
    5354                 :            :                  * representor matching and/or preserving metadata across steering domains.
    5355                 :            :                  * These flow rules are inserted in group 0 and this group is reserved by PMD
    5356                 :            :                  * for these purposes.
    5357                 :            :                  *
    5358                 :            :                  * As a result, if representor matching or extended metadata mode is enabled,
    5359                 :            :                  * group provided by the user must be incremented to avoid inserting flow rules
    5360                 :            :                  * in group 0.
    5361                 :            :                  */
    5362         [ #  # ]:          0 :                 if (group > MLX5_HW_MAX_EGRESS_GROUP)
    5363                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5364                 :            :                                                   RTE_FLOW_ERROR_TYPE_ATTR_GROUP,
    5365                 :            :                                                   NULL,
    5366                 :            :                                                   "group index not supported");
    5367                 :          0 :                 *table_group = group + 1;
    5368                 :            :         } else {
    5369                 :          0 :                 *table_group = group;
    5370                 :            :         }
    5371                 :            :         return 0;
    5372                 :            : }
    5373                 :            : 
    5374                 :            : /**
    5375                 :            :  * Translates group index specified by the user in @p attr to internal
    5376                 :            :  * group index.
    5377                 :            :  *
    5378                 :            :  * Translation is done by incrementing group index, so group n becomes n + 1.
    5379                 :            :  *
    5380                 :            :  * @param[in] dev
    5381                 :            :  *   Pointer to Ethernet device.
    5382                 :            :  * @param[in] cfg
    5383                 :            :  *   Pointer to the template table configuration.
    5384                 :            :  * @param[in] group
    5385                 :            :  *   Currently used group index (table group or jump destination).
    5386                 :            :  * @param[out] table_group
    5387                 :            :  *   Pointer to output group index.
    5388                 :            :  * @param[out] error
    5389                 :            :  *   Pointer to error structure.
    5390                 :            :  *
    5391                 :            :  * @return
    5392                 :            :  *   0 on success. Otherwise, returns negative error code, rte_errno is set
    5393                 :            :  *   and error structure is filled.
    5394                 :            :  */
    5395                 :            : static int
    5396                 :            : flow_hw_translate_group(struct rte_eth_dev *dev,
    5397                 :            :                         const struct mlx5_flow_template_table_cfg *cfg,
    5398                 :            :                         uint32_t group,
    5399                 :            :                         uint32_t *table_group,
    5400                 :            :                         struct rte_flow_error *error)
    5401                 :            : {
    5402                 :          0 :         const struct rte_flow_attr *flow_attr = &cfg->attr.flow_attr;
    5403                 :            : 
    5404                 :          0 :         return __translate_group(dev, flow_attr, cfg->external, group, table_group, error);
    5405                 :            : }
    5406                 :            : 
    5407                 :            : /**
    5408                 :            :  * Create flow table.
    5409                 :            :  *
    5410                 :            :  * This function is a wrapper over @ref flow_hw_table_create(), which translates parameters
    5411                 :            :  * provided by user to proper internal values.
    5412                 :            :  *
    5413                 :            :  * @param[in] dev
    5414                 :            :  *   Pointer to Ethernet device.
    5415                 :            :  * @param[in] attr
    5416                 :            :  *   Pointer to the table attributes.
    5417                 :            :  * @param[in] item_templates
    5418                 :            :  *   Item template array to be binded to the table.
    5419                 :            :  * @param[in] nb_item_templates
    5420                 :            :  *   Number of item templates.
    5421                 :            :  * @param[in] action_templates
    5422                 :            :  *   Action template array to be binded to the table.
    5423                 :            :  * @param[in] nb_action_templates
    5424                 :            :  *   Number of action templates.
    5425                 :            :  * @param[out] error
    5426                 :            :  *   Pointer to error structure.
    5427                 :            :  *
    5428                 :            :  * @return
    5429                 :            :  *   Table on success, Otherwise, returns negative error code, rte_errno is set
    5430                 :            :  *   and error structure is filled.
    5431                 :            :  */
    5432                 :            : static struct rte_flow_template_table *
    5433                 :          0 : flow_hw_template_table_create(struct rte_eth_dev *dev,
    5434                 :            :                               const struct rte_flow_template_table_attr *attr,
    5435                 :            :                               struct rte_flow_pattern_template *item_templates[],
    5436                 :            :                               uint8_t nb_item_templates,
    5437                 :            :                               struct rte_flow_actions_template *action_templates[],
    5438                 :            :                               uint8_t nb_action_templates,
    5439                 :            :                               struct rte_flow_error *error)
    5440                 :            : {
    5441                 :          0 :         struct mlx5_flow_template_table_cfg cfg = {
    5442                 :            :                 .attr = *attr,
    5443                 :            :                 .external = true,
    5444                 :            :         };
    5445                 :          0 :         uint32_t group = attr->flow_attr.group;
    5446                 :            : 
    5447         [ #  # ]:          0 :         if (flow_hw_translate_group(dev, &cfg, group, &cfg.attr.flow_attr.group, error))
    5448                 :            :                 return NULL;
    5449   [ #  #  #  # ]:          0 :         if (!cfg.attr.flow_attr.group &&
    5450                 :          0 :             rte_flow_template_table_resizable(dev->data->port_id, attr)) {
    5451                 :          0 :                 rte_flow_error_set(error, EINVAL,
    5452                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    5453                 :            :                                    "table cannot be resized: invalid group");
    5454                 :          0 :                 return NULL;
    5455                 :            :         }
    5456                 :          0 :         return flow_hw_table_create(dev, &cfg, item_templates, nb_item_templates,
    5457                 :            :                                     action_templates, nb_action_templates, error);
    5458                 :            : }
    5459                 :            : 
    5460                 :            : static void
    5461                 :          0 : mlx5_destroy_multi_pattern_segment(struct mlx5_multi_pattern_segment *segment)
    5462                 :            : {
    5463                 :            :         int i;
    5464                 :            : 
    5465         [ #  # ]:          0 :         if (segment->mhdr_action)
    5466                 :          0 :                 mlx5dr_action_destroy(segment->mhdr_action);
    5467         [ #  # ]:          0 :         for (i = 0; i < MLX5_MULTIPATTERN_ENCAP_NUM; i++) {
    5468         [ #  # ]:          0 :                 if (segment->reformat_action[i])
    5469                 :          0 :                         mlx5dr_action_destroy(segment->reformat_action[i]);
    5470                 :            :         }
    5471                 :          0 :         segment->capacity = 0;
    5472                 :          0 : }
    5473                 :            : 
    5474                 :            : static void
    5475                 :            : flow_hw_destroy_table_multi_pattern_ctx(struct rte_flow_template_table *table)
    5476                 :            : {
    5477                 :            :         int sx;
    5478                 :            : 
    5479         [ #  # ]:          0 :         for (sx = 0; sx < MLX5_MAX_TABLE_RESIZE_NUM; sx++)
    5480                 :          0 :                 mlx5_destroy_multi_pattern_segment(table->mpctx.segments + sx);
    5481                 :            : }
    5482                 :            : /**
    5483                 :            :  * Destroy flow table.
    5484                 :            :  *
    5485                 :            :  * @param[in] dev
    5486                 :            :  *   Pointer to the rte_eth_dev structure.
    5487                 :            :  * @param[in] table
    5488                 :            :  *   Pointer to the table to be destroyed.
    5489                 :            :  * @param[out] error
    5490                 :            :  *   Pointer to error structure.
    5491                 :            :  *
    5492                 :            :  * @return
    5493                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5494                 :            :  */
    5495                 :            : static int
    5496                 :          0 : flow_hw_table_destroy(struct rte_eth_dev *dev,
    5497                 :            :                       struct rte_flow_template_table *table,
    5498                 :            :                       struct rte_flow_error *error)
    5499                 :            : {
    5500                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    5501                 :            :         int i;
    5502                 :          0 :         uint32_t fidx = 1;
    5503                 :          0 :         uint32_t ridx = 1;
    5504                 :            : 
    5505                 :            :         /* Build ipool allocated object bitmap. */
    5506         [ #  # ]:          0 :         if (table->resource)
    5507                 :          0 :                 mlx5_ipool_flush_cache(table->resource);
    5508                 :          0 :         mlx5_ipool_flush_cache(table->flow);
    5509                 :            :         /* Check if ipool has allocated objects. */
    5510   [ #  #  #  # ]:          0 :         if (table->refcnt ||
    5511                 :          0 :             mlx5_ipool_get_next(table->flow, &fidx) ||
    5512   [ #  #  #  # ]:          0 :             (table->resource && mlx5_ipool_get_next(table->resource, &ridx))) {
    5513                 :          0 :                 DRV_LOG(WARNING, "Table %p is still in use.", (void *)table);
    5514                 :          0 :                 return rte_flow_error_set(error, EBUSY,
    5515                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    5516                 :            :                                    NULL,
    5517                 :            :                                    "table is in use");
    5518                 :            :         }
    5519         [ #  # ]:          0 :         LIST_REMOVE(table, next);
    5520         [ #  # ]:          0 :         for (i = 0; i < table->nb_item_templates; i++)
    5521                 :          0 :                 rte_atomic_fetch_sub_explicit(&table->its[i]->refcnt,
    5522                 :            :                                    1, rte_memory_order_relaxed);
    5523         [ #  # ]:          0 :         for (i = 0; i < table->nb_action_templates; i++) {
    5524                 :          0 :                 __flow_hw_action_template_destroy(dev, &table->ats[i].acts);
    5525                 :          0 :                 rte_atomic_fetch_sub_explicit(&table->ats[i].action_template->refcnt,
    5526                 :            :                                    1, rte_memory_order_relaxed);
    5527                 :            :         }
    5528                 :            :         flow_hw_destroy_table_multi_pattern_ctx(table);
    5529         [ #  # ]:          0 :         if (table->matcher_info[0].jump)
    5530                 :          0 :                 mlx5dr_action_destroy(table->matcher_info[0].jump);
    5531         [ #  # ]:          0 :         if (table->matcher_info[0].matcher)
    5532                 :          0 :                 mlx5dr_matcher_destroy(table->matcher_info[0].matcher);
    5533         [ #  # ]:          0 :         if (table->matcher_info[1].jump)
    5534                 :          0 :                 mlx5dr_action_destroy(table->matcher_info[1].jump);
    5535         [ #  # ]:          0 :         if (table->matcher_info[1].matcher)
    5536                 :          0 :                 mlx5dr_matcher_destroy(table->matcher_info[1].matcher);
    5537                 :          0 :         mlx5_hlist_unregister(priv->sh->groups, &table->grp->entry);
    5538         [ #  # ]:          0 :         if (table->resource)
    5539                 :          0 :                 mlx5_ipool_destroy(table->resource);
    5540                 :          0 :         mlx5_free(table->flow_aux);
    5541                 :          0 :         mlx5_ipool_destroy(table->flow);
    5542                 :          0 :         mlx5_free(table);
    5543                 :          0 :         return 0;
    5544                 :            : }
    5545                 :            : 
    5546                 :            : /**
    5547                 :            :  * Parse group's miss actions.
    5548                 :            :  *
    5549                 :            :  * @param[in] dev
    5550                 :            :  *   Pointer to the rte_eth_dev structure.
    5551                 :            :  * @param[in] cfg
    5552                 :            :  *   Pointer to the table_cfg structure.
    5553                 :            :  * @param[in] actions
    5554                 :            :  *   Array of actions to perform on group miss. Supported types:
    5555                 :            :  *   RTE_FLOW_ACTION_TYPE_JUMP, RTE_FLOW_ACTION_TYPE_VOID, RTE_FLOW_ACTION_TYPE_END.
    5556                 :            :  * @param[out] dst_group_id
    5557                 :            :  *   Pointer to destination group id output. will be set to 0 if actions is END,
    5558                 :            :  *   otherwise will be set to destination group id.
    5559                 :            :  * @param[out] error
    5560                 :            :  *   Pointer to error structure.
    5561                 :            :  *
    5562                 :            :  * @return
    5563                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5564                 :            :  */
    5565                 :            : 
    5566                 :            : static int
    5567                 :          0 : flow_hw_group_parse_miss_actions(struct rte_eth_dev *dev,
    5568                 :            :                                  struct mlx5_flow_template_table_cfg *cfg,
    5569                 :            :                                  const struct rte_flow_action actions[],
    5570                 :            :                                  uint32_t *dst_group_id,
    5571                 :            :                                  struct rte_flow_error *error)
    5572                 :            : {
    5573                 :            :         const struct rte_flow_action_jump *jump_conf;
    5574                 :          0 :         uint32_t temp = 0;
    5575                 :            :         uint32_t i;
    5576                 :            : 
    5577         [ #  # ]:          0 :         for (i = 0; actions[i].type != RTE_FLOW_ACTION_TYPE_END; i++) {
    5578      [ #  #  # ]:          0 :                 switch (actions[i].type) {
    5579                 :          0 :                 case RTE_FLOW_ACTION_TYPE_VOID:
    5580                 :          0 :                         continue;
    5581                 :          0 :                 case RTE_FLOW_ACTION_TYPE_JUMP:
    5582         [ #  # ]:          0 :                         if (temp)
    5583                 :          0 :                                 return rte_flow_error_set(error, ENOTSUP,
    5584                 :            :                                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED, actions,
    5585                 :            :                                                           "Miss actions can contain only a single JUMP");
    5586                 :            : 
    5587                 :          0 :                         jump_conf = (const struct rte_flow_action_jump *)actions[i].conf;
    5588         [ #  # ]:          0 :                         if (!jump_conf)
    5589                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    5590                 :            :                                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    5591                 :            :                                                           jump_conf, "Jump conf must not be NULL");
    5592                 :            : 
    5593         [ #  # ]:          0 :                         if (flow_hw_translate_group(dev, cfg, jump_conf->group, &temp, error))
    5594                 :          0 :                                 return -rte_errno;
    5595                 :            : 
    5596         [ #  # ]:          0 :                         if (!temp)
    5597                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    5598                 :            :                                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    5599                 :            :                                                           "Failed to set group miss actions - Invalid target group");
    5600                 :            :                         break;
    5601                 :          0 :                 default:
    5602                 :          0 :                         return rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION,
    5603                 :            :                                                   &actions[i], "Unsupported default miss action type");
    5604                 :            :                 }
    5605                 :            :         }
    5606                 :            : 
    5607                 :          0 :         *dst_group_id = temp;
    5608                 :          0 :         return 0;
    5609                 :            : }
    5610                 :            : 
    5611                 :            : /**
    5612                 :            :  * Set group's miss group.
    5613                 :            :  *
    5614                 :            :  * @param[in] dev
    5615                 :            :  *   Pointer to the rte_eth_dev structure.
    5616                 :            :  * @param[in] cfg
    5617                 :            :  *   Pointer to the table_cfg structure.
    5618                 :            :  * @param[in] src_grp
    5619                 :            :  *   Pointer to source group structure.
    5620                 :            :  *   if NULL, a new group will be created based on group id from cfg->attr.flow_attr.group.
    5621                 :            :  * @param[in] dst_grp
    5622                 :            :  *   Pointer to destination group structure.
    5623                 :            :  * @param[out] error
    5624                 :            :  *   Pointer to error structure.
    5625                 :            :  *
    5626                 :            :  * @return
    5627                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5628                 :            :  */
    5629                 :            : 
    5630                 :            : static int
    5631                 :          0 : flow_hw_group_set_miss_group(struct rte_eth_dev *dev,
    5632                 :            :                              struct mlx5_flow_template_table_cfg *cfg,
    5633                 :            :                              struct mlx5_flow_group *src_grp,
    5634                 :            :                              struct mlx5_flow_group *dst_grp,
    5635                 :            :                              struct rte_flow_error *error)
    5636                 :            : {
    5637                 :          0 :         struct rte_flow_error sub_error = {
    5638                 :            :                 .type = RTE_FLOW_ERROR_TYPE_NONE,
    5639                 :            :                 .cause = NULL,
    5640                 :            :                 .message = NULL,
    5641                 :            :         };
    5642                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
    5643                 :            :                 .dev = dev,
    5644                 :            :                 .error = &sub_error,
    5645                 :          0 :                 .data = &cfg->attr.flow_attr,
    5646                 :            :         };
    5647                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    5648                 :            :         struct mlx5_list_entry *ge;
    5649                 :            :         bool ref = false;
    5650                 :            :         int ret;
    5651                 :            : 
    5652         [ #  # ]:          0 :         if (!dst_grp)
    5653                 :            :                 return -EINVAL;
    5654                 :            : 
    5655                 :            :         /* If group doesn't exist - needs to be created. */
    5656         [ #  # ]:          0 :         if (!src_grp) {
    5657                 :          0 :                 ge = mlx5_hlist_register(priv->sh->groups, cfg->attr.flow_attr.group, &ctx);
    5658         [ #  # ]:          0 :                 if (!ge)
    5659                 :          0 :                         return -rte_errno;
    5660                 :            : 
    5661                 :            :                 src_grp = container_of(ge, struct mlx5_flow_group, entry);
    5662         [ #  # ]:          0 :                 LIST_INSERT_HEAD(&priv->flow_hw_grp, src_grp, next);
    5663                 :            :                 ref = true;
    5664         [ #  # ]:          0 :         } else if (!src_grp->miss_group) {
    5665                 :            :                 /* If group exists, but has no miss actions - need to increase ref_cnt. */
    5666         [ #  # ]:          0 :                 LIST_INSERT_HEAD(&priv->flow_hw_grp, src_grp, next);
    5667                 :          0 :                 src_grp->entry.ref_cnt++;
    5668                 :            :                 ref = true;
    5669                 :            :         }
    5670                 :            : 
    5671                 :          0 :         ret = mlx5dr_table_set_default_miss(src_grp->tbl, dst_grp->tbl);
    5672         [ #  # ]:          0 :         if (ret)
    5673                 :          0 :                 goto mlx5dr_error;
    5674                 :            : 
    5675                 :            :         /* If group existed and had old miss actions - ref_cnt is already correct.
    5676                 :            :          * However, need to reduce ref counter for old miss group.
    5677                 :            :          */
    5678         [ #  # ]:          0 :         if (src_grp->miss_group)
    5679                 :          0 :                 mlx5_hlist_unregister(priv->sh->groups, &src_grp->miss_group->entry);
    5680                 :            : 
    5681                 :          0 :         src_grp->miss_group = dst_grp;
    5682                 :          0 :         return 0;
    5683                 :            : 
    5684                 :            : mlx5dr_error:
    5685                 :            :         /* Reduce src_grp ref_cnt back & remove from grp list in case of mlx5dr error */
    5686         [ #  # ]:          0 :         if (ref) {
    5687                 :          0 :                 mlx5_hlist_unregister(priv->sh->groups, &src_grp->entry);
    5688         [ #  # ]:          0 :                 LIST_REMOVE(src_grp, next);
    5689                 :            :         }
    5690                 :            : 
    5691                 :          0 :         return rte_flow_error_set(error, -ret, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    5692                 :            :                                   "Failed to set group miss actions");
    5693                 :            : }
    5694                 :            : 
    5695                 :            : /**
    5696                 :            :  * Unset group's miss group.
    5697                 :            :  *
    5698                 :            :  * @param[in] dev
    5699                 :            :  *   Pointer to the rte_eth_dev structure.
    5700                 :            :  * @param[in] grp
    5701                 :            :  *   Pointer to group structure.
    5702                 :            :  * @param[out] error
    5703                 :            :  *   Pointer to error structure.
    5704                 :            :  *
    5705                 :            :  * @return
    5706                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5707                 :            :  */
    5708                 :            : 
    5709                 :            : static int
    5710                 :          0 : flow_hw_group_unset_miss_group(struct rte_eth_dev *dev,
    5711                 :            :                                struct mlx5_flow_group *grp,
    5712                 :            :                                struct rte_flow_error *error)
    5713                 :            : {
    5714                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    5715                 :            :         int ret;
    5716                 :            : 
    5717                 :            :         /* If group doesn't exist - no need to change anything. */
    5718         [ #  # ]:          0 :         if (!grp)
    5719                 :            :                 return 0;
    5720                 :            : 
    5721                 :            :         /* If group exists, but miss actions is already default behavior -
    5722                 :            :          * no need to change anything.
    5723                 :            :          */
    5724         [ #  # ]:          0 :         if (!grp->miss_group)
    5725                 :            :                 return 0;
    5726                 :            : 
    5727                 :          0 :         ret = mlx5dr_table_set_default_miss(grp->tbl, NULL);
    5728         [ #  # ]:          0 :         if (ret)
    5729                 :          0 :                 return rte_flow_error_set(error, -ret, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    5730                 :            :                                           "Failed to unset group miss actions");
    5731                 :            : 
    5732                 :          0 :         mlx5_hlist_unregister(priv->sh->groups, &grp->miss_group->entry);
    5733                 :          0 :         grp->miss_group = NULL;
    5734                 :            : 
    5735         [ #  # ]:          0 :         LIST_REMOVE(grp, next);
    5736                 :          0 :         mlx5_hlist_unregister(priv->sh->groups, &grp->entry);
    5737                 :            : 
    5738                 :          0 :         return 0;
    5739                 :            : }
    5740                 :            : 
    5741                 :            : /**
    5742                 :            :  * Set group miss actions.
    5743                 :            :  *
    5744                 :            :  * @param[in] dev
    5745                 :            :  *   Pointer to the rte_eth_dev structure.
    5746                 :            :  * @param[in] group_id
    5747                 :            :  *   Group id.
    5748                 :            :  * @param[in] attr
    5749                 :            :  *   Pointer to group attributes structure.
    5750                 :            :  * @param[in] actions
    5751                 :            :  *   Array of actions to perform on group miss. Supported types:
    5752                 :            :  *   RTE_FLOW_ACTION_TYPE_JUMP, RTE_FLOW_ACTION_TYPE_VOID, RTE_FLOW_ACTION_TYPE_END.
    5753                 :            :  * @param[out] error
    5754                 :            :  *   Pointer to error structure.
    5755                 :            :  *
    5756                 :            :  * @return
    5757                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5758                 :            :  */
    5759                 :            : 
    5760                 :            : static int
    5761                 :          0 : flow_hw_group_set_miss_actions(struct rte_eth_dev *dev,
    5762                 :            :                                uint32_t group_id,
    5763                 :            :                                const struct rte_flow_group_attr *attr,
    5764                 :            :                                const struct rte_flow_action actions[],
    5765                 :            :                                struct rte_flow_error *error)
    5766                 :            : {
    5767                 :          0 :         struct rte_flow_error sub_error = {
    5768                 :            :                 .type = RTE_FLOW_ERROR_TYPE_NONE,
    5769                 :            :                 .cause = NULL,
    5770                 :            :                 .message = NULL,
    5771                 :            :         };
    5772                 :          0 :         struct mlx5_flow_template_table_cfg cfg = {
    5773                 :            :                 .external = true,
    5774                 :            :                 .attr = {
    5775                 :            :                         .flow_attr = {
    5776                 :            :                                 .group = group_id,
    5777                 :          0 :                                 .ingress = attr->ingress,
    5778                 :          0 :                                 .egress = attr->egress,
    5779                 :          0 :                                 .transfer = attr->transfer,
    5780                 :            :                         },
    5781                 :            :                 },
    5782                 :            :         };
    5783                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
    5784                 :            :                 .dev = dev,
    5785                 :            :                 .error = &sub_error,
    5786                 :            :                 .data = &cfg.attr.flow_attr,
    5787                 :            :         };
    5788                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    5789                 :            :         struct mlx5_flow_group *src_grp = NULL;
    5790                 :            :         struct mlx5_flow_group *dst_grp = NULL;
    5791                 :            :         struct mlx5_list_entry *ge;
    5792                 :          0 :         uint32_t dst_group_id = 0;
    5793                 :            :         int ret;
    5794                 :            : 
    5795         [ #  # ]:          0 :         if (flow_hw_translate_group(dev, &cfg, group_id, &group_id, error))
    5796                 :          0 :                 return -rte_errno;
    5797                 :            : 
    5798         [ #  # ]:          0 :         if (!group_id)
    5799                 :          0 :                 return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    5800                 :            :                                           NULL, "Failed to set group miss actions - invalid group id");
    5801                 :            : 
    5802                 :          0 :         ret = flow_hw_group_parse_miss_actions(dev, &cfg, actions, &dst_group_id, error);
    5803         [ #  # ]:          0 :         if (ret)
    5804                 :          0 :                 return -rte_errno;
    5805                 :            : 
    5806         [ #  # ]:          0 :         if (dst_group_id == group_id) {
    5807                 :          0 :                 return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    5808                 :            :                                           NULL, "Failed to set group miss actions - target group id must differ from group_id");
    5809                 :            :         }
    5810                 :            : 
    5811                 :          0 :         cfg.attr.flow_attr.group = group_id;
    5812                 :          0 :         ge = mlx5_hlist_lookup(priv->sh->groups, group_id, &ctx);
    5813         [ #  # ]:          0 :         if (ge)
    5814                 :            :                 src_grp = container_of(ge, struct mlx5_flow_group, entry);
    5815                 :            : 
    5816         [ #  # ]:          0 :         if (dst_group_id) {
    5817                 :            :                 /* Increase ref_cnt for new miss group. */
    5818                 :          0 :                 cfg.attr.flow_attr.group = dst_group_id;
    5819                 :          0 :                 ge = mlx5_hlist_register(priv->sh->groups, dst_group_id, &ctx);
    5820         [ #  # ]:          0 :                 if (!ge)
    5821                 :          0 :                         return -rte_errno;
    5822                 :            : 
    5823                 :            :                 dst_grp = container_of(ge, struct mlx5_flow_group, entry);
    5824                 :            : 
    5825                 :          0 :                 cfg.attr.flow_attr.group = group_id;
    5826                 :          0 :                 ret = flow_hw_group_set_miss_group(dev, &cfg, src_grp, dst_grp, error);
    5827         [ #  # ]:          0 :                 if (ret)
    5828                 :          0 :                         goto error;
    5829                 :            :         } else {
    5830                 :          0 :                 return flow_hw_group_unset_miss_group(dev, src_grp, error);
    5831                 :            :         }
    5832                 :            : 
    5833                 :            :         return 0;
    5834                 :            : 
    5835                 :            : error:
    5836                 :            :         if (dst_grp)
    5837                 :          0 :                 mlx5_hlist_unregister(priv->sh->groups, &dst_grp->entry);
    5838                 :          0 :         return -rte_errno;
    5839                 :            : }
    5840                 :            : 
    5841                 :            : static bool
    5842                 :            : flow_hw_modify_field_is_used(const struct rte_flow_action_modify_field *action,
    5843                 :            :                              enum rte_flow_field_id field)
    5844                 :            : {
    5845   [ #  #  #  #  :          0 :         return action->src.field == field || action->dst.field == field;
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
    5846                 :            : }
    5847                 :            : 
    5848                 :            : static bool
    5849                 :            : flow_hw_modify_field_is_geneve_opt(enum rte_flow_field_id field)
    5850                 :            : {
    5851                 :            :         return field == RTE_FLOW_FIELD_GENEVE_OPT_TYPE ||
    5852                 :          0 :                field == RTE_FLOW_FIELD_GENEVE_OPT_CLASS ||
    5853                 :            :                field == RTE_FLOW_FIELD_GENEVE_OPT_DATA;
    5854                 :            : }
    5855                 :            : 
    5856                 :            : static bool
    5857                 :          0 : flow_hw_modify_field_is_add_dst_valid(const struct rte_flow_action_modify_field *conf)
    5858                 :            : {
    5859         [ #  # ]:          0 :         if (conf->operation != RTE_FLOW_MODIFY_ADD)
    5860                 :            :                 return true;
    5861         [ #  # ]:          0 :         if (conf->src.field == RTE_FLOW_FIELD_POINTER ||
    5862                 :            :             conf->src.field == RTE_FLOW_FIELD_VALUE)
    5863                 :            :                 return true;
    5864         [ #  # ]:          0 :         switch (conf->dst.field) {
    5865                 :            :         case RTE_FLOW_FIELD_IPV4_TTL:
    5866                 :            :         case RTE_FLOW_FIELD_IPV6_HOPLIMIT:
    5867                 :            :         case RTE_FLOW_FIELD_TCP_SEQ_NUM:
    5868                 :            :         case RTE_FLOW_FIELD_TCP_ACK_NUM:
    5869                 :            :         case RTE_FLOW_FIELD_TAG:
    5870                 :            :         case RTE_FLOW_FIELD_META:
    5871                 :            :         case RTE_FLOW_FIELD_FLEX_ITEM:
    5872                 :            :         case RTE_FLOW_FIELD_TCP_DATA_OFFSET:
    5873                 :            :         case RTE_FLOW_FIELD_IPV4_IHL:
    5874                 :            :         case RTE_FLOW_FIELD_IPV4_TOTAL_LEN:
    5875                 :            :         case RTE_FLOW_FIELD_IPV6_PAYLOAD_LEN:
    5876                 :            :                 return true;
    5877                 :            :         default:
    5878                 :            :                 break;
    5879                 :            :         }
    5880                 :          0 :         return false;
    5881                 :            : }
    5882                 :            : 
    5883                 :            : /**
    5884                 :            :  * Validate the level value for modify field action.
    5885                 :            :  *
    5886                 :            :  * @param[in] data
    5887                 :            :  *   Pointer to the rte_flow_field_data structure either src or dst.
    5888                 :            :  * @param[in] inner_supported
    5889                 :            :  *   Indicator whether inner should be supported.
    5890                 :            :  * @param[out] error
    5891                 :            :  *   Pointer to error structure.
    5892                 :            :  *
    5893                 :            :  * @return
    5894                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5895                 :            :  */
    5896                 :            : static int
    5897                 :          0 : flow_hw_validate_modify_field_level(const struct rte_flow_field_data *data,
    5898                 :            :                                     bool inner_supported,
    5899                 :            :                                     struct rte_flow_error *error)
    5900                 :            : {
    5901   [ #  #  #  #  :          0 :         switch ((int)data->field) {
                      # ]
    5902                 :            :         case RTE_FLOW_FIELD_START:
    5903                 :            :         case RTE_FLOW_FIELD_VLAN_TYPE:
    5904                 :            :         case RTE_FLOW_FIELD_RANDOM:
    5905                 :            :         case RTE_FLOW_FIELD_FLEX_ITEM:
    5906                 :            :                 /*
    5907                 :            :                  * Level shouldn't be valid since field isn't supported or
    5908                 :            :                  * doesn't use 'level'.
    5909                 :            :                  */
    5910                 :            :                 break;
    5911                 :            :         case RTE_FLOW_FIELD_MARK:
    5912                 :            :         case RTE_FLOW_FIELD_META:
    5913                 :            :         case RTE_FLOW_FIELD_METER_COLOR:
    5914                 :            :         case RTE_FLOW_FIELD_HASH_RESULT:
    5915                 :            :                 /* For meta data fields encapsulation level is don't-care. */
    5916                 :            :                 break;
    5917                 :          0 :         case RTE_FLOW_FIELD_TAG:
    5918                 :            :         case MLX5_RTE_FLOW_FIELD_META_REG:
    5919                 :            :                 /*
    5920                 :            :                  * The tag array for RTE_FLOW_FIELD_TAG type is provided using
    5921                 :            :                  * 'tag_index' field. In old API, it was provided using 'level'
    5922                 :            :                  * field and it is still supported for backwards compatibility.
    5923                 :            :                  * Therefore, for meta tag field only, level is matter. It is
    5924                 :            :                  * taken as tag index when 'tag_index' field isn't set, and
    5925                 :            :                  * return error otherwise.
    5926                 :            :                  */
    5927         [ #  # ]:          0 :                 if (data->level > 0) {
    5928         [ #  # ]:          0 :                         if (data->tag_index > 0)
    5929                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    5930                 :            :                                                           RTE_FLOW_ERROR_TYPE_ACTION,
    5931                 :            :                                                           data,
    5932                 :            :                                                           "tag array can be provided using 'level' or 'tag_index' fields, not both");
    5933                 :          0 :                         DRV_LOG(WARNING,
    5934                 :            :                                 "tag array provided in 'level' field instead of 'tag_index' field.");
    5935                 :            :                 }
    5936                 :            :                 break;
    5937                 :          0 :         case RTE_FLOW_FIELD_MAC_DST:
    5938                 :            :         case RTE_FLOW_FIELD_MAC_SRC:
    5939                 :            :         case RTE_FLOW_FIELD_MAC_TYPE:
    5940                 :            :         case RTE_FLOW_FIELD_IPV4_IHL:
    5941                 :            :         case RTE_FLOW_FIELD_IPV4_TOTAL_LEN:
    5942                 :            :         case RTE_FLOW_FIELD_IPV4_DSCP:
    5943                 :            :         case RTE_FLOW_FIELD_IPV4_ECN:
    5944                 :            :         case RTE_FLOW_FIELD_IPV4_TTL:
    5945                 :            :         case RTE_FLOW_FIELD_IPV4_SRC:
    5946                 :            :         case RTE_FLOW_FIELD_IPV4_DST:
    5947                 :            :         case RTE_FLOW_FIELD_IPV6_TRAFFIC_CLASS:
    5948                 :            :         case RTE_FLOW_FIELD_IPV6_FLOW_LABEL:
    5949                 :            :         case RTE_FLOW_FIELD_IPV6_PAYLOAD_LEN:
    5950                 :            :         case RTE_FLOW_FIELD_IPV6_HOPLIMIT:
    5951                 :            :         case RTE_FLOW_FIELD_IPV6_SRC:
    5952                 :            :         case RTE_FLOW_FIELD_IPV6_DST:
    5953                 :            :         case RTE_FLOW_FIELD_TCP_PORT_SRC:
    5954                 :            :         case RTE_FLOW_FIELD_TCP_PORT_DST:
    5955                 :            :         case RTE_FLOW_FIELD_TCP_FLAGS:
    5956                 :            :         case RTE_FLOW_FIELD_TCP_DATA_OFFSET:
    5957                 :            :         case RTE_FLOW_FIELD_UDP_PORT_SRC:
    5958                 :            :         case RTE_FLOW_FIELD_UDP_PORT_DST:
    5959         [ #  # ]:          0 :                 if (data->level > 2)
    5960                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    5961                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    5962                 :            :                                                   data,
    5963                 :            :                                                   "second inner header fields modification is not supported");
    5964         [ #  # ]:          0 :                 if (inner_supported)
    5965                 :            :                         break;
    5966                 :            :                 /* Fallthrough */
    5967                 :            :         case RTE_FLOW_FIELD_VLAN_ID:
    5968                 :            :         case RTE_FLOW_FIELD_IPV4_PROTO:
    5969                 :            :         case RTE_FLOW_FIELD_IPV6_PROTO:
    5970                 :            :         case RTE_FLOW_FIELD_IPV6_DSCP:
    5971                 :            :         case RTE_FLOW_FIELD_IPV6_ECN:
    5972                 :            :         case RTE_FLOW_FIELD_TCP_SEQ_NUM:
    5973                 :            :         case RTE_FLOW_FIELD_TCP_ACK_NUM:
    5974                 :            :         case RTE_FLOW_FIELD_ESP_PROTO:
    5975                 :            :         case RTE_FLOW_FIELD_ESP_SPI:
    5976                 :            :         case RTE_FLOW_FIELD_ESP_SEQ_NUM:
    5977                 :            :         case RTE_FLOW_FIELD_VXLAN_VNI:
    5978                 :            :         case RTE_FLOW_FIELD_VXLAN_LAST_RSVD:
    5979                 :            :         case RTE_FLOW_FIELD_GENEVE_VNI:
    5980                 :            :         case RTE_FLOW_FIELD_GENEVE_OPT_TYPE:
    5981                 :            :         case RTE_FLOW_FIELD_GENEVE_OPT_CLASS:
    5982                 :            :         case RTE_FLOW_FIELD_GENEVE_OPT_DATA:
    5983                 :            :         case RTE_FLOW_FIELD_GTP_TEID:
    5984                 :            :         case RTE_FLOW_FIELD_GTP_PSC_QFI:
    5985         [ #  # ]:          0 :                 if (data->level > 1)
    5986                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    5987                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    5988                 :            :                                                   data,
    5989                 :            :                                                   "inner header fields modification is not supported");
    5990                 :            :                 break;
    5991                 :          0 :         case RTE_FLOW_FIELD_MPLS:
    5992         [ #  # ]:          0 :                 if (data->level == 1)
    5993                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    5994                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    5995                 :            :                                                   data,
    5996                 :            :                                                   "outer MPLS header modification is not supported");
    5997         [ #  # ]:          0 :                 if (data->level > 2)
    5998                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    5999                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    6000                 :            :                                                   data,
    6001                 :            :                                                   "inner MPLS header modification is not supported");
    6002                 :            :                 break;
    6003                 :          0 :         case RTE_FLOW_FIELD_POINTER:
    6004                 :            :         case RTE_FLOW_FIELD_VALUE:
    6005                 :            :         default:
    6006                 :            :                 MLX5_ASSERT(false);
    6007                 :            :         }
    6008                 :            :         return 0;
    6009                 :            : }
    6010                 :            : 
    6011                 :            : static int
    6012                 :          0 : flow_hw_validate_action_modify_field(struct rte_eth_dev *dev,
    6013                 :            :                                      const struct rte_flow_action *action,
    6014                 :            :                                      const struct rte_flow_action *mask,
    6015                 :            :                                      struct rte_flow_error *error)
    6016                 :            : {
    6017                 :          0 :         const struct rte_flow_action_modify_field *action_conf = action->conf;
    6018                 :          0 :         const struct rte_flow_action_modify_field *mask_conf = mask->conf;
    6019                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    6020                 :          0 :         struct mlx5_hca_attr *attr = &priv->sh->cdev->config.hca_attr;
    6021                 :            :         int ret;
    6022                 :            : 
    6023         [ #  # ]:          0 :         if (!mask_conf)
    6024                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6025                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    6026                 :            :                                           "modify_field mask conf is missing");
    6027         [ #  # ]:          0 :         if (action_conf->operation != mask_conf->operation)
    6028                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6029                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    6030                 :            :                                 "modify_field operation mask and template are not equal");
    6031         [ #  # ]:          0 :         if (action_conf->dst.field != mask_conf->dst.field)
    6032                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6033                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    6034                 :            :                                 "destination field mask and template are not equal");
    6035                 :          0 :         if (action_conf->dst.field == RTE_FLOW_FIELD_POINTER ||
    6036         [ #  # ]:          0 :             action_conf->dst.field == RTE_FLOW_FIELD_VALUE ||
    6037                 :            :             action_conf->dst.field == RTE_FLOW_FIELD_HASH_RESULT)
    6038                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6039                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    6040                 :            :                                 "immediate value, pointer and hash result cannot be used as destination");
    6041                 :          0 :         ret = flow_hw_validate_modify_field_level(&action_conf->dst, false, error);
    6042         [ #  # ]:          0 :         if (ret)
    6043                 :            :                 return ret;
    6044   [ #  #  #  # ]:          0 :         if (action_conf->dst.field != RTE_FLOW_FIELD_FLEX_ITEM &&
    6045                 :            :             !flow_hw_modify_field_is_geneve_opt(action_conf->dst.field)) {
    6046         [ #  # ]:          0 :                 if (action_conf->dst.tag_index &&
    6047                 :            :                     !flow_modify_field_support_tag_array(action_conf->dst.field))
    6048                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    6049                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, action,
    6050                 :            :                                         "destination tag index is not supported");
    6051         [ #  # ]:          0 :                 if (action_conf->dst.class_id)
    6052                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    6053                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, action,
    6054                 :            :                                         "destination class id is not supported");
    6055                 :            :         }
    6056         [ #  # ]:          0 :         if (mask_conf->dst.level != UINT8_MAX)
    6057                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6058                 :            :                         RTE_FLOW_ERROR_TYPE_ACTION, action,
    6059                 :            :                         "destination encapsulation level must be fully masked");
    6060         [ #  # ]:          0 :         if (mask_conf->dst.offset != UINT32_MAX)
    6061                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6062                 :            :                         RTE_FLOW_ERROR_TYPE_ACTION, action,
    6063                 :            :                         "destination offset level must be fully masked");
    6064         [ #  # ]:          0 :         if (action_conf->src.field != mask_conf->src.field)
    6065                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6066                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    6067                 :            :                                 "destination field mask and template are not equal");
    6068         [ #  # ]:          0 :         if (action_conf->src.field != RTE_FLOW_FIELD_POINTER &&
    6069                 :            :             action_conf->src.field != RTE_FLOW_FIELD_VALUE) {
    6070   [ #  #  #  # ]:          0 :                 if (action_conf->src.field != RTE_FLOW_FIELD_FLEX_ITEM &&
    6071                 :            :                     !flow_hw_modify_field_is_geneve_opt(action_conf->src.field)) {
    6072         [ #  # ]:          0 :                         if (action_conf->src.tag_index &&
    6073                 :            :                             !flow_modify_field_support_tag_array(action_conf->src.field))
    6074                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    6075                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, action,
    6076                 :            :                                         "source tag index is not supported");
    6077         [ #  # ]:          0 :                         if (action_conf->src.class_id)
    6078                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    6079                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, action,
    6080                 :            :                                         "source class id is not supported");
    6081                 :            :                 }
    6082         [ #  # ]:          0 :                 if (mask_conf->src.level != UINT8_MAX)
    6083                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    6084                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    6085                 :            :                                 "source encapsulation level must be fully masked");
    6086         [ #  # ]:          0 :                 if (mask_conf->src.offset != UINT32_MAX)
    6087                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    6088                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    6089                 :            :                                 "source offset level must be fully masked");
    6090                 :          0 :                 ret = flow_hw_validate_modify_field_level(&action_conf->src, true, error);
    6091         [ #  # ]:          0 :                 if (ret)
    6092                 :            :                         return ret;
    6093                 :            :         }
    6094         [ #  # ]:          0 :         if ((action_conf->dst.field == RTE_FLOW_FIELD_TAG &&
    6095   [ #  #  #  # ]:          0 :              action_conf->dst.tag_index >= MLX5_FLOW_HW_TAGS_MAX &&
    6096                 :          0 :              action_conf->dst.tag_index != RTE_PMD_MLX5_LINEAR_HASH_TAG_INDEX) ||
    6097         [ #  # ]:          0 :             (action_conf->src.field == RTE_FLOW_FIELD_TAG &&
    6098   [ #  #  #  # ]:          0 :              action_conf->src.tag_index >= MLX5_FLOW_HW_TAGS_MAX &&
    6099                 :            :              action_conf->src.tag_index != RTE_PMD_MLX5_LINEAR_HASH_TAG_INDEX))
    6100                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6101                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    6102                 :            :                                  "tag index is out of range");
    6103   [ #  #  #  # ]:          0 :         if ((action_conf->dst.field == RTE_FLOW_FIELD_TAG &&
    6104   [ #  #  #  # ]:          0 :              flow_hw_get_reg_id(dev, RTE_FLOW_ITEM_TYPE_TAG, action_conf->dst.tag_index) == REG_NON) ||
    6105         [ #  # ]:          0 :             (action_conf->src.field == RTE_FLOW_FIELD_TAG &&
    6106         [ #  # ]:          0 :              flow_hw_get_reg_id(dev, RTE_FLOW_ITEM_TYPE_TAG, action_conf->src.tag_index) == REG_NON))
    6107                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6108                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    6109                 :            :                                           "tag index is out of range");
    6110         [ #  # ]:          0 :         if (mask_conf->width != UINT32_MAX)
    6111                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6112                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    6113                 :            :                                 "modify_field width field must be fully masked");
    6114         [ #  # ]:          0 :         if (flow_hw_modify_field_is_used(action_conf, RTE_FLOW_FIELD_START))
    6115                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6116                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    6117                 :            :                                 "modifying arbitrary place in a packet is not supported");
    6118         [ #  # ]:          0 :         if (flow_hw_modify_field_is_used(action_conf, RTE_FLOW_FIELD_VLAN_TYPE))
    6119                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6120                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    6121                 :            :                                 "modifying vlan_type is not supported");
    6122         [ #  # ]:          0 :         if (flow_hw_modify_field_is_used(action_conf, RTE_FLOW_FIELD_RANDOM))
    6123                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6124                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    6125                 :            :                                 "modifying random value is not supported");
    6126                 :            :         /**
    6127                 :            :          * Geneve VNI modification is supported only when Geneve header is
    6128                 :            :          * parsed natively. When GENEVE options are supported, they both Geneve
    6129                 :            :          * and options headers are parsed as a flex parser.
    6130                 :            :          */
    6131         [ #  # ]:          0 :         if (flow_hw_modify_field_is_used(action_conf, RTE_FLOW_FIELD_GENEVE_VNI) &&
    6132         [ #  # ]:          0 :             attr->geneve_tlv_opt)
    6133                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6134                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    6135                 :            :                                 "modifying Geneve VNI is not supported when GENEVE opt is supported");
    6136   [ #  #  #  # ]:          0 :         if (priv->tlv_options == NULL &&
    6137         [ #  # ]:          0 :             (flow_hw_modify_field_is_used(action_conf, RTE_FLOW_FIELD_GENEVE_OPT_TYPE) ||
    6138         [ #  # ]:          0 :              flow_hw_modify_field_is_used(action_conf, RTE_FLOW_FIELD_GENEVE_OPT_CLASS) ||
    6139                 :            :              flow_hw_modify_field_is_used(action_conf, RTE_FLOW_FIELD_GENEVE_OPT_DATA)))
    6140                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6141                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    6142                 :            :                                 "modifying Geneve TLV option is supported only after parser configuration");
    6143                 :            :         /* Due to HW bug, tunnel MPLS header is read only. */
    6144         [ #  # ]:          0 :         if (action_conf->dst.field == RTE_FLOW_FIELD_MPLS)
    6145                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6146                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    6147                 :            :                                 "MPLS cannot be used as destination");
    6148                 :            :         /* ADD_FIELD is not supported for all the fields. */
    6149         [ #  # ]:          0 :         if (!flow_hw_modify_field_is_add_dst_valid(action_conf))
    6150                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6151                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    6152                 :            :                                 "invalid add_field destination");
    6153                 :            :         return 0;
    6154                 :            : }
    6155                 :            : 
    6156                 :            : static int
    6157                 :          0 : flow_hw_validate_action_port_representor(struct rte_eth_dev *dev __rte_unused,
    6158                 :            :                                          const struct rte_flow_actions_template_attr *attr,
    6159                 :            :                                          const struct rte_flow_action *action,
    6160                 :            :                                          const struct rte_flow_action *mask,
    6161                 :            :                                          struct rte_flow_error *error)
    6162                 :            : {
    6163                 :            :         const struct rte_flow_action_ethdev *action_conf = NULL;
    6164                 :            :         const struct rte_flow_action_ethdev *mask_conf = NULL;
    6165                 :            : 
    6166                 :            :         /* If transfer is set, port has been validated as proxy port. */
    6167         [ #  # ]:          0 :         if (!attr->transfer)
    6168                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6169                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    6170                 :            :                                           "cannot use port_representor actions"
    6171                 :            :                                           " without an E-Switch");
    6172         [ #  # ]:          0 :         if (!action || !mask)
    6173                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6174                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    6175                 :            :                                           "actiona and mask configuration must be set");
    6176                 :          0 :         action_conf = action->conf;
    6177                 :          0 :         mask_conf = mask->conf;
    6178   [ #  #  #  #  :          0 :         if (!mask_conf || mask_conf->port_id != MLX5_REPRESENTED_PORT_ESW_MGR ||
                   #  # ]
    6179         [ #  # ]:          0 :             !action_conf || action_conf->port_id != MLX5_REPRESENTED_PORT_ESW_MGR)
    6180                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6181                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    6182                 :            :                                           "only eswitch manager port 0xffff is"
    6183                 :            :                                           " supported");
    6184                 :            :         return 0;
    6185                 :            : }
    6186                 :            : 
    6187                 :            : static int
    6188                 :          0 : flow_hw_validate_target_port_id(struct rte_eth_dev *dev,
    6189                 :            :                                 uint16_t target_port_id)
    6190                 :            : {
    6191                 :            :         struct mlx5_priv *port_priv;
    6192                 :            :         struct mlx5_priv *dev_priv;
    6193                 :            : 
    6194         [ #  # ]:          0 :         if (target_port_id == MLX5_REPRESENTED_PORT_ESW_MGR)
    6195                 :            :                 return 0;
    6196                 :            : 
    6197                 :          0 :         port_priv = mlx5_port_to_eswitch_info(target_port_id, false);
    6198         [ #  # ]:          0 :         if (!port_priv) {
    6199                 :          0 :                 rte_errno = EINVAL;
    6200                 :          0 :                 DRV_LOG(ERR, "Port %u Failed to obtain E-Switch info for port %u",
    6201                 :            :                         dev->data->port_id, target_port_id);
    6202                 :          0 :                 return -rte_errno;
    6203                 :            :         }
    6204                 :            : 
    6205                 :          0 :         dev_priv = mlx5_dev_to_eswitch_info(dev);
    6206         [ #  # ]:          0 :         if (!dev_priv) {
    6207                 :          0 :                 rte_errno = EINVAL;
    6208                 :          0 :                 DRV_LOG(ERR, "Port %u Failed to obtain E-Switch info for transfer proxy",
    6209                 :            :                         dev->data->port_id);
    6210                 :          0 :                 return -rte_errno;
    6211                 :            :         }
    6212                 :            : 
    6213         [ #  # ]:          0 :         if (port_priv->domain_id != dev_priv->domain_id) {
    6214                 :          0 :                 rte_errno = EINVAL;
    6215                 :          0 :                 DRV_LOG(ERR, "Port %u Failed to obtain E-Switch info for transfer proxy",
    6216                 :            :                         dev->data->port_id);
    6217                 :          0 :                 return -rte_errno;
    6218                 :            :         }
    6219                 :            : 
    6220                 :            :         return 0;
    6221                 :            : }
    6222                 :            : 
    6223                 :            : static int
    6224                 :          0 : flow_hw_validate_action_represented_port(struct rte_eth_dev *dev,
    6225                 :            :                                          const struct rte_flow_action *action,
    6226                 :            :                                          const struct rte_flow_action *mask,
    6227                 :            :                                          struct rte_flow_error *error)
    6228                 :            : {
    6229                 :          0 :         const struct rte_flow_action_ethdev *action_conf = action->conf;
    6230                 :          0 :         const struct rte_flow_action_ethdev *mask_conf = mask->conf;
    6231                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    6232                 :            : 
    6233         [ #  # ]:          0 :         if (!priv->sh->config.dv_esw_en)
    6234                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6235                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    6236                 :            :                                           "cannot use represented_port actions"
    6237                 :            :                                           " without an E-Switch");
    6238   [ #  #  #  # ]:          0 :         if (mask_conf && mask_conf->port_id) {
    6239         [ #  # ]:          0 :                 if (!action_conf)
    6240                 :          0 :                         return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
    6241                 :            :                                                   action, "port index was not provided");
    6242                 :            : 
    6243         [ #  # ]:          0 :                 if (flow_hw_validate_target_port_id(dev, action_conf->port_id))
    6244                 :          0 :                         return rte_flow_error_set(error, rte_errno, RTE_FLOW_ERROR_TYPE_ACTION,
    6245                 :            :                                                   action, "port index is invalid");
    6246                 :            :         }
    6247                 :            :         return 0;
    6248                 :            : }
    6249                 :            : 
    6250                 :            : /**
    6251                 :            :  * Validate AGE action.
    6252                 :            :  *
    6253                 :            :  * @param[in] dev
    6254                 :            :  *   Pointer to rte_eth_dev structure.
    6255                 :            :  * @param[in] action
    6256                 :            :  *   Pointer to the indirect action.
    6257                 :            :  * @param[in] action_flags
    6258                 :            :  *   Holds the actions detected until now.
    6259                 :            :  * @param[in] fixed_cnt
    6260                 :            :  *   Indicator if this list has a fixed COUNT action.
    6261                 :            :  * @param[out] error
    6262                 :            :  *   Pointer to error structure.
    6263                 :            :  *
    6264                 :            :  * @return
    6265                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    6266                 :            :  */
    6267                 :            : static int
    6268                 :          0 : flow_hw_validate_action_age(struct rte_eth_dev *dev,
    6269                 :            :                             const struct rte_flow_action *action,
    6270                 :            :                             uint64_t action_flags, bool fixed_cnt,
    6271                 :            :                             struct rte_flow_error *error)
    6272                 :            : {
    6273                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    6274                 :          0 :         struct mlx5_age_info *age_info = GET_PORT_AGE_INFO(priv);
    6275                 :            : 
    6276         [ #  # ]:          0 :         if (!priv->sh->cdev->config.devx)
    6277                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    6278                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    6279                 :            :                                           NULL, "AGE action not supported");
    6280         [ #  # ]:          0 :         if (age_info->ages_ipool == NULL)
    6281                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6282                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    6283                 :            :                                           "aging pool not initialized");
    6284         [ #  # ]:          0 :         if ((action_flags & MLX5_FLOW_ACTION_AGE) ||
    6285                 :            :             (action_flags & MLX5_FLOW_ACTION_INDIRECT_AGE))
    6286                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6287                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    6288                 :            :                                           "duplicate AGE actions set");
    6289         [ #  # ]:          0 :         if (fixed_cnt)
    6290                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6291                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    6292                 :            :                                           "AGE and fixed COUNT combination is not supported");
    6293                 :            :         return 0;
    6294                 :            : }
    6295                 :            : 
    6296                 :            : /**
    6297                 :            :  * Validate count action.
    6298                 :            :  *
    6299                 :            :  * @param[in] dev
    6300                 :            :  *   Pointer to rte_eth_dev structure.
    6301                 :            :  * @param[in] action
    6302                 :            :  *   Pointer to the indirect action.
    6303                 :            :  * @param[in] mask
    6304                 :            :  *   Pointer to the indirect action mask.
    6305                 :            :  * @param[in] action_flags
    6306                 :            :  *   Holds the actions detected until now.
    6307                 :            :  * @param[out] error
    6308                 :            :  *   Pointer to error structure.
    6309                 :            :  *
    6310                 :            :  * @return
    6311                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    6312                 :            :  */
    6313                 :            : static int
    6314                 :          0 : flow_hw_validate_action_count(struct rte_eth_dev *dev,
    6315                 :            :                               const struct rte_flow_action *action,
    6316                 :            :                               const struct rte_flow_action *mask,
    6317                 :            :                               uint64_t action_flags,
    6318                 :            :                               struct rte_flow_error *error)
    6319                 :            : {
    6320                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    6321                 :          0 :         const struct rte_flow_action_count *count = mask->conf;
    6322                 :            : 
    6323         [ #  # ]:          0 :         if (!priv->sh->cdev->config.devx)
    6324                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    6325                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    6326                 :            :                                           "count action not supported");
    6327         [ #  # ]:          0 :         if (!priv->hws_cpool)
    6328                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6329                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    6330                 :            :                                           "counters pool not initialized");
    6331         [ #  # ]:          0 :         if ((action_flags & MLX5_FLOW_ACTION_COUNT) ||
    6332                 :            :             (action_flags & MLX5_FLOW_ACTION_INDIRECT_COUNT))
    6333                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6334                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    6335                 :            :                                           "duplicate count actions set");
    6336   [ #  #  #  #  :          0 :         if (count && count->id && (action_flags & MLX5_FLOW_ACTION_AGE))
                   #  # ]
    6337                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6338                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, mask,
    6339                 :            :                                           "AGE and COUNT action shared by mask combination is not supported");
    6340                 :            :         return 0;
    6341                 :            : }
    6342                 :            : 
    6343                 :            : /**
    6344                 :            :  * Validate meter_mark action.
    6345                 :            :  *
    6346                 :            :  * @param[in] dev
    6347                 :            :  *   Pointer to rte_eth_dev structure.
    6348                 :            :  * @param[in] action
    6349                 :            :  *   Pointer to the indirect action.
    6350                 :            :  * @param[in] indirect
    6351                 :            :  *   If true, then provided action was passed using an indirect action.
    6352                 :            :  * @param[out] error
    6353                 :            :  *   Pointer to error structure.
    6354                 :            :  *
    6355                 :            :  * @return
    6356                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    6357                 :            :  */
    6358                 :            : static int
    6359                 :          0 : flow_hw_validate_action_meter_mark(struct rte_eth_dev *dev,
    6360                 :            :                               const struct rte_flow_action *action,
    6361                 :            :                               bool indirect,
    6362                 :            :                               struct rte_flow_error *error)
    6363                 :            : {
    6364                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    6365                 :            : 
    6366                 :            :         RTE_SET_USED(action);
    6367                 :            : 
    6368         [ #  # ]:          0 :         if (!priv->sh->cdev->config.devx)
    6369                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    6370                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    6371                 :            :                                           "meter_mark action not supported");
    6372   [ #  #  #  # ]:          0 :         if (!indirect && priv->shared_host)
    6373                 :          0 :                 return rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, action,
    6374                 :            :                                           "meter_mark action can only be used on host port");
    6375         [ #  # ]:          0 :         if (!priv->hws_mpool)
    6376                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6377                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    6378                 :            :                                           "meter_mark pool not initialized");
    6379                 :            :         return 0;
    6380                 :            : }
    6381                 :            : 
    6382                 :            : /**
    6383                 :            :  * Validate indirect action.
    6384                 :            :  *
    6385                 :            :  * @param[in] dev
    6386                 :            :  *   Pointer to rte_eth_dev structure.
    6387                 :            :  * @param[in] action
    6388                 :            :  *   Pointer to the indirect action.
    6389                 :            :  * @param[in] mask
    6390                 :            :  *   Pointer to the indirect action mask.
    6391                 :            :  * @param[in, out] action_flags
    6392                 :            :  *   Holds the actions detected until now.
    6393                 :            :  * @param[in, out] fixed_cnt
    6394                 :            :  *   Pointer to indicator if this list has a fixed COUNT action.
    6395                 :            :  * @param[out] error
    6396                 :            :  *   Pointer to error structure.
    6397                 :            :  *
    6398                 :            :  * @return
    6399                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    6400                 :            :  */
    6401                 :            : static int
    6402                 :          0 : flow_hw_validate_action_indirect(struct rte_eth_dev *dev,
    6403                 :            :                                  const struct rte_flow_action *action,
    6404                 :            :                                  const struct rte_flow_action *mask,
    6405                 :            :                                  uint64_t *action_flags, bool *fixed_cnt,
    6406                 :            :                                  struct rte_flow_error *error)
    6407                 :            : {
    6408                 :            :         uint32_t type;
    6409                 :            :         int ret;
    6410                 :            : 
    6411         [ #  # ]:          0 :         if (!mask)
    6412                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6413                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    6414                 :            :                                           "Unable to determine indirect action type without a mask specified");
    6415                 :          0 :         type = mask->type;
    6416   [ #  #  #  #  :          0 :         switch (type) {
                #  #  # ]
    6417                 :          0 :         case RTE_FLOW_ACTION_TYPE_METER_MARK:
    6418                 :          0 :                 ret = flow_hw_validate_action_meter_mark(dev, mask, true, error);
    6419         [ #  # ]:          0 :                 if (ret < 0)
    6420                 :            :                         return ret;
    6421                 :          0 :                 *action_flags |= MLX5_FLOW_ACTION_METER;
    6422                 :          0 :                 break;
    6423                 :          0 :         case RTE_FLOW_ACTION_TYPE_RSS:
    6424                 :            :                 /* TODO: Validation logic (same as flow_hw_actions_validate) */
    6425                 :          0 :                 *action_flags |= MLX5_FLOW_ACTION_RSS;
    6426                 :          0 :                 break;
    6427                 :          0 :         case RTE_FLOW_ACTION_TYPE_CONNTRACK:
    6428                 :            :                 /* TODO: Validation logic (same as flow_hw_actions_validate) */
    6429                 :          0 :                 *action_flags |= MLX5_FLOW_ACTION_CT;
    6430                 :          0 :                 break;
    6431                 :          0 :         case RTE_FLOW_ACTION_TYPE_COUNT:
    6432   [ #  #  #  # ]:          0 :                 if (action->conf && mask->conf) {
    6433         [ #  # ]:          0 :                         if ((*action_flags & MLX5_FLOW_ACTION_AGE) ||
    6434                 :            :                             (*action_flags & MLX5_FLOW_ACTION_INDIRECT_AGE))
    6435                 :            :                                 /*
    6436                 :            :                                  * AGE cannot use indirect counter which is
    6437                 :            :                                  * shared with enother flow rules.
    6438                 :            :                                  */
    6439                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    6440                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    6441                 :            :                                                   NULL,
    6442                 :            :                                                   "AGE and fixed COUNT combination is not supported");
    6443                 :          0 :                         *fixed_cnt = true;
    6444                 :            :                 }
    6445                 :          0 :                 ret = flow_hw_validate_action_count(dev, action, mask,
    6446                 :            :                                                     *action_flags, error);
    6447         [ #  # ]:          0 :                 if (ret < 0)
    6448                 :            :                         return ret;
    6449                 :          0 :                 *action_flags |= MLX5_FLOW_ACTION_INDIRECT_COUNT;
    6450                 :          0 :                 break;
    6451                 :          0 :         case RTE_FLOW_ACTION_TYPE_AGE:
    6452                 :          0 :                 ret = flow_hw_validate_action_age(dev, action, *action_flags,
    6453                 :          0 :                                                   *fixed_cnt, error);
    6454         [ #  # ]:          0 :                 if (ret < 0)
    6455                 :            :                         return ret;
    6456                 :          0 :                 *action_flags |= MLX5_FLOW_ACTION_INDIRECT_AGE;
    6457                 :          0 :                 break;
    6458                 :          0 :         case RTE_FLOW_ACTION_TYPE_QUOTA:
    6459                 :            :                 /* TODO: add proper quota verification */
    6460                 :          0 :                 *action_flags |= MLX5_FLOW_ACTION_QUOTA;
    6461                 :          0 :                 break;
    6462                 :          0 :         default:
    6463                 :          0 :                 DRV_LOG(WARNING, "Unsupported shared action type: %d", type);
    6464                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    6465                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED, mask,
    6466                 :            :                                           "Unsupported indirect action type");
    6467                 :            :         }
    6468                 :            :         return 0;
    6469                 :            : }
    6470                 :            : 
    6471                 :            : /**
    6472                 :            :  * Validate ipv6_ext_push action.
    6473                 :            :  *
    6474                 :            :  * @param[in] dev
    6475                 :            :  *   Pointer to rte_eth_dev structure.
    6476                 :            :  * @param[in] action
    6477                 :            :  *   Pointer to the indirect action.
    6478                 :            :  * @param[out] error
    6479                 :            :  *   Pointer to error structure.
    6480                 :            :  *
    6481                 :            :  * @return
    6482                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    6483                 :            :  */
    6484                 :            : static int
    6485                 :          0 : flow_hw_validate_action_ipv6_ext_push(struct rte_eth_dev *dev __rte_unused,
    6486                 :            :                                       const struct rte_flow_action *action,
    6487                 :            :                                       struct rte_flow_error *error)
    6488                 :            : {
    6489                 :          0 :         const struct rte_flow_action_ipv6_ext_push *raw_push_data = action->conf;
    6490                 :            : 
    6491   [ #  #  #  #  :          0 :         if (!raw_push_data || !raw_push_data->size || !raw_push_data->data)
                   #  # ]
    6492                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6493                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    6494                 :            :                                           "invalid ipv6_ext_push data");
    6495   [ #  #  #  # ]:          0 :         if (raw_push_data->type != IPPROTO_ROUTING ||
    6496                 :            :             raw_push_data->size > MLX5_PUSH_MAX_LEN)
    6497                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6498                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    6499                 :            :                                           "Unsupported ipv6_ext_push type or length");
    6500                 :            :         return 0;
    6501                 :            : }
    6502                 :            : 
    6503                 :            : /**
    6504                 :            :  * Process `... / raw_decap / raw_encap / ...` actions sequence.
    6505                 :            :  * The PMD handles the sequence as a single encap or decap reformat action,
    6506                 :            :  * depending on the raw_encap configuration.
    6507                 :            :  *
    6508                 :            :  * The function assumes that the raw_decap / raw_encap location
    6509                 :            :  * in actions template list complies with relative HWS actions order:
    6510                 :            :  * for the required reformat configuration:
    6511                 :            :  * ENCAP configuration must appear before [JUMP|DROP|PORT]
    6512                 :            :  * DECAP configuration must appear at the template head.
    6513                 :            :  */
    6514                 :            : static uint64_t
    6515                 :            : mlx5_decap_encap_reformat_type(const struct rte_flow_action *actions,
    6516                 :            :                                uint32_t encap_ind, uint64_t flags)
    6517                 :            : {
    6518                 :          0 :         const struct rte_flow_action_raw_encap *encap = actions[encap_ind].conf;
    6519                 :            : 
    6520         [ #  # ]:          0 :         if ((flags & MLX5_FLOW_ACTION_DECAP) == 0)
    6521                 :            :                 return MLX5_FLOW_ACTION_ENCAP;
    6522         [ #  # ]:          0 :         if (actions[encap_ind - 1].type != RTE_FLOW_ACTION_TYPE_RAW_DECAP)
    6523                 :            :                 return MLX5_FLOW_ACTION_ENCAP;
    6524                 :          0 :         return encap->size >= MLX5_ENCAPSULATION_DECISION_SIZE ?
    6525         [ #  # ]:          0 :                MLX5_FLOW_ACTION_ENCAP : MLX5_FLOW_ACTION_DECAP;
    6526                 :            : }
    6527                 :            : 
    6528                 :            : enum mlx5_hw_indirect_list_relative_position {
    6529                 :            :         MLX5_INDIRECT_LIST_POSITION_UNKNOWN = -1,
    6530                 :            :         MLX5_INDIRECT_LIST_POSITION_BEFORE_MH = 0,
    6531                 :            :         MLX5_INDIRECT_LIST_POSITION_AFTER_MH,
    6532                 :            : };
    6533                 :            : 
    6534                 :            : static enum mlx5_hw_indirect_list_relative_position
    6535                 :          0 : mlx5_hw_indirect_list_mh_position(const struct rte_flow_action *action)
    6536                 :            : {
    6537                 :          0 :         const struct rte_flow_action_indirect_list *conf = action->conf;
    6538   [ #  #  #  # ]:          0 :         enum mlx5_indirect_list_type list_type = mlx5_get_indirect_list_type(conf->handle);
    6539                 :            :         enum mlx5_hw_indirect_list_relative_position pos = MLX5_INDIRECT_LIST_POSITION_UNKNOWN;
    6540                 :            :         const union {
    6541                 :            :                 struct mlx5_indlst_legacy *legacy;
    6542                 :            :                 struct mlx5_hw_encap_decap_action *reformat;
    6543                 :            :                 struct rte_flow_action_list_handle *handle;
    6544                 :            :         } h = { .handle = conf->handle};
    6545                 :            : 
    6546   [ #  #  #  # ]:          0 :         switch (list_type) {
    6547                 :          0 :         case  MLX5_INDIRECT_ACTION_LIST_TYPE_LEGACY:
    6548      [ #  #  # ]:          0 :                 switch (h.legacy->legacy_type) {
    6549                 :            :                 case RTE_FLOW_ACTION_TYPE_AGE:
    6550                 :            :                 case RTE_FLOW_ACTION_TYPE_COUNT:
    6551                 :            :                 case RTE_FLOW_ACTION_TYPE_CONNTRACK:
    6552                 :            :                 case RTE_FLOW_ACTION_TYPE_METER_MARK:
    6553                 :            :                 case RTE_FLOW_ACTION_TYPE_QUOTA:
    6554                 :            :                         pos = MLX5_INDIRECT_LIST_POSITION_BEFORE_MH;
    6555                 :            :                         break;
    6556                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RSS:
    6557                 :            :                         pos = MLX5_INDIRECT_LIST_POSITION_AFTER_MH;
    6558                 :          0 :                         break;
    6559                 :          0 :                 default:
    6560                 :            :                         pos = MLX5_INDIRECT_LIST_POSITION_UNKNOWN;
    6561                 :          0 :                         break;
    6562                 :            :                 }
    6563                 :            :                 break;
    6564                 :            :         case MLX5_INDIRECT_ACTION_LIST_TYPE_MIRROR:
    6565                 :            :                 pos = MLX5_INDIRECT_LIST_POSITION_AFTER_MH;
    6566                 :            :                 break;
    6567                 :          0 :         case MLX5_INDIRECT_ACTION_LIST_TYPE_REFORMAT:
    6568      [ #  #  # ]:          0 :                 switch (h.reformat->action_type) {
    6569                 :            :                 case MLX5DR_ACTION_TYP_REFORMAT_TNL_L2_TO_L2:
    6570                 :            :                 case MLX5DR_ACTION_TYP_REFORMAT_TNL_L3_TO_L2:
    6571                 :            :                         pos = MLX5_INDIRECT_LIST_POSITION_BEFORE_MH;
    6572                 :            :                         break;
    6573                 :          0 :                 case MLX5DR_ACTION_TYP_REFORMAT_L2_TO_TNL_L2:
    6574                 :            :                 case MLX5DR_ACTION_TYP_REFORMAT_L2_TO_TNL_L3:
    6575                 :            :                         pos = MLX5_INDIRECT_LIST_POSITION_AFTER_MH;
    6576                 :          0 :                         break;
    6577                 :          0 :                 default:
    6578                 :            :                         pos = MLX5_INDIRECT_LIST_POSITION_UNKNOWN;
    6579                 :          0 :                         break;
    6580                 :            :                 }
    6581                 :            :                 break;
    6582                 :          0 :         default:
    6583                 :            :                 pos = MLX5_INDIRECT_LIST_POSITION_UNKNOWN;
    6584                 :          0 :                 break;
    6585                 :            :         }
    6586                 :          0 :         return pos;
    6587                 :            : }
    6588                 :            : 
    6589                 :            : #define MLX5_HW_EXPAND_MH_FAILED 0xffff
    6590                 :            : 
    6591                 :            : static inline uint16_t
    6592                 :          0 : flow_hw_template_expand_modify_field(struct rte_flow_action actions[],
    6593                 :            :                                      struct rte_flow_action masks[],
    6594                 :            :                                      const struct rte_flow_action *mf_actions,
    6595                 :            :                                      const struct rte_flow_action *mf_masks,
    6596                 :            :                                      uint64_t flags, uint32_t act_num,
    6597                 :            :                                      uint32_t mf_num)
    6598                 :            : {
    6599                 :            :         uint32_t i, tail;
    6600                 :            : 
    6601                 :            :         MLX5_ASSERT(actions && masks);
    6602                 :            :         MLX5_ASSERT(mf_num > 0);
    6603         [ #  # ]:          0 :         if (flags & MLX5_FLOW_ACTION_MODIFY_FIELD) {
    6604                 :            :                 /*
    6605                 :            :                  * Application action template already has Modify Field.
    6606                 :            :                  * It's location will be used in DR.
    6607                 :            :                  * Expanded MF action can be added before the END.
    6608                 :            :                  */
    6609                 :          0 :                 i = act_num - 1;
    6610                 :          0 :                 goto insert;
    6611                 :            :         }
    6612                 :            :         /**
    6613                 :            :          * Locate the first action positioned BEFORE the new MF.
    6614                 :            :          *
    6615                 :            :          * Search for a place to insert modify header
    6616                 :            :          * from the END action backwards:
    6617                 :            :          * 1. END is always present in actions array
    6618                 :            :          * 2. END location is always at action[act_num - 1]
    6619                 :            :          * 3. END always positioned AFTER modify field location
    6620                 :            :          *
    6621                 :            :          * Relative actions order is the same for RX, TX and FDB.
    6622                 :            :          *
    6623                 :            :          * Current actions order (draft-3)
    6624                 :            :          * @see action_order_arr[]
    6625                 :            :          */
    6626         [ #  # ]:          0 :         for (i = act_num - 2; (int)i >= 0; i--) {
    6627                 :            :                 enum mlx5_hw_indirect_list_relative_position pos;
    6628                 :          0 :                 enum rte_flow_action_type type = actions[i].type;
    6629                 :            :                 uint64_t reformat_type;
    6630                 :            : 
    6631         [ #  # ]:          0 :                 if (type == RTE_FLOW_ACTION_TYPE_INDIRECT)
    6632                 :          0 :                         type = masks[i].type;
    6633   [ #  #  #  # ]:          0 :                 switch (type) {
    6634                 :            :                 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
    6635                 :            :                 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
    6636                 :            :                 case RTE_FLOW_ACTION_TYPE_DROP:
    6637                 :            :                 case RTE_FLOW_ACTION_TYPE_SEND_TO_KERNEL:
    6638                 :            :                 case RTE_FLOW_ACTION_TYPE_JUMP:
    6639                 :            :                 case RTE_FLOW_ACTION_TYPE_JUMP_TO_TABLE_INDEX:
    6640                 :            :                 case RTE_FLOW_ACTION_TYPE_QUEUE:
    6641                 :            :                 case RTE_FLOW_ACTION_TYPE_RSS:
    6642                 :            :                 case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
    6643                 :            :                 case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR:
    6644                 :            :                 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
    6645                 :            :                 case RTE_FLOW_ACTION_TYPE_VOID:
    6646                 :            :                 case RTE_FLOW_ACTION_TYPE_END:
    6647                 :            :                         break;
    6648                 :            :                 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
    6649                 :            :                         reformat_type =
    6650                 :            :                                 mlx5_decap_encap_reformat_type(actions, i,
    6651                 :            :                                                                flags);
    6652                 :            :                         if (reformat_type == MLX5_FLOW_ACTION_DECAP) {
    6653                 :          0 :                                 i++;
    6654                 :          0 :                                 goto insert;
    6655                 :            :                         }
    6656         [ #  # ]:          0 :                         if (actions[i - 1].type == RTE_FLOW_ACTION_TYPE_RAW_DECAP)
    6657                 :            :                                 i--;
    6658                 :            :                         break;
    6659                 :          0 :                 case RTE_FLOW_ACTION_TYPE_INDIRECT_LIST:
    6660                 :          0 :                         pos = mlx5_hw_indirect_list_mh_position(&actions[i]);
    6661         [ #  # ]:          0 :                         if (pos == MLX5_INDIRECT_LIST_POSITION_UNKNOWN)
    6662                 :            :                                 return MLX5_HW_EXPAND_MH_FAILED;
    6663         [ #  # ]:          0 :                         if (pos == MLX5_INDIRECT_LIST_POSITION_BEFORE_MH)
    6664                 :          0 :                                 goto insert;
    6665                 :            :                         break;
    6666                 :          0 :                 default:
    6667                 :          0 :                         i++; /* new MF inserted AFTER actions[i] */
    6668                 :          0 :                         goto insert;
    6669                 :            :                 }
    6670                 :            :         }
    6671                 :            :         i = 0;
    6672                 :          0 : insert:
    6673                 :          0 :         tail = act_num - i; /* num action to move */
    6674                 :          0 :         memmove(actions + i + mf_num, actions + i, sizeof(actions[0]) * tail);
    6675                 :          0 :         memcpy(actions + i, mf_actions, sizeof(actions[0]) * mf_num);
    6676                 :          0 :         memmove(masks + i + mf_num, masks + i, sizeof(masks[0]) * tail);
    6677                 :            :         memcpy(masks + i, mf_masks, sizeof(masks[0]) * mf_num);
    6678                 :          0 :         return i;
    6679                 :            : }
    6680                 :            : 
    6681                 :            : static int
    6682                 :          0 : flow_hw_validate_action_push_vlan(struct rte_eth_dev *dev,
    6683                 :            :                                   const
    6684                 :            :                                   struct rte_flow_actions_template_attr *attr,
    6685                 :            :                                   const struct rte_flow_action *action,
    6686                 :            :                                   const struct rte_flow_action *mask,
    6687                 :            :                                   struct rte_flow_error *error)
    6688                 :            : {
    6689                 :            : #define X_FIELD(ptr, t, f) (((ptr)->conf) && ((t *)((ptr)->conf))->f)
    6690                 :            : 
    6691                 :          0 :         const bool masked_push =
    6692   [ #  #  #  # ]:          0 :                 X_FIELD(mask + MLX5_HW_VLAN_PUSH_TYPE_IDX,
    6693                 :            :                         const struct rte_flow_action_of_push_vlan, ethertype);
    6694                 :            :         bool masked_param;
    6695                 :            : 
    6696                 :            :         /*
    6697                 :            :          * Mandatory actions order:
    6698                 :            :          * OF_PUSH_VLAN / OF_SET_VLAN_VID [ / OF_SET_VLAN_PCP ]
    6699                 :            :          */
    6700                 :            :         RTE_SET_USED(dev);
    6701                 :            :         RTE_SET_USED(attr);
    6702                 :            :         /* Check that mark matches OF_PUSH_VLAN */
    6703         [ #  # ]:          0 :         if (mask[MLX5_HW_VLAN_PUSH_TYPE_IDX].type !=
    6704                 :            :             RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN)
    6705                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6706                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
    6707                 :            :                                           action, "OF_PUSH_VLAN: mask does not match");
    6708                 :            :         /* Check that the second template and mask items are SET_VLAN_VID */
    6709         [ #  # ]:          0 :         if (action[MLX5_HW_VLAN_PUSH_VID_IDX].type !=
    6710                 :          0 :             RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID ||
    6711         [ #  # ]:          0 :             mask[MLX5_HW_VLAN_PUSH_VID_IDX].type !=
    6712                 :            :             RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID)
    6713                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6714                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
    6715                 :            :                                           action, "OF_PUSH_VLAN: invalid actions order");
    6716   [ #  #  #  # ]:          0 :         masked_param = X_FIELD(mask + MLX5_HW_VLAN_PUSH_VID_IDX,
    6717                 :            :                                const struct rte_flow_action_of_set_vlan_vid,
    6718                 :            :                                vlan_vid);
    6719                 :            :         /*
    6720                 :            :          * PMD requires OF_SET_VLAN_VID mask to must match OF_PUSH_VLAN
    6721                 :            :          */
    6722         [ #  # ]:          0 :         if (masked_push ^ masked_param)
    6723                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6724                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    6725                 :            :                                           "OF_SET_VLAN_VID: mask does not match OF_PUSH_VLAN");
    6726         [ #  # ]:          0 :         if (is_of_vlan_pcp_present(action)) {
    6727         [ #  # ]:          0 :                 if (mask[MLX5_HW_VLAN_PUSH_PCP_IDX].type !=
    6728                 :            :                      RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP)
    6729                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    6730                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    6731                 :            :                                                   action, "OF_SET_VLAN_PCP: missing mask configuration");
    6732   [ #  #  #  # ]:          0 :                 masked_param = X_FIELD(mask + MLX5_HW_VLAN_PUSH_PCP_IDX,
    6733                 :            :                                        const struct
    6734                 :            :                                        rte_flow_action_of_set_vlan_pcp,
    6735                 :            :                                        vlan_pcp);
    6736                 :            :                 /*
    6737                 :            :                  * PMD requires OF_SET_VLAN_PCP mask to must match OF_PUSH_VLAN
    6738                 :            :                  */
    6739         [ #  # ]:          0 :                 if (masked_push ^ masked_param)
    6740                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    6741                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION, action,
    6742                 :            :                                                   "OF_SET_VLAN_PCP: mask does not match OF_PUSH_VLAN");
    6743                 :            :         }
    6744                 :            :         return 0;
    6745                 :            : #undef X_FIELD
    6746                 :            : }
    6747                 :            : 
    6748                 :            : static int
    6749                 :          0 : flow_hw_validate_action_default_miss(struct rte_eth_dev *dev,
    6750                 :            :                                      const struct rte_flow_actions_template_attr *attr,
    6751                 :            :                                      uint64_t action_flags,
    6752                 :            :                                      struct rte_flow_error *error)
    6753                 :            : {
    6754                 :            :         /*
    6755                 :            :          * The private DEFAULT_MISS action is used internally for LACP in control
    6756                 :            :          * flows. So this validation can be ignored. It can be kept right now since
    6757                 :            :          * the validation will be done only once.
    6758                 :            :          */
    6759                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    6760                 :            : 
    6761         [ #  # ]:          0 :         if (!attr->ingress || attr->egress || attr->transfer)
    6762                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6763                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    6764                 :            :                                           "DEFAULT MISS is only supported in ingress.");
    6765         [ #  # ]:          0 :         if (!priv->hw_def_miss)
    6766                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6767                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    6768                 :            :                                           "DEFAULT MISS action does not exist.");
    6769         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_FATE_ACTIONS)
    6770                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6771                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    6772                 :            :                                           "DEFAULT MISS should be the only termination.");
    6773                 :            :         return 0;
    6774                 :            : }
    6775                 :            : 
    6776                 :            : static int
    6777                 :          0 : flow_hw_validate_action_nat64(struct rte_eth_dev *dev,
    6778                 :            :                               const struct rte_flow_actions_template_attr *attr,
    6779                 :            :                               const struct rte_flow_action *action,
    6780                 :            :                               const struct rte_flow_action *mask,
    6781                 :            :                               uint64_t action_flags,
    6782                 :            :                               struct rte_flow_error *error)
    6783                 :            : {
    6784                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    6785                 :            :         const struct rte_flow_action_nat64 *nat64_c;
    6786                 :            :         enum rte_flow_nat64_type cov_type;
    6787                 :            : 
    6788                 :            :         RTE_SET_USED(action_flags);
    6789   [ #  #  #  # ]:          0 :         if (mask->conf && ((const struct rte_flow_action_nat64 *)mask->conf)->type) {
    6790                 :          0 :                 nat64_c = (const struct rte_flow_action_nat64 *)action->conf;
    6791                 :          0 :                 cov_type = nat64_c->type;
    6792   [ #  #  #  # ]:          0 :                 if ((attr->ingress && !priv->action_nat64[MLX5DR_TABLE_TYPE_NIC_RX][cov_type]) ||
    6793   [ #  #  #  # ]:          0 :                     (attr->egress && !priv->action_nat64[MLX5DR_TABLE_TYPE_NIC_TX][cov_type]) ||
    6794   [ #  #  #  # ]:          0 :                     (attr->transfer && !priv->action_nat64[MLX5DR_TABLE_TYPE_FDB][cov_type]))
    6795                 :          0 :                         goto err_out;
    6796                 :            :         } else {
    6797                 :            :                 /*
    6798                 :            :                  * Usually, the actions will be used on both directions. For non-masked actions,
    6799                 :            :                  * both directions' actions will be checked.
    6800                 :            :                  */
    6801         [ #  # ]:          0 :                 if (attr->ingress)
    6802         [ #  # ]:          0 :                         if (!priv->action_nat64[MLX5DR_TABLE_TYPE_NIC_RX][RTE_FLOW_NAT64_6TO4] ||
    6803         [ #  # ]:          0 :                             !priv->action_nat64[MLX5DR_TABLE_TYPE_NIC_RX][RTE_FLOW_NAT64_4TO6])
    6804                 :          0 :                                 goto err_out;
    6805         [ #  # ]:          0 :                 if (attr->egress)
    6806         [ #  # ]:          0 :                         if (!priv->action_nat64[MLX5DR_TABLE_TYPE_NIC_TX][RTE_FLOW_NAT64_6TO4] ||
    6807         [ #  # ]:          0 :                             !priv->action_nat64[MLX5DR_TABLE_TYPE_NIC_TX][RTE_FLOW_NAT64_4TO6])
    6808                 :          0 :                                 goto err_out;
    6809         [ #  # ]:          0 :                 if (attr->transfer)
    6810         [ #  # ]:          0 :                         if (!priv->action_nat64[MLX5DR_TABLE_TYPE_FDB][RTE_FLOW_NAT64_6TO4] ||
    6811         [ #  # ]:          0 :                             !priv->action_nat64[MLX5DR_TABLE_TYPE_FDB][RTE_FLOW_NAT64_4TO6])
    6812                 :          0 :                                 goto err_out;
    6813                 :            :         }
    6814                 :            :         return 0;
    6815                 :          0 : err_out:
    6816                 :          0 :         return rte_flow_error_set(error, EOPNOTSUPP, RTE_FLOW_ERROR_TYPE_ACTION,
    6817                 :            :                                   NULL, "NAT64 action is not supported.");
    6818                 :            : }
    6819                 :            : 
    6820                 :            : static int
    6821                 :          0 : flow_hw_validate_action_jump(struct rte_eth_dev *dev,
    6822                 :            :                              const struct rte_flow_actions_template_attr *attr,
    6823                 :            :                              const struct rte_flow_action *action,
    6824                 :            :                              const struct rte_flow_action *mask,
    6825                 :            :                              struct rte_flow_error *error)
    6826                 :            : {
    6827                 :          0 :         const struct rte_flow_action_jump *m = mask->conf;
    6828                 :          0 :         const struct rte_flow_action_jump *v = action->conf;
    6829                 :          0 :         struct mlx5_flow_template_table_cfg cfg = {
    6830                 :            :                 .external = true,
    6831                 :            :                 .attr = {
    6832                 :            :                         .flow_attr = {
    6833                 :          0 :                                 .ingress = attr->ingress,
    6834                 :          0 :                                 .egress = attr->egress,
    6835                 :          0 :                                 .transfer = attr->transfer,
    6836                 :            :                         },
    6837                 :            :                 },
    6838                 :            :         };
    6839                 :          0 :         uint32_t t_group = 0;
    6840                 :            : 
    6841   [ #  #  #  # ]:          0 :         if (!m || !m->group)
    6842                 :            :                 return 0;
    6843         [ #  # ]:          0 :         if (!v)
    6844                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6845                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    6846                 :            :                                           "Invalid jump action configuration");
    6847         [ #  # ]:          0 :         if (flow_hw_translate_group(dev, &cfg, v->group, &t_group, error))
    6848                 :          0 :                 return -rte_errno;
    6849         [ #  # ]:          0 :         if (t_group == 0)
    6850                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6851                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    6852                 :            :                                           "Unsupported action - jump to root table");
    6853                 :            :         return 0;
    6854                 :            : }
    6855                 :            : 
    6856                 :            : static int
    6857                 :          0 : mlx5_flow_validate_action_jump_to_table_index(const struct rte_flow_action *action,
    6858                 :            :                              const struct rte_flow_action *mask,
    6859                 :            :                              struct rte_flow_error *error)
    6860                 :            : {
    6861                 :          0 :         const struct rte_flow_action_jump_to_table_index *m = mask->conf;
    6862                 :          0 :         const struct rte_flow_action_jump_to_table_index *v = action->conf;
    6863                 :            :         struct mlx5dr_action *jump_action;
    6864                 :            :         uint32_t t_group = 0;
    6865                 :            : 
    6866   [ #  #  #  # ]:          0 :         if (!m || !m->table)
    6867                 :            :                 return 0;
    6868         [ #  # ]:          0 :         if (!v)
    6869                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6870                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    6871                 :            :                                           "Invalid jump to matcher action configuration");
    6872                 :          0 :         t_group = v->table->grp->group_id;
    6873         [ #  # ]:          0 :         if (t_group == 0)
    6874                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6875                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    6876                 :            :                                           "Unsupported action - jump to root table");
    6877         [ #  # ]:          0 :         if (likely(!rte_flow_template_table_resizable(0, &v->table->cfg.attr))) {
    6878                 :          0 :                 jump_action = v->table->matcher_info[0].jump;
    6879                 :            :         } else {
    6880                 :            :                 uint32_t selector;
    6881                 :          0 :                 rte_rwlock_read_lock(&v->table->matcher_replace_rwlk);
    6882                 :          0 :                 selector = v->table->matcher_selector;
    6883                 :          0 :                 jump_action = v->table->matcher_info[selector].jump;
    6884                 :            :                 rte_rwlock_read_unlock(&v->table->matcher_replace_rwlk);
    6885                 :            :         }
    6886         [ #  # ]:          0 :         if (jump_action == NULL)
    6887                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6888                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    6889                 :            :                                           "Unsupported action - table is not an rule array");
    6890                 :            :         return 0;
    6891                 :            : }
    6892                 :            : 
    6893                 :            : static int
    6894                 :          0 : mlx5_hw_validate_action_mark(struct rte_eth_dev *dev,
    6895                 :            :                              const struct rte_flow_action *template_action,
    6896                 :            :                              const struct rte_flow_action *template_mask,
    6897                 :            :                              uint64_t action_flags,
    6898                 :            :                              const struct rte_flow_actions_template_attr *template_attr,
    6899                 :            :                              struct rte_flow_error *error)
    6900                 :            : {
    6901                 :          0 :         const struct rte_flow_action_mark *mark_mask = template_mask->conf;
    6902                 :            :         const struct rte_flow_action *action =
    6903   [ #  #  #  # ]:          0 :                 mark_mask && mark_mask->id ? template_action :
    6904                 :          0 :                 &(const struct rte_flow_action) {
    6905                 :            :                 .type = RTE_FLOW_ACTION_TYPE_MARK,
    6906                 :          0 :                 .conf = &(const struct rte_flow_action_mark) {
    6907                 :            :                         .id = MLX5_FLOW_MARK_MAX - 1
    6908                 :            :                 }
    6909                 :            :         };
    6910                 :          0 :         const struct rte_flow_attr attr = {
    6911                 :          0 :                 .ingress = template_attr->ingress,
    6912                 :          0 :                 .egress = template_attr->egress,
    6913                 :          0 :                 .transfer = template_attr->transfer
    6914                 :            :         };
    6915                 :            : 
    6916                 :          0 :         return mlx5_flow_validate_action_mark(dev, action, action_flags,
    6917                 :            :                                               &attr, error);
    6918                 :            : }
    6919                 :            : 
    6920                 :            : static int
    6921                 :          0 : mlx5_hw_validate_action_queue(struct rte_eth_dev *dev,
    6922                 :            :                               const struct rte_flow_action *template_action,
    6923                 :            :                               const struct rte_flow_action *template_mask,
    6924                 :            :                               const struct rte_flow_actions_template_attr *template_attr,
    6925                 :            :                               uint64_t action_flags,
    6926                 :            :                               struct rte_flow_error *error)
    6927                 :            : {
    6928                 :          0 :         const struct rte_flow_action_queue *queue_mask = template_mask->conf;
    6929                 :          0 :         const struct rte_flow_attr attr = {
    6930                 :          0 :                 .ingress = template_attr->ingress,
    6931                 :          0 :                 .egress = template_attr->egress,
    6932                 :          0 :                 .transfer = template_attr->transfer
    6933                 :            :         };
    6934   [ #  #  #  # ]:          0 :         bool masked = queue_mask != NULL && queue_mask->index;
    6935                 :            : 
    6936         [ #  # ]:          0 :         if (template_attr->egress || template_attr->transfer)
    6937                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6938                 :            :                                           RTE_FLOW_ERROR_TYPE_ATTR, NULL,
    6939                 :            :                                           "QUEUE action supported for ingress only");
    6940         [ #  # ]:          0 :         if (masked)
    6941                 :          0 :                 return mlx5_flow_validate_action_queue(template_action, action_flags, dev,
    6942                 :            :                                                        &attr, error);
    6943                 :            :         else
    6944                 :            :                 return 0;
    6945                 :            : }
    6946                 :            : 
    6947                 :            : static int
    6948                 :          0 : mlx5_hw_validate_action_rss(struct rte_eth_dev *dev,
    6949                 :            :                               const struct rte_flow_action *template_action,
    6950                 :            :                               const struct rte_flow_action *template_mask,
    6951                 :            :                               const struct rte_flow_actions_template_attr *template_attr,
    6952                 :            :                               __rte_unused uint64_t action_flags,
    6953                 :            :                               struct rte_flow_error *error)
    6954                 :            : {
    6955                 :          0 :         const struct rte_flow_action_rss *mask = template_mask->conf;
    6956                 :            : 
    6957         [ #  # ]:          0 :         if (template_attr->egress || template_attr->transfer)
    6958                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6959                 :            :                                           RTE_FLOW_ERROR_TYPE_ATTR, NULL,
    6960                 :            :                                           "RSS action supported for ingress only");
    6961         [ #  # ]:          0 :         if (mask != NULL)
    6962                 :          0 :                 return mlx5_validate_action_rss(dev, template_action, error);
    6963                 :            :         else
    6964                 :            :                 return 0;
    6965                 :            : }
    6966                 :            : 
    6967                 :            : static int
    6968                 :          0 : mlx5_hw_validate_action_l2_encap(struct rte_eth_dev *dev,
    6969                 :            :                                  const struct rte_flow_action *template_action,
    6970                 :            :                                  const struct rte_flow_action *template_mask,
    6971                 :            :                                  const struct rte_flow_actions_template_attr *template_attr,
    6972                 :            :                                  uint64_t action_flags,
    6973                 :            :                                  struct rte_flow_error *error)
    6974                 :            : {
    6975                 :          0 :         const struct rte_flow_action_vxlan_encap default_action_conf = {
    6976                 :            :                 .definition = (struct rte_flow_item *)
    6977                 :          0 :                         (struct rte_flow_item [1]) {
    6978                 :            :                         [0] = { .type = RTE_FLOW_ITEM_TYPE_END }
    6979                 :            :                 }
    6980                 :            :         };
    6981                 :          0 :         const struct rte_flow_action *action = template_mask->conf ?
    6982         [ #  # ]:          0 :                 template_action : &(const struct rte_flow_action) {
    6983                 :          0 :                         .type = template_mask->type,
    6984                 :            :                         .conf = &default_action_conf
    6985                 :            :         };
    6986                 :          0 :         const struct rte_flow_attr attr = {
    6987                 :          0 :                 .ingress = template_attr->ingress,
    6988                 :          0 :                 .egress = template_attr->egress,
    6989                 :          0 :                 .transfer = template_attr->transfer
    6990                 :            :         };
    6991                 :            : 
    6992                 :          0 :         return mlx5_flow_dv_validate_action_l2_encap(dev, action_flags, action,
    6993                 :            :                                                      &attr, error);
    6994                 :            : }
    6995                 :            : 
    6996                 :            : static int
    6997                 :          0 : mlx5_hw_validate_action_l2_decap(struct rte_eth_dev *dev,
    6998                 :            :                                  const struct rte_flow_action *template_action,
    6999                 :            :                                  const struct rte_flow_action *template_mask,
    7000                 :            :                                  const struct rte_flow_actions_template_attr *template_attr,
    7001                 :            :                                  uint64_t action_flags,
    7002                 :            :                                  struct rte_flow_error *error)
    7003                 :            : {
    7004                 :          0 :         const struct rte_flow_action_vxlan_encap default_action_conf = {
    7005                 :            :                 .definition = (struct rte_flow_item *)
    7006                 :          0 :                         (struct rte_flow_item [1]) {
    7007                 :            :                                 [0] = { .type = RTE_FLOW_ITEM_TYPE_END }
    7008                 :            :                         }
    7009                 :            :         };
    7010                 :          0 :         const struct rte_flow_action *action = template_mask->conf ?
    7011         [ #  # ]:          0 :                                                template_action : &(const struct rte_flow_action) {
    7012                 :          0 :                         .type = template_mask->type,
    7013                 :            :                         .conf = &default_action_conf
    7014                 :            :                 };
    7015                 :          0 :         const struct rte_flow_attr attr = {
    7016                 :          0 :                 .ingress = template_attr->ingress,
    7017                 :          0 :                 .egress = template_attr->egress,
    7018                 :          0 :                 .transfer = template_attr->transfer
    7019                 :            :         };
    7020                 :            :         uint64_t item_flags =
    7021                 :          0 :                 action->type == RTE_FLOW_ACTION_TYPE_VXLAN_DECAP ?
    7022         [ #  # ]:          0 :                 MLX5_FLOW_LAYER_VXLAN : 0;
    7023                 :            : 
    7024                 :          0 :         return mlx5_flow_dv_validate_action_decap(dev, action_flags, action,
    7025                 :            :                                                   item_flags, &attr, error);
    7026                 :            : }
    7027                 :            : 
    7028                 :            : static int
    7029                 :            : mlx5_hw_validate_action_conntrack(struct rte_eth_dev *dev,
    7030                 :            :                                   const struct rte_flow_action *template_action,
    7031                 :            :                                   const struct rte_flow_action *template_mask,
    7032                 :            :                                   const struct rte_flow_actions_template_attr *template_attr,
    7033                 :            :                                   uint64_t action_flags,
    7034                 :            :                                   struct rte_flow_error *error)
    7035                 :            : {
    7036                 :            :         RTE_SET_USED(template_action);
    7037                 :            :         RTE_SET_USED(template_mask);
    7038                 :            :         RTE_SET_USED(template_attr);
    7039                 :          0 :         return mlx5_flow_dv_validate_action_aso_ct(dev, action_flags,
    7040                 :            :                                                    MLX5_FLOW_LAYER_OUTER_L4_TCP,
    7041                 :            :                                                    false, error);
    7042                 :            : }
    7043                 :            : 
    7044                 :            : static int
    7045                 :          0 : flow_hw_validate_action_raw_encap(const struct rte_flow_action *action,
    7046                 :            :                                   const struct rte_flow_action *mask,
    7047                 :            :                                   struct rte_flow_error *error)
    7048                 :            : {
    7049                 :          0 :         const struct rte_flow_action_raw_encap *mask_conf = mask->conf;
    7050                 :          0 :         const struct rte_flow_action_raw_encap *action_conf = action->conf;
    7051                 :            : 
    7052   [ #  #  #  # ]:          0 :         if (!mask_conf || !mask_conf->size)
    7053                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    7054                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, mask,
    7055                 :            :                                           "raw_encap: size must be masked");
    7056   [ #  #  #  # ]:          0 :         if (!action_conf || !action_conf->size)
    7057                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    7058                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    7059                 :            :                                           "raw_encap: invalid action configuration");
    7060   [ #  #  #  # ]:          0 :         if (mask_conf->data && !action_conf->data)
    7061                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    7062                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
    7063                 :            :                                           action, "raw_encap: masked data is missing");
    7064                 :            :         return 0;
    7065                 :            : }
    7066                 :            : 
    7067                 :            : 
    7068                 :            : static int
    7069                 :          0 : flow_hw_validate_action_raw_reformat(struct rte_eth_dev *dev,
    7070                 :            :                                      const struct rte_flow_action *template_action,
    7071                 :            :                                      const struct rte_flow_action *template_mask,
    7072                 :            :                                      const struct
    7073                 :            :                                      rte_flow_actions_template_attr *template_attr,
    7074                 :            :                                      uint64_t *action_flags,
    7075                 :            :                                      struct rte_flow_error *error)
    7076                 :            : {
    7077                 :            :         const struct rte_flow_action *encap_action = NULL;
    7078                 :            :         const struct rte_flow_action *encap_mask = NULL;
    7079                 :            :         const struct rte_flow_action_raw_decap *raw_decap = NULL;
    7080                 :            :         const struct rte_flow_action_raw_encap *raw_encap = NULL;
    7081                 :          0 :         const struct rte_flow_attr attr = {
    7082                 :          0 :                 .ingress = template_attr->ingress,
    7083                 :          0 :                 .egress = template_attr->egress,
    7084                 :          0 :                 .transfer = template_attr->transfer
    7085                 :            :         };
    7086                 :            :         uint64_t item_flags = 0;
    7087                 :          0 :         int ret, actions_n = 0;
    7088                 :            : 
    7089         [ #  # ]:          0 :         if (template_action->type == RTE_FLOW_ACTION_TYPE_RAW_DECAP) {
    7090                 :          0 :                 raw_decap = template_mask->conf ?
    7091         [ #  # ]:          0 :                             template_action->conf : &empty_decap;
    7092         [ #  # ]:          0 :                 if ((template_action + 1)->type == RTE_FLOW_ACTION_TYPE_RAW_ENCAP) {
    7093         [ #  # ]:          0 :                         if ((template_mask + 1)->type != RTE_FLOW_ACTION_TYPE_RAW_ENCAP)
    7094                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    7095                 :            :                                                           RTE_FLOW_ERROR_TYPE_ACTION,
    7096                 :          0 :                                                           template_mask + 1, "invalid mask type");
    7097                 :          0 :                         encap_action = template_action + 1;
    7098                 :          0 :                         encap_mask = template_mask + 1;
    7099                 :            :                 }
    7100                 :            :         } else {
    7101                 :            :                 encap_action = template_action;
    7102                 :            :                 encap_mask = template_mask;
    7103                 :            :         }
    7104         [ #  # ]:          0 :         if (encap_action) {
    7105                 :          0 :                 raw_encap = encap_action->conf;
    7106                 :          0 :                 ret = flow_hw_validate_action_raw_encap(encap_action,
    7107                 :            :                                                         encap_mask, error);
    7108         [ #  # ]:          0 :                 if (ret)
    7109                 :            :                         return ret;
    7110                 :            :         }
    7111                 :          0 :         return mlx5_flow_dv_validate_action_raw_encap_decap(dev, raw_decap,
    7112                 :            :                                                             raw_encap, &attr,
    7113                 :            :                                                             action_flags,
    7114                 :            :                                                             &actions_n,
    7115                 :            :                                                             template_action,
    7116                 :            :                                                             item_flags, error);
    7117                 :            : }
    7118                 :            : 
    7119                 :            : 
    7120                 :            : 
    7121                 :            : static int
    7122                 :          0 : mlx5_flow_hw_actions_validate(struct rte_eth_dev *dev,
    7123                 :            :                               const struct rte_flow_actions_template_attr *attr,
    7124                 :            :                               const struct rte_flow_action actions[],
    7125                 :            :                               const struct rte_flow_action masks[],
    7126                 :            :                               uint64_t *act_flags,
    7127                 :            :                               struct rte_flow_error *error)
    7128                 :            : {
    7129                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    7130                 :            :         const struct rte_flow_action_count *count_mask = NULL;
    7131                 :          0 :         bool fixed_cnt = false;
    7132                 :          0 :         uint64_t action_flags = 0;
    7133                 :            :         bool actions_end = false;
    7134                 :            : #ifdef HAVE_MLX5DV_DR_ACTION_CREATE_DEST_ROOT_TABLE
    7135                 :            :         int table_type;
    7136                 :            : #endif
    7137                 :            :         uint16_t i;
    7138                 :            :         int ret;
    7139                 :            :         const struct rte_flow_action_ipv6_ext_remove *remove_data;
    7140                 :            : 
    7141         [ #  # ]:          0 :         if (!mlx5_hw_ctx_validate(dev, error))
    7142                 :          0 :                 return -rte_errno;
    7143                 :            :         /* FDB actions are only valid to proxy port. */
    7144   [ #  #  #  #  :          0 :         if (attr->transfer && (!priv->sh->config.dv_esw_en || !priv->master))
                   #  # ]
    7145                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    7146                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    7147                 :            :                                           NULL,
    7148                 :            :                                           "transfer actions are only valid to proxy port");
    7149         [ #  # ]:          0 :         for (i = 0; !actions_end; ++i) {
    7150                 :          0 :                 const struct rte_flow_action *action = &actions[i];
    7151                 :          0 :                 const struct rte_flow_action *mask = &masks[i];
    7152                 :            : 
    7153                 :            :                 MLX5_ASSERT(i < MLX5_HW_MAX_ACTS);
    7154         [ #  # ]:          0 :                 if (action->type != RTE_FLOW_ACTION_TYPE_INDIRECT &&
    7155         [ #  # ]:          0 :                     action->type != mask->type)
    7156                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    7157                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    7158                 :            :                                                   action,
    7159                 :            :                                                   "mask type does not match action type");
    7160   [ #  #  #  #  :          0 :                 switch ((int)action->type) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    7161                 :            :                 case RTE_FLOW_ACTION_TYPE_VOID:
    7162                 :          0 :                         break;
    7163                 :            :                 case RTE_FLOW_ACTION_TYPE_INDIRECT_LIST:
    7164                 :            :                         break;
    7165                 :          0 :                 case RTE_FLOW_ACTION_TYPE_INDIRECT:
    7166                 :          0 :                         ret = flow_hw_validate_action_indirect(dev, action,
    7167                 :            :                                                                mask,
    7168                 :            :                                                                &action_flags,
    7169                 :            :                                                                &fixed_cnt,
    7170                 :            :                                                                error);
    7171         [ #  # ]:          0 :                         if (ret < 0)
    7172                 :          0 :                                 return ret;
    7173                 :            :                         break;
    7174                 :          0 :                 case RTE_FLOW_ACTION_TYPE_FLAG:
    7175                 :            :                         /* TODO: Validation logic */
    7176                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_FLAG;
    7177                 :          0 :                         break;
    7178                 :          0 :                 case RTE_FLOW_ACTION_TYPE_MARK:
    7179                 :          0 :                         ret = mlx5_hw_validate_action_mark(dev, action, mask,
    7180                 :            :                                                            action_flags,
    7181                 :            :                                                            attr, error);
    7182         [ #  # ]:          0 :                         if (ret)
    7183                 :          0 :                                 return ret;
    7184                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_MARK;
    7185                 :          0 :                         break;
    7186                 :          0 :                 case RTE_FLOW_ACTION_TYPE_DROP:
    7187                 :          0 :                         ret = mlx5_flow_validate_action_drop
    7188                 :            :                                 (dev, action_flags,
    7189                 :          0 :                                  &(struct rte_flow_attr){.egress = attr->egress},
    7190                 :            :                                  error);
    7191         [ #  # ]:          0 :                         if (ret)
    7192                 :          0 :                                 return ret;
    7193                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_DROP;
    7194                 :          0 :                         break;
    7195                 :          0 :                 case RTE_FLOW_ACTION_TYPE_JUMP:
    7196                 :            :                         /* Only validate the jump to root table in template stage. */
    7197                 :          0 :                         ret = flow_hw_validate_action_jump(dev, attr, action, mask, error);
    7198         [ #  # ]:          0 :                         if (ret)
    7199                 :          0 :                                 return ret;
    7200                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_JUMP;
    7201                 :          0 :                         break;
    7202                 :            : #ifdef HAVE_MLX5DV_DR_ACTION_CREATE_DEST_ROOT_TABLE
    7203                 :            :                 case RTE_FLOW_ACTION_TYPE_SEND_TO_KERNEL:
    7204                 :            :                         if (priv->shared_host)
    7205                 :            :                                 return rte_flow_error_set(error, ENOTSUP,
    7206                 :            :                                                           RTE_FLOW_ERROR_TYPE_ACTION,
    7207                 :            :                                                           action,
    7208                 :            :                                                           "action not supported in guest port");
    7209                 :            :                         table_type = attr->ingress ? MLX5DR_TABLE_TYPE_NIC_RX :
    7210                 :            :                                      ((attr->egress) ? MLX5DR_TABLE_TYPE_NIC_TX :
    7211                 :            :                                      MLX5DR_TABLE_TYPE_FDB);
    7212                 :            :                         if (!priv->hw_send_to_kernel[table_type])
    7213                 :            :                                 return rte_flow_error_set(error, ENOTSUP,
    7214                 :            :                                                           RTE_FLOW_ERROR_TYPE_ACTION,
    7215                 :            :                                                           action,
    7216                 :            :                                                           "action is not available");
    7217                 :            :                         action_flags |= MLX5_FLOW_ACTION_SEND_TO_KERNEL;
    7218                 :            :                         break;
    7219                 :            : #endif
    7220                 :          0 :                 case RTE_FLOW_ACTION_TYPE_QUEUE:
    7221                 :          0 :                         ret = mlx5_hw_validate_action_queue(dev, action, mask,
    7222                 :            :                                                             attr, action_flags,
    7223                 :            :                                                             error);
    7224         [ #  # ]:          0 :                         if (ret)
    7225                 :          0 :                                 return ret;
    7226                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_QUEUE;
    7227                 :          0 :                         break;
    7228                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RSS:
    7229                 :          0 :                         ret = mlx5_hw_validate_action_rss(dev, action, mask,
    7230                 :            :                                                           attr, action_flags,
    7231                 :            :                                                           error);
    7232         [ #  # ]:          0 :                         if (ret)
    7233                 :          0 :                                 return ret;
    7234                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_RSS;
    7235                 :          0 :                         break;
    7236                 :          0 :                 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
    7237                 :            :                 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
    7238                 :          0 :                         ret = mlx5_hw_validate_action_l2_encap(dev, action, mask,
    7239                 :            :                                                                attr, action_flags,
    7240                 :            :                                                                error);
    7241         [ #  # ]:          0 :                         if (ret)
    7242                 :          0 :                                 return ret;
    7243                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_ENCAP;
    7244                 :          0 :                         break;
    7245                 :          0 :                 case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
    7246                 :            :                 case RTE_FLOW_ACTION_TYPE_NVGRE_DECAP:
    7247                 :          0 :                         ret = mlx5_hw_validate_action_l2_decap(dev, action, mask,
    7248                 :            :                                                                attr, action_flags,
    7249                 :            :                                                                error);
    7250         [ #  # ]:          0 :                         if (ret)
    7251                 :          0 :                                 return ret;
    7252                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_DECAP;
    7253                 :          0 :                         break;
    7254                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
    7255                 :            :                 case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
    7256                 :          0 :                         ret = flow_hw_validate_action_raw_reformat(dev, action,
    7257                 :            :                                                                    mask, attr,
    7258                 :            :                                                                    &action_flags,
    7259                 :            :                                                                    error);
    7260         [ #  # ]:          0 :                         if (ret)
    7261                 :          0 :                                 return ret;
    7262         [ #  # ]:          0 :                         if (action->type == RTE_FLOW_ACTION_TYPE_RAW_DECAP &&
    7263         [ #  # ]:          0 :                            (action + 1)->type == RTE_FLOW_ACTION_TYPE_RAW_ENCAP) {
    7264                 :          0 :                                 action_flags |= MLX5_FLOW_XCAP_ACTIONS;
    7265                 :          0 :                                 i++;
    7266                 :            :                         }
    7267                 :            :                         break;
    7268                 :          0 :                 case RTE_FLOW_ACTION_TYPE_IPV6_EXT_PUSH:
    7269                 :          0 :                         ret = flow_hw_validate_action_ipv6_ext_push(dev, action, error);
    7270         [ #  # ]:          0 :                         if (ret < 0)
    7271                 :          0 :                                 return ret;
    7272                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_IPV6_ROUTING_PUSH;
    7273                 :          0 :                         break;
    7274                 :          0 :                 case RTE_FLOW_ACTION_TYPE_IPV6_EXT_REMOVE:
    7275                 :          0 :                         remove_data = action->conf;
    7276                 :            :                         /* Remove action must be shared. */
    7277   [ #  #  #  # ]:          0 :                         if (remove_data->type != IPPROTO_ROUTING || !mask) {
    7278                 :          0 :                                 DRV_LOG(ERR, "Only supports shared IPv6 routing remove");
    7279                 :          0 :                                 return -EINVAL;
    7280                 :            :                         }
    7281                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_IPV6_ROUTING_REMOVE;
    7282                 :          0 :                         break;
    7283                 :          0 :                 case RTE_FLOW_ACTION_TYPE_METER:
    7284                 :            :                         /* TODO: Validation logic */
    7285                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_METER;
    7286                 :          0 :                         break;
    7287                 :          0 :                 case RTE_FLOW_ACTION_TYPE_METER_MARK:
    7288                 :          0 :                         ret = flow_hw_validate_action_meter_mark(dev, action, false, error);
    7289         [ #  # ]:          0 :                         if (ret < 0)
    7290                 :          0 :                                 return ret;
    7291                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_METER;
    7292                 :          0 :                         break;
    7293                 :          0 :                 case RTE_FLOW_ACTION_TYPE_MODIFY_FIELD:
    7294                 :          0 :                         ret = flow_hw_validate_action_modify_field(dev, action, mask,
    7295                 :            :                                                                    error);
    7296         [ #  # ]:          0 :                         if (ret < 0)
    7297                 :          0 :                                 return ret;
    7298                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_MODIFY_FIELD;
    7299                 :          0 :                         break;
    7300                 :          0 :                 case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
    7301                 :          0 :                         ret = flow_hw_validate_action_represented_port
    7302                 :            :                                         (dev, action, mask, error);
    7303         [ #  # ]:          0 :                         if (ret < 0)
    7304                 :          0 :                                 return ret;
    7305                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_PORT_ID;
    7306                 :          0 :                         break;
    7307                 :          0 :                 case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR:
    7308                 :          0 :                         ret = flow_hw_validate_action_port_representor
    7309                 :            :                                         (dev, attr, action, mask, error);
    7310         [ #  # ]:          0 :                         if (ret < 0)
    7311                 :          0 :                                 return ret;
    7312                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_PORT_REPRESENTOR;
    7313                 :          0 :                         break;
    7314                 :          0 :                 case RTE_FLOW_ACTION_TYPE_AGE:
    7315   [ #  #  #  # ]:          0 :                         if (count_mask && count_mask->id)
    7316                 :          0 :                                 fixed_cnt = true;
    7317                 :          0 :                         ret = flow_hw_validate_action_age(dev, action,
    7318                 :            :                                                           action_flags,
    7319                 :            :                                                           fixed_cnt, error);
    7320         [ #  # ]:          0 :                         if (ret < 0)
    7321                 :          0 :                                 return ret;
    7322                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_AGE;
    7323                 :          0 :                         break;
    7324                 :          0 :                 case RTE_FLOW_ACTION_TYPE_COUNT:
    7325                 :          0 :                         ret = flow_hw_validate_action_count(dev, action, mask,
    7326                 :            :                                                             action_flags,
    7327                 :            :                                                             error);
    7328         [ #  # ]:          0 :                         if (ret < 0)
    7329                 :          0 :                                 return ret;
    7330                 :          0 :                         count_mask = mask->conf;
    7331                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_COUNT;
    7332                 :          0 :                         break;
    7333                 :          0 :                 case RTE_FLOW_ACTION_TYPE_CONNTRACK:
    7334                 :          0 :                         ret = mlx5_hw_validate_action_conntrack(dev, action, mask,
    7335                 :            :                                                                 attr, action_flags,
    7336                 :            :                                                                 error);
    7337         [ #  # ]:          0 :                         if (ret)
    7338                 :          0 :                                 return ret;
    7339                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_CT;
    7340                 :          0 :                         break;
    7341                 :          0 :                 case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:
    7342                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_OF_POP_VLAN;
    7343                 :          0 :                         break;
    7344                 :          0 :                 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
    7345                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_OF_SET_VLAN_VID;
    7346                 :          0 :                         break;
    7347                 :          0 :                 case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
    7348                 :          0 :                         ret = flow_hw_validate_action_push_vlan
    7349                 :            :                                         (dev, attr, action, mask, error);
    7350         [ #  # ]:          0 :                         if (ret != 0)
    7351                 :          0 :                                 return ret;
    7352                 :          0 :                         i += is_of_vlan_pcp_present(action) ?
    7353         [ #  # ]:          0 :                                 MLX5_HW_VLAN_PUSH_PCP_IDX :
    7354                 :            :                                 MLX5_HW_VLAN_PUSH_VID_IDX;
    7355                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_OF_PUSH_VLAN;
    7356                 :          0 :                         break;
    7357                 :          0 :                 case RTE_FLOW_ACTION_TYPE_NAT64:
    7358                 :          0 :                         ret = flow_hw_validate_action_nat64(dev, attr, action, mask,
    7359                 :            :                                                             action_flags, error);
    7360         [ #  # ]:          0 :                         if (ret != 0)
    7361                 :          0 :                                 return ret;
    7362                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_NAT64;
    7363                 :          0 :                         break;
    7364                 :          0 :                 case RTE_FLOW_ACTION_TYPE_END:
    7365                 :            :                         actions_end = true;
    7366                 :          0 :                         break;
    7367                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_DEFAULT_MISS:
    7368                 :          0 :                         ret = flow_hw_validate_action_default_miss(dev, attr,
    7369                 :            :                                                                    action_flags, error);
    7370         [ #  # ]:          0 :                         if (ret < 0)
    7371                 :          0 :                                 return ret;
    7372                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_DEFAULT_MISS;
    7373                 :          0 :                         break;
    7374                 :          0 :                 case RTE_FLOW_ACTION_TYPE_JUMP_TO_TABLE_INDEX:
    7375                 :          0 :                         ret = mlx5_flow_validate_action_jump_to_table_index(action, mask, error);
    7376         [ #  # ]:          0 :                         if (ret < 0)
    7377                 :          0 :                                 return ret;
    7378                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_JUMP_TO_TABLE_INDEX;
    7379                 :          0 :                         break;
    7380                 :          0 :                 default:
    7381                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    7382                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    7383                 :            :                                                   action,
    7384                 :            :                                                   "action not supported in template API");
    7385                 :            :                 }
    7386                 :            :         }
    7387         [ #  # ]:          0 :         if (act_flags != NULL)
    7388                 :          0 :                 *act_flags = action_flags;
    7389                 :            :         return 0;
    7390                 :            : }
    7391                 :            : 
    7392                 :            : static int
    7393                 :          0 : flow_hw_actions_validate(struct rte_eth_dev *dev,
    7394                 :            :                          const struct rte_flow_actions_template_attr *attr,
    7395                 :            :                          const struct rte_flow_action actions[],
    7396                 :            :                          const struct rte_flow_action masks[],
    7397                 :            :                          struct rte_flow_error *error)
    7398                 :            : {
    7399                 :          0 :         return mlx5_flow_hw_actions_validate(dev, attr, actions, masks, NULL, error);
    7400                 :            : }
    7401                 :            : 
    7402                 :            : 
    7403                 :            : static enum mlx5dr_action_type mlx5_hw_dr_action_types[] = {
    7404                 :            :         [RTE_FLOW_ACTION_TYPE_MARK] = MLX5DR_ACTION_TYP_TAG,
    7405                 :            :         [RTE_FLOW_ACTION_TYPE_FLAG] = MLX5DR_ACTION_TYP_TAG,
    7406                 :            :         [RTE_FLOW_ACTION_TYPE_DROP] = MLX5DR_ACTION_TYP_DROP,
    7407                 :            :         [RTE_FLOW_ACTION_TYPE_JUMP] = MLX5DR_ACTION_TYP_TBL,
    7408                 :            :         [RTE_FLOW_ACTION_TYPE_QUEUE] = MLX5DR_ACTION_TYP_TIR,
    7409                 :            :         [RTE_FLOW_ACTION_TYPE_RSS] = MLX5DR_ACTION_TYP_TIR,
    7410                 :            :         [RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP] = MLX5DR_ACTION_TYP_REFORMAT_L2_TO_TNL_L2,
    7411                 :            :         [RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP] = MLX5DR_ACTION_TYP_REFORMAT_L2_TO_TNL_L2,
    7412                 :            :         [RTE_FLOW_ACTION_TYPE_VXLAN_DECAP] = MLX5DR_ACTION_TYP_REFORMAT_TNL_L2_TO_L2,
    7413                 :            :         [RTE_FLOW_ACTION_TYPE_NVGRE_DECAP] = MLX5DR_ACTION_TYP_REFORMAT_TNL_L2_TO_L2,
    7414                 :            :         [RTE_FLOW_ACTION_TYPE_MODIFY_FIELD] = MLX5DR_ACTION_TYP_MODIFY_HDR,
    7415                 :            :         [RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT] = MLX5DR_ACTION_TYP_VPORT,
    7416                 :            :         [RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR] = MLX5DR_ACTION_TYP_MISS,
    7417                 :            :         [RTE_FLOW_ACTION_TYPE_CONNTRACK] = MLX5DR_ACTION_TYP_ASO_CT,
    7418                 :            :         [RTE_FLOW_ACTION_TYPE_OF_POP_VLAN] = MLX5DR_ACTION_TYP_POP_VLAN,
    7419                 :            :         [RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN] = MLX5DR_ACTION_TYP_PUSH_VLAN,
    7420                 :            :         [RTE_FLOW_ACTION_TYPE_SEND_TO_KERNEL] = MLX5DR_ACTION_TYP_DEST_ROOT,
    7421                 :            :         [RTE_FLOW_ACTION_TYPE_IPV6_EXT_PUSH] = MLX5DR_ACTION_TYP_PUSH_IPV6_ROUTE_EXT,
    7422                 :            :         [RTE_FLOW_ACTION_TYPE_IPV6_EXT_REMOVE] = MLX5DR_ACTION_TYP_POP_IPV6_ROUTE_EXT,
    7423                 :            :         [RTE_FLOW_ACTION_TYPE_NAT64] = MLX5DR_ACTION_TYP_NAT64,
    7424                 :            :         [RTE_FLOW_ACTION_TYPE_JUMP_TO_TABLE_INDEX] = MLX5DR_ACTION_TYP_JUMP_TO_MATCHER,
    7425                 :            : };
    7426                 :            : 
    7427                 :            : static inline void
    7428                 :            : action_template_set_type(struct rte_flow_actions_template *at,
    7429                 :            :                          enum mlx5dr_action_type *action_types,
    7430                 :            :                          unsigned int action_src, uint16_t *curr_off,
    7431                 :            :                          enum mlx5dr_action_type type)
    7432                 :            : {
    7433                 :          0 :         at->dr_off[action_src] = *curr_off;
    7434                 :          0 :         action_types[*curr_off] = type;
    7435                 :          0 :         *curr_off = *curr_off + 1;
    7436                 :          0 : }
    7437                 :            : 
    7438                 :            : static int
    7439                 :          0 : flow_hw_dr_actions_template_handle_shared(int type, uint32_t action_src,
    7440                 :            :                                           enum mlx5dr_action_type *action_types,
    7441                 :            :                                           uint16_t *curr_off, uint16_t *cnt_off,
    7442                 :            :                                           struct rte_flow_actions_template *at)
    7443                 :            : {
    7444   [ #  #  #  #  :          0 :         switch (type) {
                      # ]
    7445                 :            :         case RTE_FLOW_ACTION_TYPE_RSS:
    7446                 :            :                 action_template_set_type(at, action_types, action_src, curr_off,
    7447                 :            :                                          MLX5DR_ACTION_TYP_TIR);
    7448                 :            :                 break;
    7449                 :          0 :         case RTE_FLOW_ACTION_TYPE_AGE:
    7450                 :            :         case RTE_FLOW_ACTION_TYPE_COUNT:
    7451                 :            :                 /*
    7452                 :            :                  * Both AGE and COUNT action need counter, the first one fills
    7453                 :            :                  * the action_types array, and the second only saves the offset.
    7454                 :            :                  */
    7455         [ #  # ]:          0 :                 if (*cnt_off == UINT16_MAX) {
    7456                 :          0 :                         *cnt_off = *curr_off;
    7457                 :            :                         action_template_set_type(at, action_types,
    7458                 :            :                                                  action_src, curr_off,
    7459                 :            :                                                  MLX5DR_ACTION_TYP_CTR);
    7460                 :            :                 }
    7461                 :          0 :                 at->dr_off[action_src] = *cnt_off;
    7462                 :          0 :                 break;
    7463                 :            :         case RTE_FLOW_ACTION_TYPE_CONNTRACK:
    7464                 :            :                 action_template_set_type(at, action_types, action_src, curr_off,
    7465                 :            :                                          MLX5DR_ACTION_TYP_ASO_CT);
    7466                 :            :                 break;
    7467                 :            :         case RTE_FLOW_ACTION_TYPE_QUOTA:
    7468                 :            :         case RTE_FLOW_ACTION_TYPE_METER_MARK:
    7469                 :            :                 action_template_set_type(at, action_types, action_src, curr_off,
    7470                 :            :                                          MLX5DR_ACTION_TYP_ASO_METER);
    7471                 :            :                 break;
    7472                 :          0 :         default:
    7473                 :          0 :                 DRV_LOG(WARNING, "Unsupported shared action type: %d", type);
    7474                 :          0 :                 return -EINVAL;
    7475                 :            :         }
    7476                 :            :         return 0;
    7477                 :            : }
    7478                 :            : 
    7479                 :            : 
    7480                 :            : static int
    7481                 :          0 : flow_hw_template_actions_list(struct rte_flow_actions_template *at,
    7482                 :            :                               unsigned int action_src,
    7483                 :            :                               enum mlx5dr_action_type *action_types,
    7484                 :            :                               uint16_t *curr_off, uint16_t *cnt_off)
    7485                 :            : {
    7486                 :            :         int ret;
    7487                 :          0 :         const struct rte_flow_action_indirect_list *indlst_conf = at->actions[action_src].conf;
    7488   [ #  #  #  # ]:          0 :         enum mlx5_indirect_list_type list_type = mlx5_get_indirect_list_type(indlst_conf->handle);
    7489                 :            :         const union {
    7490                 :            :                 struct mlx5_indlst_legacy *legacy;
    7491                 :            :                 struct rte_flow_action_list_handle *handle;
    7492                 :            :         } indlst_obj = { .handle = indlst_conf->handle };
    7493                 :            :         enum mlx5dr_action_type type;
    7494                 :            : 
    7495   [ #  #  #  # ]:          0 :         switch (list_type) {
    7496                 :          0 :         case MLX5_INDIRECT_ACTION_LIST_TYPE_LEGACY:
    7497                 :          0 :                 ret = flow_hw_dr_actions_template_handle_shared
    7498                 :          0 :                         (indlst_obj.legacy->legacy_type, action_src,
    7499                 :            :                          action_types, curr_off, cnt_off, at);
    7500         [ #  # ]:          0 :                 if (ret)
    7501                 :          0 :                         return ret;
    7502                 :            :                 break;
    7503                 :            :         case MLX5_INDIRECT_ACTION_LIST_TYPE_MIRROR:
    7504                 :            :                 action_template_set_type(at, action_types, action_src, curr_off,
    7505                 :            :                                          MLX5DR_ACTION_TYP_DEST_ARRAY);
    7506                 :            :                 break;
    7507                 :          0 :         case MLX5_INDIRECT_ACTION_LIST_TYPE_REFORMAT:
    7508                 :          0 :                 type = ((struct mlx5_hw_encap_decap_action *)
    7509                 :            :                         (indlst_conf->handle))->action_type;
    7510                 :            :                 action_template_set_type(at, action_types, action_src, curr_off, type);
    7511                 :            :                 break;
    7512                 :          0 :         default:
    7513                 :          0 :                 DRV_LOG(ERR, "Unsupported indirect list type");
    7514                 :          0 :                 return -EINVAL;
    7515                 :            :         }
    7516                 :            :         return 0;
    7517                 :            : }
    7518                 :            : 
    7519                 :            : /**
    7520                 :            :  * Create DR action template based on a provided sequence of flow actions.
    7521                 :            :  *
    7522                 :            :  * @param[in] dev
    7523                 :            :  *   Pointer to the rte_eth_dev structure.
    7524                 :            :  * @param[in] at
    7525                 :            :  *   Pointer to flow actions template to be updated.
    7526                 :            :  * @param[out] action_types
    7527                 :            :  *   Action types array to be filled.
    7528                 :            :  * @param[out] tmpl_flags
    7529                 :            :  *   Template DR flags to be filled.
    7530                 :            :  *
    7531                 :            :  * @return
    7532                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    7533                 :            :  */
    7534                 :            : static int
    7535                 :          0 : flow_hw_parse_flow_actions_to_dr_actions(struct rte_eth_dev *dev,
    7536                 :            :                                         struct rte_flow_actions_template *at,
    7537                 :            :                                         enum mlx5dr_action_type action_types[MLX5_HW_MAX_ACTS],
    7538                 :            :                                         uint32_t *tmpl_flags __rte_unused)
    7539                 :            : {
    7540                 :            :         unsigned int i;
    7541                 :            :         uint16_t curr_off;
    7542                 :            :         enum mlx5dr_action_type reformat_act_type = MLX5DR_ACTION_TYP_REFORMAT_TNL_L2_TO_L2;
    7543                 :            :         uint16_t reformat_off = UINT16_MAX;
    7544                 :            :         uint16_t mhdr_off = UINT16_MAX;
    7545                 :            :         uint16_t recom_off = UINT16_MAX;
    7546                 :          0 :         uint16_t cnt_off = UINT16_MAX;
    7547                 :            :         enum mlx5dr_action_type recom_type = MLX5DR_ACTION_TYP_LAST;
    7548                 :            :         int ret;
    7549                 :            : 
    7550         [ #  # ]:          0 :         for (i = 0, curr_off = 0; at->actions[i].type != RTE_FLOW_ACTION_TYPE_END; ++i) {
    7551                 :            :                 const struct rte_flow_action_raw_encap *raw_encap_data;
    7552                 :            :                 size_t data_size;
    7553                 :            :                 enum mlx5dr_action_type type;
    7554                 :            : 
    7555         [ #  # ]:          0 :                 if (curr_off >= MLX5_HW_MAX_ACTS)
    7556                 :          0 :                         goto err_actions_num;
    7557   [ #  #  #  #  :          0 :                 switch ((int)at->actions[i].type) {
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    7558                 :            :                 case RTE_FLOW_ACTION_TYPE_VOID:
    7559                 :            :                         break;
    7560                 :          0 :                 case RTE_FLOW_ACTION_TYPE_INDIRECT_LIST:
    7561                 :          0 :                         ret = flow_hw_template_actions_list(at, i, action_types,
    7562                 :            :                                                             &curr_off, &cnt_off);
    7563         [ #  # ]:          0 :                         if (ret)
    7564                 :          0 :                                 return ret;
    7565                 :            :                         break;
    7566                 :          0 :                 case RTE_FLOW_ACTION_TYPE_INDIRECT:
    7567                 :          0 :                         ret = flow_hw_dr_actions_template_handle_shared
    7568                 :          0 :                                 (at->masks[i].type, i, action_types,
    7569                 :            :                                  &curr_off, &cnt_off, at);
    7570         [ #  # ]:          0 :                         if (ret)
    7571                 :          0 :                                 return ret;
    7572                 :            :                         break;
    7573                 :          0 :                 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
    7574                 :            :                 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
    7575                 :            :                 case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
    7576                 :            :                 case RTE_FLOW_ACTION_TYPE_NVGRE_DECAP:
    7577                 :            :                         MLX5_ASSERT(reformat_off == UINT16_MAX);
    7578                 :          0 :                         reformat_off = curr_off++;
    7579                 :          0 :                         reformat_act_type = mlx5_hw_dr_action_types[at->actions[i].type];
    7580                 :          0 :                         break;
    7581                 :          0 :                 case RTE_FLOW_ACTION_TYPE_IPV6_EXT_PUSH:
    7582                 :            :                         MLX5_ASSERT(recom_off == UINT16_MAX);
    7583                 :            :                         recom_type = MLX5DR_ACTION_TYP_PUSH_IPV6_ROUTE_EXT;
    7584                 :          0 :                         recom_off = curr_off++;
    7585                 :          0 :                         break;
    7586                 :          0 :                 case RTE_FLOW_ACTION_TYPE_IPV6_EXT_REMOVE:
    7587                 :            :                         MLX5_ASSERT(recom_off == UINT16_MAX);
    7588                 :            :                         recom_type = MLX5DR_ACTION_TYP_POP_IPV6_ROUTE_EXT;
    7589                 :          0 :                         recom_off = curr_off++;
    7590                 :          0 :                         break;
    7591                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
    7592                 :          0 :                         raw_encap_data = at->actions[i].conf;
    7593                 :          0 :                         data_size = raw_encap_data->size;
    7594         [ #  # ]:          0 :                         if (reformat_off != UINT16_MAX) {
    7595                 :            :                                 reformat_act_type = data_size < MLX5_ENCAPSULATION_DECISION_SIZE ?
    7596         [ #  # ]:          0 :                                         MLX5DR_ACTION_TYP_REFORMAT_TNL_L3_TO_L2 :
    7597                 :            :                                         MLX5DR_ACTION_TYP_REFORMAT_L2_TO_TNL_L3;
    7598                 :            :                         } else {
    7599                 :          0 :                                 reformat_off = curr_off++;
    7600                 :            :                                 reformat_act_type = MLX5DR_ACTION_TYP_REFORMAT_L2_TO_TNL_L2;
    7601                 :            :                         }
    7602                 :            :                         break;
    7603                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
    7604                 :          0 :                         reformat_off = curr_off++;
    7605                 :            :                         reformat_act_type = MLX5DR_ACTION_TYP_REFORMAT_TNL_L2_TO_L2;
    7606                 :          0 :                         break;
    7607                 :          0 :                 case RTE_FLOW_ACTION_TYPE_MODIFY_FIELD:
    7608         [ #  # ]:          0 :                         if (mhdr_off == UINT16_MAX) {
    7609                 :          0 :                                 mhdr_off = curr_off++;
    7610                 :          0 :                                 type = mlx5_hw_dr_action_types[at->actions[i].type];
    7611                 :          0 :                                 action_types[mhdr_off] = type;
    7612                 :            :                         }
    7613                 :            :                         break;
    7614                 :          0 :                 case RTE_FLOW_ACTION_TYPE_METER:
    7615                 :          0 :                         at->dr_off[i] = curr_off;
    7616                 :          0 :                         action_types[curr_off++] = MLX5DR_ACTION_TYP_ASO_METER;
    7617         [ #  # ]:          0 :                         if (curr_off >= MLX5_HW_MAX_ACTS)
    7618                 :          0 :                                 goto err_actions_num;
    7619                 :          0 :                         action_types[curr_off++] = MLX5DR_ACTION_TYP_TBL;
    7620                 :          0 :                         break;
    7621                 :          0 :                 case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
    7622                 :          0 :                         type = mlx5_hw_dr_action_types[at->actions[i].type];
    7623                 :          0 :                         at->dr_off[i] = curr_off;
    7624                 :          0 :                         action_types[curr_off++] = type;
    7625                 :          0 :                         i += is_of_vlan_pcp_present(at->actions + i) ?
    7626         [ #  # ]:          0 :                                 MLX5_HW_VLAN_PUSH_PCP_IDX :
    7627                 :            :                                 MLX5_HW_VLAN_PUSH_VID_IDX;
    7628                 :          0 :                         break;
    7629                 :          0 :                 case RTE_FLOW_ACTION_TYPE_METER_MARK:
    7630                 :          0 :                         at->dr_off[i] = curr_off;
    7631                 :          0 :                         action_types[curr_off++] = MLX5DR_ACTION_TYP_ASO_METER;
    7632         [ #  # ]:          0 :                         if (curr_off >= MLX5_HW_MAX_ACTS)
    7633                 :          0 :                                 goto err_actions_num;
    7634                 :            :                         break;
    7635                 :          0 :                 case RTE_FLOW_ACTION_TYPE_AGE:
    7636                 :            :                 case RTE_FLOW_ACTION_TYPE_COUNT:
    7637                 :            :                         /*
    7638                 :            :                          * Both AGE and COUNT action need counter, the first
    7639                 :            :                          * one fills the action_types array, and the second only
    7640                 :            :                          * saves the offset.
    7641                 :            :                          */
    7642         [ #  # ]:          0 :                         if (cnt_off == UINT16_MAX) {
    7643                 :          0 :                                 cnt_off = curr_off++;
    7644                 :          0 :                                 action_types[cnt_off] = MLX5DR_ACTION_TYP_CTR;
    7645                 :            :                         }
    7646                 :          0 :                         at->dr_off[i] = cnt_off;
    7647                 :          0 :                         break;
    7648                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_DEFAULT_MISS:
    7649                 :          0 :                         at->dr_off[i] = curr_off;
    7650                 :          0 :                         action_types[curr_off++] = MLX5DR_ACTION_TYP_MISS;
    7651                 :          0 :                         break;
    7652                 :          0 :                 case RTE_FLOW_ACTION_TYPE_JUMP_TO_TABLE_INDEX:
    7653                 :          0 :                         *tmpl_flags |= MLX5DR_ACTION_TEMPLATE_FLAG_RELAXED_ORDER;
    7654                 :          0 :                         at->dr_off[i] = curr_off;
    7655                 :          0 :                         action_types[curr_off++] = MLX5DR_ACTION_TYP_JUMP_TO_MATCHER;
    7656                 :          0 :                         break;
    7657                 :          0 :                 default:
    7658                 :          0 :                         type = mlx5_hw_dr_action_types[at->actions[i].type];
    7659                 :          0 :                         at->dr_off[i] = curr_off;
    7660                 :          0 :                         action_types[curr_off++] = type;
    7661                 :          0 :                         break;
    7662                 :            :                 }
    7663                 :            :         }
    7664         [ #  # ]:          0 :         if (curr_off >= MLX5_HW_MAX_ACTS)
    7665                 :          0 :                 goto err_actions_num;
    7666         [ #  # ]:          0 :         if (mhdr_off != UINT16_MAX)
    7667                 :          0 :                 at->mhdr_off = mhdr_off;
    7668         [ #  # ]:          0 :         if (reformat_off != UINT16_MAX) {
    7669                 :          0 :                 at->reformat_off = reformat_off;
    7670                 :          0 :                 action_types[reformat_off] = reformat_act_type;
    7671                 :            :         }
    7672         [ #  # ]:          0 :         if (recom_off != UINT16_MAX) {
    7673                 :          0 :                 at->recom_off = recom_off;
    7674                 :          0 :                 action_types[recom_off] = recom_type;
    7675                 :            :         }
    7676                 :          0 :         at->dr_actions_num = curr_off;
    7677                 :            : 
    7678                 :            :         /* Create srh flex parser for remove anchor. */
    7679         [ #  # ]:          0 :         if ((recom_type == MLX5DR_ACTION_TYP_POP_IPV6_ROUTE_EXT ||
    7680         [ #  # ]:          0 :              recom_type == MLX5DR_ACTION_TYP_PUSH_IPV6_ROUTE_EXT) &&
    7681                 :          0 :             (ret = mlx5_alloc_srh_flex_parser(dev))) {
    7682                 :          0 :                 DRV_LOG(ERR, "Failed to create srv6 flex parser");
    7683                 :          0 :                 return ret;
    7684                 :            :         }
    7685                 :            :         return 0;
    7686                 :          0 : err_actions_num:
    7687                 :          0 :         DRV_LOG(ERR, "Number of HW actions (%u) exceeded maximum (%u) allowed in template",
    7688                 :            :                 curr_off, MLX5_HW_MAX_ACTS);
    7689                 :          0 :         return -EINVAL;
    7690                 :            : }
    7691                 :            : 
    7692                 :            : static void
    7693                 :          0 : flow_hw_set_vlan_vid(struct rte_eth_dev *dev,
    7694                 :            :                      struct rte_flow_action *ra,
    7695                 :            :                      struct rte_flow_action *rm,
    7696                 :            :                      struct rte_flow_action_modify_field *spec,
    7697                 :            :                      struct rte_flow_action_modify_field *mask,
    7698                 :            :                      int set_vlan_vid_ix)
    7699                 :            : {
    7700                 :            :         struct rte_flow_error error;
    7701         [ #  # ]:          0 :         const bool masked = rm[set_vlan_vid_ix].conf &&
    7702                 :            :                 (((const struct rte_flow_action_of_set_vlan_vid *)
    7703         [ #  # ]:          0 :                         rm[set_vlan_vid_ix].conf)->vlan_vid != 0);
    7704                 :          0 :         const struct rte_flow_action_of_set_vlan_vid *conf =
    7705                 :          0 :                 ra[set_vlan_vid_ix].conf;
    7706                 :          0 :         int width = mlx5_flow_item_field_width(dev, RTE_FLOW_FIELD_VLAN_ID, 0,
    7707                 :            :                                                NULL, &error);
    7708                 :          0 :         *spec = (typeof(*spec)) {
    7709                 :            :                 .operation = RTE_FLOW_MODIFY_SET,
    7710                 :            :                 .dst = {
    7711                 :            :                         .field = RTE_FLOW_FIELD_VLAN_ID,
    7712                 :            :                         .level = 0, .offset = 0,
    7713                 :            :                 },
    7714                 :            :                 .src = {
    7715                 :            :                         .field = RTE_FLOW_FIELD_VALUE,
    7716                 :            :                 },
    7717                 :            :                 .width = width,
    7718                 :            :         };
    7719                 :          0 :         *mask = (typeof(*mask)) {
    7720                 :            :                 .operation = RTE_FLOW_MODIFY_SET,
    7721                 :            :                 .dst = {
    7722                 :            :                         .field = RTE_FLOW_FIELD_VLAN_ID,
    7723                 :            :                         .level = 0xff, .offset = 0xffffffff,
    7724                 :            :                 },
    7725                 :            :                 .src = {
    7726                 :            :                         .field = RTE_FLOW_FIELD_VALUE,
    7727                 :            :                 },
    7728                 :            :                 .width = 0xffffffff,
    7729                 :            :         };
    7730         [ #  # ]:          0 :         if (masked) {
    7731                 :          0 :                 uint32_t mask_val = 0xffffffff;
    7732                 :            : 
    7733         [ #  # ]:          0 :                 rte_memcpy(spec->src.value, &conf->vlan_vid, sizeof(conf->vlan_vid));
    7734         [ #  # ]:          0 :                 rte_memcpy(mask->src.value, &mask_val, sizeof(mask_val));
    7735                 :            :         }
    7736                 :          0 :         ra[set_vlan_vid_ix].type = RTE_FLOW_ACTION_TYPE_MODIFY_FIELD;
    7737                 :          0 :         ra[set_vlan_vid_ix].conf = spec;
    7738                 :          0 :         rm[set_vlan_vid_ix].type = RTE_FLOW_ACTION_TYPE_MODIFY_FIELD;
    7739                 :          0 :         rm[set_vlan_vid_ix].conf = mask;
    7740                 :          0 : }
    7741                 :            : 
    7742                 :            : static __rte_always_inline int
    7743                 :            : flow_hw_set_vlan_vid_construct(struct rte_eth_dev *dev,
    7744                 :            :                                struct mlx5_modification_cmd *mhdr_cmd,
    7745                 :            :                                struct mlx5_action_construct_data *act_data,
    7746                 :            :                                const struct mlx5_hw_actions *hw_acts,
    7747                 :            :                                const struct rte_flow_action *action)
    7748                 :            : {
    7749                 :            :         struct rte_flow_error error;
    7750                 :          0 :         rte_be16_t vid = ((const struct rte_flow_action_of_set_vlan_vid *)
    7751                 :          0 :                            action->conf)->vlan_vid;
    7752                 :          0 :         int width = mlx5_flow_item_field_width(dev, RTE_FLOW_FIELD_VLAN_ID, 0,
    7753                 :            :                                                NULL, &error);
    7754   [ #  #  #  #  :          0 :         struct rte_flow_action_modify_field conf = {
          #  #  #  #  #  
                      # ]
    7755                 :            :                 .operation = RTE_FLOW_MODIFY_SET,
    7756                 :            :                 .dst = {
    7757                 :            :                         .field = RTE_FLOW_FIELD_VLAN_ID,
    7758                 :            :                         .level = 0, .offset = 0,
    7759                 :            :                 },
    7760                 :            :                 .src = {
    7761                 :            :                         .field = RTE_FLOW_FIELD_VALUE,
    7762                 :            :                 },
    7763                 :            :                 .width = width,
    7764                 :            :         };
    7765                 :            :         struct rte_flow_action modify_action = {
    7766                 :            :                 .type = RTE_FLOW_ACTION_TYPE_MODIFY_FIELD,
    7767                 :            :                 .conf = &conf
    7768                 :            :         };
    7769                 :            : 
    7770                 :            :         rte_memcpy(conf.src.value, &vid, sizeof(vid));
    7771                 :            :         return flow_hw_modify_field_construct(mhdr_cmd, act_data, hw_acts, &modify_action);
    7772                 :            : }
    7773                 :            : 
    7774                 :            : static int
    7775                 :          0 : flow_hw_flex_item_acquire(struct rte_eth_dev *dev,
    7776                 :            :                           struct rte_flow_item_flex_handle *handle,
    7777                 :            :                           uint8_t *flex_item)
    7778                 :            : {
    7779                 :          0 :         int index = mlx5_flex_acquire_index(dev, handle, false);
    7780                 :            : 
    7781                 :            :         MLX5_ASSERT(index >= 0 && index < (int)(sizeof(uint32_t) * CHAR_BIT));
    7782         [ #  # ]:          0 :         if (index < 0)
    7783                 :            :                 return -1;
    7784         [ #  # ]:          0 :         if (!(*flex_item & RTE_BIT32(index))) {
    7785                 :            :                 /* Don't count same flex item again. */
    7786                 :          0 :                 if (mlx5_flex_acquire_index(dev, handle, true) != index)
    7787                 :            :                         MLX5_ASSERT(false);
    7788                 :          0 :                 *flex_item |= (uint8_t)RTE_BIT32(index);
    7789                 :            :         }
    7790                 :            :         return 0;
    7791                 :            : }
    7792                 :            : 
    7793                 :            : static void
    7794                 :          0 : flow_hw_flex_item_release(struct rte_eth_dev *dev, uint8_t *flex_item)
    7795                 :            : {
    7796         [ #  # ]:          0 :         while (*flex_item) {
    7797                 :          0 :                 int index = rte_bsf32(*flex_item);
    7798                 :            : 
    7799                 :          0 :                 mlx5_flex_release_index(dev, index);
    7800                 :          0 :                 *flex_item &= ~(uint8_t)RTE_BIT32(index);
    7801                 :            :         }
    7802                 :          0 : }
    7803                 :            : static __rte_always_inline void
    7804                 :            : flow_hw_actions_template_replace_container(const
    7805                 :            :                                            struct rte_flow_action *actions,
    7806                 :            :                                            const
    7807                 :            :                                            struct rte_flow_action *masks,
    7808                 :            :                                            struct rte_flow_action *new_actions,
    7809                 :            :                                            struct rte_flow_action *new_masks,
    7810                 :            :                                            struct rte_flow_action **ra,
    7811                 :            :                                            struct rte_flow_action **rm,
    7812                 :            :                                            uint32_t act_num)
    7813                 :            : {
    7814                 :          0 :         memcpy(new_actions, actions, sizeof(actions[0]) * act_num);
    7815                 :            :         memcpy(new_masks, masks, sizeof(masks[0]) * act_num);
    7816                 :            :         *ra = (void *)(uintptr_t)new_actions;
    7817                 :            :         *rm = (void *)(uintptr_t)new_masks;
    7818                 :          0 : }
    7819                 :            : 
    7820                 :            : /* Action template copies these actions in rte_flow_conv() */
    7821                 :            : 
    7822                 :            : static const struct rte_flow_action rx_meta_copy_action =  {
    7823                 :            :         .type = RTE_FLOW_ACTION_TYPE_MODIFY_FIELD,
    7824                 :            :         .conf = &(struct rte_flow_action_modify_field){
    7825                 :            :                 .operation = RTE_FLOW_MODIFY_SET,
    7826                 :            :                 .dst = {
    7827                 :            :                         .field = (enum rte_flow_field_id)
    7828                 :            :                                 MLX5_RTE_FLOW_FIELD_META_REG,
    7829                 :            :                         .tag_index = REG_B,
    7830                 :            :                 },
    7831                 :            :                 .src = {
    7832                 :            :                         .field = (enum rte_flow_field_id)
    7833                 :            :                                 MLX5_RTE_FLOW_FIELD_META_REG,
    7834                 :            :                         .tag_index = REG_C_1,
    7835                 :            :                 },
    7836                 :            :                 .width = 32,
    7837                 :            :         }
    7838                 :            : };
    7839                 :            : 
    7840                 :            : static const struct rte_flow_action rx_meta_copy_mask = {
    7841                 :            :         .type = RTE_FLOW_ACTION_TYPE_MODIFY_FIELD,
    7842                 :            :         .conf = &(struct rte_flow_action_modify_field){
    7843                 :            :                 .operation = RTE_FLOW_MODIFY_SET,
    7844                 :            :                 .dst = {
    7845                 :            :                         .field = (enum rte_flow_field_id)
    7846                 :            :                                 MLX5_RTE_FLOW_FIELD_META_REG,
    7847                 :            :                         .level = UINT8_MAX,
    7848                 :            :                         .tag_index = UINT8_MAX,
    7849                 :            :                         .offset = UINT32_MAX,
    7850                 :            :                 },
    7851                 :            :                 .src = {
    7852                 :            :                         .field = (enum rte_flow_field_id)
    7853                 :            :                                 MLX5_RTE_FLOW_FIELD_META_REG,
    7854                 :            :                         .level = UINT8_MAX,
    7855                 :            :                         .tag_index = UINT8_MAX,
    7856                 :            :                         .offset = UINT32_MAX,
    7857                 :            :                 },
    7858                 :            :                 .width = UINT32_MAX,
    7859                 :            :         }
    7860                 :            : };
    7861                 :            : 
    7862                 :            : static const struct rte_flow_action quota_color_inc_action = {
    7863                 :            :         .type = RTE_FLOW_ACTION_TYPE_MODIFY_FIELD,
    7864                 :            :         .conf = &(struct rte_flow_action_modify_field) {
    7865                 :            :                 .operation = RTE_FLOW_MODIFY_ADD,
    7866                 :            :                 .dst = {
    7867                 :            :                         .field = RTE_FLOW_FIELD_METER_COLOR,
    7868                 :            :                         .level = 0, .offset = 0
    7869                 :            :                 },
    7870                 :            :                 .src = {
    7871                 :            :                         .field = RTE_FLOW_FIELD_VALUE,
    7872                 :            :                         .level = 1,
    7873                 :            :                         .offset = 0,
    7874                 :            :                 },
    7875                 :            :                 .width = 2
    7876                 :            :         }
    7877                 :            : };
    7878                 :            : 
    7879                 :            : static const struct rte_flow_action quota_color_inc_mask = {
    7880                 :            :         .type = RTE_FLOW_ACTION_TYPE_MODIFY_FIELD,
    7881                 :            :         .conf = &(struct rte_flow_action_modify_field) {
    7882                 :            :                 .operation = RTE_FLOW_MODIFY_ADD,
    7883                 :            :                 .dst = {
    7884                 :            :                         .field = RTE_FLOW_FIELD_METER_COLOR,
    7885                 :            :                         .level = UINT8_MAX,
    7886                 :            :                         .tag_index = UINT8_MAX,
    7887                 :            :                         .offset = UINT32_MAX,
    7888                 :            :                 },
    7889                 :            :                 .src = {
    7890                 :            :                         .field = RTE_FLOW_FIELD_VALUE,
    7891                 :            :                         .level = 3,
    7892                 :            :                         .offset = 0
    7893                 :            :                 },
    7894                 :            :                 .width = UINT32_MAX
    7895                 :            :         }
    7896                 :            : };
    7897                 :            : 
    7898                 :            : /**
    7899                 :            :  * Create flow action template.
    7900                 :            :  *
    7901                 :            :  * @param[in] dev
    7902                 :            :  *   Pointer to the rte_eth_dev structure.
    7903                 :            :  * @param[in] attr
    7904                 :            :  *   Pointer to the action template attributes.
    7905                 :            :  * @param[in] actions
    7906                 :            :  *   Associated actions (list terminated by the END action).
    7907                 :            :  * @param[in] masks
    7908                 :            :  *   List of actions that marks which of the action's member is constant.
    7909                 :            :  * @param[in] nt_mode
    7910                 :            :  *   Non template mode.
    7911                 :            :  * @param[out] error
    7912                 :            :  *   Pointer to error structure.
    7913                 :            :  *
    7914                 :            :  * @return
    7915                 :            :  *   Action template pointer on success, NULL otherwise and rte_errno is set.
    7916                 :            :  */
    7917                 :            : static struct rte_flow_actions_template *
    7918                 :          0 : __flow_hw_actions_template_create(struct rte_eth_dev *dev,
    7919                 :            :                         const struct rte_flow_actions_template_attr *attr,
    7920                 :            :                         const struct rte_flow_action actions[],
    7921                 :            :                         const struct rte_flow_action masks[],
    7922                 :            :                         bool nt_mode,
    7923                 :            :                         struct rte_flow_error *error)
    7924                 :            : {
    7925                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    7926                 :            :         int len, act_len, mask_len;
    7927                 :            :         int orig_act_len;
    7928                 :            :         unsigned int act_num;
    7929                 :            :         unsigned int i;
    7930                 :            :         struct rte_flow_actions_template *at = NULL;
    7931                 :            :         uint16_t pos;
    7932                 :          0 :         uint64_t action_flags = 0;
    7933                 :            :         struct rte_flow_action tmp_action[MLX5_HW_MAX_ACTS];
    7934                 :            :         struct rte_flow_action tmp_mask[MLX5_HW_MAX_ACTS];
    7935                 :            :         struct rte_flow_action *ra = (void *)(uintptr_t)actions;
    7936                 :            :         struct rte_flow_action *rm = (void *)(uintptr_t)masks;
    7937                 :            :         int set_vlan_vid_ix = -1;
    7938                 :          0 :         struct rte_flow_action_modify_field set_vlan_vid_spec = {0, };
    7939                 :          0 :         struct rte_flow_action_modify_field set_vlan_vid_mask = {0, };
    7940                 :            :         struct rte_flow_action mf_actions[MLX5_HW_MAX_ACTS];
    7941                 :            :         struct rte_flow_action mf_masks[MLX5_HW_MAX_ACTS];
    7942                 :            :         uint32_t expand_mf_num = 0;
    7943                 :          0 :         uint16_t src_off[MLX5_HW_MAX_ACTS] = {0, };
    7944                 :          0 :         enum mlx5dr_action_type action_types[MLX5_HW_MAX_ACTS] = { MLX5DR_ACTION_TYP_LAST };
    7945                 :          0 :         uint32_t tmpl_flags = 0;
    7946                 :            :         int ret;
    7947                 :            : 
    7948   [ #  #  #  # ]:          0 :         if (!nt_mode && mlx5_flow_hw_actions_validate(dev, attr, actions, masks,
    7949                 :            :                                                       &action_flags, error))
    7950                 :            :                 return NULL;
    7951         [ #  # ]:          0 :         for (i = 0; ra[i].type != RTE_FLOW_ACTION_TYPE_END; ++i) {
    7952      [ #  #  # ]:          0 :                 switch (ra[i].type) {
    7953                 :            :                 /* OF_PUSH_VLAN *MUST* come before OF_SET_VLAN_VID */
    7954                 :          0 :                 case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
    7955                 :          0 :                         i += is_of_vlan_pcp_present(ra + i) ?
    7956         [ #  # ]:          0 :                                 MLX5_HW_VLAN_PUSH_PCP_IDX :
    7957                 :            :                                 MLX5_HW_VLAN_PUSH_VID_IDX;
    7958                 :          0 :                         break;
    7959                 :          0 :                 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
    7960                 :          0 :                         set_vlan_vid_ix = i;
    7961                 :          0 :                         break;
    7962                 :            :                 default:
    7963                 :            :                         break;
    7964                 :            :                 }
    7965                 :            :         }
    7966                 :            :         /*
    7967                 :            :          * Count flow actions to allocate required space for storing DR offsets and to check
    7968                 :            :          * if temporary buffer would not be overrun.
    7969                 :            :          */
    7970                 :          0 :         act_num = i + 1;
    7971         [ #  # ]:          0 :         if (act_num >= MLX5_HW_MAX_ACTS) {
    7972                 :          0 :                 rte_flow_error_set(error, EINVAL,
    7973                 :            :                                    RTE_FLOW_ERROR_TYPE_ACTION, NULL, "Too many actions");
    7974                 :          0 :                 return NULL;
    7975                 :            :         }
    7976         [ #  # ]:          0 :         if (set_vlan_vid_ix != -1) {
    7977                 :            :                 /* If temporary action buffer was not used, copy template actions to it */
    7978                 :            :                 if (ra == actions)
    7979                 :            :                         flow_hw_actions_template_replace_container(actions,
    7980                 :            :                                                                    masks,
    7981                 :            :                                                                    tmp_action,
    7982                 :            :                                                                    tmp_mask,
    7983                 :            :                                                                    &ra, &rm,
    7984                 :            :                                                                    act_num);
    7985                 :          0 :                 flow_hw_set_vlan_vid(dev, ra, rm,
    7986                 :            :                                      &set_vlan_vid_spec, &set_vlan_vid_mask,
    7987                 :            :                                      set_vlan_vid_ix);
    7988                 :          0 :                 action_flags |= MLX5_FLOW_ACTION_MODIFY_FIELD;
    7989                 :            :         }
    7990         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_QUOTA) {
    7991                 :          0 :                 mf_actions[expand_mf_num] = quota_color_inc_action;
    7992                 :          0 :                 mf_masks[expand_mf_num] = quota_color_inc_mask;
    7993                 :            :                 expand_mf_num++;
    7994                 :            :         }
    7995         [ #  # ]:          0 :         if (priv->sh->config.dv_xmeta_en == MLX5_XMETA_MODE_META32_HWS &&
    7996                 :          0 :             priv->sh->config.dv_esw_en &&
    7997         [ #  # ]:          0 :             (action_flags & (MLX5_FLOW_ACTION_QUEUE | MLX5_FLOW_ACTION_RSS))) {
    7998                 :            :                 /* Insert META copy */
    7999                 :          0 :                 mf_actions[expand_mf_num] = rx_meta_copy_action;
    8000                 :          0 :                 mf_masks[expand_mf_num] = rx_meta_copy_mask;
    8001                 :          0 :                 expand_mf_num++;
    8002                 :            :         }
    8003         [ #  # ]:          0 :         if (expand_mf_num) {
    8004         [ #  # ]:          0 :                 if (act_num + expand_mf_num > MLX5_HW_MAX_ACTS) {
    8005                 :          0 :                         rte_flow_error_set(error, E2BIG,
    8006                 :            :                                            RTE_FLOW_ERROR_TYPE_ACTION,
    8007                 :            :                                            NULL, "cannot expand: too many actions");
    8008                 :          0 :                         return NULL;
    8009                 :            :                 }
    8010         [ #  # ]:          0 :                 if (ra == actions)
    8011                 :            :                         flow_hw_actions_template_replace_container(actions,
    8012                 :            :                                                                    masks,
    8013                 :            :                                                                    tmp_action,
    8014                 :            :                                                                    tmp_mask,
    8015                 :            :                                                                    &ra, &rm,
    8016                 :            :                                                                    act_num);
    8017                 :            :                 /* Application should make sure only one Q/RSS exist in one rule. */
    8018                 :          0 :                 pos = flow_hw_template_expand_modify_field(ra, rm,
    8019                 :            :                                                            mf_actions,
    8020                 :            :                                                            mf_masks,
    8021                 :            :                                                            action_flags,
    8022                 :            :                                                            act_num,
    8023                 :            :                                                            expand_mf_num);
    8024         [ #  # ]:          0 :                 if (pos == MLX5_HW_EXPAND_MH_FAILED) {
    8025                 :          0 :                         rte_flow_error_set(error, ENOMEM,
    8026                 :            :                                            RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    8027                 :            :                                            NULL, "modify header expansion failed");
    8028                 :          0 :                         return NULL;
    8029                 :            :                 }
    8030                 :            :                 act_num += expand_mf_num;
    8031         [ #  # ]:          0 :                 for (i = pos + expand_mf_num; i < act_num; i++)
    8032                 :          0 :                         src_off[i] += expand_mf_num;
    8033                 :          0 :                 action_flags |= MLX5_FLOW_ACTION_MODIFY_FIELD;
    8034                 :            :         }
    8035                 :          0 :         act_len = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, NULL, 0, ra, error);
    8036         [ #  # ]:          0 :         if (act_len <= 0)
    8037                 :            :                 return NULL;
    8038                 :          0 :         len = RTE_ALIGN(act_len, 16);
    8039                 :          0 :         mask_len = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, NULL, 0, rm, error);
    8040         [ #  # ]:          0 :         if (mask_len <= 0)
    8041                 :            :                 return NULL;
    8042                 :          0 :         len += RTE_ALIGN(mask_len, 16);
    8043                 :          0 :         len += RTE_ALIGN(act_num * sizeof(*at->dr_off), 16);
    8044                 :          0 :         len += RTE_ALIGN(act_num * sizeof(*at->src_off), 16);
    8045                 :          0 :         orig_act_len = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, NULL, 0, actions, error);
    8046         [ #  # ]:          0 :         if (orig_act_len <= 0)
    8047                 :            :                 return NULL;
    8048                 :          0 :         len += RTE_ALIGN(orig_act_len, 16);
    8049                 :          0 :         at = mlx5_malloc(MLX5_MEM_ZERO, len + sizeof(*at),
    8050                 :          0 :                          RTE_CACHE_LINE_SIZE, rte_socket_id());
    8051         [ #  # ]:          0 :         if (!at) {
    8052                 :          0 :                 rte_flow_error_set(error, ENOMEM,
    8053                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    8054                 :            :                                    NULL,
    8055                 :            :                                    "cannot allocate action template");
    8056                 :          0 :                 return NULL;
    8057                 :            :         }
    8058                 :            :         /* Actions part is in the first part. */
    8059                 :          0 :         at->attr = *attr;
    8060                 :          0 :         at->actions = (struct rte_flow_action *)(at + 1);
    8061                 :          0 :         act_len = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, at->actions,
    8062                 :            :                                 len, ra, error);
    8063         [ #  # ]:          0 :         if (act_len <= 0)
    8064                 :          0 :                 goto error;
    8065                 :            :         /* Masks part is in the second part. */
    8066                 :          0 :         at->masks = (struct rte_flow_action *)(((uint8_t *)at->actions) + act_len);
    8067                 :          0 :         mask_len = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, at->masks,
    8068                 :          0 :                                  len - act_len, rm, error);
    8069         [ #  # ]:          0 :         if (mask_len <= 0)
    8070                 :          0 :                 goto error;
    8071                 :            :         /* DR actions offsets in the third part. */
    8072                 :          0 :         at->dr_off = (uint16_t *)((uint8_t *)at->masks + mask_len);
    8073                 :          0 :         at->src_off = RTE_PTR_ADD(at->dr_off,
    8074                 :            :                                   RTE_ALIGN(act_num * sizeof(*at->dr_off), 16));
    8075                 :            :         memcpy(at->src_off, src_off, act_num * sizeof(at->src_off[0]));
    8076                 :          0 :         at->orig_actions = RTE_PTR_ADD(at->src_off,
    8077                 :            :                                        RTE_ALIGN(act_num * sizeof(*at->src_off), 16));
    8078                 :          0 :         orig_act_len = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, at->orig_actions, orig_act_len,
    8079                 :            :                                      actions, error);
    8080         [ #  # ]:          0 :         if (orig_act_len <= 0)
    8081                 :          0 :                 goto error;
    8082                 :          0 :         at->actions_num = act_num;
    8083         [ #  # ]:          0 :         for (i = 0; i < at->actions_num; ++i)
    8084                 :          0 :                 at->dr_off[i] = UINT16_MAX;
    8085                 :          0 :         at->reformat_off = UINT16_MAX;
    8086                 :          0 :         at->mhdr_off = UINT16_MAX;
    8087                 :          0 :         at->recom_off = UINT16_MAX;
    8088         [ #  # ]:          0 :         for (i = 0; actions->type != RTE_FLOW_ACTION_TYPE_END;
    8089                 :          0 :              actions++, masks++, i++) {
    8090                 :            :                 const struct rte_flow_action_modify_field *info;
    8091                 :            : 
    8092      [ #  #  # ]:          0 :                 switch (actions->type) {
    8093                 :            :                 /*
    8094                 :            :                  * mlx5 PMD hacks indirect action index directly to the action conf.
    8095                 :            :                  * The rte_flow_conv() function copies the content from conf pointer.
    8096                 :            :                  * Need to restore the indirect action index from action conf here.
    8097                 :            :                  */
    8098                 :          0 :                 case RTE_FLOW_ACTION_TYPE_INDIRECT:
    8099                 :          0 :                         at->actions[i].conf = ra[i].conf;
    8100                 :          0 :                         at->masks[i].conf = rm[i].conf;
    8101                 :          0 :                         break;
    8102                 :          0 :                 case RTE_FLOW_ACTION_TYPE_MODIFY_FIELD:
    8103                 :          0 :                         info = actions->conf;
    8104   [ #  #  #  # ]:          0 :                         if ((info->dst.field == RTE_FLOW_FIELD_FLEX_ITEM &&
    8105                 :          0 :                              flow_hw_flex_item_acquire(dev, info->dst.flex_handle,
    8106                 :          0 :                                                        &at->flex_item)) ||
    8107   [ #  #  #  # ]:          0 :                             (info->src.field == RTE_FLOW_FIELD_FLEX_ITEM &&
    8108                 :          0 :                              flow_hw_flex_item_acquire(dev, info->src.flex_handle,
    8109                 :            :                                                        &at->flex_item)))
    8110                 :          0 :                                 goto error;
    8111                 :            :                         break;
    8112                 :            :                 default:
    8113                 :            :                         break;
    8114                 :            :                 }
    8115                 :            :         }
    8116                 :          0 :         ret = flow_hw_parse_flow_actions_to_dr_actions(dev, at, action_types, &tmpl_flags);
    8117         [ #  # ]:          0 :         if (ret)
    8118                 :          0 :                 goto error;
    8119                 :          0 :         at->action_flags = action_flags;
    8120                 :            :         /* In non template mode there is no need to create the dr template. */
    8121         [ #  # ]:          0 :         if (nt_mode)
    8122                 :            :                 return at;
    8123                 :          0 :         at->tmpl = mlx5dr_action_template_create(action_types, tmpl_flags);
    8124         [ #  # ]:          0 :         if (!at->tmpl) {
    8125                 :          0 :                 DRV_LOG(ERR, "Failed to create DR action template: %d", rte_errno);
    8126                 :          0 :                 goto error;
    8127                 :            :         }
    8128                 :          0 :         rte_atomic_fetch_add_explicit(&at->refcnt, 1, rte_memory_order_relaxed);
    8129         [ #  # ]:          0 :         LIST_INSERT_HEAD(&priv->flow_hw_at, at, next);
    8130                 :          0 :         return at;
    8131                 :          0 : error:
    8132                 :            :         if (at) {
    8133                 :          0 :                 mlx5_free(at);
    8134                 :            :         }
    8135                 :          0 :         rte_flow_error_set(error, rte_errno,
    8136                 :            :                            RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    8137                 :            :                            "Failed to create action template");
    8138                 :          0 :         return NULL;
    8139                 :            : }
    8140                 :            : 
    8141                 :            : /**
    8142                 :            :  * Create flow action template.
    8143                 :            :  *
    8144                 :            :  * @param[in] dev
    8145                 :            :  *   Pointer to the rte_eth_dev structure.
    8146                 :            :  * @param[in] attr
    8147                 :            :  *   Pointer to the action template attributes.
    8148                 :            :  * @param[in] actions
    8149                 :            :  *   Associated actions (list terminated by the END action).
    8150                 :            :  * @param[in] masks
    8151                 :            :  *   List of actions that marks which of the action's member is constant.
    8152                 :            :  * @param[out] error
    8153                 :            :  *   Pointer to error structure.
    8154                 :            :  *
    8155                 :            :  * @return
    8156                 :            :  *   Action template pointer on success, NULL otherwise and rte_errno is set.
    8157                 :            :  */
    8158                 :            : static struct rte_flow_actions_template *
    8159                 :          0 : flow_hw_actions_template_create(struct rte_eth_dev *dev,
    8160                 :            :                         const struct rte_flow_actions_template_attr *attr,
    8161                 :            :                         const struct rte_flow_action actions[],
    8162                 :            :                         const struct rte_flow_action masks[],
    8163                 :            :                         struct rte_flow_error *error)
    8164                 :            : {
    8165                 :          0 :         return __flow_hw_actions_template_create(dev, attr, actions, masks, false, error);
    8166                 :            : }
    8167                 :            : 
    8168                 :            : /**
    8169                 :            :  * Destroy flow action template.
    8170                 :            :  *
    8171                 :            :  * @param[in] dev
    8172                 :            :  *   Pointer to the rte_eth_dev structure.
    8173                 :            :  * @param[in] template
    8174                 :            :  *   Pointer to the action template to be destroyed.
    8175                 :            :  * @param[out] error
    8176                 :            :  *   Pointer to error structure.
    8177                 :            :  *
    8178                 :            :  * @return
    8179                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    8180                 :            :  */
    8181                 :            : static int
    8182                 :          0 : flow_hw_actions_template_destroy(struct rte_eth_dev *dev,
    8183                 :            :                                  struct rte_flow_actions_template *template,
    8184                 :            :                                  struct rte_flow_error *error __rte_unused)
    8185                 :            : {
    8186                 :            :         uint64_t flag = MLX5_FLOW_ACTION_IPV6_ROUTING_REMOVE |
    8187                 :            :                         MLX5_FLOW_ACTION_IPV6_ROUTING_PUSH;
    8188                 :            : 
    8189         [ #  # ]:          0 :         if (rte_atomic_load_explicit(&template->refcnt, rte_memory_order_relaxed) > 1) {
    8190                 :          0 :                 DRV_LOG(WARNING, "Action template %p is still in use.",
    8191                 :            :                         (void *)template);
    8192                 :          0 :                 return rte_flow_error_set(error, EBUSY,
    8193                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    8194                 :            :                                    NULL,
    8195                 :            :                                    "action template is in use");
    8196                 :            :         }
    8197         [ #  # ]:          0 :         if (template->action_flags & flag)
    8198                 :          0 :                 mlx5_free_srh_flex_parser(dev);
    8199         [ #  # ]:          0 :         LIST_REMOVE(template, next);
    8200                 :          0 :         flow_hw_flex_item_release(dev, &template->flex_item);
    8201         [ #  # ]:          0 :         if (template->tmpl)
    8202                 :          0 :                 mlx5dr_action_template_destroy(template->tmpl);
    8203                 :          0 :         mlx5_free(template);
    8204                 :          0 :         return 0;
    8205                 :            : }
    8206                 :            : 
    8207                 :            : static struct rte_flow_item *
    8208                 :          0 : flow_hw_prepend_item(const struct rte_flow_item *items,
    8209                 :            :                      const uint32_t nb_items,
    8210                 :            :                      const struct rte_flow_item *new_item,
    8211                 :            :                      struct rte_flow_error *error)
    8212                 :            : {
    8213                 :            :         struct rte_flow_item *copied_items;
    8214                 :            :         size_t size;
    8215                 :            : 
    8216                 :            :         /* Allocate new array of items. */
    8217                 :          0 :         size = sizeof(*copied_items) * (nb_items + 1);
    8218                 :          0 :         copied_items = mlx5_malloc(MLX5_MEM_ZERO, size, 0, rte_socket_id());
    8219         [ #  # ]:          0 :         if (!copied_items) {
    8220                 :          0 :                 rte_flow_error_set(error, ENOMEM,
    8221                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    8222                 :            :                                    NULL,
    8223                 :            :                                    "cannot allocate item template");
    8224                 :          0 :                 return NULL;
    8225                 :            :         }
    8226                 :            :         /* Put new item at the beginning and copy the rest. */
    8227                 :          0 :         copied_items[0] = *new_item;
    8228         [ #  # ]:          0 :         rte_memcpy(&copied_items[1], items, sizeof(*items) * nb_items);
    8229                 :            :         return copied_items;
    8230                 :            : }
    8231                 :            : 
    8232                 :            : static int
    8233                 :          0 : flow_hw_item_compare_field_validate(enum rte_flow_field_id arg_field,
    8234                 :            :                                     enum rte_flow_field_id base_field,
    8235                 :            :                                     struct rte_flow_error *error)
    8236                 :            : {
    8237      [ #  #  # ]:          0 :         switch (arg_field) {
    8238                 :            :         case RTE_FLOW_FIELD_TAG:
    8239                 :            :         case RTE_FLOW_FIELD_META:
    8240                 :            :         case RTE_FLOW_FIELD_ESP_SEQ_NUM:
    8241                 :            :                 break;
    8242                 :          0 :         case RTE_FLOW_FIELD_RANDOM:
    8243         [ #  # ]:          0 :                 if (base_field == RTE_FLOW_FIELD_VALUE)
    8244                 :            :                         return 0;
    8245                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    8246                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    8247                 :            :                                           NULL,
    8248                 :            :                                           "compare random is supported only with immediate value");
    8249                 :          0 :         default:
    8250                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    8251                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    8252                 :            :                                           NULL,
    8253                 :            :                                           "compare item argument field is not supported");
    8254                 :            :         }
    8255         [ #  # ]:          0 :         switch (base_field) {
    8256                 :            :         case RTE_FLOW_FIELD_TAG:
    8257                 :            :         case RTE_FLOW_FIELD_META:
    8258                 :            :         case RTE_FLOW_FIELD_VALUE:
    8259                 :            :         case RTE_FLOW_FIELD_ESP_SEQ_NUM:
    8260                 :            :                 break;
    8261                 :          0 :         default:
    8262                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    8263                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    8264                 :            :                                           NULL,
    8265                 :            :                                           "compare item base field is not supported");
    8266                 :            :         }
    8267                 :            :         return 0;
    8268                 :            : }
    8269                 :            : 
    8270                 :            : static inline uint32_t
    8271                 :            : flow_hw_item_compare_width_supported(enum rte_flow_field_id field)
    8272                 :            : {
    8273      [ #  #  # ]:          0 :         switch (field) {
    8274                 :            :         case RTE_FLOW_FIELD_TAG:
    8275                 :            :         case RTE_FLOW_FIELD_META:
    8276                 :            :         case RTE_FLOW_FIELD_ESP_SEQ_NUM:
    8277                 :            :                 return 32;
    8278                 :          0 :         case RTE_FLOW_FIELD_RANDOM:
    8279                 :          0 :                 return 16;
    8280                 :            :         default:
    8281                 :            :                 break;
    8282                 :            :         }
    8283                 :          0 :         return 0;
    8284                 :            : }
    8285                 :            : 
    8286                 :            : static int
    8287                 :          0 : flow_hw_validate_item_compare(const struct rte_flow_item *item,
    8288                 :            :                               struct rte_flow_error *error)
    8289                 :            : {
    8290                 :          0 :         const struct rte_flow_item_compare *comp_m = item->mask;
    8291                 :          0 :         const struct rte_flow_item_compare *comp_v = item->spec;
    8292                 :            :         int ret;
    8293                 :            : 
    8294         [ #  # ]:          0 :         if (unlikely(!comp_m))
    8295                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    8296                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    8297                 :            :                                    NULL,
    8298                 :            :                                    "compare item mask is missing");
    8299         [ #  # ]:          0 :         if (comp_m->width != UINT32_MAX)
    8300                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    8301                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    8302                 :            :                                    NULL,
    8303                 :            :                                    "compare item only support full mask");
    8304                 :          0 :         ret = flow_hw_item_compare_field_validate(comp_m->a.field,
    8305                 :          0 :                                                   comp_m->b.field, error);
    8306         [ #  # ]:          0 :         if (ret < 0)
    8307                 :            :                 return ret;
    8308         [ #  # ]:          0 :         if (comp_v) {
    8309                 :            :                 uint32_t width;
    8310                 :            : 
    8311         [ #  # ]:          0 :                 if (comp_v->operation != comp_m->operation ||
    8312         [ #  # ]:          0 :                     comp_v->a.field != comp_m->a.field ||
    8313         [ #  # ]:          0 :                     comp_v->b.field != comp_m->b.field)
    8314                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    8315                 :            :                                            RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    8316                 :            :                                            NULL,
    8317                 :            :                                            "compare item spec/mask not matching");
    8318                 :            :                 width = flow_hw_item_compare_width_supported(comp_v->a.field);
    8319                 :            :                 MLX5_ASSERT(width > 0);
    8320         [ #  # ]:          0 :                 if ((comp_v->width & comp_m->width) != width)
    8321                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    8322                 :            :                                            RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    8323                 :            :                                            NULL,
    8324                 :            :                                            "compare item only support full mask");
    8325                 :            :         }
    8326                 :            :         return 0;
    8327                 :            : }
    8328                 :            : 
    8329                 :            : static inline int
    8330                 :            : mlx5_hw_validate_item_nsh(struct rte_eth_dev *dev,
    8331                 :            :                           const struct rte_flow_item *item,
    8332                 :            :                           struct rte_flow_error *error)
    8333                 :            : {
    8334                 :          0 :         return mlx5_flow_validate_item_nsh(dev, item, error);
    8335                 :            : }
    8336                 :            : 
    8337                 :            : static bool
    8338                 :            : mlx5_hw_flow_tunnel_ip_check(uint64_t last_item, uint64_t *item_flags)
    8339                 :            : {
    8340                 :            :         bool tunnel;
    8341                 :            : 
    8342   [ #  #  #  # ]:          0 :         if (last_item == MLX5_FLOW_LAYER_OUTER_L3_IPV4) {
    8343                 :            :                 tunnel = true;
    8344                 :          0 :                 *item_flags |= MLX5_FLOW_LAYER_IPIP;
    8345                 :          0 :         } else if (last_item == MLX5_FLOW_LAYER_OUTER_L3_IPV6 ||
    8346   [ #  #  #  # ]:          0 :                    last_item == MLX5_FLOW_ITEM_OUTER_IPV6_ROUTING_EXT) {
    8347                 :            :                 tunnel = true;
    8348                 :          0 :                 *item_flags |= MLX5_FLOW_LAYER_IPV6_ENCAP;
    8349                 :            :         } else {
    8350                 :            :                 tunnel = false;
    8351                 :            :         }
    8352                 :            :         return tunnel;
    8353                 :            : }
    8354                 :            : 
    8355                 :            : const struct rte_flow_item_ipv4 hws_nic_ipv4_mask = {
    8356                 :            :         .hdr = {
    8357                 :            :                 .version = 0xf,
    8358                 :            :                 .ihl = 0xf,
    8359                 :            :                 .type_of_service = 0xff,
    8360                 :            :                 .total_length = RTE_BE16(0xffff),
    8361                 :            :                 .packet_id = RTE_BE16(0xffff),
    8362                 :            :                 .fragment_offset = RTE_BE16(0xffff),
    8363                 :            :                 .time_to_live = 0xff,
    8364                 :            :                 .next_proto_id = 0xff,
    8365                 :            :                 .src_addr = RTE_BE32(0xffffffff),
    8366                 :            :                 .dst_addr = RTE_BE32(0xffffffff),
    8367                 :            :         },
    8368                 :            : };
    8369                 :            : 
    8370                 :            : const struct rte_flow_item_ipv6 hws_nic_ipv6_mask = {
    8371                 :            :         .hdr = {
    8372                 :            :                 .vtc_flow = RTE_BE32(0xffffffff),
    8373                 :            :                 .payload_len = RTE_BE16(0xffff),
    8374                 :            :                 .proto = 0xff,
    8375                 :            :                 .hop_limits = 0xff,
    8376                 :            :                 .src_addr = RTE_IPV6_MASK_FULL,
    8377                 :            :                 .dst_addr = RTE_IPV6_MASK_FULL,
    8378                 :            :         },
    8379                 :            :         .has_frag_ext = 1,
    8380                 :            : };
    8381                 :            : 
    8382                 :            : static int
    8383                 :          0 : flow_hw_validate_item_ptype(const struct rte_flow_item *item,
    8384                 :            :                             struct rte_flow_error *error)
    8385                 :            : {
    8386                 :          0 :         const struct rte_flow_item_ptype *ptype = item->mask;
    8387                 :            : 
    8388                 :            :         /* HWS does not allow empty PTYPE mask */
    8389         [ #  # ]:          0 :         if (!ptype)
    8390                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    8391                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    8392                 :            :                                           NULL, "empty ptype mask");
    8393         [ #  # ]:          0 :         if (!(ptype->packet_type &
    8394                 :            :               (RTE_PTYPE_L2_MASK | RTE_PTYPE_L3_MASK | RTE_PTYPE_L4_MASK |
    8395                 :            :                RTE_PTYPE_INNER_L2_MASK | RTE_PTYPE_INNER_L3_MASK |
    8396                 :            :                RTE_PTYPE_INNER_L4_MASK)))
    8397                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    8398                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    8399                 :            :                                           NULL, "ptype mask not supported");
    8400                 :            :         return 0;
    8401                 :            : }
    8402                 :            : 
    8403                 :            : struct mlx5_hw_pattern_validation_ctx {
    8404                 :            :         const struct rte_flow_item *geneve_item;
    8405                 :            :         const struct rte_flow_item *flex_item;
    8406                 :            : };
    8407                 :            : 
    8408                 :            : static int
    8409                 :          0 : flow_hw_pattern_validate(struct rte_eth_dev *dev,
    8410                 :            :                          const struct rte_flow_pattern_template_attr *attr,
    8411                 :            :                          const struct rte_flow_item items[],
    8412                 :            :                          uint64_t *item_flags,
    8413                 :            :                          struct rte_flow_error *error)
    8414                 :            : {
    8415                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    8416                 :            :         const struct rte_flow_item *item;
    8417                 :            :         const struct rte_flow_item *gtp_item = NULL;
    8418                 :            :         const struct rte_flow_item *gre_item = NULL;
    8419                 :          0 :         const struct rte_flow_attr flow_attr = {
    8420                 :          0 :                 .ingress = attr->ingress,
    8421                 :          0 :                 .egress = attr->egress,
    8422                 :          0 :                 .transfer = attr->transfer
    8423                 :            :         };
    8424                 :            :         int ret, tag_idx;
    8425                 :            :         uint32_t tag_bitmap = 0;
    8426                 :            :         uint64_t last_item = 0;
    8427                 :            : 
    8428         [ #  # ]:          0 :         if (!mlx5_hw_ctx_validate(dev, error))
    8429                 :          0 :                 return -rte_errno;
    8430         [ #  # ]:          0 :         if (!attr->ingress && !attr->egress && !attr->transfer)
    8431                 :          0 :                 return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ATTR, NULL,
    8432                 :            :                                           "at least one of the direction attributes"
    8433                 :            :                                           " must be specified");
    8434         [ #  # ]:          0 :         if (priv->sh->config.dv_esw_en) {
    8435                 :            :                 MLX5_ASSERT(priv->master || priv->representor);
    8436         [ #  # ]:          0 :                 if (priv->master) {
    8437         [ #  # ]:          0 :                         if ((attr->ingress && attr->egress) ||
    8438         [ #  # ]:          0 :                             (attr->ingress && attr->transfer) ||
    8439         [ #  # ]:          0 :                             (attr->egress && attr->transfer))
    8440                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    8441                 :            :                                                           RTE_FLOW_ERROR_TYPE_ATTR, NULL,
    8442                 :            :                                                           "only one direction attribute at once"
    8443                 :            :                                                           " can be used on transfer proxy port");
    8444                 :            :                 } else {
    8445         [ #  # ]:          0 :                         if (attr->transfer)
    8446                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    8447                 :            :                                                           RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER, NULL,
    8448                 :            :                                                           "transfer attribute cannot be used with"
    8449                 :            :                                                           " port representors");
    8450         [ #  # ]:          0 :                         if (attr->ingress && attr->egress)
    8451                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    8452                 :            :                                                           RTE_FLOW_ERROR_TYPE_ATTR, NULL,
    8453                 :            :                                                           "ingress and egress direction attributes"
    8454                 :            :                                                           " cannot be used at the same time on"
    8455                 :            :                                                           " port representors");
    8456                 :            :                 }
    8457                 :            :         } else {
    8458         [ #  # ]:          0 :                 if (attr->transfer)
    8459                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    8460                 :            :                                                   RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER, NULL,
    8461                 :            :                                                   "transfer attribute cannot be used when"
    8462                 :            :                                                   " E-Switch is disabled");
    8463                 :            :         }
    8464         [ #  # ]:          0 :         for (item = items; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
    8465                 :          0 :                 bool tunnel = *item_flags & MLX5_FLOW_LAYER_TUNNEL;
    8466                 :            : 
    8467   [ #  #  #  #  :          0 :                 switch ((int)item->type) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
    8468                 :          0 :                 case RTE_FLOW_ITEM_TYPE_PTYPE:
    8469                 :          0 :                         ret = flow_hw_validate_item_ptype(item, error);
    8470         [ #  # ]:          0 :                         if (ret)
    8471                 :          0 :                                 return ret;
    8472                 :            :                         last_item = MLX5_FLOW_ITEM_PTYPE;
    8473                 :            :                         break;
    8474                 :          0 :                 case RTE_FLOW_ITEM_TYPE_TAG:
    8475                 :            :                 {
    8476                 :          0 :                         const struct rte_flow_item_tag *tag =
    8477                 :            :                                 (const struct rte_flow_item_tag *)item->spec;
    8478                 :            : 
    8479         [ #  # ]:          0 :                         if (tag == NULL)
    8480                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    8481                 :            :                                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    8482                 :            :                                                           NULL,
    8483                 :            :                                                           "Tag spec is NULL");
    8484         [ #  # ]:          0 :                         if (tag->index >= MLX5_FLOW_HW_TAGS_MAX &&
    8485                 :            :                             tag->index != RTE_PMD_MLX5_LINEAR_HASH_TAG_INDEX)
    8486                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    8487                 :            :                                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    8488                 :            :                                                           NULL,
    8489                 :            :                                                           "Invalid tag index");
    8490         [ #  # ]:          0 :                         tag_idx = flow_hw_get_reg_id(dev, RTE_FLOW_ITEM_TYPE_TAG, tag->index);
    8491         [ #  # ]:          0 :                         if (tag_idx == REG_NON)
    8492                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    8493                 :            :                                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    8494                 :            :                                                           NULL,
    8495                 :            :                                                           "Unsupported tag index");
    8496         [ #  # ]:          0 :                         if (tag_bitmap & (1 << tag_idx))
    8497                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    8498                 :            :                                                           RTE_FLOW_ERROR_TYPE_ITEM,
    8499                 :            :                                                           NULL,
    8500                 :            :                                                           "Duplicated tag index");
    8501                 :          0 :                         tag_bitmap |= 1 << tag_idx;
    8502                 :            :                         last_item = MLX5_FLOW_ITEM_TAG;
    8503                 :          0 :                         break;
    8504                 :            :                 }
    8505                 :          0 :                 case MLX5_RTE_FLOW_ITEM_TYPE_TAG:
    8506                 :            :                 {
    8507                 :          0 :                         const struct rte_flow_item_tag *tag =
    8508                 :            :                                 (const struct rte_flow_item_tag *)item->spec;
    8509                 :          0 :                         uint16_t regcs = (uint8_t)priv->sh->cdev->config.hca_attr.set_reg_c;
    8510                 :            : 
    8511         [ #  # ]:          0 :                         if (!((1 << (tag->index - REG_C_0)) & regcs))
    8512                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    8513                 :            :                                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    8514                 :            :                                                           NULL,
    8515                 :            :                                                           "Unsupported internal tag index");
    8516         [ #  # ]:          0 :                         if (tag_bitmap & (1 << tag->index))
    8517                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    8518                 :            :                                                           RTE_FLOW_ERROR_TYPE_ITEM,
    8519                 :            :                                                           NULL,
    8520                 :            :                                                           "Duplicated tag index");
    8521                 :          0 :                         tag_bitmap |= 1 << tag->index;
    8522                 :          0 :                         break;
    8523                 :            :                 }
    8524                 :          0 :                 case RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT:
    8525   [ #  #  #  # ]:          0 :                         if (attr->ingress && priv->sh->config.repr_matching)
    8526                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    8527                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    8528                 :            :                                                   "represented port item cannot be used"
    8529                 :            :                                                   " when ingress attribute is set");
    8530         [ #  # ]:          0 :                         if (attr->egress)
    8531                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    8532                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    8533                 :            :                                                   "represented port item cannot be used"
    8534                 :            :                                                   " when egress attribute is set");
    8535                 :            :                         last_item = MLX5_FLOW_ITEM_REPRESENTED_PORT;
    8536                 :            :                         break;
    8537                 :          0 :                 case RTE_FLOW_ITEM_TYPE_META:
    8538                 :            :                         /* ingress + group 0 is not supported */
    8539                 :          0 :                         *item_flags |= MLX5_FLOW_ITEM_METADATA;
    8540                 :          0 :                         break;
    8541                 :            :                 case RTE_FLOW_ITEM_TYPE_METER_COLOR:
    8542                 :            :                 {
    8543                 :            :                         int reg = flow_hw_get_reg_id(dev,
    8544                 :            :                                                      RTE_FLOW_ITEM_TYPE_METER_COLOR,
    8545                 :            :                                                      0);
    8546         [ #  # ]:          0 :                         if (reg == REG_NON)
    8547                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    8548                 :            :                                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    8549                 :            :                                                           NULL,
    8550                 :            :                                                           "Unsupported meter color register");
    8551         [ #  # ]:          0 :                         if (*item_flags &
    8552                 :            :                             (MLX5_FLOW_ITEM_QUOTA | MLX5_FLOW_LAYER_ASO_CT))
    8553                 :          0 :                                 return rte_flow_error_set
    8554                 :            :                                         (error, EINVAL,
    8555                 :            :                                          RTE_FLOW_ERROR_TYPE_ITEM, NULL, "Only one ASO item is supported");
    8556                 :            :                         last_item = MLX5_FLOW_ITEM_METER_COLOR;
    8557                 :            :                         break;
    8558                 :            :                 }
    8559                 :          0 :                 case RTE_FLOW_ITEM_TYPE_AGGR_AFFINITY:
    8560                 :            :                 {
    8561         [ #  # ]:          0 :                         if (!priv->sh->lag_rx_port_affinity_en)
    8562                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    8563                 :            :                                                           RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    8564                 :            :                                                           "Unsupported aggregated affinity with Older FW");
    8565   [ #  #  #  #  :          0 :                         if ((attr->transfer && priv->fdb_def_rule) || attr->egress)
                   #  # ]
    8566                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    8567                 :            :                                                           RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    8568                 :            :                                                           "Aggregated affinity item not supported"
    8569                 :            :                                                           " with egress or transfer"
    8570                 :            :                                                           " attribute");
    8571                 :            :                         last_item = MLX5_FLOW_ITEM_AGGR_AFFINITY;
    8572                 :            :                         break;
    8573                 :            :                 }
    8574                 :          0 :                 case RTE_FLOW_ITEM_TYPE_GENEVE:
    8575                 :            :                         last_item = MLX5_FLOW_LAYER_GENEVE;
    8576                 :          0 :                         break;
    8577                 :          0 :                 case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
    8578                 :            :                 {
    8579                 :            :                         last_item = MLX5_FLOW_LAYER_GENEVE_OPT;
    8580                 :          0 :                         ret = mlx5_flow_geneve_tlv_option_validate(priv, item,
    8581                 :            :                                                                    error);
    8582         [ #  # ]:          0 :                         if (ret < 0)
    8583                 :          0 :                                 return ret;
    8584                 :            :                         break;
    8585                 :            :                 }
    8586                 :          0 :                 case RTE_FLOW_ITEM_TYPE_COMPARE:
    8587                 :            :                 {
    8588                 :            :                         last_item = MLX5_FLOW_ITEM_COMPARE;
    8589                 :          0 :                         ret = flow_hw_validate_item_compare(item, error);
    8590         [ #  # ]:          0 :                         if (ret)
    8591                 :          0 :                                 return ret;
    8592                 :            :                         break;
    8593                 :            :                 }
    8594                 :          0 :                 case RTE_FLOW_ITEM_TYPE_ETH:
    8595                 :          0 :                         ret = mlx5_flow_validate_item_eth(dev, item,
    8596                 :            :                                                           *item_flags,
    8597                 :            :                                                           true, error);
    8598         [ #  # ]:          0 :                         if (ret < 0)
    8599                 :          0 :                                 return ret;
    8600         [ #  # ]:          0 :                         last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L2 :
    8601                 :            :                                     MLX5_FLOW_LAYER_OUTER_L2;
    8602                 :            :                         break;
    8603                 :          0 :                 case RTE_FLOW_ITEM_TYPE_VLAN:
    8604                 :          0 :                         ret = mlx5_flow_dv_validate_item_vlan(item, *item_flags,
    8605                 :            :                                                               dev, error);
    8606         [ #  # ]:          0 :                         if (ret < 0)
    8607                 :          0 :                                 return ret;
    8608         [ #  # ]:          0 :                         last_item = tunnel ? MLX5_FLOW_LAYER_INNER_VLAN :
    8609                 :            :                                     MLX5_FLOW_LAYER_OUTER_VLAN;
    8610                 :            :                         break;
    8611                 :            :                 case RTE_FLOW_ITEM_TYPE_IPV4:
    8612                 :          0 :                         tunnel |= mlx5_hw_flow_tunnel_ip_check(last_item,
    8613                 :            :                                                                item_flags);
    8614                 :          0 :                         ret = mlx5_flow_dv_validate_item_ipv4(dev, item,
    8615                 :            :                                                               *item_flags,
    8616                 :            :                                                               last_item, 0,
    8617                 :            :                                                               &hws_nic_ipv4_mask,
    8618                 :            :                                                               error);
    8619         [ #  # ]:          0 :                         if (ret)
    8620                 :          0 :                                 return ret;
    8621         [ #  # ]:          0 :                         last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV4 :
    8622                 :            :                                     MLX5_FLOW_LAYER_OUTER_L3_IPV4;
    8623                 :            :                         break;
    8624                 :            :                 case RTE_FLOW_ITEM_TYPE_IPV6:
    8625                 :          0 :                         tunnel |= mlx5_hw_flow_tunnel_ip_check(last_item,
    8626                 :            :                                                                item_flags);
    8627                 :          0 :                         ret = mlx5_flow_validate_item_ipv6(dev, item,
    8628                 :            :                                                            *item_flags,
    8629                 :            :                                                            last_item, 0,
    8630                 :            :                                                            &hws_nic_ipv6_mask,
    8631                 :            :                                                            error);
    8632         [ #  # ]:          0 :                         if (ret < 0)
    8633                 :          0 :                                 return ret;
    8634         [ #  # ]:          0 :                         last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV6 :
    8635                 :            :                                     MLX5_FLOW_LAYER_OUTER_L3_IPV6;
    8636                 :            :                         break;
    8637                 :          0 :                 case RTE_FLOW_ITEM_TYPE_UDP:
    8638                 :          0 :                         ret = mlx5_flow_validate_item_udp(dev, item,
    8639                 :            :                                                           *item_flags,
    8640                 :            :                                                           0xff, error);
    8641         [ #  # ]:          0 :                         if (ret)
    8642                 :          0 :                                 return ret;
    8643         [ #  # ]:          0 :                         last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L4_UDP :
    8644                 :            :                                     MLX5_FLOW_LAYER_OUTER_L4_UDP;
    8645                 :            :                         break;
    8646                 :          0 :                 case RTE_FLOW_ITEM_TYPE_TCP:
    8647                 :          0 :                         ret = mlx5_flow_validate_item_tcp
    8648                 :            :                                 (dev, item, *item_flags,
    8649                 :            :                                  0xff, &nic_tcp_mask, error);
    8650         [ #  # ]:          0 :                         if (ret < 0)
    8651                 :          0 :                                 return ret;
    8652         [ #  # ]:          0 :                         last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L4_TCP :
    8653                 :            :                                     MLX5_FLOW_LAYER_OUTER_L4_TCP;
    8654                 :            :                         break;
    8655                 :          0 :                 case RTE_FLOW_ITEM_TYPE_GTP:
    8656                 :            :                         gtp_item = item;
    8657                 :          0 :                         ret = mlx5_flow_dv_validate_item_gtp(dev, gtp_item,
    8658                 :            :                                                              *item_flags, error);
    8659         [ #  # ]:          0 :                         if (ret < 0)
    8660                 :          0 :                                 return ret;
    8661                 :            :                         last_item = MLX5_FLOW_LAYER_GTP;
    8662                 :            :                         break;
    8663                 :          0 :                 case RTE_FLOW_ITEM_TYPE_GTP_PSC:
    8664                 :          0 :                         ret = mlx5_flow_dv_validate_item_gtp_psc(dev, item,
    8665                 :            :                                                                  last_item,
    8666                 :            :                                                                  gtp_item,
    8667                 :            :                                                                  false, error);
    8668         [ #  # ]:          0 :                         if (ret < 0)
    8669                 :          0 :                                 return ret;
    8670                 :            :                         last_item = MLX5_FLOW_LAYER_GTP_PSC;
    8671                 :            :                         break;
    8672                 :          0 :                 case RTE_FLOW_ITEM_TYPE_VXLAN:
    8673                 :          0 :                         ret = mlx5_flow_validate_item_vxlan(dev, 0, item,
    8674                 :            :                                                             *item_flags,
    8675                 :            :                                                             false, error);
    8676         [ #  # ]:          0 :                         if (ret < 0)
    8677                 :          0 :                                 return ret;
    8678                 :            :                         last_item = MLX5_FLOW_LAYER_VXLAN;
    8679                 :            :                         break;
    8680                 :          0 :                 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
    8681                 :          0 :                         ret = mlx5_flow_validate_item_vxlan_gpe(item,
    8682                 :            :                                                                 *item_flags,
    8683                 :            :                                                                 dev, error);
    8684         [ #  # ]:          0 :                         if (ret < 0)
    8685                 :          0 :                                 return ret;
    8686                 :            :                         last_item = MLX5_FLOW_LAYER_VXLAN_GPE;
    8687                 :            :                         break;
    8688                 :          0 :                 case RTE_FLOW_ITEM_TYPE_MPLS:
    8689                 :          0 :                         ret = mlx5_flow_validate_item_mpls(dev, item,
    8690                 :            :                                                            *item_flags,
    8691                 :            :                                                            last_item, error);
    8692         [ #  # ]:          0 :                         if (ret < 0)
    8693                 :          0 :                                 return ret;
    8694                 :            :                         last_item = MLX5_FLOW_LAYER_MPLS;
    8695                 :            :                         break;
    8696                 :          0 :                 case MLX5_RTE_FLOW_ITEM_TYPE_SQ:
    8697                 :            :                 case RTE_FLOW_ITEM_TYPE_TX_QUEUE:
    8698                 :            :                         last_item = MLX5_FLOW_ITEM_SQ;
    8699                 :          0 :                         break;
    8700                 :          0 :                 case RTE_FLOW_ITEM_TYPE_GRE:
    8701                 :          0 :                         ret = mlx5_flow_validate_item_gre(dev, item,
    8702                 :            :                                                           *item_flags,
    8703                 :            :                                                           0xff, error);
    8704         [ #  # ]:          0 :                         if (ret < 0)
    8705                 :          0 :                                 return ret;
    8706                 :            :                         gre_item = item;
    8707                 :            :                         last_item = MLX5_FLOW_LAYER_GRE;
    8708                 :            :                         break;
    8709                 :          0 :                 case RTE_FLOW_ITEM_TYPE_GRE_KEY:
    8710         [ #  # ]:          0 :                         if (!(*item_flags & MLX5_FLOW_LAYER_GRE))
    8711                 :          0 :                                 return rte_flow_error_set
    8712                 :            :                                         (error, EINVAL,
    8713                 :            :                                          RTE_FLOW_ERROR_TYPE_ITEM, item, "GRE item is missing");
    8714                 :          0 :                         ret = mlx5_flow_validate_item_gre_key
    8715                 :            :                                 (dev, item, *item_flags, gre_item, error);
    8716         [ #  # ]:          0 :                         if (ret < 0)
    8717                 :          0 :                                 return ret;
    8718                 :            :                         last_item = MLX5_FLOW_LAYER_GRE_KEY;
    8719                 :            :                         break;
    8720                 :          0 :                 case RTE_FLOW_ITEM_TYPE_GRE_OPTION:
    8721         [ #  # ]:          0 :                         if (!(*item_flags & MLX5_FLOW_LAYER_GRE))
    8722                 :          0 :                                 return rte_flow_error_set
    8723                 :            :                                         (error, EINVAL,
    8724                 :            :                                          RTE_FLOW_ERROR_TYPE_ITEM, item, "GRE item is missing");
    8725                 :          0 :                         ret = mlx5_flow_validate_item_gre_option(dev, item,
    8726                 :            :                                                                  *item_flags,
    8727                 :            :                                                                  &flow_attr,
    8728                 :            :                                                                  gre_item,
    8729                 :            :                                                                  error);
    8730         [ #  # ]:          0 :                         if (ret < 0)
    8731                 :          0 :                                 return ret;
    8732                 :            :                         last_item = MLX5_FLOW_LAYER_GRE;
    8733                 :            :                         break;
    8734                 :          0 :                 case RTE_FLOW_ITEM_TYPE_NVGRE:
    8735                 :          0 :                         ret = mlx5_flow_validate_item_nvgre(dev, item,
    8736                 :            :                                                             *item_flags, 0xff,
    8737                 :            :                                                             error);
    8738         [ #  # ]:          0 :                         if (ret)
    8739                 :          0 :                                 return ret;
    8740                 :            :                         last_item = MLX5_FLOW_LAYER_NVGRE;
    8741                 :            :                         break;
    8742                 :          0 :                 case RTE_FLOW_ITEM_TYPE_ICMP:
    8743                 :          0 :                         ret = mlx5_flow_validate_item_icmp(dev, item,
    8744                 :            :                                                            *item_flags, 0xff,
    8745                 :            :                                                            error);
    8746         [ #  # ]:          0 :                         if (ret < 0)
    8747                 :          0 :                                 return ret;
    8748                 :            :                         last_item = MLX5_FLOW_LAYER_ICMP;
    8749                 :            :                         break;
    8750                 :          0 :                 case RTE_FLOW_ITEM_TYPE_ICMP6:
    8751                 :          0 :                         ret = mlx5_flow_validate_item_icmp6(dev, item,
    8752                 :            :                                                             *item_flags, 0xff,
    8753                 :            :                                                             error);
    8754         [ #  # ]:          0 :                         if (ret < 0)
    8755                 :          0 :                                 return ret;
    8756                 :            :                         last_item = MLX5_FLOW_LAYER_ICMP6;
    8757                 :            :                         break;
    8758                 :          0 :                 case RTE_FLOW_ITEM_TYPE_ICMP6_ECHO_REQUEST:
    8759                 :            :                 case RTE_FLOW_ITEM_TYPE_ICMP6_ECHO_REPLY:
    8760                 :          0 :                         ret = mlx5_flow_validate_item_icmp6_echo(dev, item,
    8761                 :            :                                                                  *item_flags,
    8762                 :            :                                                                  0xff, error);
    8763         [ #  # ]:          0 :                         if (ret < 0)
    8764                 :          0 :                                 return ret;
    8765                 :            :                         last_item = MLX5_FLOW_LAYER_ICMP6;
    8766                 :            :                         break;
    8767                 :          0 :                 case RTE_FLOW_ITEM_TYPE_CONNTRACK:
    8768         [ #  # ]:          0 :                         if (*item_flags &
    8769                 :            :                             (MLX5_FLOW_ITEM_QUOTA | MLX5_FLOW_LAYER_ASO_CT))
    8770                 :          0 :                                 return rte_flow_error_set
    8771                 :            :                                         (error, EINVAL,
    8772                 :            :                                          RTE_FLOW_ERROR_TYPE_ITEM, NULL, "Only one ASO item is supported");
    8773                 :          0 :                         ret = mlx5_flow_dv_validate_item_aso_ct(dev, item,
    8774                 :            :                                                                 item_flags,
    8775                 :            :                                                                 error);
    8776         [ #  # ]:          0 :                         if (ret < 0)
    8777                 :          0 :                                 return ret;
    8778                 :            :                         break;
    8779                 :          0 :                 case RTE_FLOW_ITEM_TYPE_QUOTA:
    8780         [ #  # ]:          0 :                         if (*item_flags &
    8781                 :            :                             (MLX5_FLOW_ITEM_METER_COLOR |
    8782                 :            :                              MLX5_FLOW_LAYER_ASO_CT))
    8783                 :          0 :                                 return rte_flow_error_set
    8784                 :            :                                         (error, EINVAL,
    8785                 :            :                                          RTE_FLOW_ERROR_TYPE_ITEM, NULL, "Only one ASO item is supported");
    8786                 :            :                         last_item = MLX5_FLOW_ITEM_QUOTA;
    8787                 :            :                         break;
    8788                 :          0 :                 case RTE_FLOW_ITEM_TYPE_ESP:
    8789                 :          0 :                         ret = mlx5_flow_os_validate_item_esp(dev, item,
    8790                 :            :                                                              *item_flags, 0xff,
    8791                 :            :                                                              error);
    8792         [ #  # ]:          0 :                         if (ret < 0)
    8793                 :          0 :                                 return ret;
    8794                 :            :                         last_item = MLX5_FLOW_ITEM_ESP;
    8795                 :            :                         break;
    8796                 :          0 :                 case RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT:
    8797                 :            :                         last_item = tunnel ?
    8798         [ #  # ]:          0 :                                     MLX5_FLOW_ITEM_INNER_IPV6_ROUTING_EXT :
    8799                 :            :                                     MLX5_FLOW_ITEM_OUTER_IPV6_ROUTING_EXT;
    8800                 :            :                         break;
    8801                 :          0 :                 case RTE_FLOW_ITEM_TYPE_FLEX:
    8802                 :            :                         /* match mlx5dr_definer_conv_items_to_hl() */
    8803                 :            :                         last_item = tunnel ?
    8804         [ #  # ]:          0 :                                     MLX5_FLOW_ITEM_INNER_FLEX :
    8805                 :            :                                     MLX5_FLOW_ITEM_OUTER_FLEX;
    8806                 :            :                         break;
    8807                 :          0 :                 case RTE_FLOW_ITEM_TYPE_RANDOM:
    8808                 :            :                         last_item = MLX5_FLOW_ITEM_RANDOM;
    8809                 :          0 :                         break;
    8810                 :          0 :                 case RTE_FLOW_ITEM_TYPE_NSH:
    8811                 :            :                         last_item = MLX5_FLOW_ITEM_NSH;
    8812                 :            :                         ret = mlx5_hw_validate_item_nsh(dev, item, error);
    8813         [ #  # ]:          0 :                         if (ret < 0)
    8814                 :          0 :                                 return ret;
    8815                 :            :                         break;
    8816                 :            :                 case RTE_FLOW_ITEM_TYPE_INTEGRITY:
    8817                 :            :                         /*
    8818                 :            :                          * Integrity flow item validation require access to
    8819                 :            :                          * both item mask and spec.
    8820                 :            :                          * Current HWS model allows item mask in pattern
    8821                 :            :                          * template and item spec in flow rule.
    8822                 :            :                          */
    8823                 :            :                         break;
    8824                 :            :                 case RTE_FLOW_ITEM_TYPE_IB_BTH:
    8825                 :            :                 case RTE_FLOW_ITEM_TYPE_VOID:
    8826                 :            :                 case RTE_FLOW_ITEM_TYPE_END:
    8827                 :            :                         break;
    8828                 :          0 :                 default:
    8829                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    8830                 :            :                                                   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    8831                 :            :                                                   NULL,
    8832                 :            :                                                   "Unsupported item type");
    8833                 :            :                 }
    8834                 :          0 :                 *item_flags |= last_item;
    8835                 :            :         }
    8836                 :          0 :         return 1 + RTE_PTR_DIFF(item, items) / sizeof(item[0]);
    8837                 :            : }
    8838                 :            : 
    8839                 :            : /*
    8840                 :            :  * Verify that the tested flow patterns fits STE size limit in HWS group.
    8841                 :            :  *
    8842                 :            :  *
    8843                 :            :  * Return values:
    8844                 :            :  * 0       : Tested patterns fit STE size limit
    8845                 :            :  * -EINVAL : Invalid parameters detected
    8846                 :            :  * -E2BIG  : Tested patterns exceed STE size limit
    8847                 :            :  */
    8848                 :            : static int
    8849                 :          0 : pattern_template_validate(struct rte_eth_dev *dev,
    8850                 :            :                           struct rte_flow_pattern_template *pt[],
    8851                 :            :                           uint32_t pt_num,
    8852                 :            :                           struct rte_flow_error *error)
    8853                 :            : {
    8854                 :          0 :         struct mlx5_flow_template_table_cfg tbl_cfg = {
    8855                 :            :                 .attr = {
    8856                 :            :                         .nb_flows = 64,
    8857                 :            :                         .insertion_type = RTE_FLOW_TABLE_INSERTION_TYPE_PATTERN,
    8858                 :            :                         .hash_func = RTE_FLOW_TABLE_HASH_FUNC_DEFAULT,
    8859                 :            :                         .flow_attr = {
    8860                 :            :                                 .group = 1,
    8861                 :          0 :                                 .ingress = pt[0]->attr.ingress,
    8862                 :          0 :                                 .egress = pt[0]->attr.egress,
    8863                 :          0 :                                 .transfer = pt[0]->attr.transfer
    8864                 :            :                         }
    8865                 :            :                 }
    8866                 :            :         };
    8867                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    8868                 :            :         struct rte_flow_actions_template *action_template;
    8869                 :            :         struct rte_flow_template_table *tmpl_tbl;
    8870                 :            :         int ret;
    8871                 :            : 
    8872         [ #  # ]:          0 :         if (pt[0]->attr.ingress) {
    8873                 :          0 :                 action_template =
    8874                 :          0 :                         priv->action_template_drop[MLX5DR_TABLE_TYPE_NIC_RX];
    8875         [ #  # ]:          0 :         } else if (pt[0]->attr.egress) {
    8876                 :          0 :                 action_template =
    8877                 :          0 :                         priv->action_template_drop[MLX5DR_TABLE_TYPE_NIC_TX];
    8878         [ #  # ]:          0 :         } else if (pt[0]->attr.transfer) {
    8879                 :          0 :                 action_template =
    8880                 :          0 :                         priv->action_template_drop[MLX5DR_TABLE_TYPE_FDB];
    8881                 :            :         } else {
    8882                 :            :                 ret = EINVAL;
    8883                 :          0 :                 goto end;
    8884                 :            :         }
    8885                 :            : 
    8886         [ #  # ]:          0 :         if (pt[0]->item_flags & MLX5_FLOW_ITEM_COMPARE)
    8887                 :          0 :                 tbl_cfg.attr.nb_flows = 1;
    8888                 :          0 :         tmpl_tbl = flow_hw_table_create(dev, &tbl_cfg, pt, pt_num,
    8889                 :            :                                         &action_template, 1, error);
    8890         [ #  # ]:          0 :         if (tmpl_tbl) {
    8891                 :            :                 ret = 0;
    8892                 :          0 :                 flow_hw_table_destroy(dev, tmpl_tbl, error);
    8893                 :            :         } else {
    8894      [ #  #  # ]:          0 :                 switch (rte_errno) {
    8895                 :            :                 case E2BIG:
    8896                 :            :                         ret = E2BIG;
    8897                 :            :                         break;
    8898                 :            :                 case ENOTSUP:
    8899                 :            :                         ret = EINVAL;
    8900                 :            :                         break;
    8901                 :            :                 default:
    8902                 :            :                         ret = 0;
    8903                 :            :                         break;
    8904                 :            :                 }
    8905                 :            :         }
    8906                 :            : end:
    8907                 :            :         if (ret)
    8908                 :          0 :                 rte_flow_error_set(error, ret, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    8909                 :            :                                    NULL, "failed to validate pattern template");
    8910                 :          0 :         return -ret;
    8911                 :            : }
    8912                 :            : 
    8913                 :            : /**
    8914                 :            :  * Create flow item template.
    8915                 :            :  *
    8916                 :            :  * @param[in] dev
    8917                 :            :  *   Pointer to the rte_eth_dev structure.
    8918                 :            :  * @param[in] attr
    8919                 :            :  *   Pointer to the item template attributes.
    8920                 :            :  * @param[in] items
    8921                 :            :  *   The template item pattern.
    8922                 :            :  * @param[out] error
    8923                 :            :  *   Pointer to error structure.
    8924                 :            :  *
    8925                 :            :  * @return
    8926                 :            :  *  Item template pointer on success, NULL otherwise and rte_errno is set.
    8927                 :            :  */
    8928                 :            : static struct rte_flow_pattern_template *
    8929                 :          0 : flow_hw_pattern_template_create(struct rte_eth_dev *dev,
    8930                 :            :                              const struct rte_flow_pattern_template_attr *attr,
    8931                 :            :                              const struct rte_flow_item items[],
    8932                 :            :                              struct rte_flow_error *error)
    8933                 :            : {
    8934                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    8935                 :            :         struct rte_flow_pattern_template *it;
    8936                 :            :         struct rte_flow_item *copied_items = NULL;
    8937                 :            :         const struct rte_flow_item *tmpl_items;
    8938                 :          0 :         uint64_t orig_item_nb, item_flags = 0;
    8939                 :          0 :         struct rte_flow_item port = {
    8940                 :            :                 .type = RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT,
    8941                 :            :                 .mask = &rte_flow_item_ethdev_mask,
    8942                 :            :         };
    8943                 :          0 :         struct rte_flow_item_tag tag_v = {
    8944                 :            :                 .data = 0,
    8945                 :            :                 .index = REG_C_0,
    8946                 :            :         };
    8947                 :          0 :         struct rte_flow_item_tag tag_m = {
    8948                 :            :                 .data = flow_hw_tx_tag_regc_mask(dev),
    8949                 :            :                 .index = 0xff,
    8950                 :            :         };
    8951                 :          0 :         struct rte_flow_item tag = {
    8952                 :            :                 .type = (enum rte_flow_item_type)MLX5_RTE_FLOW_ITEM_TYPE_TAG,
    8953                 :            :                 .spec = &tag_v,
    8954                 :            :                 .mask = &tag_m,
    8955                 :            :                 .last = NULL
    8956                 :            :         };
    8957                 :            :         int it_items_size;
    8958                 :            :         unsigned int i = 0;
    8959                 :            :         int rc;
    8960                 :            : 
    8961                 :            :         /* Validate application items only */
    8962                 :          0 :         rc = flow_hw_pattern_validate(dev, attr, items, &item_flags, error);
    8963         [ #  # ]:          0 :         if (rc < 0)
    8964                 :            :                 return NULL;
    8965                 :          0 :         orig_item_nb = rc;
    8966   [ #  #  #  # ]:          0 :         if (priv->sh->config.dv_esw_en &&
    8967                 :            :             priv->sh->config.repr_matching &&
    8968         [ #  # ]:          0 :             attr->ingress && !attr->egress && !attr->transfer) {
    8969                 :          0 :                 copied_items = flow_hw_prepend_item(items, orig_item_nb, &port, error);
    8970         [ #  # ]:          0 :                 if (!copied_items)
    8971                 :            :                         return NULL;
    8972                 :            :                 tmpl_items = copied_items;
    8973   [ #  #  #  # ]:          0 :         } else if (priv->sh->config.dv_esw_en &&
    8974                 :            :                    priv->sh->config.repr_matching &&
    8975         [ #  # ]:          0 :                    !attr->ingress && attr->egress && !attr->transfer) {
    8976         [ #  # ]:          0 :                 if (item_flags & MLX5_FLOW_ITEM_SQ) {
    8977                 :          0 :                         DRV_LOG(DEBUG, "Port %u omitting implicit REG_C_0 match for egress "
    8978                 :            :                                        "pattern template", dev->data->port_id);
    8979                 :            :                         tmpl_items = items;
    8980                 :          0 :                         goto setup_pattern_template;
    8981                 :            :                 }
    8982                 :          0 :                 copied_items = flow_hw_prepend_item(items, orig_item_nb, &tag, error);
    8983         [ #  # ]:          0 :                 if (!copied_items)
    8984                 :            :                         return NULL;
    8985                 :            :                 tmpl_items = copied_items;
    8986                 :            :         } else {
    8987                 :            :                 tmpl_items = items;
    8988                 :            :         }
    8989                 :          0 : setup_pattern_template:
    8990                 :          0 :         it = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*it), 0, rte_socket_id());
    8991         [ #  # ]:          0 :         if (!it) {
    8992                 :          0 :                 rte_flow_error_set(error, ENOMEM,
    8993                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    8994                 :            :                                    NULL,
    8995                 :            :                                    "cannot allocate item template");
    8996                 :          0 :                 goto error;
    8997                 :            :         }
    8998                 :          0 :         it->attr = *attr;
    8999                 :          0 :         it->item_flags = item_flags;
    9000                 :          0 :         it->orig_item_nb = orig_item_nb;
    9001                 :          0 :         it_items_size = rte_flow_conv(RTE_FLOW_CONV_OP_PATTERN, NULL, 0, tmpl_items, error);
    9002         [ #  # ]:          0 :         if (it_items_size <= 0) {
    9003                 :          0 :                 rte_flow_error_set(error, ENOMEM,
    9004                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    9005                 :            :                                    NULL,
    9006                 :            :                                    "Failed to determine buffer size for pattern");
    9007                 :          0 :                 goto error;
    9008                 :            :         }
    9009                 :          0 :         it_items_size = RTE_ALIGN(it_items_size, 16);
    9010                 :          0 :         it->items = mlx5_malloc(MLX5_MEM_ZERO, it_items_size, 0, rte_dev_numa_node(dev->device));
    9011         [ #  # ]:          0 :         if (it->items == NULL) {
    9012                 :          0 :                 rte_flow_error_set(error, ENOMEM,
    9013                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    9014                 :            :                                    NULL,
    9015                 :            :                                    "Cannot allocate memory for pattern");
    9016                 :          0 :                 goto error;
    9017                 :            :         }
    9018                 :          0 :         rc = rte_flow_conv(RTE_FLOW_CONV_OP_PATTERN, it->items, it_items_size, tmpl_items, error);
    9019         [ #  # ]:          0 :         if (rc <= 0) {
    9020                 :          0 :                 rte_flow_error_set(error, ENOMEM,
    9021                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    9022                 :            :                                    NULL,
    9023                 :            :                                    "Failed to store pattern");
    9024                 :          0 :                 goto error;
    9025                 :            :         }
    9026                 :          0 :         it->mt = mlx5dr_match_template_create(tmpl_items, attr->relaxed_matching);
    9027         [ #  # ]:          0 :         if (!it->mt) {
    9028                 :          0 :                 rte_flow_error_set(error, rte_errno,
    9029                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    9030                 :            :                                    NULL,
    9031                 :            :                                    "cannot create match template");
    9032                 :          0 :                 goto error;
    9033                 :            :         }
    9034         [ #  # ]:          0 :         if (copied_items) {
    9035         [ #  # ]:          0 :                 if (attr->ingress)
    9036                 :          0 :                         it->implicit_port = true;
    9037         [ #  # ]:          0 :                 else if (attr->egress)
    9038                 :          0 :                         it->implicit_tag = true;
    9039                 :          0 :                 mlx5_free(copied_items);
    9040                 :            :                 copied_items = NULL;
    9041                 :            :         }
    9042                 :            :         /* Either inner or outer, can't both. */
    9043         [ #  # ]:          0 :         if (it->item_flags & (MLX5_FLOW_ITEM_OUTER_IPV6_ROUTING_EXT |
    9044                 :            :                               MLX5_FLOW_ITEM_INNER_IPV6_ROUTING_EXT)) {
    9045         [ #  # ]:          0 :                 if (((it->item_flags & MLX5_FLOW_ITEM_OUTER_IPV6_ROUTING_EXT) &&
    9046         [ #  # ]:          0 :                      (it->item_flags & MLX5_FLOW_ITEM_INNER_IPV6_ROUTING_EXT)) ||
    9047                 :          0 :                     (mlx5_alloc_srh_flex_parser(dev))) {
    9048                 :          0 :                         rte_flow_error_set(error, rte_errno,
    9049                 :            :                                            RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    9050                 :            :                                            "cannot create IPv6 routing extension support");
    9051                 :          0 :                         goto error;
    9052                 :            :                 }
    9053                 :            :         }
    9054         [ #  # ]:          0 :         if (it->item_flags & MLX5_FLOW_ITEM_FLEX) {
    9055         [ #  # ]:          0 :                 for (i = 0; items[i].type != RTE_FLOW_ITEM_TYPE_END; i++) {
    9056                 :          0 :                         const struct rte_flow_item_flex *spec = items[i].spec;
    9057                 :            :                         struct rte_flow_item_flex_handle *handle;
    9058                 :            : 
    9059         [ #  # ]:          0 :                         if (items[i].type != RTE_FLOW_ITEM_TYPE_FLEX)
    9060                 :          0 :                                 continue;
    9061                 :          0 :                         handle = spec->handle;
    9062         [ #  # ]:          0 :                         if (flow_hw_flex_item_acquire(dev, handle,
    9063                 :          0 :                                                       &it->flex_item)) {
    9064                 :          0 :                                 rte_flow_error_set(error, EINVAL,
    9065                 :            :                                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    9066                 :            :                                                    NULL, "cannot create hw FLEX item");
    9067                 :          0 :                                 goto error;
    9068                 :            :                         }
    9069                 :            :                 }
    9070                 :            :         }
    9071         [ #  # ]:          0 :         if (it->item_flags & MLX5_FLOW_LAYER_GENEVE_OPT) {
    9072         [ #  # ]:          0 :                 for (i = 0; items[i].type != RTE_FLOW_ITEM_TYPE_END; i++) {
    9073                 :          0 :                         const struct rte_flow_item_geneve_opt *spec =
    9074                 :            :                                 items[i].spec;
    9075                 :            : 
    9076         [ #  # ]:          0 :                         if (items[i].type != RTE_FLOW_ITEM_TYPE_GENEVE_OPT)
    9077                 :          0 :                                 continue;
    9078         [ #  # ]:          0 :                         if (mlx5_geneve_tlv_option_register(priv, spec,
    9079                 :          0 :                                                             &it->geneve_opt_mng)) {
    9080                 :          0 :                                 rte_flow_error_set(error, EINVAL,
    9081                 :            :                                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    9082                 :            :                                                    NULL, "cannot register GENEVE TLV option");
    9083                 :          0 :                                 goto error;
    9084                 :            :                         }
    9085                 :            :                 }
    9086                 :            :         }
    9087                 :          0 :         rte_atomic_fetch_add_explicit(&it->refcnt, 1, rte_memory_order_relaxed);
    9088                 :          0 :         rc = pattern_template_validate(dev, &it, 1, error);
    9089         [ #  # ]:          0 :         if (rc)
    9090                 :          0 :                 goto error;
    9091         [ #  # ]:          0 :         LIST_INSERT_HEAD(&priv->flow_hw_itt, it, next);
    9092                 :          0 :         return it;
    9093                 :          0 : error:
    9094         [ #  # ]:          0 :         if (it) {
    9095         [ #  # ]:          0 :                 if (it->flex_item)
    9096                 :          0 :                         flow_hw_flex_item_release(dev, &it->flex_item);
    9097         [ #  # ]:          0 :                 if (it->geneve_opt_mng.nb_options)
    9098                 :          0 :                         mlx5_geneve_tlv_options_unregister(priv, &it->geneve_opt_mng);
    9099         [ #  # ]:          0 :                 if (it->mt)
    9100                 :          0 :                         claim_zero(mlx5dr_match_template_destroy(it->mt));
    9101                 :          0 :                 mlx5_free(it->items);
    9102                 :          0 :                 mlx5_free(it);
    9103                 :            :         }
    9104         [ #  # ]:          0 :         if (copied_items)
    9105                 :          0 :                 mlx5_free(copied_items);
    9106                 :            :         return NULL;
    9107                 :            : }
    9108                 :            : 
    9109                 :            : /**
    9110                 :            :  * Destroy flow item template.
    9111                 :            :  *
    9112                 :            :  * @param[in] dev
    9113                 :            :  *   Pointer to the rte_eth_dev structure.
    9114                 :            :  * @param[in] template
    9115                 :            :  *   Pointer to the item template to be destroyed.
    9116                 :            :  * @param[out] error
    9117                 :            :  *   Pointer to error structure.
    9118                 :            :  *
    9119                 :            :  * @return
    9120                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    9121                 :            :  */
    9122                 :            : static int
    9123                 :          0 : flow_hw_pattern_template_destroy(struct rte_eth_dev *dev,
    9124                 :            :                               struct rte_flow_pattern_template *template,
    9125                 :            :                               struct rte_flow_error *error __rte_unused)
    9126                 :            : {
    9127                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    9128                 :            : 
    9129         [ #  # ]:          0 :         if (rte_atomic_load_explicit(&template->refcnt, rte_memory_order_relaxed) > 1) {
    9130                 :          0 :                 DRV_LOG(WARNING, "Item template %p is still in use.",
    9131                 :            :                         (void *)template);
    9132                 :          0 :                 return rte_flow_error_set(error, EBUSY,
    9133                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    9134                 :            :                                    NULL,
    9135                 :            :                                    "item template is in use");
    9136                 :            :         }
    9137         [ #  # ]:          0 :         if (template->item_flags & (MLX5_FLOW_ITEM_OUTER_IPV6_ROUTING_EXT |
    9138                 :            :                                     MLX5_FLOW_ITEM_INNER_IPV6_ROUTING_EXT))
    9139                 :          0 :                 mlx5_free_srh_flex_parser(dev);
    9140         [ #  # ]:          0 :         LIST_REMOVE(template, next);
    9141                 :          0 :         flow_hw_flex_item_release(dev, &template->flex_item);
    9142                 :          0 :         mlx5_geneve_tlv_options_unregister(priv, &template->geneve_opt_mng);
    9143                 :          0 :         claim_zero(mlx5dr_match_template_destroy(template->mt));
    9144                 :          0 :         mlx5_free(template->items);
    9145                 :          0 :         mlx5_free(template);
    9146                 :          0 :         return 0;
    9147                 :            : }
    9148                 :            : 
    9149                 :            : /*
    9150                 :            :  * Get information about HWS pre-configurable resources.
    9151                 :            :  *
    9152                 :            :  * @param[in] dev
    9153                 :            :  *   Pointer to the rte_eth_dev structure.
    9154                 :            :  * @param[out] port_info
    9155                 :            :  *   Pointer to port information.
    9156                 :            :  * @param[out] queue_info
    9157                 :            :  *   Pointer to queue information.
    9158                 :            :  * @param[out] error
    9159                 :            :  *   Pointer to error structure.
    9160                 :            :  *
    9161                 :            :  * @return
    9162                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    9163                 :            :  */
    9164                 :            : static int
    9165                 :          0 : flow_hw_info_get(struct rte_eth_dev *dev,
    9166                 :            :                  struct rte_flow_port_info *port_info,
    9167                 :            :                  struct rte_flow_queue_info *queue_info,
    9168                 :            :                  struct rte_flow_error *error __rte_unused)
    9169                 :            : {
    9170                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    9171                 :          0 :         uint16_t port_id = dev->data->port_id;
    9172                 :            :         struct rte_mtr_capabilities mtr_cap;
    9173                 :            :         int ret;
    9174                 :            : 
    9175                 :            :         memset(port_info, 0, sizeof(*port_info));
    9176                 :            :         /* Queue size is unlimited from low-level. */
    9177                 :          0 :         port_info->max_nb_queues = UINT32_MAX;
    9178                 :          0 :         queue_info->max_size = UINT32_MAX;
    9179                 :            : 
    9180                 :            :         memset(&mtr_cap, 0, sizeof(struct rte_mtr_capabilities));
    9181                 :          0 :         ret = rte_mtr_capabilities_get(port_id, &mtr_cap, NULL);
    9182         [ #  # ]:          0 :         if (!ret)
    9183                 :          0 :                 port_info->max_nb_meters = mtr_cap.n_max;
    9184                 :          0 :         port_info->max_nb_counters = priv->sh->hws_max_nb_counters;
    9185                 :          0 :         port_info->max_nb_aging_objects = port_info->max_nb_counters;
    9186                 :          0 :         return 0;
    9187                 :            : }
    9188                 :            : 
    9189                 :            : /**
    9190                 :            :  * Create group callback.
    9191                 :            :  *
    9192                 :            :  * @param[in] tool_ctx
    9193                 :            :  *   Pointer to the hash list related context.
    9194                 :            :  * @param[in] cb_ctx
    9195                 :            :  *   Pointer to the group creation context.
    9196                 :            :  *
    9197                 :            :  * @return
    9198                 :            :  *   Group entry on success, NULL otherwise and rte_errno is set.
    9199                 :            :  */
    9200                 :            : struct mlx5_list_entry *
    9201                 :          0 : flow_hw_grp_create_cb(void *tool_ctx, void *cb_ctx)
    9202                 :          0 : {
    9203                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
    9204                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
    9205                 :          0 :         struct rte_eth_dev *dev = ctx->dev;
    9206                 :          0 :         struct rte_flow_attr *attr = (struct rte_flow_attr *)ctx->data;
    9207                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    9208                 :          0 :         struct mlx5dr_table_attr dr_tbl_attr = {0};
    9209                 :          0 :         struct rte_flow_error *error = ctx->error;
    9210                 :            :         struct mlx5_flow_group *grp_data;
    9211                 :            :         struct mlx5dr_table *tbl = NULL;
    9212                 :            :         struct mlx5dr_action *jump;
    9213                 :          0 :         uint32_t idx = 0;
    9214   [ #  #  #  #  :          0 :         MKSTR(matcher_name, "%s_%s_%u_%u_matcher_list",
             #  #  #  # ]
    9215                 :            :               attr->transfer ? "FDB" : "NIC", attr->egress ? "egress" : "ingress",
    9216                 :            :               attr->group, idx);
    9217                 :            : 
    9218                 :          0 :         grp_data = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_HW_GRP], &idx);
    9219         [ #  # ]:          0 :         if (!grp_data) {
    9220                 :          0 :                 rte_flow_error_set(error, ENOMEM,
    9221                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    9222                 :            :                                    NULL,
    9223                 :            :                                    "cannot allocate flow table data entry");
    9224                 :          0 :                 return NULL;
    9225                 :            :         }
    9226                 :          0 :         dr_tbl_attr.level = attr->group;
    9227         [ #  # ]:          0 :         if (attr->transfer)
    9228                 :          0 :                 dr_tbl_attr.type = MLX5DR_TABLE_TYPE_FDB;
    9229         [ #  # ]:          0 :         else if (attr->egress)
    9230                 :          0 :                 dr_tbl_attr.type = MLX5DR_TABLE_TYPE_NIC_TX;
    9231                 :            :         else
    9232                 :          0 :                 dr_tbl_attr.type = MLX5DR_TABLE_TYPE_NIC_RX;
    9233                 :          0 :         tbl = mlx5dr_table_create(priv->dr_ctx, &dr_tbl_attr);
    9234         [ #  # ]:          0 :         if (!tbl)
    9235                 :          0 :                 goto error;
    9236                 :          0 :         grp_data->tbl = tbl;
    9237         [ #  # ]:          0 :         if (attr->group) {
    9238                 :            :                 /* Jump action be used by non-root table. */
    9239                 :          0 :                 jump = mlx5dr_action_create_dest_table
    9240                 :            :                         (priv->dr_ctx, tbl,
    9241                 :          0 :                          mlx5_hw_act_flag[!!attr->group][dr_tbl_attr.type]);
    9242         [ #  # ]:          0 :                 if (!jump)
    9243                 :          0 :                         goto error;
    9244                 :          0 :                 grp_data->jump.hws_action = jump;
    9245                 :            :                 /* Jump action be used by root table.  */
    9246                 :          0 :                 jump = mlx5dr_action_create_dest_table
    9247                 :            :                         (priv->dr_ctx, tbl,
    9248                 :            :                          mlx5_hw_act_flag[MLX5_HW_ACTION_FLAG_ROOT]
    9249                 :          0 :                                          [dr_tbl_attr.type]);
    9250         [ #  # ]:          0 :                 if (!jump)
    9251                 :          0 :                         goto error;
    9252                 :          0 :                 grp_data->jump.root_action = jump;
    9253                 :            :         }
    9254                 :            : 
    9255                 :          0 :         grp_data->matchers = mlx5_list_create(matcher_name, sh, true,
    9256                 :            :                                               flow_matcher_create_cb,
    9257                 :            :                                               flow_matcher_match_cb,
    9258                 :            :                                               flow_matcher_remove_cb,
    9259                 :            :                                               flow_matcher_clone_cb,
    9260                 :            :                                               flow_matcher_clone_free_cb);
    9261                 :          0 :         grp_data->dev = dev;
    9262                 :          0 :         grp_data->idx = idx;
    9263                 :          0 :         grp_data->group_id = attr->group;
    9264                 :          0 :         grp_data->type = dr_tbl_attr.type;
    9265                 :          0 :         return &grp_data->entry;
    9266                 :          0 : error:
    9267         [ #  # ]:          0 :         if (grp_data->jump.root_action)
    9268                 :          0 :                 mlx5dr_action_destroy(grp_data->jump.root_action);
    9269         [ #  # ]:          0 :         if (grp_data->jump.hws_action)
    9270                 :          0 :                 mlx5dr_action_destroy(grp_data->jump.hws_action);
    9271         [ #  # ]:          0 :         if (tbl)
    9272                 :          0 :                 mlx5dr_table_destroy(tbl);
    9273         [ #  # ]:          0 :         if (idx)
    9274                 :          0 :                 mlx5_ipool_free(sh->ipool[MLX5_IPOOL_HW_GRP], idx);
    9275                 :          0 :         rte_flow_error_set(error, ENOMEM,
    9276                 :            :                            RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    9277                 :            :                            NULL,
    9278                 :            :                            "cannot allocate flow dr table");
    9279                 :          0 :         return NULL;
    9280                 :            : }
    9281                 :            : 
    9282                 :            : /**
    9283                 :            :  * Remove group callback.
    9284                 :            :  *
    9285                 :            :  * @param[in] tool_ctx
    9286                 :            :  *   Pointer to the hash list related context.
    9287                 :            :  * @param[in] entry
    9288                 :            :  *   Pointer to the entry to be removed.
    9289                 :            :  */
    9290                 :            : void
    9291                 :          0 : flow_hw_grp_remove_cb(void *tool_ctx, struct mlx5_list_entry *entry)
    9292                 :            : {
    9293                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
    9294                 :            :         struct mlx5_flow_group *grp_data =
    9295                 :            :                     container_of(entry, struct mlx5_flow_group, entry);
    9296                 :            : 
    9297                 :            :         MLX5_ASSERT(entry && sh);
    9298                 :            :         /* To use the wrapper glue functions instead. */
    9299         [ #  # ]:          0 :         if (grp_data->jump.hws_action)
    9300                 :          0 :                 mlx5dr_action_destroy(grp_data->jump.hws_action);
    9301         [ #  # ]:          0 :         if (grp_data->jump.root_action)
    9302                 :          0 :                 mlx5dr_action_destroy(grp_data->jump.root_action);
    9303                 :          0 :         mlx5_list_destroy(grp_data->matchers);
    9304                 :          0 :         mlx5dr_table_destroy(grp_data->tbl);
    9305                 :          0 :         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_HW_GRP], grp_data->idx);
    9306                 :          0 : }
    9307                 :            : 
    9308                 :            : /**
    9309                 :            :  * Match group callback.
    9310                 :            :  *
    9311                 :            :  * @param[in] tool_ctx
    9312                 :            :  *   Pointer to the hash list related context.
    9313                 :            :  * @param[in] entry
    9314                 :            :  *   Pointer to the group to be matched.
    9315                 :            :  * @param[in] cb_ctx
    9316                 :            :  *   Pointer to the group matching context.
    9317                 :            :  *
    9318                 :            :  * @return
    9319                 :            :  *   0 on matched, 1 on miss matched.
    9320                 :            :  */
    9321                 :            : int
    9322                 :          0 : flow_hw_grp_match_cb(void *tool_ctx __rte_unused, struct mlx5_list_entry *entry,
    9323                 :            :                      void *cb_ctx)
    9324                 :            : {
    9325                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
    9326                 :            :         struct mlx5_flow_group *grp_data =
    9327                 :            :                 container_of(entry, struct mlx5_flow_group, entry);
    9328                 :          0 :         struct rte_flow_attr *attr =
    9329                 :            :                         (struct rte_flow_attr *)ctx->data;
    9330                 :            : 
    9331                 :          0 :         return (grp_data->dev != ctx->dev) ||
    9332         [ #  # ]:          0 :                 (grp_data->group_id != attr->group) ||
    9333   [ #  #  #  # ]:          0 :                 ((grp_data->type != MLX5DR_TABLE_TYPE_FDB) &&
    9334         [ #  # ]:          0 :                 attr->transfer) ||
    9335         [ #  # ]:          0 :                 ((grp_data->type != MLX5DR_TABLE_TYPE_NIC_TX) &&
    9336   [ #  #  #  # ]:          0 :                 attr->egress) ||
    9337         [ #  # ]:          0 :                 ((grp_data->type != MLX5DR_TABLE_TYPE_NIC_RX) &&
    9338                 :            :                 attr->ingress);
    9339                 :            : }
    9340                 :            : 
    9341                 :            : /**
    9342                 :            :  * Clone group entry callback.
    9343                 :            :  *
    9344                 :            :  * @param[in] tool_ctx
    9345                 :            :  *   Pointer to the hash list related context.
    9346                 :            :  * @param[in] entry
    9347                 :            :  *   Pointer to the group to be matched.
    9348                 :            :  * @param[in] cb_ctx
    9349                 :            :  *   Pointer to the group matching context.
    9350                 :            :  *
    9351                 :            :  * @return
    9352                 :            :  *   0 on matched, 1 on miss matched.
    9353                 :            :  */
    9354                 :            : struct mlx5_list_entry *
    9355                 :          0 : flow_hw_grp_clone_cb(void *tool_ctx, struct mlx5_list_entry *oentry,
    9356                 :            :                      void *cb_ctx)
    9357                 :            : {
    9358                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
    9359                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
    9360                 :            :         struct mlx5_flow_group *grp_data;
    9361                 :          0 :         struct rte_flow_error *error = ctx->error;
    9362                 :          0 :         uint32_t idx = 0;
    9363                 :            : 
    9364                 :          0 :         grp_data = mlx5_ipool_malloc(sh->ipool[MLX5_IPOOL_HW_GRP], &idx);
    9365         [ #  # ]:          0 :         if (!grp_data) {
    9366                 :          0 :                 rte_flow_error_set(error, ENOMEM,
    9367                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    9368                 :            :                                    NULL,
    9369                 :            :                                    "cannot allocate flow table data entry");
    9370                 :          0 :                 return NULL;
    9371                 :            :         }
    9372                 :            :         memcpy(grp_data, oentry, sizeof(*grp_data));
    9373                 :          0 :         grp_data->idx = idx;
    9374                 :          0 :         return &grp_data->entry;
    9375                 :            : }
    9376                 :            : 
    9377                 :            : /**
    9378                 :            :  * Free cloned group entry callback.
    9379                 :            :  *
    9380                 :            :  * @param[in] tool_ctx
    9381                 :            :  *   Pointer to the hash list related context.
    9382                 :            :  * @param[in] entry
    9383                 :            :  *   Pointer to the group to be freed.
    9384                 :            :  */
    9385                 :            : void
    9386                 :          0 : flow_hw_grp_clone_free_cb(void *tool_ctx, struct mlx5_list_entry *entry)
    9387                 :            : {
    9388                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
    9389                 :            :         struct mlx5_flow_group *grp_data =
    9390                 :            :                     container_of(entry, struct mlx5_flow_group, entry);
    9391                 :            : 
    9392                 :          0 :         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_HW_GRP], grp_data->idx);
    9393                 :          0 : }
    9394                 :            : 
    9395                 :            : /**
    9396                 :            :  * Create and cache a vport action for given @p dev port. vport actions
    9397                 :            :  * cache is used in HWS with FDB flows.
    9398                 :            :  *
    9399                 :            :  * This function does not create any function if proxy port for @p dev port
    9400                 :            :  * was not configured for HW Steering.
    9401                 :            :  *
    9402                 :            :  * This function assumes that E-Switch is enabled and PMD is running with
    9403                 :            :  * HW Steering configured.
    9404                 :            :  *
    9405                 :            :  * @param dev
    9406                 :            :  *   Pointer to Ethernet device which will be the action destination.
    9407                 :            :  *
    9408                 :            :  * @return
    9409                 :            :  *   0 on success, positive value otherwise.
    9410                 :            :  */
    9411                 :            : int
    9412                 :          0 : flow_hw_create_vport_action(struct rte_eth_dev *dev)
    9413                 :            : {
    9414                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    9415                 :            :         struct rte_eth_dev *proxy_dev;
    9416                 :            :         struct mlx5_priv *proxy_priv;
    9417                 :          0 :         uint16_t port_id = dev->data->port_id;
    9418                 :          0 :         uint16_t proxy_port_id = port_id;
    9419                 :            :         int ret;
    9420                 :            : 
    9421                 :          0 :         ret = mlx5_flow_pick_transfer_proxy(dev, &proxy_port_id, NULL);
    9422         [ #  # ]:          0 :         if (ret)
    9423                 :            :                 return ret;
    9424                 :          0 :         proxy_dev = &rte_eth_devices[proxy_port_id];
    9425                 :          0 :         proxy_priv = proxy_dev->data->dev_private;
    9426         [ #  # ]:          0 :         if (!proxy_priv->hw_vport)
    9427                 :            :                 return 0;
    9428         [ #  # ]:          0 :         if (proxy_priv->hw_vport[port_id]) {
    9429                 :          0 :                 DRV_LOG(ERR, "port %u HWS vport action already created",
    9430                 :            :                         port_id);
    9431                 :          0 :                 return -EINVAL;
    9432                 :            :         }
    9433                 :          0 :         proxy_priv->hw_vport[port_id] = mlx5dr_action_create_dest_vport
    9434                 :            :                         (proxy_priv->dr_ctx, priv->dev_port,
    9435                 :            :                          MLX5DR_ACTION_FLAG_HWS_FDB);
    9436         [ #  # ]:          0 :         if (!proxy_priv->hw_vport[port_id]) {
    9437                 :          0 :                 DRV_LOG(ERR, "port %u unable to create HWS vport action",
    9438                 :            :                         port_id);
    9439                 :          0 :                 return -EINVAL;
    9440                 :            :         }
    9441                 :            :         return 0;
    9442                 :            : }
    9443                 :            : 
    9444                 :            : /**
    9445                 :            :  * Destroys the vport action associated with @p dev device
    9446                 :            :  * from actions' cache.
    9447                 :            :  *
    9448                 :            :  * This function does not destroy any action if there is no action cached
    9449                 :            :  * for @p dev or proxy port was not configured for HW Steering.
    9450                 :            :  *
    9451                 :            :  * This function assumes that E-Switch is enabled and PMD is running with
    9452                 :            :  * HW Steering configured.
    9453                 :            :  *
    9454                 :            :  * @param dev
    9455                 :            :  *   Pointer to Ethernet device which will be the action destination.
    9456                 :            :  */
    9457                 :            : void
    9458                 :          0 : flow_hw_destroy_vport_action(struct rte_eth_dev *dev)
    9459                 :            : {
    9460                 :            :         struct rte_eth_dev *proxy_dev;
    9461                 :            :         struct mlx5_priv *proxy_priv;
    9462                 :          0 :         uint16_t port_id = dev->data->port_id;
    9463                 :          0 :         uint16_t proxy_port_id = port_id;
    9464                 :            : 
    9465         [ #  # ]:          0 :         if (mlx5_flow_pick_transfer_proxy(dev, &proxy_port_id, NULL))
    9466                 :          0 :                 return;
    9467                 :          0 :         proxy_dev = &rte_eth_devices[proxy_port_id];
    9468                 :          0 :         proxy_priv = proxy_dev->data->dev_private;
    9469   [ #  #  #  # ]:          0 :         if (!proxy_priv->hw_vport || !proxy_priv->hw_vport[port_id])
    9470                 :            :                 return;
    9471                 :          0 :         mlx5dr_action_destroy(proxy_priv->hw_vport[port_id]);
    9472                 :          0 :         proxy_priv->hw_vport[port_id] = NULL;
    9473                 :            : }
    9474                 :            : 
    9475                 :            : static int
    9476                 :          0 : flow_hw_create_vport_actions(struct mlx5_priv *priv)
    9477                 :            : {
    9478                 :            :         uint16_t port_id;
    9479                 :            : 
    9480                 :            :         MLX5_ASSERT(!priv->hw_vport);
    9481                 :          0 :         priv->hw_vport = mlx5_malloc(MLX5_MEM_ZERO,
    9482                 :            :                                      sizeof(*priv->hw_vport) * RTE_MAX_ETHPORTS,
    9483                 :            :                                      0, SOCKET_ID_ANY);
    9484         [ #  # ]:          0 :         if (!priv->hw_vport)
    9485                 :            :                 return -ENOMEM;
    9486                 :          0 :         DRV_LOG(DEBUG, "port %u :: creating vport actions", priv->dev_data->port_id);
    9487                 :          0 :         DRV_LOG(DEBUG, "port %u ::    domain_id=%u", priv->dev_data->port_id, priv->domain_id);
    9488         [ #  # ]:          0 :         MLX5_ETH_FOREACH_DEV(port_id, NULL) {
    9489                 :          0 :                 struct mlx5_priv *port_priv = rte_eth_devices[port_id].data->dev_private;
    9490                 :            : 
    9491         [ #  # ]:          0 :                 if (!port_priv ||
    9492         [ #  # ]:          0 :                     port_priv->domain_id != priv->domain_id)
    9493                 :          0 :                         continue;
    9494                 :          0 :                 DRV_LOG(DEBUG, "port %u :: for port_id=%u, calling mlx5dr_action_create_dest_vport() with ibport=%u",
    9495                 :            :                         priv->dev_data->port_id, port_id, port_priv->dev_port);
    9496                 :          0 :                 priv->hw_vport[port_id] = mlx5dr_action_create_dest_vport
    9497                 :            :                                 (priv->dr_ctx, port_priv->dev_port,
    9498                 :            :                                  MLX5DR_ACTION_FLAG_HWS_FDB);
    9499                 :          0 :                 DRV_LOG(DEBUG, "port %u :: priv->hw_vport[%u]=%p",
    9500                 :            :                         priv->dev_data->port_id, port_id, (void *)priv->hw_vport[port_id]);
    9501         [ #  # ]:          0 :                 if (!priv->hw_vport[port_id])
    9502                 :            :                         return -EINVAL;
    9503                 :            :         }
    9504                 :            :         return 0;
    9505                 :            : }
    9506                 :            : 
    9507                 :            : static void
    9508                 :          0 : flow_hw_free_vport_actions(struct mlx5_priv *priv)
    9509                 :            : {
    9510                 :            :         uint16_t port_id;
    9511                 :            : 
    9512         [ #  # ]:          0 :         if (!priv->hw_vport)
    9513                 :            :                 return;
    9514         [ #  # ]:          0 :         for (port_id = 0; port_id < RTE_MAX_ETHPORTS; ++port_id)
    9515         [ #  # ]:          0 :                 if (priv->hw_vport[port_id])
    9516                 :          0 :                         mlx5dr_action_destroy(priv->hw_vport[port_id]);
    9517                 :          0 :         mlx5_free(priv->hw_vport);
    9518                 :          0 :         priv->hw_vport = NULL;
    9519                 :            : }
    9520                 :            : 
    9521                 :            : static void
    9522                 :            : flow_hw_create_send_to_kernel_actions(struct mlx5_priv *priv __rte_unused)
    9523                 :            : {
    9524                 :            : #ifdef HAVE_MLX5DV_DR_ACTION_CREATE_DEST_ROOT_TABLE
    9525                 :            :         int action_flag;
    9526                 :            :         int i;
    9527                 :            :         bool is_vf_sf_dev = priv->sh->dev_cap.vf || priv->sh->dev_cap.sf;
    9528                 :            : 
    9529                 :            :         for (i = MLX5DR_TABLE_TYPE_NIC_RX; i < MLX5DR_TABLE_TYPE_MAX; i++) {
    9530                 :            :                 if ((!priv->sh->config.dv_esw_en || is_vf_sf_dev) &&
    9531                 :            :                      i == MLX5DR_TABLE_TYPE_FDB)
    9532                 :            :                         continue;
    9533                 :            :                 action_flag = mlx5_hw_act_flag[1][i];
    9534                 :            :                 priv->hw_send_to_kernel[i] =
    9535                 :            :                                 mlx5dr_action_create_dest_root(priv->dr_ctx,
    9536                 :            :                                                         MLX5_HW_LOWEST_PRIO_ROOT,
    9537                 :            :                                                         action_flag);
    9538                 :            :                 if (!priv->hw_send_to_kernel[i]) {
    9539                 :            :                         DRV_LOG(WARNING, "Unable to create HWS send to kernel action");
    9540                 :            :                         return;
    9541                 :            :                 }
    9542                 :            :         }
    9543                 :            : #endif
    9544                 :            : }
    9545                 :            : 
    9546                 :            : static void
    9547                 :          0 : flow_hw_destroy_send_to_kernel_action(struct mlx5_priv *priv)
    9548                 :            : {
    9549                 :            :         int i;
    9550         [ #  # ]:          0 :         for (i = MLX5DR_TABLE_TYPE_NIC_RX; i < MLX5DR_TABLE_TYPE_MAX; i++) {
    9551         [ #  # ]:          0 :                 if (priv->hw_send_to_kernel[i]) {
    9552                 :          0 :                         mlx5dr_action_destroy(priv->hw_send_to_kernel[i]);
    9553                 :          0 :                         priv->hw_send_to_kernel[i] = NULL;
    9554                 :            :                 }
    9555                 :            :         }
    9556                 :          0 : }
    9557                 :            : 
    9558                 :            : static void
    9559                 :          0 : flow_hw_destroy_nat64_actions(struct mlx5_priv *priv)
    9560                 :            : {
    9561                 :            :         uint32_t i;
    9562                 :            : 
    9563         [ #  # ]:          0 :         for (i = MLX5DR_TABLE_TYPE_NIC_RX; i < MLX5DR_TABLE_TYPE_MAX; i++) {
    9564         [ #  # ]:          0 :                 if (priv->action_nat64[i][RTE_FLOW_NAT64_6TO4]) {
    9565                 :          0 :                         (void)mlx5dr_action_destroy(priv->action_nat64[i][RTE_FLOW_NAT64_6TO4]);
    9566                 :          0 :                         priv->action_nat64[i][RTE_FLOW_NAT64_6TO4] = NULL;
    9567                 :            :                 }
    9568         [ #  # ]:          0 :                 if (priv->action_nat64[i][RTE_FLOW_NAT64_4TO6]) {
    9569                 :          0 :                         (void)mlx5dr_action_destroy(priv->action_nat64[i][RTE_FLOW_NAT64_4TO6]);
    9570                 :          0 :                         priv->action_nat64[i][RTE_FLOW_NAT64_4TO6] = NULL;
    9571                 :            :                 }
    9572                 :            :         }
    9573                 :          0 : }
    9574                 :            : 
    9575                 :            : static int
    9576                 :          0 : flow_hw_create_nat64_actions(struct mlx5_priv *priv, struct rte_flow_error *error)
    9577                 :            : {
    9578                 :            :         struct mlx5dr_action_nat64_attr attr;
    9579                 :            :         uint8_t regs[MLX5_FLOW_NAT64_REGS_MAX];
    9580                 :            :         uint32_t i;
    9581                 :          0 :         const uint32_t flags[MLX5DR_TABLE_TYPE_MAX] = {
    9582                 :            :                 MLX5DR_ACTION_FLAG_HWS_RX | MLX5DR_ACTION_FLAG_SHARED,
    9583                 :            :                 MLX5DR_ACTION_FLAG_HWS_TX | MLX5DR_ACTION_FLAG_SHARED,
    9584                 :            :                 MLX5DR_ACTION_FLAG_HWS_FDB | MLX5DR_ACTION_FLAG_SHARED,
    9585                 :            :         };
    9586                 :            :         struct mlx5dr_action *act;
    9587                 :            : 
    9588                 :          0 :         attr.registers = regs;
    9589                 :            :         /* Try to use 3 registers by default. */
    9590                 :          0 :         attr.num_of_registers = MLX5_FLOW_NAT64_REGS_MAX;
    9591         [ #  # ]:          0 :         for (i = 0; i < MLX5_FLOW_NAT64_REGS_MAX; i++) {
    9592                 :            :                 MLX5_ASSERT(priv->sh->registers.nat64_regs[i] != REG_NON);
    9593                 :          0 :                 regs[i] = mlx5_convert_reg_to_field(priv->sh->registers.nat64_regs[i]);
    9594                 :            :         }
    9595         [ #  # ]:          0 :         for (i = MLX5DR_TABLE_TYPE_NIC_RX; i < MLX5DR_TABLE_TYPE_MAX; i++) {
    9596   [ #  #  #  # ]:          0 :                 if (i == MLX5DR_TABLE_TYPE_FDB && !priv->sh->config.dv_esw_en)
    9597                 :          0 :                         continue;
    9598                 :          0 :                 attr.flags = (enum mlx5dr_action_nat64_flags)
    9599                 :            :                              (MLX5DR_ACTION_NAT64_V6_TO_V4 | MLX5DR_ACTION_NAT64_BACKUP_ADDR);
    9600                 :          0 :                 act = mlx5dr_action_create_nat64(priv->dr_ctx, &attr, flags[i]);
    9601         [ #  # ]:          0 :                 if (!act)
    9602                 :          0 :                         return rte_flow_error_set(error, rte_errno,
    9603                 :            :                                                   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    9604                 :            :                                                   "Failed to create v6 to v4 action.");
    9605                 :          0 :                 priv->action_nat64[i][RTE_FLOW_NAT64_6TO4] = act;
    9606                 :          0 :                 attr.flags = (enum mlx5dr_action_nat64_flags)
    9607                 :            :                              (MLX5DR_ACTION_NAT64_V4_TO_V6 | MLX5DR_ACTION_NAT64_BACKUP_ADDR);
    9608                 :          0 :                 act = mlx5dr_action_create_nat64(priv->dr_ctx, &attr, flags[i]);
    9609         [ #  # ]:          0 :                 if (!act)
    9610                 :          0 :                         return rte_flow_error_set(error, rte_errno,
    9611                 :            :                                                   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    9612                 :            :                                                   "Failed to create v4 to v6 action.");
    9613                 :          0 :                 priv->action_nat64[i][RTE_FLOW_NAT64_4TO6] = act;
    9614                 :            :         }
    9615                 :            :         return 0;
    9616                 :            : }
    9617                 :            : 
    9618                 :            : /**
    9619                 :            :  * Create an egress pattern template matching on source SQ.
    9620                 :            :  *
    9621                 :            :  * @param dev
    9622                 :            :  *   Pointer to Ethernet device.
    9623                 :            :  * @param[out] error
    9624                 :            :  *   Pointer to error structure.
    9625                 :            :  *
    9626                 :            :  * @return
    9627                 :            :  *   Pointer to pattern template on success. NULL otherwise, and rte_errno is set.
    9628                 :            :  */
    9629                 :            : static struct rte_flow_pattern_template *
    9630                 :          0 : flow_hw_create_tx_repr_sq_pattern_tmpl(struct rte_eth_dev *dev, struct rte_flow_error *error)
    9631                 :            : {
    9632                 :          0 :         struct rte_flow_pattern_template_attr attr = {
    9633                 :            :                 .relaxed_matching = 0,
    9634                 :            :                 .egress = 1,
    9635                 :            :         };
    9636                 :          0 :         struct mlx5_rte_flow_item_sq sq_mask = {
    9637                 :            :                 .queue = UINT32_MAX,
    9638                 :            :         };
    9639                 :          0 :         struct rte_flow_item items[] = {
    9640                 :            :                 {
    9641                 :            :                         .type = (enum rte_flow_item_type)MLX5_RTE_FLOW_ITEM_TYPE_SQ,
    9642                 :            :                         .mask = &sq_mask,
    9643                 :            :                 },
    9644                 :            :                 {
    9645                 :            :                         .type = RTE_FLOW_ITEM_TYPE_END,
    9646                 :            :                 },
    9647                 :            :         };
    9648                 :            : 
    9649                 :          0 :         return flow_hw_pattern_template_create(dev, &attr, items, error);
    9650                 :            : }
    9651                 :            : 
    9652                 :            : static __rte_always_inline uint32_t
    9653                 :            : flow_hw_tx_tag_regc_mask(struct rte_eth_dev *dev)
    9654                 :            : {
    9655                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    9656                 :          0 :         uint32_t mask = priv->sh->dv_regc0_mask;
    9657                 :            : 
    9658                 :            :         /* Mask is verified during device initialization. Sanity checking here. */
    9659                 :            :         MLX5_ASSERT(mask != 0);
    9660                 :            :         /*
    9661                 :            :          * Availability of sufficient number of bits in REG_C_0 is verified on initialization.
    9662                 :            :          * Sanity checking here.
    9663                 :            :          */
    9664                 :            :         MLX5_ASSERT(rte_popcount32(mask) >= rte_popcount32(priv->vport_meta_mask));
    9665                 :            :         return mask;
    9666                 :            : }
    9667                 :            : 
    9668                 :            : static __rte_always_inline uint32_t
    9669                 :            : flow_hw_tx_tag_regc_value(struct rte_eth_dev *dev)
    9670                 :            : {
    9671                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    9672                 :            :         uint32_t tag;
    9673                 :            : 
    9674                 :            :         /* Mask is verified during device initialization. Sanity checking here. */
    9675                 :            :         MLX5_ASSERT(priv->vport_meta_mask != 0);
    9676         [ #  # ]:          0 :         tag = priv->vport_meta_tag >> (rte_bsf32(priv->vport_meta_mask));
    9677                 :            :         /*
    9678                 :            :          * Availability of sufficient number of bits in REG_C_0 is verified on initialization.
    9679                 :            :          * Sanity checking here.
    9680                 :            :          */
    9681                 :            :         MLX5_ASSERT((tag & priv->sh->dv_regc0_mask) == tag);
    9682                 :            :         return tag;
    9683                 :            : }
    9684                 :            : 
    9685                 :            : static void
    9686                 :            : flow_hw_update_action_mask(struct rte_flow_action *action,
    9687                 :            :                            struct rte_flow_action *mask,
    9688                 :            :                            enum rte_flow_action_type type,
    9689                 :            :                            void *conf_v,
    9690                 :            :                            void *conf_m)
    9691                 :            : {
    9692                 :          0 :         action->type = type;
    9693                 :          0 :         action->conf = conf_v;
    9694                 :          0 :         mask->type = type;
    9695                 :          0 :         mask->conf = conf_m;
    9696                 :            : }
    9697                 :            : 
    9698                 :            : /**
    9699                 :            :  * Create an egress actions template with MODIFY_FIELD action for setting unused REG_C_0 bits
    9700                 :            :  * to vport tag and JUMP action to group 1.
    9701                 :            :  *
    9702                 :            :  * If extended metadata mode is enabled, then MODIFY_FIELD action for copying software metadata
    9703                 :            :  * to REG_C_1 is added as well.
    9704                 :            :  *
    9705                 :            :  * @param dev
    9706                 :            :  *   Pointer to Ethernet device.
    9707                 :            :  * @param[out] error
    9708                 :            :  *   Pointer to error structure.
    9709                 :            :  *
    9710                 :            :  * @return
    9711                 :            :  *   Pointer to actions template on success. NULL otherwise, and rte_errno is set.
    9712                 :            :  */
    9713                 :            : static struct rte_flow_actions_template *
    9714                 :          0 : flow_hw_create_tx_repr_tag_jump_acts_tmpl(struct rte_eth_dev *dev,
    9715                 :            :                                           struct rte_flow_error *error)
    9716                 :            : {
    9717         [ #  # ]:          0 :         uint32_t tag_mask = flow_hw_tx_tag_regc_mask(dev);
    9718                 :          0 :         uint32_t tag_value = flow_hw_tx_tag_regc_value(dev);
    9719                 :          0 :         struct rte_flow_actions_template_attr attr = {
    9720                 :            :                 .egress = 1,
    9721                 :            :         };
    9722         [ #  # ]:          0 :         struct rte_flow_action_modify_field set_tag_v = {
    9723                 :            :                 .operation = RTE_FLOW_MODIFY_SET,
    9724                 :            :                 .dst = {
    9725                 :            :                         .field = (enum rte_flow_field_id)MLX5_RTE_FLOW_FIELD_META_REG,
    9726                 :            :                         .tag_index = REG_C_0,
    9727                 :            :                         .offset = rte_bsf32(tag_mask),
    9728                 :            :                 },
    9729                 :            :                 .src = {
    9730                 :            :                         .field = RTE_FLOW_FIELD_VALUE,
    9731                 :            :                 },
    9732                 :            :                 .width = rte_popcount32(tag_mask),
    9733                 :            :         };
    9734                 :          0 :         struct rte_flow_action_modify_field set_tag_m = {
    9735                 :            :                 .operation = RTE_FLOW_MODIFY_SET,
    9736                 :            :                 .dst = {
    9737                 :            :                         .field = (enum rte_flow_field_id)MLX5_RTE_FLOW_FIELD_META_REG,
    9738                 :            :                         .level = UINT8_MAX,
    9739                 :            :                         .tag_index = UINT8_MAX,
    9740                 :            :                         .offset = UINT32_MAX,
    9741                 :            :                 },
    9742                 :            :                 .src = {
    9743                 :            :                         .field = RTE_FLOW_FIELD_VALUE,
    9744                 :            :                 },
    9745                 :            :                 .width = UINT32_MAX,
    9746                 :            :         };
    9747                 :          0 :         struct rte_flow_action_modify_field copy_metadata_v = {
    9748                 :            :                 .operation = RTE_FLOW_MODIFY_SET,
    9749                 :            :                 .dst = {
    9750                 :            :                         .field = (enum rte_flow_field_id)MLX5_RTE_FLOW_FIELD_META_REG,
    9751                 :            :                         .tag_index = REG_C_1,
    9752                 :            :                 },
    9753                 :            :                 .src = {
    9754                 :            :                         .field = (enum rte_flow_field_id)MLX5_RTE_FLOW_FIELD_META_REG,
    9755                 :            :                         .tag_index = REG_A,
    9756                 :            :                 },
    9757                 :            :                 .width = 32,
    9758                 :            :         };
    9759                 :          0 :         struct rte_flow_action_modify_field copy_metadata_m = {
    9760                 :            :                 .operation = RTE_FLOW_MODIFY_SET,
    9761                 :            :                 .dst = {
    9762                 :            :                         .field = (enum rte_flow_field_id)MLX5_RTE_FLOW_FIELD_META_REG,
    9763                 :            :                         .level = UINT8_MAX,
    9764                 :            :                         .tag_index = UINT8_MAX,
    9765                 :            :                         .offset = UINT32_MAX,
    9766                 :            :                 },
    9767                 :            :                 .src = {
    9768                 :            :                         .field = (enum rte_flow_field_id)MLX5_RTE_FLOW_FIELD_META_REG,
    9769                 :            :                         .level = UINT8_MAX,
    9770                 :            :                         .tag_index = UINT8_MAX,
    9771                 :            :                         .offset = UINT32_MAX,
    9772                 :            :                 },
    9773                 :            :                 .width = UINT32_MAX,
    9774                 :            :         };
    9775                 :          0 :         struct rte_flow_action_jump jump_v = {
    9776                 :            :                 .group = MLX5_HW_LOWEST_USABLE_GROUP,
    9777                 :            :         };
    9778                 :          0 :         struct rte_flow_action_jump jump_m = {
    9779                 :            :                 .group = UINT32_MAX,
    9780                 :            :         };
    9781                 :          0 :         struct rte_flow_action actions_v[4] = { { 0 } };
    9782         [ #  # ]:          0 :         struct rte_flow_action actions_m[4] = { { 0 } };
    9783                 :            :         unsigned int idx = 0;
    9784                 :            : 
    9785                 :            :         rte_memcpy(set_tag_v.src.value, &tag_value, sizeof(tag_value));
    9786                 :            :         rte_memcpy(set_tag_m.src.value, &tag_mask, sizeof(tag_mask));
    9787                 :            :         flow_hw_update_action_mask(&actions_v[idx], &actions_m[idx],
    9788                 :            :                                    RTE_FLOW_ACTION_TYPE_MODIFY_FIELD,
    9789                 :            :                                    &set_tag_v, &set_tag_m);
    9790                 :            :         idx++;
    9791         [ #  # ]:          0 :         if (MLX5_SH(dev)->config.dv_xmeta_en == MLX5_XMETA_MODE_META32_HWS) {
    9792                 :            :                 flow_hw_update_action_mask(&actions_v[idx], &actions_m[idx],
    9793                 :            :                                            RTE_FLOW_ACTION_TYPE_MODIFY_FIELD,
    9794                 :            :                                            &copy_metadata_v, &copy_metadata_m);
    9795                 :            :                 idx++;
    9796                 :            :         }
    9797                 :            :         flow_hw_update_action_mask(&actions_v[idx], &actions_m[idx], RTE_FLOW_ACTION_TYPE_JUMP,
    9798                 :            :                                    &jump_v, &jump_m);
    9799                 :          0 :         idx++;
    9800                 :            :         flow_hw_update_action_mask(&actions_v[idx], &actions_m[idx], RTE_FLOW_ACTION_TYPE_END,
    9801                 :            :                                    NULL, NULL);
    9802                 :            :         idx++;
    9803                 :            :         MLX5_ASSERT(idx <= RTE_DIM(actions_v));
    9804                 :          0 :         return flow_hw_actions_template_create(dev, &attr, actions_v, actions_m, error);
    9805                 :            : }
    9806                 :            : 
    9807                 :            : static void
    9808                 :          0 : flow_hw_cleanup_tx_repr_tagging(struct rte_eth_dev *dev)
    9809                 :            : {
    9810                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    9811                 :            : 
    9812         [ #  # ]:          0 :         if (priv->hw_tx_repr_tagging_tbl) {
    9813                 :          0 :                 flow_hw_table_destroy(dev, priv->hw_tx_repr_tagging_tbl, NULL);
    9814                 :          0 :                 priv->hw_tx_repr_tagging_tbl = NULL;
    9815                 :            :         }
    9816         [ #  # ]:          0 :         if (priv->hw_tx_repr_tagging_at) {
    9817                 :          0 :                 flow_hw_actions_template_destroy(dev, priv->hw_tx_repr_tagging_at, NULL);
    9818                 :          0 :                 priv->hw_tx_repr_tagging_at = NULL;
    9819                 :            :         }
    9820         [ #  # ]:          0 :         if (priv->hw_tx_repr_tagging_pt) {
    9821                 :          0 :                 flow_hw_pattern_template_destroy(dev, priv->hw_tx_repr_tagging_pt, NULL);
    9822                 :          0 :                 priv->hw_tx_repr_tagging_pt = NULL;
    9823                 :            :         }
    9824                 :          0 : }
    9825                 :            : 
    9826                 :            : /**
    9827                 :            :  * Setup templates and table used to create default Tx flow rules. These default rules
    9828                 :            :  * allow for matching Tx representor traffic using a vport tag placed in unused bits of
    9829                 :            :  * REG_C_0 register.
    9830                 :            :  *
    9831                 :            :  * @param dev
    9832                 :            :  *   Pointer to Ethernet device.
    9833                 :            :  * @param[out] error
    9834                 :            :  *   Pointer to error structure.
    9835                 :            :  *
    9836                 :            :  * @return
    9837                 :            :  *   0 on success, negative errno value otherwise.
    9838                 :            :  */
    9839                 :            : static int
    9840                 :          0 : flow_hw_setup_tx_repr_tagging(struct rte_eth_dev *dev, struct rte_flow_error *error)
    9841                 :            : {
    9842                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    9843                 :          0 :         struct rte_flow_template_table_attr attr = {
    9844                 :            :                 .flow_attr = {
    9845                 :            :                         .group = 0,
    9846                 :            :                         .priority = MLX5_HW_LOWEST_PRIO_ROOT,
    9847                 :            :                         .egress = 1,
    9848                 :            :                 },
    9849                 :            :                 .nb_flows = MLX5_HW_CTRL_FLOW_NB_RULES,
    9850                 :            :         };
    9851                 :          0 :         struct mlx5_flow_template_table_cfg cfg = {
    9852                 :            :                 .attr = attr,
    9853                 :            :                 .external = false,
    9854                 :            :         };
    9855                 :            : 
    9856                 :            :         MLX5_ASSERT(priv->sh->config.dv_esw_en);
    9857                 :            :         MLX5_ASSERT(priv->sh->config.repr_matching);
    9858                 :          0 :         priv->hw_tx_repr_tagging_pt =
    9859                 :          0 :                 flow_hw_create_tx_repr_sq_pattern_tmpl(dev, error);
    9860         [ #  # ]:          0 :         if (!priv->hw_tx_repr_tagging_pt)
    9861                 :          0 :                 goto err;
    9862                 :          0 :         priv->hw_tx_repr_tagging_at =
    9863                 :          0 :                 flow_hw_create_tx_repr_tag_jump_acts_tmpl(dev, error);
    9864         [ #  # ]:          0 :         if (!priv->hw_tx_repr_tagging_at)
    9865                 :          0 :                 goto err;
    9866                 :          0 :         priv->hw_tx_repr_tagging_tbl = flow_hw_table_create(dev, &cfg,
    9867                 :            :                                                             &priv->hw_tx_repr_tagging_pt, 1,
    9868                 :            :                                                             &priv->hw_tx_repr_tagging_at, 1,
    9869                 :            :                                                             error);
    9870         [ #  # ]:          0 :         if (!priv->hw_tx_repr_tagging_tbl)
    9871                 :          0 :                 goto err;
    9872                 :            :         return 0;
    9873                 :          0 : err:
    9874                 :          0 :         flow_hw_cleanup_tx_repr_tagging(dev);
    9875                 :          0 :         return -rte_errno;
    9876                 :            : }
    9877                 :            : 
    9878                 :            : static uint32_t
    9879                 :            : flow_hw_esw_mgr_regc_marker_mask(struct rte_eth_dev *dev)
    9880                 :            : {
    9881                 :          0 :         uint32_t mask = MLX5_SH(dev)->dv_regc0_mask;
    9882                 :            : 
    9883                 :            :         /* Mask is verified during device initialization. */
    9884                 :            :         MLX5_ASSERT(mask != 0);
    9885                 :            :         return mask;
    9886                 :            : }
    9887                 :            : 
    9888                 :            : static uint32_t
    9889                 :            : flow_hw_esw_mgr_regc_marker(struct rte_eth_dev *dev)
    9890                 :            : {
    9891                 :          0 :         uint32_t mask = MLX5_SH(dev)->dv_regc0_mask;
    9892                 :            : 
    9893                 :            :         /* Mask is verified during device initialization. */
    9894                 :            :         MLX5_ASSERT(mask != 0);
    9895                 :          0 :         return RTE_BIT32(rte_bsf32(mask));
    9896                 :            : }
    9897                 :            : 
    9898                 :            : /**
    9899                 :            :  * Creates a flow pattern template used to match on E-Switch Manager.
    9900                 :            :  * This template is used to set up a table for SQ miss default flow.
    9901                 :            :  *
    9902                 :            :  * @param dev
    9903                 :            :  *   Pointer to Ethernet device.
    9904                 :            :  * @param error
    9905                 :            :  *   Pointer to error structure.
    9906                 :            :  *
    9907                 :            :  * @return
    9908                 :            :  *   Pointer to flow pattern template on success, NULL otherwise.
    9909                 :            :  */
    9910                 :            : static struct rte_flow_pattern_template *
    9911                 :          0 : flow_hw_create_ctrl_esw_mgr_pattern_template(struct rte_eth_dev *dev,
    9912                 :            :                                              struct rte_flow_error *error)
    9913                 :            : {
    9914                 :          0 :         struct rte_flow_pattern_template_attr attr = {
    9915                 :            :                 .relaxed_matching = 0,
    9916                 :            :                 .transfer = 1,
    9917                 :            :         };
    9918                 :          0 :         struct rte_flow_item_ethdev port_spec = {
    9919                 :            :                 .port_id = MLX5_REPRESENTED_PORT_ESW_MGR,
    9920                 :            :         };
    9921                 :          0 :         struct rte_flow_item_ethdev port_mask = {
    9922                 :            :                 .port_id = UINT16_MAX,
    9923                 :            :         };
    9924                 :          0 :         struct mlx5_rte_flow_item_sq sq_mask = {
    9925                 :            :                 .queue = UINT32_MAX,
    9926                 :            :         };
    9927                 :          0 :         struct rte_flow_item items[] = {
    9928                 :            :                 {
    9929                 :            :                         .type = RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT,
    9930                 :            :                         .spec = &port_spec,
    9931                 :            :                         .mask = &port_mask,
    9932                 :            :                 },
    9933                 :            :                 {
    9934                 :            :                         .type = (enum rte_flow_item_type)MLX5_RTE_FLOW_ITEM_TYPE_SQ,
    9935                 :            :                         .mask = &sq_mask,
    9936                 :            :                 },
    9937                 :            :                 {
    9938                 :            :                         .type = RTE_FLOW_ITEM_TYPE_END,
    9939                 :            :                 },
    9940                 :            :         };
    9941                 :            : 
    9942                 :          0 :         return flow_hw_pattern_template_create(dev, &attr, items, error);
    9943                 :            : }
    9944                 :            : 
    9945                 :            : /**
    9946                 :            :  * Creates a flow pattern template used to match REG_C_0 and a SQ.
    9947                 :            :  * Matching on REG_C_0 is set up to match on all bits usable by user-space.
    9948                 :            :  * If traffic was sent from E-Switch Manager, then all usable bits will be set to 0,
    9949                 :            :  * except the least significant bit, which will be set to 1.
    9950                 :            :  *
    9951                 :            :  * This template is used to set up a table for SQ miss default flow.
    9952                 :            :  *
    9953                 :            :  * @param dev
    9954                 :            :  *   Pointer to Ethernet device.
    9955                 :            :  * @param error
    9956                 :            :  *   Pointer to error structure.
    9957                 :            :  *
    9958                 :            :  * @return
    9959                 :            :  *   Pointer to flow pattern template on success, NULL otherwise.
    9960                 :            :  */
    9961                 :            : static struct rte_flow_pattern_template *
    9962                 :          0 : flow_hw_create_ctrl_regc_sq_pattern_template(struct rte_eth_dev *dev,
    9963                 :            :                                              struct rte_flow_error *error)
    9964                 :            : {
    9965                 :          0 :         struct rte_flow_pattern_template_attr attr = {
    9966                 :            :                 .relaxed_matching = 0,
    9967                 :            :                 .transfer = 1,
    9968                 :            :         };
    9969                 :          0 :         struct rte_flow_item_tag reg_c0_spec = {
    9970                 :            :                 .index = (uint8_t)REG_C_0,
    9971                 :            :         };
    9972                 :          0 :         struct rte_flow_item_tag reg_c0_mask = {
    9973                 :            :                 .index = 0xff,
    9974                 :            :                 .data = flow_hw_esw_mgr_regc_marker_mask(dev),
    9975                 :            :         };
    9976                 :          0 :         struct mlx5_rte_flow_item_sq queue_mask = {
    9977                 :            :                 .queue = UINT32_MAX,
    9978                 :            :         };
    9979                 :          0 :         struct rte_flow_item items[] = {
    9980                 :            :                 {
    9981                 :            :                         .type = (enum rte_flow_item_type)
    9982                 :            :                                 MLX5_RTE_FLOW_ITEM_TYPE_TAG,
    9983                 :            :                         .spec = &reg_c0_spec,
    9984                 :            :                         .mask = &reg_c0_mask,
    9985                 :            :                 },
    9986                 :            :                 {
    9987                 :            :                         .type = (enum rte_flow_item_type)
    9988                 :            :                                 MLX5_RTE_FLOW_ITEM_TYPE_SQ,
    9989                 :            :                         .mask = &queue_mask,
    9990                 :            :                 },
    9991                 :            :                 {
    9992                 :            :                         .type = RTE_FLOW_ITEM_TYPE_END,
    9993                 :            :                 },
    9994                 :            :         };
    9995                 :            : 
    9996                 :          0 :         return flow_hw_pattern_template_create(dev, &attr, items, error);
    9997                 :            : }
    9998                 :            : 
    9999                 :            : /**
   10000                 :            :  * Creates a flow pattern template with unmasked represented port matching.
   10001                 :            :  * This template is used to set up a table for default transfer flows
   10002                 :            :  * directing packets to group 1.
   10003                 :            :  *
   10004                 :            :  * @param dev
   10005                 :            :  *   Pointer to Ethernet device.
   10006                 :            :  * @param error
   10007                 :            :  *   Pointer to error structure.
   10008                 :            :  *
   10009                 :            :  * @return
   10010                 :            :  *   Pointer to flow pattern template on success, NULL otherwise.
   10011                 :            :  */
   10012                 :            : static struct rte_flow_pattern_template *
   10013                 :          0 : flow_hw_create_ctrl_port_pattern_template(struct rte_eth_dev *dev,
   10014                 :            :                                           struct rte_flow_error *error)
   10015                 :            : {
   10016                 :          0 :         struct rte_flow_pattern_template_attr attr = {
   10017                 :            :                 .relaxed_matching = 0,
   10018                 :            :                 .transfer = 1,
   10019                 :            :         };
   10020                 :          0 :         struct rte_flow_item_ethdev port_mask = {
   10021                 :            :                 .port_id = UINT16_MAX,
   10022                 :            :         };
   10023                 :          0 :         struct rte_flow_item items[] = {
   10024                 :            :                 {
   10025                 :            :                         .type = RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT,
   10026                 :            :                         .mask = &port_mask,
   10027                 :            :                 },
   10028                 :            :                 {
   10029                 :            :                         .type = RTE_FLOW_ITEM_TYPE_END,
   10030                 :            :                 },
   10031                 :            :         };
   10032                 :            : 
   10033                 :          0 :         return flow_hw_pattern_template_create(dev, &attr, items, error);
   10034                 :            : }
   10035                 :            : 
   10036                 :            : /*
   10037                 :            :  * Creating a flow pattern template with all ETH packets matching.
   10038                 :            :  * This template is used to set up a table for default Tx copy (Tx metadata
   10039                 :            :  * to REG_C_1) flow rule usage.
   10040                 :            :  *
   10041                 :            :  * @param dev
   10042                 :            :  *   Pointer to Ethernet device.
   10043                 :            :  * @param error
   10044                 :            :  *   Pointer to error structure.
   10045                 :            :  *
   10046                 :            :  * @return
   10047                 :            :  *   Pointer to flow pattern template on success, NULL otherwise.
   10048                 :            :  */
   10049                 :            : static struct rte_flow_pattern_template *
   10050                 :          0 : flow_hw_create_tx_default_mreg_copy_pattern_template(struct rte_eth_dev *dev,
   10051                 :            :                                                      struct rte_flow_error *error)
   10052                 :            : {
   10053                 :          0 :         struct rte_flow_pattern_template_attr tx_pa_attr = {
   10054                 :            :                 .relaxed_matching = 0,
   10055                 :            :                 .egress = 1,
   10056                 :            :         };
   10057                 :          0 :         struct rte_flow_item_eth promisc = {
   10058                 :            :                 .hdr.dst_addr.addr_bytes = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
   10059                 :            :                 .hdr.src_addr.addr_bytes = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
   10060                 :            :                 .hdr.ether_type = 0,
   10061                 :            :         };
   10062                 :          0 :         struct rte_flow_item eth_all[] = {
   10063                 :            :                 [0] = {
   10064                 :            :                         .type = RTE_FLOW_ITEM_TYPE_ETH,
   10065                 :            :                         .spec = &promisc,
   10066                 :            :                         .mask = &promisc,
   10067                 :            :                 },
   10068                 :            :                 [1] = {
   10069                 :            :                         .type = RTE_FLOW_ITEM_TYPE_END,
   10070                 :            :                 },
   10071                 :            :         };
   10072                 :            : 
   10073                 :          0 :         return flow_hw_pattern_template_create(dev, &tx_pa_attr, eth_all, error);
   10074                 :            : }
   10075                 :            : 
   10076                 :            : /*
   10077                 :            :  * Creating a flow pattern template with all LACP packets matching, only for NIC
   10078                 :            :  * ingress domain.
   10079                 :            :  *
   10080                 :            :  * @param dev
   10081                 :            :  *   Pointer to Ethernet device.
   10082                 :            :  * @param error
   10083                 :            :  *   Pointer to error structure.
   10084                 :            :  *
   10085                 :            :  * @return
   10086                 :            :  *   Pointer to flow pattern template on success, NULL otherwise.
   10087                 :            :  */
   10088                 :            : static struct rte_flow_pattern_template *
   10089                 :          0 : flow_hw_create_lacp_rx_pattern_template(struct rte_eth_dev *dev, struct rte_flow_error *error)
   10090                 :            : {
   10091                 :          0 :         struct rte_flow_pattern_template_attr pa_attr = {
   10092                 :            :                 .relaxed_matching = 0,
   10093                 :            :                 .ingress = 1,
   10094                 :            :         };
   10095                 :          0 :         struct rte_flow_item_eth lacp_mask = {
   10096                 :            :                 .dst.addr_bytes = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
   10097                 :            :                 .src.addr_bytes = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
   10098                 :            :                 .type = 0xFFFF,
   10099                 :            :         };
   10100                 :          0 :         struct rte_flow_item eth_all[] = {
   10101                 :            :                 [0] = {
   10102                 :            :                         .type = RTE_FLOW_ITEM_TYPE_ETH,
   10103                 :            :                         .mask = &lacp_mask,
   10104                 :            :                 },
   10105                 :            :                 [1] = {
   10106                 :            :                         .type = RTE_FLOW_ITEM_TYPE_END,
   10107                 :            :                 },
   10108                 :            :         };
   10109                 :          0 :         return flow_hw_pattern_template_create(dev, &pa_attr, eth_all, error);
   10110                 :            : }
   10111                 :            : 
   10112                 :            : /**
   10113                 :            :  * Creates a flow actions template with modify field action and masked jump action.
   10114                 :            :  * Modify field action sets the least significant bit of REG_C_0 (usable by user-space)
   10115                 :            :  * to 1, meaning that packet was originated from E-Switch Manager. Jump action
   10116                 :            :  * transfers steering to group 1.
   10117                 :            :  *
   10118                 :            :  * @param dev
   10119                 :            :  *   Pointer to Ethernet device.
   10120                 :            :  * @param error
   10121                 :            :  *   Pointer to error structure.
   10122                 :            :  *
   10123                 :            :  * @return
   10124                 :            :  *   Pointer to flow actions template on success, NULL otherwise.
   10125                 :            :  */
   10126                 :            : static struct rte_flow_actions_template *
   10127                 :          0 : flow_hw_create_ctrl_regc_jump_actions_template(struct rte_eth_dev *dev,
   10128                 :            :                                                struct rte_flow_error *error)
   10129                 :            : {
   10130         [ #  # ]:          0 :         uint32_t marker_mask = flow_hw_esw_mgr_regc_marker_mask(dev);
   10131                 :          0 :         uint32_t marker_bits = flow_hw_esw_mgr_regc_marker(dev);
   10132                 :          0 :         struct rte_flow_actions_template_attr attr = {
   10133                 :            :                 .transfer = 1,
   10134                 :            :         };
   10135         [ #  # ]:          0 :         struct rte_flow_action_modify_field set_reg_v = {
   10136                 :            :                 .operation = RTE_FLOW_MODIFY_SET,
   10137                 :            :                 .dst = {
   10138                 :            :                         .field = (enum rte_flow_field_id)MLX5_RTE_FLOW_FIELD_META_REG,
   10139                 :            :                         .tag_index = REG_C_0,
   10140                 :            :                 },
   10141                 :            :                 .src = {
   10142                 :            :                         .field = RTE_FLOW_FIELD_VALUE,
   10143                 :            :                 },
   10144                 :            :                 .width = rte_popcount32(marker_mask),
   10145                 :            :         };
   10146                 :          0 :         struct rte_flow_action_modify_field set_reg_m = {
   10147                 :            :                 .operation = RTE_FLOW_MODIFY_SET,
   10148                 :            :                 .dst = {
   10149                 :            :                         .field = (enum rte_flow_field_id)MLX5_RTE_FLOW_FIELD_META_REG,
   10150                 :            :                         .level = UINT8_MAX,
   10151                 :            :                         .tag_index = UINT8_MAX,
   10152                 :            :                         .offset = UINT32_MAX,
   10153                 :            :                 },
   10154                 :            :                 .src = {
   10155                 :            :                         .field = RTE_FLOW_FIELD_VALUE,
   10156                 :            :                 },
   10157                 :            :                 .width = UINT32_MAX,
   10158                 :            :         };
   10159                 :          0 :         struct rte_flow_action_jump jump_v = {
   10160                 :            :                 .group = MLX5_HW_LOWEST_USABLE_GROUP,
   10161                 :            :         };
   10162                 :          0 :         struct rte_flow_action_jump jump_m = {
   10163                 :            :                 .group = UINT32_MAX,
   10164                 :            :         };
   10165                 :          0 :         struct rte_flow_action actions_v[] = {
   10166                 :            :                 {
   10167                 :            :                         .type = RTE_FLOW_ACTION_TYPE_MODIFY_FIELD,
   10168                 :            :                         .conf = &set_reg_v,
   10169                 :            :                 },
   10170                 :            :                 {
   10171                 :            :                         .type = RTE_FLOW_ACTION_TYPE_JUMP,
   10172                 :            :                         .conf = &jump_v,
   10173                 :            :                 },
   10174                 :            :                 {
   10175                 :            :                         .type = RTE_FLOW_ACTION_TYPE_END,
   10176                 :            :                 }
   10177                 :            :         };
   10178                 :          0 :         struct rte_flow_action actions_m[] = {
   10179                 :            :                 {
   10180                 :            :                         .type = RTE_FLOW_ACTION_TYPE_MODIFY_FIELD,
   10181                 :            :                         .conf = &set_reg_m,
   10182                 :            :                 },
   10183                 :            :                 {
   10184                 :            :                         .type = RTE_FLOW_ACTION_TYPE_JUMP,
   10185                 :            :                         .conf = &jump_m,
   10186                 :            :                 },
   10187                 :            :                 {
   10188                 :            :                         .type = RTE_FLOW_ACTION_TYPE_END,
   10189                 :            :                 }
   10190                 :            :         };
   10191                 :            : 
   10192         [ #  # ]:          0 :         set_reg_v.dst.offset = rte_bsf32(marker_mask);
   10193                 :            :         rte_memcpy(set_reg_v.src.value, &marker_bits, sizeof(marker_bits));
   10194                 :            :         rte_memcpy(set_reg_m.src.value, &marker_mask, sizeof(marker_mask));
   10195                 :          0 :         return flow_hw_actions_template_create(dev, &attr, actions_v, actions_m, error);
   10196                 :            : }
   10197                 :            : 
   10198                 :            : /**
   10199                 :            :  * Creates a flow actions template with an unmasked JUMP action. Flows
   10200                 :            :  * based on this template will perform a jump to some group. This template
   10201                 :            :  * is used to set up tables for control flows.
   10202                 :            :  *
   10203                 :            :  * @param dev
   10204                 :            :  *   Pointer to Ethernet device.
   10205                 :            :  * @param group
   10206                 :            :  *   Destination group for this action template.
   10207                 :            :  * @param error
   10208                 :            :  *   Pointer to error structure.
   10209                 :            :  *
   10210                 :            :  * @return
   10211                 :            :  *   Pointer to flow actions template on success, NULL otherwise.
   10212                 :            :  */
   10213                 :            : static struct rte_flow_actions_template *
   10214                 :          0 : flow_hw_create_ctrl_jump_actions_template(struct rte_eth_dev *dev,
   10215                 :            :                                           uint32_t group,
   10216                 :            :                                           struct rte_flow_error *error)
   10217                 :            : {
   10218                 :          0 :         struct rte_flow_actions_template_attr attr = {
   10219                 :            :                 .transfer = 1,
   10220                 :            :         };
   10221                 :          0 :         struct rte_flow_action_jump jump_v = {
   10222                 :            :                 .group = group,
   10223                 :            :         };
   10224                 :          0 :         struct rte_flow_action_jump jump_m = {
   10225                 :            :                 .group = UINT32_MAX,
   10226                 :            :         };
   10227                 :          0 :         struct rte_flow_action actions_v[] = {
   10228                 :            :                 {
   10229                 :            :                         .type = RTE_FLOW_ACTION_TYPE_JUMP,
   10230                 :            :                         .conf = &jump_v,
   10231                 :            :                 },
   10232                 :            :                 {
   10233                 :            :                         .type = RTE_FLOW_ACTION_TYPE_END,
   10234                 :            :                 }
   10235                 :            :         };
   10236                 :          0 :         struct rte_flow_action actions_m[] = {
   10237                 :            :                 {
   10238                 :            :                         .type = RTE_FLOW_ACTION_TYPE_JUMP,
   10239                 :            :                         .conf = &jump_m,
   10240                 :            :                 },
   10241                 :            :                 {
   10242                 :            :                         .type = RTE_FLOW_ACTION_TYPE_END,
   10243                 :            :                 }
   10244                 :            :         };
   10245                 :            : 
   10246                 :          0 :         return flow_hw_actions_template_create(dev, &attr, actions_v,
   10247                 :            :                                                actions_m, error);
   10248                 :            : }
   10249                 :            : 
   10250                 :            : /**
   10251                 :            :  * Creates a flow action template with a unmasked REPRESENTED_PORT action.
   10252                 :            :  * It is used to create control flow tables.
   10253                 :            :  *
   10254                 :            :  * @param dev
   10255                 :            :  *   Pointer to Ethernet device.
   10256                 :            :  * @param error
   10257                 :            :  *   Pointer to error structure.
   10258                 :            :  *
   10259                 :            :  * @return
   10260                 :            :  *   Pointer to flow action template on success, NULL otherwise.
   10261                 :            :  */
   10262                 :            : static struct rte_flow_actions_template *
   10263                 :          0 : flow_hw_create_ctrl_port_actions_template(struct rte_eth_dev *dev,
   10264                 :            :                                           struct rte_flow_error *error)
   10265                 :            : {
   10266                 :          0 :         struct rte_flow_actions_template_attr attr = {
   10267                 :            :                 .transfer = 1,
   10268                 :            :         };
   10269                 :          0 :         struct rte_flow_action_ethdev port_v = {
   10270                 :            :                 .port_id = 0,
   10271                 :            :         };
   10272                 :          0 :         struct rte_flow_action actions_v[] = {
   10273                 :            :                 {
   10274                 :            :                         .type = RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT,
   10275                 :            :                         .conf = &port_v,
   10276                 :            :                 },
   10277                 :            :                 {
   10278                 :            :                         .type = RTE_FLOW_ACTION_TYPE_END,
   10279                 :            :                 }
   10280                 :            :         };
   10281                 :          0 :         struct rte_flow_action_ethdev port_m = {
   10282                 :            :                 .port_id = 0,
   10283                 :            :         };
   10284                 :          0 :         struct rte_flow_action actions_m[] = {
   10285                 :            :                 {
   10286                 :            :                         .type = RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT,
   10287                 :            :                         .conf = &port_m,
   10288                 :            :                 },
   10289                 :            :                 {
   10290                 :            :                         .type = RTE_FLOW_ACTION_TYPE_END,
   10291                 :            :                 }
   10292                 :            :         };
   10293                 :            : 
   10294                 :          0 :         return flow_hw_actions_template_create(dev, &attr, actions_v, actions_m, error);
   10295                 :            : }
   10296                 :            : 
   10297                 :            : /*
   10298                 :            :  * Creating an actions template to use header modify action for register
   10299                 :            :  * copying. This template is used to set up a table for copy flow.
   10300                 :            :  *
   10301                 :            :  * @param dev
   10302                 :            :  *   Pointer to Ethernet device.
   10303                 :            :  * @param error
   10304                 :            :  *   Pointer to error structure.
   10305                 :            :  *
   10306                 :            :  * @return
   10307                 :            :  *   Pointer to flow actions template on success, NULL otherwise.
   10308                 :            :  */
   10309                 :            : static struct rte_flow_actions_template *
   10310                 :          0 : flow_hw_create_tx_default_mreg_copy_actions_template(struct rte_eth_dev *dev,
   10311                 :            :                                                      struct rte_flow_error *error)
   10312                 :            : {
   10313                 :          0 :         struct rte_flow_actions_template_attr tx_act_attr = {
   10314                 :            :                 .egress = 1,
   10315                 :            :         };
   10316                 :          0 :         const struct rte_flow_action_modify_field mreg_action = {
   10317                 :            :                 .operation = RTE_FLOW_MODIFY_SET,
   10318                 :            :                 .dst = {
   10319                 :            :                         .field = (enum rte_flow_field_id)MLX5_RTE_FLOW_FIELD_META_REG,
   10320                 :            :                         .tag_index = REG_C_1,
   10321                 :            :                 },
   10322                 :            :                 .src = {
   10323                 :            :                         .field = (enum rte_flow_field_id)MLX5_RTE_FLOW_FIELD_META_REG,
   10324                 :            :                         .tag_index = REG_A,
   10325                 :            :                 },
   10326                 :            :                 .width = 32,
   10327                 :            :         };
   10328                 :          0 :         const struct rte_flow_action_modify_field mreg_mask = {
   10329                 :            :                 .operation = RTE_FLOW_MODIFY_SET,
   10330                 :            :                 .dst = {
   10331                 :            :                         .field = (enum rte_flow_field_id)MLX5_RTE_FLOW_FIELD_META_REG,
   10332                 :            :                         .level = UINT8_MAX,
   10333                 :            :                         .tag_index = UINT8_MAX,
   10334                 :            :                         .offset = UINT32_MAX,
   10335                 :            :                 },
   10336                 :            :                 .src = {
   10337                 :            :                         .field = (enum rte_flow_field_id)MLX5_RTE_FLOW_FIELD_META_REG,
   10338                 :            :                         .level = UINT8_MAX,
   10339                 :            :                         .tag_index = UINT8_MAX,
   10340                 :            :                         .offset = UINT32_MAX,
   10341                 :            :                 },
   10342                 :            :                 .width = UINT32_MAX,
   10343                 :            :         };
   10344                 :          0 :         const struct rte_flow_action_jump jump_action = {
   10345                 :            :                 .group = 1,
   10346                 :            :         };
   10347                 :          0 :         const struct rte_flow_action_jump jump_mask = {
   10348                 :            :                 .group = UINT32_MAX,
   10349                 :            :         };
   10350                 :          0 :         const struct rte_flow_action actions[] = {
   10351                 :            :                 [0] = {
   10352                 :            :                         .type = RTE_FLOW_ACTION_TYPE_MODIFY_FIELD,
   10353                 :            :                         .conf = &mreg_action,
   10354                 :            :                 },
   10355                 :            :                 [1] = {
   10356                 :            :                         .type = RTE_FLOW_ACTION_TYPE_JUMP,
   10357                 :            :                         .conf = &jump_action,
   10358                 :            :                 },
   10359                 :            :                 [2] = {
   10360                 :            :                         .type = RTE_FLOW_ACTION_TYPE_END,
   10361                 :            :                 },
   10362                 :            :         };
   10363                 :          0 :         const struct rte_flow_action masks[] = {
   10364                 :            :                 [0] = {
   10365                 :            :                         .type = RTE_FLOW_ACTION_TYPE_MODIFY_FIELD,
   10366                 :            :                         .conf = &mreg_mask,
   10367                 :            :                 },
   10368                 :            :                 [1] = {
   10369                 :            :                         .type = RTE_FLOW_ACTION_TYPE_JUMP,
   10370                 :            :                         .conf = &jump_mask,
   10371                 :            :                 },
   10372                 :            :                 [2] = {
   10373                 :            :                         .type = RTE_FLOW_ACTION_TYPE_END,
   10374                 :            :                 },
   10375                 :            :         };
   10376                 :            : 
   10377                 :          0 :         return flow_hw_actions_template_create(dev, &tx_act_attr, actions,
   10378                 :            :                                                masks, error);
   10379                 :            : }
   10380                 :            : 
   10381                 :            : /*
   10382                 :            :  * Creating an actions template to use default miss to re-route packets to the
   10383                 :            :  * kernel driver stack.
   10384                 :            :  * On root table, only DEFAULT_MISS action can be used.
   10385                 :            :  *
   10386                 :            :  * @param dev
   10387                 :            :  *   Pointer to Ethernet device.
   10388                 :            :  * @param error
   10389                 :            :  *   Pointer to error structure.
   10390                 :            :  *
   10391                 :            :  * @return
   10392                 :            :  *   Pointer to flow actions template on success, NULL otherwise.
   10393                 :            :  */
   10394                 :            : static struct rte_flow_actions_template *
   10395                 :          0 : flow_hw_create_lacp_rx_actions_template(struct rte_eth_dev *dev, struct rte_flow_error *error)
   10396                 :            : {
   10397                 :          0 :         struct rte_flow_actions_template_attr act_attr = {
   10398                 :            :                 .ingress = 1,
   10399                 :            :         };
   10400                 :          0 :         const struct rte_flow_action actions[] = {
   10401                 :            :                 [0] = {
   10402                 :            :                         .type = (enum rte_flow_action_type)
   10403                 :            :                                 MLX5_RTE_FLOW_ACTION_TYPE_DEFAULT_MISS,
   10404                 :            :                 },
   10405                 :            :                 [1] = {
   10406                 :            :                         .type = RTE_FLOW_ACTION_TYPE_END,
   10407                 :            :                 },
   10408                 :            :         };
   10409                 :            : 
   10410                 :          0 :         return flow_hw_actions_template_create(dev, &act_attr, actions, actions, error);
   10411                 :            : }
   10412                 :            : 
   10413                 :            : /**
   10414                 :            :  * Creates a control flow table used to transfer traffic from E-Switch Manager
   10415                 :            :  * and TX queues from group 0 to group 1.
   10416                 :            :  *
   10417                 :            :  * @param dev
   10418                 :            :  *   Pointer to Ethernet device.
   10419                 :            :  * @param it
   10420                 :            :  *   Pointer to flow pattern template.
   10421                 :            :  * @param at
   10422                 :            :  *   Pointer to flow actions template.
   10423                 :            :  * @param error
   10424                 :            :  *   Pointer to error structure.
   10425                 :            :  *
   10426                 :            :  * @return
   10427                 :            :  *   Pointer to flow table on success, NULL otherwise.
   10428                 :            :  */
   10429                 :            : static struct rte_flow_template_table*
   10430                 :          0 : flow_hw_create_ctrl_sq_miss_root_table(struct rte_eth_dev *dev,
   10431                 :            :                                        struct rte_flow_pattern_template *it,
   10432                 :            :                                        struct rte_flow_actions_template *at,
   10433                 :            :                                        struct rte_flow_error *error)
   10434                 :            : {
   10435                 :          0 :         struct rte_flow_template_table_attr attr = {
   10436                 :            :                 .flow_attr = {
   10437                 :            :                         .group = 0,
   10438                 :            :                         .priority = MLX5_HW_LOWEST_PRIO_ROOT,
   10439                 :            :                         .ingress = 0,
   10440                 :            :                         .egress = 0,
   10441                 :            :                         .transfer = 1,
   10442                 :            :                 },
   10443                 :            :                 .nb_flows = MLX5_HW_CTRL_FLOW_NB_RULES,
   10444                 :            :         };
   10445                 :          0 :         struct mlx5_flow_template_table_cfg cfg = {
   10446                 :            :                 .attr = attr,
   10447                 :            :                 .external = false,
   10448                 :            :         };
   10449                 :            : 
   10450                 :          0 :         return flow_hw_table_create(dev, &cfg, &it, 1, &at, 1, error);
   10451                 :            : }
   10452                 :            : 
   10453                 :            : 
   10454                 :            : /**
   10455                 :            :  * Creates a control flow table used to transfer traffic from E-Switch Manager
   10456                 :            :  * and TX queues from group 0 to group 1.
   10457                 :            :  *
   10458                 :            :  * @param dev
   10459                 :            :  *   Pointer to Ethernet device.
   10460                 :            :  * @param it
   10461                 :            :  *   Pointer to flow pattern template.
   10462                 :            :  * @param at
   10463                 :            :  *   Pointer to flow actions template.
   10464                 :            :  * @param error
   10465                 :            :  *   Pointer to error structure.
   10466                 :            :  *
   10467                 :            :  * @return
   10468                 :            :  *   Pointer to flow table on success, NULL otherwise.
   10469                 :            :  */
   10470                 :            : static struct rte_flow_template_table*
   10471                 :          0 : flow_hw_create_ctrl_sq_miss_table(struct rte_eth_dev *dev,
   10472                 :            :                                   struct rte_flow_pattern_template *it,
   10473                 :            :                                   struct rte_flow_actions_template *at,
   10474                 :            :                                   struct rte_flow_error *error)
   10475                 :            : {
   10476                 :          0 :         struct rte_flow_template_table_attr attr = {
   10477                 :            :                 .flow_attr = {
   10478                 :            :                         .group = 1,
   10479                 :            :                         .priority = MLX5_HW_LOWEST_PRIO_NON_ROOT,
   10480                 :            :                         .ingress = 0,
   10481                 :            :                         .egress = 0,
   10482                 :            :                         .transfer = 1,
   10483                 :            :                 },
   10484                 :            :                 .nb_flows = MLX5_HW_CTRL_FLOW_NB_RULES,
   10485                 :            :         };
   10486                 :          0 :         struct mlx5_flow_template_table_cfg cfg = {
   10487                 :            :                 .attr = attr,
   10488                 :            :                 .external = false,
   10489                 :            :         };
   10490                 :            : 
   10491                 :          0 :         return flow_hw_table_create(dev, &cfg, &it, 1, &at, 1, error);
   10492                 :            : }
   10493                 :            : 
   10494                 :            : /*
   10495                 :            :  * Creating the default Tx metadata copy table on NIC Tx group 0.
   10496                 :            :  *
   10497                 :            :  * @param dev
   10498                 :            :  *   Pointer to Ethernet device.
   10499                 :            :  * @param pt
   10500                 :            :  *   Pointer to flow pattern template.
   10501                 :            :  * @param at
   10502                 :            :  *   Pointer to flow actions template.
   10503                 :            :  * @param error
   10504                 :            :  *   Pointer to error structure.
   10505                 :            :  *
   10506                 :            :  * @return
   10507                 :            :  *   Pointer to flow table on success, NULL otherwise.
   10508                 :            :  */
   10509                 :            : static struct rte_flow_template_table*
   10510                 :          0 : flow_hw_create_tx_default_mreg_copy_table(struct rte_eth_dev *dev,
   10511                 :            :                                           struct rte_flow_pattern_template *pt,
   10512                 :            :                                           struct rte_flow_actions_template *at,
   10513                 :            :                                           struct rte_flow_error *error)
   10514                 :            : {
   10515                 :          0 :         struct rte_flow_template_table_attr tx_tbl_attr = {
   10516                 :            :                 .flow_attr = {
   10517                 :            :                         .group = 0, /* Root */
   10518                 :            :                         .priority = MLX5_HW_LOWEST_PRIO_ROOT,
   10519                 :            :                         .egress = 1,
   10520                 :            :                 },
   10521                 :            :                 .nb_flows = 1, /* One default flow rule for all. */
   10522                 :            :         };
   10523                 :          0 :         struct mlx5_flow_template_table_cfg tx_tbl_cfg = {
   10524                 :            :                 .attr = tx_tbl_attr,
   10525                 :            :                 .external = false,
   10526                 :            :         };
   10527                 :            : 
   10528                 :          0 :         return flow_hw_table_create(dev, &tx_tbl_cfg, &pt, 1, &at, 1, error);
   10529                 :            : }
   10530                 :            : 
   10531                 :            : /**
   10532                 :            :  * Creates a control flow table used to transfer traffic
   10533                 :            :  * from group 0 to group 1.
   10534                 :            :  *
   10535                 :            :  * @param dev
   10536                 :            :  *   Pointer to Ethernet device.
   10537                 :            :  * @param it
   10538                 :            :  *   Pointer to flow pattern template.
   10539                 :            :  * @param at
   10540                 :            :  *   Pointer to flow actions template.
   10541                 :            :  * @param error
   10542                 :            :  *   Pointer to error structure.
   10543                 :            :  *
   10544                 :            :  * @return
   10545                 :            :  *   Pointer to flow table on success, NULL otherwise.
   10546                 :            :  */
   10547                 :            : static struct rte_flow_template_table *
   10548                 :          0 : flow_hw_create_ctrl_jump_table(struct rte_eth_dev *dev,
   10549                 :            :                                struct rte_flow_pattern_template *it,
   10550                 :            :                                struct rte_flow_actions_template *at,
   10551                 :            :                                struct rte_flow_error *error)
   10552                 :            : {
   10553                 :          0 :         struct rte_flow_template_table_attr attr = {
   10554                 :            :                 .flow_attr = {
   10555                 :            :                         .group = 0,
   10556                 :            :                         .priority = 0,
   10557                 :            :                         .ingress = 0,
   10558                 :            :                         .egress = 0,
   10559                 :            :                         .transfer = 1,
   10560                 :            :                 },
   10561                 :            :                 .nb_flows = MLX5_HW_CTRL_FLOW_NB_RULES,
   10562                 :            :         };
   10563                 :          0 :         struct mlx5_flow_template_table_cfg cfg = {
   10564                 :            :                 .attr = attr,
   10565                 :            :                 .external = false,
   10566                 :            :         };
   10567                 :            : 
   10568                 :          0 :         return flow_hw_table_create(dev, &cfg, &it, 1, &at, 1, error);
   10569                 :            : }
   10570                 :            : 
   10571                 :            : /**
   10572                 :            :  * Cleans up all template tables and pattern, and actions templates used for
   10573                 :            :  * FDB control flow rules.
   10574                 :            :  *
   10575                 :            :  * @param dev
   10576                 :            :  *   Pointer to Ethernet device.
   10577                 :            :  */
   10578                 :            : static void
   10579                 :          0 : flow_hw_cleanup_ctrl_fdb_tables(struct rte_eth_dev *dev)
   10580                 :            : {
   10581                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   10582                 :            :         struct mlx5_flow_hw_ctrl_fdb *hw_ctrl_fdb;
   10583                 :            : 
   10584         [ #  # ]:          0 :         if (!priv->hw_ctrl_fdb)
   10585                 :            :                 return;
   10586                 :            :         hw_ctrl_fdb = priv->hw_ctrl_fdb;
   10587                 :            :         /* Clean up templates used for LACP default miss table. */
   10588         [ #  # ]:          0 :         if (hw_ctrl_fdb->hw_lacp_rx_tbl)
   10589                 :          0 :                 claim_zero(flow_hw_table_destroy(dev, hw_ctrl_fdb->hw_lacp_rx_tbl, NULL));
   10590         [ #  # ]:          0 :         if (hw_ctrl_fdb->lacp_rx_actions_tmpl)
   10591                 :          0 :                 claim_zero(flow_hw_actions_template_destroy(dev, hw_ctrl_fdb->lacp_rx_actions_tmpl,
   10592                 :            :                            NULL));
   10593         [ #  # ]:          0 :         if (hw_ctrl_fdb->lacp_rx_items_tmpl)
   10594                 :          0 :                 claim_zero(flow_hw_pattern_template_destroy(dev, hw_ctrl_fdb->lacp_rx_items_tmpl,
   10595                 :            :                            NULL));
   10596                 :            :         /* Clean up templates used for default Tx metadata copy. */
   10597         [ #  # ]:          0 :         if (hw_ctrl_fdb->hw_tx_meta_cpy_tbl)
   10598                 :          0 :                 claim_zero(flow_hw_table_destroy(dev, hw_ctrl_fdb->hw_tx_meta_cpy_tbl, NULL));
   10599         [ #  # ]:          0 :         if (hw_ctrl_fdb->tx_meta_actions_tmpl)
   10600                 :          0 :                 claim_zero(flow_hw_actions_template_destroy(dev, hw_ctrl_fdb->tx_meta_actions_tmpl,
   10601                 :            :                            NULL));
   10602         [ #  # ]:          0 :         if (hw_ctrl_fdb->tx_meta_items_tmpl)
   10603                 :          0 :                 claim_zero(flow_hw_pattern_template_destroy(dev, hw_ctrl_fdb->tx_meta_items_tmpl,
   10604                 :            :                            NULL));
   10605                 :            :         /* Clean up templates used for default FDB jump rule. */
   10606         [ #  # ]:          0 :         if (hw_ctrl_fdb->hw_esw_zero_tbl)
   10607                 :          0 :                 claim_zero(flow_hw_table_destroy(dev, hw_ctrl_fdb->hw_esw_zero_tbl, NULL));
   10608         [ #  # ]:          0 :         if (hw_ctrl_fdb->jump_one_actions_tmpl)
   10609                 :          0 :                 claim_zero(flow_hw_actions_template_destroy(dev, hw_ctrl_fdb->jump_one_actions_tmpl,
   10610                 :            :                            NULL));
   10611         [ #  # ]:          0 :         if (hw_ctrl_fdb->port_items_tmpl)
   10612                 :          0 :                 claim_zero(flow_hw_pattern_template_destroy(dev, hw_ctrl_fdb->port_items_tmpl,
   10613                 :            :                            NULL));
   10614                 :            :         /* Clean up templates used for default SQ miss flow rules - non-root table. */
   10615         [ #  # ]:          0 :         if (hw_ctrl_fdb->hw_esw_sq_miss_tbl)
   10616                 :          0 :                 claim_zero(flow_hw_table_destroy(dev, hw_ctrl_fdb->hw_esw_sq_miss_tbl, NULL));
   10617         [ #  # ]:          0 :         if (hw_ctrl_fdb->regc_sq_items_tmpl)
   10618                 :          0 :                 claim_zero(flow_hw_pattern_template_destroy(dev, hw_ctrl_fdb->regc_sq_items_tmpl,
   10619                 :            :                            NULL));
   10620         [ #  # ]:          0 :         if (hw_ctrl_fdb->port_actions_tmpl)
   10621                 :          0 :                 claim_zero(flow_hw_actions_template_destroy(dev, hw_ctrl_fdb->port_actions_tmpl,
   10622                 :            :                            NULL));
   10623                 :            :         /* Clean up templates used for default SQ miss flow rules - root table. */
   10624         [ #  # ]:          0 :         if (hw_ctrl_fdb->hw_esw_sq_miss_root_tbl)
   10625                 :          0 :                 claim_zero(flow_hw_table_destroy(dev, hw_ctrl_fdb->hw_esw_sq_miss_root_tbl, NULL));
   10626         [ #  # ]:          0 :         if (hw_ctrl_fdb->regc_jump_actions_tmpl)
   10627                 :          0 :                 claim_zero(flow_hw_actions_template_destroy(dev,
   10628                 :            :                            hw_ctrl_fdb->regc_jump_actions_tmpl, NULL));
   10629         [ #  # ]:          0 :         if (hw_ctrl_fdb->esw_mgr_items_tmpl)
   10630                 :          0 :                 claim_zero(flow_hw_pattern_template_destroy(dev, hw_ctrl_fdb->esw_mgr_items_tmpl,
   10631                 :            :                            NULL));
   10632                 :            :         /* Clean up templates structure for FDB control flow rules. */
   10633                 :          0 :         mlx5_free(hw_ctrl_fdb);
   10634                 :          0 :         priv->hw_ctrl_fdb = NULL;
   10635                 :            : }
   10636                 :            : 
   10637                 :            : /*
   10638                 :            :  * Create a table on the root group to for the LACP traffic redirecting.
   10639                 :            :  *
   10640                 :            :  * @param dev
   10641                 :            :  *   Pointer to Ethernet device.
   10642                 :            :  * @param it
   10643                 :            :  *   Pointer to flow pattern template.
   10644                 :            :  * @param at
   10645                 :            :  *   Pointer to flow actions template.
   10646                 :            :  *
   10647                 :            :  * @return
   10648                 :            :  *   Pointer to flow table on success, NULL otherwise.
   10649                 :            :  */
   10650                 :            : static struct rte_flow_template_table *
   10651                 :          0 : flow_hw_create_lacp_rx_table(struct rte_eth_dev *dev,
   10652                 :            :                              struct rte_flow_pattern_template *it,
   10653                 :            :                              struct rte_flow_actions_template *at,
   10654                 :            :                              struct rte_flow_error *error)
   10655                 :            : {
   10656                 :          0 :         struct rte_flow_template_table_attr attr = {
   10657                 :            :                 .flow_attr = {
   10658                 :            :                         .group = 0,
   10659                 :            :                         .priority = 0,
   10660                 :            :                         .ingress = 1,
   10661                 :            :                         .egress = 0,
   10662                 :            :                         .transfer = 0,
   10663                 :            :                 },
   10664                 :            :                 .nb_flows = 1,
   10665                 :            :         };
   10666                 :          0 :         struct mlx5_flow_template_table_cfg cfg = {
   10667                 :            :                 .attr = attr,
   10668                 :            :                 .external = false,
   10669                 :            :         };
   10670                 :            : 
   10671                 :          0 :         return flow_hw_table_create(dev, &cfg, &it, 1, &at, 1, error);
   10672                 :            : }
   10673                 :            : 
   10674                 :            : /**
   10675                 :            :  * Creates a set of flow tables used to create control flows used
   10676                 :            :  * when E-Switch is engaged.
   10677                 :            :  *
   10678                 :            :  * @param dev
   10679                 :            :  *   Pointer to Ethernet device.
   10680                 :            :  * @param error
   10681                 :            :  *   Pointer to error structure.
   10682                 :            :  *
   10683                 :            :  * @return
   10684                 :            :  *   0 on success, negative values otherwise
   10685                 :            :  */
   10686                 :            : static int
   10687                 :          0 : flow_hw_create_ctrl_tables(struct rte_eth_dev *dev, struct rte_flow_error *error)
   10688                 :            : {
   10689                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   10690                 :            :         struct mlx5_flow_hw_ctrl_fdb *hw_ctrl_fdb;
   10691                 :          0 :         uint32_t xmeta = priv->sh->config.dv_xmeta_en;
   10692                 :          0 :         uint32_t repr_matching = priv->sh->config.repr_matching;
   10693                 :          0 :         uint32_t fdb_def_rule = priv->sh->config.fdb_def_rule;
   10694                 :            : 
   10695                 :            :         MLX5_ASSERT(priv->hw_ctrl_fdb == NULL);
   10696                 :          0 :         hw_ctrl_fdb = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*hw_ctrl_fdb), 0, SOCKET_ID_ANY);
   10697         [ #  # ]:          0 :         if (!hw_ctrl_fdb) {
   10698                 :          0 :                 DRV_LOG(ERR, "port %u failed to allocate memory for FDB control flow templates",
   10699                 :            :                         dev->data->port_id);
   10700                 :          0 :                 rte_errno = ENOMEM;
   10701                 :          0 :                 goto err;
   10702                 :            :         }
   10703                 :          0 :         priv->hw_ctrl_fdb = hw_ctrl_fdb;
   10704         [ #  # ]:          0 :         if (fdb_def_rule) {
   10705                 :            :                 /* Create templates and table for default SQ miss flow rules - root table. */
   10706                 :          0 :                 hw_ctrl_fdb->esw_mgr_items_tmpl =
   10707                 :          0 :                                 flow_hw_create_ctrl_esw_mgr_pattern_template(dev, error);
   10708         [ #  # ]:          0 :                 if (!hw_ctrl_fdb->esw_mgr_items_tmpl) {
   10709                 :          0 :                         DRV_LOG(ERR, "port %u failed to create E-Switch Manager item"
   10710                 :            :                                 " template for control flows", dev->data->port_id);
   10711                 :          0 :                         goto err;
   10712                 :            :                 }
   10713                 :          0 :                 hw_ctrl_fdb->regc_jump_actions_tmpl =
   10714                 :          0 :                                 flow_hw_create_ctrl_regc_jump_actions_template(dev, error);
   10715         [ #  # ]:          0 :                 if (!hw_ctrl_fdb->regc_jump_actions_tmpl) {
   10716                 :          0 :                         DRV_LOG(ERR, "port %u failed to create REG_C set and jump action template"
   10717                 :            :                                 " for control flows", dev->data->port_id);
   10718                 :          0 :                         goto err;
   10719                 :            :                 }
   10720                 :          0 :                 hw_ctrl_fdb->hw_esw_sq_miss_root_tbl =
   10721                 :          0 :                                 flow_hw_create_ctrl_sq_miss_root_table
   10722                 :            :                                         (dev, hw_ctrl_fdb->esw_mgr_items_tmpl,
   10723                 :            :                                          hw_ctrl_fdb->regc_jump_actions_tmpl, error);
   10724         [ #  # ]:          0 :                 if (!hw_ctrl_fdb->hw_esw_sq_miss_root_tbl) {
   10725                 :          0 :                         DRV_LOG(ERR, "port %u failed to create table for default sq miss (root table)"
   10726                 :            :                                 " for control flows", dev->data->port_id);
   10727                 :          0 :                         goto err;
   10728                 :            :                 }
   10729                 :            :                 /* Create templates and table for default SQ miss flow rules - non-root table. */
   10730                 :          0 :                 hw_ctrl_fdb->regc_sq_items_tmpl =
   10731                 :          0 :                                 flow_hw_create_ctrl_regc_sq_pattern_template(dev, error);
   10732         [ #  # ]:          0 :                 if (!hw_ctrl_fdb->regc_sq_items_tmpl) {
   10733                 :          0 :                         DRV_LOG(ERR, "port %u failed to create SQ item template for"
   10734                 :            :                                 " control flows", dev->data->port_id);
   10735                 :          0 :                         goto err;
   10736                 :            :                 }
   10737                 :          0 :                 hw_ctrl_fdb->port_actions_tmpl =
   10738                 :          0 :                                 flow_hw_create_ctrl_port_actions_template(dev, error);
   10739         [ #  # ]:          0 :                 if (!hw_ctrl_fdb->port_actions_tmpl) {
   10740                 :          0 :                         DRV_LOG(ERR, "port %u failed to create port action template"
   10741                 :            :                                 " for control flows", dev->data->port_id);
   10742                 :          0 :                         goto err;
   10743                 :            :                 }
   10744                 :          0 :                 hw_ctrl_fdb->hw_esw_sq_miss_tbl =
   10745                 :          0 :                                 flow_hw_create_ctrl_sq_miss_table
   10746                 :            :                                         (dev, hw_ctrl_fdb->regc_sq_items_tmpl,
   10747                 :            :                                          hw_ctrl_fdb->port_actions_tmpl, error);
   10748         [ #  # ]:          0 :                 if (!hw_ctrl_fdb->hw_esw_sq_miss_tbl) {
   10749                 :          0 :                         DRV_LOG(ERR, "port %u failed to create table for default sq miss (non-root table)"
   10750                 :            :                                 " for control flows", dev->data->port_id);
   10751                 :          0 :                         goto err;
   10752                 :            :                 }
   10753                 :            :                 /* Create templates and table for default FDB jump flow rules. */
   10754                 :          0 :                 hw_ctrl_fdb->port_items_tmpl =
   10755                 :          0 :                                 flow_hw_create_ctrl_port_pattern_template(dev, error);
   10756         [ #  # ]:          0 :                 if (!hw_ctrl_fdb->port_items_tmpl) {
   10757                 :          0 :                         DRV_LOG(ERR, "port %u failed to create SQ item template for"
   10758                 :            :                                 " control flows", dev->data->port_id);
   10759                 :          0 :                         goto err;
   10760                 :            :                 }
   10761                 :          0 :                 hw_ctrl_fdb->jump_one_actions_tmpl =
   10762                 :          0 :                                 flow_hw_create_ctrl_jump_actions_template
   10763                 :            :                                         (dev, MLX5_HW_LOWEST_USABLE_GROUP, error);
   10764         [ #  # ]:          0 :                 if (!hw_ctrl_fdb->jump_one_actions_tmpl) {
   10765                 :          0 :                         DRV_LOG(ERR, "port %u failed to create jump action template"
   10766                 :            :                                 " for control flows", dev->data->port_id);
   10767                 :          0 :                         goto err;
   10768                 :            :                 }
   10769                 :          0 :                 hw_ctrl_fdb->hw_esw_zero_tbl = flow_hw_create_ctrl_jump_table
   10770                 :            :                                 (dev, hw_ctrl_fdb->port_items_tmpl,
   10771                 :            :                                  hw_ctrl_fdb->jump_one_actions_tmpl, error);
   10772         [ #  # ]:          0 :                 if (!hw_ctrl_fdb->hw_esw_zero_tbl) {
   10773                 :          0 :                         DRV_LOG(ERR, "port %u failed to create table for default jump to group 1"
   10774                 :            :                                 " for control flows", dev->data->port_id);
   10775                 :          0 :                         goto err;
   10776                 :            :                 }
   10777                 :            :         }
   10778                 :            :         /* Create templates and table for default Tx metadata copy flow rule. */
   10779         [ #  # ]:          0 :         if (!repr_matching && xmeta == MLX5_XMETA_MODE_META32_HWS) {
   10780                 :          0 :                 hw_ctrl_fdb->tx_meta_items_tmpl =
   10781                 :          0 :                         flow_hw_create_tx_default_mreg_copy_pattern_template(dev, error);
   10782         [ #  # ]:          0 :                 if (!hw_ctrl_fdb->tx_meta_items_tmpl) {
   10783                 :          0 :                         DRV_LOG(ERR, "port %u failed to Tx metadata copy pattern"
   10784                 :            :                                 " template for control flows", dev->data->port_id);
   10785                 :          0 :                         goto err;
   10786                 :            :                 }
   10787                 :          0 :                 hw_ctrl_fdb->tx_meta_actions_tmpl =
   10788                 :          0 :                         flow_hw_create_tx_default_mreg_copy_actions_template(dev, error);
   10789         [ #  # ]:          0 :                 if (!hw_ctrl_fdb->tx_meta_actions_tmpl) {
   10790                 :          0 :                         DRV_LOG(ERR, "port %u failed to Tx metadata copy actions"
   10791                 :            :                                 " template for control flows", dev->data->port_id);
   10792                 :          0 :                         goto err;
   10793                 :            :                 }
   10794                 :          0 :                 hw_ctrl_fdb->hw_tx_meta_cpy_tbl =
   10795                 :          0 :                         flow_hw_create_tx_default_mreg_copy_table
   10796                 :            :                                 (dev, hw_ctrl_fdb->tx_meta_items_tmpl,
   10797                 :            :                                  hw_ctrl_fdb->tx_meta_actions_tmpl, error);
   10798         [ #  # ]:          0 :                 if (!hw_ctrl_fdb->hw_tx_meta_cpy_tbl) {
   10799                 :          0 :                         DRV_LOG(ERR, "port %u failed to create table for default"
   10800                 :            :                                 " Tx metadata copy flow rule", dev->data->port_id);
   10801                 :          0 :                         goto err;
   10802                 :            :                 }
   10803                 :            :         }
   10804                 :            :         /* Create LACP default miss table. */
   10805   [ #  #  #  #  :          0 :         if (!priv->sh->config.lacp_by_user && priv->pf_bond >= 0 && priv->master) {
                   #  # ]
   10806                 :          0 :                 hw_ctrl_fdb->lacp_rx_items_tmpl =
   10807                 :          0 :                                 flow_hw_create_lacp_rx_pattern_template(dev, error);
   10808         [ #  # ]:          0 :                 if (!hw_ctrl_fdb->lacp_rx_items_tmpl) {
   10809                 :          0 :                         DRV_LOG(ERR, "port %u failed to create pattern template"
   10810                 :            :                                 " for LACP Rx traffic", dev->data->port_id);
   10811                 :          0 :                         goto err;
   10812                 :            :                 }
   10813                 :          0 :                 hw_ctrl_fdb->lacp_rx_actions_tmpl =
   10814                 :          0 :                                 flow_hw_create_lacp_rx_actions_template(dev, error);
   10815         [ #  # ]:          0 :                 if (!hw_ctrl_fdb->lacp_rx_actions_tmpl) {
   10816                 :          0 :                         DRV_LOG(ERR, "port %u failed to create actions template"
   10817                 :            :                                 " for LACP Rx traffic", dev->data->port_id);
   10818                 :          0 :                         goto err;
   10819                 :            :                 }
   10820                 :          0 :                 hw_ctrl_fdb->hw_lacp_rx_tbl = flow_hw_create_lacp_rx_table
   10821                 :            :                                 (dev, hw_ctrl_fdb->lacp_rx_items_tmpl,
   10822                 :            :                                  hw_ctrl_fdb->lacp_rx_actions_tmpl, error);
   10823         [ #  # ]:          0 :                 if (!hw_ctrl_fdb->hw_lacp_rx_tbl) {
   10824                 :          0 :                         DRV_LOG(ERR, "port %u failed to create template table for"
   10825                 :            :                                 " for LACP Rx traffic", dev->data->port_id);
   10826                 :          0 :                         goto err;
   10827                 :            :                 }
   10828                 :            :         }
   10829                 :            :         return 0;
   10830                 :            : 
   10831                 :          0 : err:
   10832                 :          0 :         flow_hw_cleanup_ctrl_fdb_tables(dev);
   10833                 :          0 :         return -EINVAL;
   10834                 :            : }
   10835                 :            : 
   10836                 :            : static void
   10837                 :          0 : flow_hw_ct_mng_destroy(struct rte_eth_dev *dev,
   10838                 :            :                        struct mlx5_aso_ct_pools_mng *ct_mng)
   10839                 :            : {
   10840                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   10841                 :            : 
   10842                 :          0 :         mlx5_aso_ct_queue_uninit(priv->sh, ct_mng);
   10843                 :          0 :         mlx5_free(ct_mng);
   10844                 :          0 : }
   10845                 :            : 
   10846                 :            : static void
   10847                 :          0 : flow_hw_ct_pool_destroy(struct rte_eth_dev *dev,
   10848                 :            :                         struct mlx5_aso_ct_pool *pool)
   10849                 :            : {
   10850                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   10851                 :            : 
   10852         [ #  # ]:          0 :         if (pool->dr_action)
   10853                 :          0 :                 mlx5dr_action_destroy(pool->dr_action);
   10854         [ #  # ]:          0 :         if (!priv->shared_host) {
   10855         [ #  # ]:          0 :                 if (pool->devx_obj)
   10856                 :          0 :                         claim_zero(mlx5_devx_cmd_destroy(pool->devx_obj));
   10857         [ #  # ]:          0 :                 if (pool->cts)
   10858                 :          0 :                         mlx5_ipool_destroy(pool->cts);
   10859                 :            :         }
   10860                 :          0 :         mlx5_free(pool);
   10861                 :          0 : }
   10862                 :            : 
   10863                 :            : static struct mlx5_aso_ct_pool *
   10864                 :          0 : flow_hw_ct_pool_create(struct rte_eth_dev *dev,
   10865                 :            :                        uint32_t nb_conn_tracks)
   10866                 :            : {
   10867         [ #  # ]:          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   10868                 :            :         struct mlx5_aso_ct_pool *pool;
   10869                 :            :         struct mlx5_devx_obj *obj;
   10870                 :            :         uint32_t nb_cts = rte_align32pow2(nb_conn_tracks);
   10871                 :            :         uint32_t log_obj_size = rte_log2_u32(nb_cts);
   10872                 :          0 :         struct mlx5_indexed_pool_config cfg = {
   10873                 :            :                 .size = sizeof(struct mlx5_aso_ct_action),
   10874                 :            :                 .trunk_size = 1 << 12,
   10875                 :            :                 .per_core_cache = 1 << 13,
   10876                 :            :                 .need_lock = 1,
   10877                 :          0 :                 .release_mem_en = !!priv->sh->config.reclaim_mode,
   10878                 :            :                 .malloc = mlx5_malloc,
   10879                 :            :                 .free = mlx5_free,
   10880                 :            :                 .type = "mlx5_hw_ct_action",
   10881                 :            :         };
   10882                 :            :         int reg_id;
   10883                 :            :         uint32_t flags = 0;
   10884                 :            : 
   10885                 :          0 :         pool = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*pool), 0, SOCKET_ID_ANY);
   10886         [ #  # ]:          0 :         if (!pool) {
   10887                 :          0 :                 rte_errno = ENOMEM;
   10888                 :          0 :                 return NULL;
   10889                 :            :         }
   10890         [ #  # ]:          0 :         if (!priv->shared_host) {
   10891                 :            :                 /*
   10892                 :            :                  * No need for local cache if CT number is a small number. Since
   10893                 :            :                  * flow insertion rate will be very limited in that case. Here let's
   10894                 :            :                  * set the number to less than default trunk size 4K.
   10895                 :            :                  */
   10896         [ #  # ]:          0 :                 if (nb_cts <= cfg.trunk_size) {
   10897                 :          0 :                         cfg.per_core_cache = 0;
   10898                 :          0 :                         cfg.trunk_size = nb_cts;
   10899         [ #  # ]:          0 :                 } else if (nb_cts <= MLX5_HW_IPOOL_SIZE_THRESHOLD) {
   10900                 :          0 :                         cfg.per_core_cache = MLX5_HW_IPOOL_CACHE_MIN;
   10901                 :            :                 }
   10902                 :          0 :                 cfg.max_idx = nb_cts;
   10903                 :          0 :                 pool->cts = mlx5_ipool_create(&cfg);
   10904         [ #  # ]:          0 :                 if (!pool->cts)
   10905                 :          0 :                         goto err;
   10906                 :          0 :                 obj = mlx5_devx_cmd_create_conn_track_offload_obj(priv->sh->cdev->ctx,
   10907                 :          0 :                                                                   priv->sh->cdev->pdn,
   10908                 :            :                                                                   log_obj_size);
   10909         [ #  # ]:          0 :                 if (!obj) {
   10910                 :          0 :                         rte_errno = ENODATA;
   10911                 :          0 :                         DRV_LOG(ERR, "Failed to create conn_track_offload_obj using DevX.");
   10912                 :          0 :                         goto err;
   10913                 :            :                 }
   10914                 :          0 :                 pool->devx_obj = obj;
   10915                 :            :         } else {
   10916                 :            :                 struct rte_eth_dev *host_dev = priv->shared_host;
   10917                 :          0 :                 struct mlx5_priv *host_priv = host_dev->data->dev_private;
   10918                 :            : 
   10919                 :          0 :                 pool->devx_obj = host_priv->hws_ctpool->devx_obj;
   10920                 :          0 :                 pool->cts = host_priv->hws_ctpool->cts;
   10921                 :            :                 MLX5_ASSERT(pool->cts);
   10922                 :            :                 MLX5_ASSERT(!nb_conn_tracks);
   10923                 :            :         }
   10924                 :          0 :         reg_id = mlx5_flow_get_reg_id(dev, MLX5_ASO_CONNTRACK, 0, NULL);
   10925                 :            :         flags |= MLX5DR_ACTION_FLAG_HWS_RX | MLX5DR_ACTION_FLAG_HWS_TX;
   10926   [ #  #  #  # ]:          0 :         if (priv->sh->config.dv_esw_en && priv->master)
   10927                 :            :                 flags |= MLX5DR_ACTION_FLAG_HWS_FDB;
   10928                 :          0 :         pool->dr_action = mlx5dr_action_create_aso_ct(priv->dr_ctx,
   10929                 :          0 :                                                       (struct mlx5dr_devx_obj *)pool->devx_obj,
   10930                 :          0 :                                                       reg_id - REG_C_0, flags);
   10931         [ #  # ]:          0 :         if (!pool->dr_action)
   10932                 :          0 :                 goto err;
   10933                 :          0 :         pool->sq = priv->ct_mng->aso_sqs;
   10934                 :            :         /* Assign the last extra ASO SQ as public SQ. */
   10935                 :          0 :         pool->shared_sq = &priv->ct_mng->aso_sqs[priv->nb_queue - 1];
   10936                 :          0 :         return pool;
   10937                 :          0 : err:
   10938                 :          0 :         flow_hw_ct_pool_destroy(dev, pool);
   10939                 :          0 :         return NULL;
   10940                 :            : }
   10941                 :            : 
   10942                 :            : static int
   10943                 :          0 : mlx5_flow_ct_init(struct rte_eth_dev *dev,
   10944                 :            :                   uint32_t nb_conn_tracks,
   10945                 :            :                   uint16_t nb_queue)
   10946                 :            : {
   10947                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   10948                 :            :         uint32_t mem_size;
   10949                 :            :         int ret = -ENOMEM;
   10950                 :            : 
   10951         [ #  # ]:          0 :         if (!priv->shared_host) {
   10952                 :          0 :                 mem_size = sizeof(struct mlx5_aso_sq) * nb_queue +
   10953                 :            :                                 sizeof(*priv->ct_mng);
   10954                 :          0 :                 priv->ct_mng = mlx5_malloc(MLX5_MEM_ZERO, mem_size,
   10955                 :            :                                                 RTE_CACHE_LINE_SIZE,
   10956                 :            :                                                 SOCKET_ID_ANY);
   10957         [ #  # ]:          0 :                 if (!priv->ct_mng)
   10958                 :          0 :                         goto err;
   10959                 :          0 :                 ret = mlx5_aso_ct_queue_init(priv->sh, priv->ct_mng,
   10960                 :            :                                                 nb_queue);
   10961         [ #  # ]:          0 :                 if (ret)
   10962                 :          0 :                         goto err;
   10963                 :            :         }
   10964                 :          0 :         priv->hws_ctpool = flow_hw_ct_pool_create(dev, nb_conn_tracks);
   10965         [ #  # ]:          0 :         if (!priv->hws_ctpool)
   10966                 :          0 :                 goto err;
   10967                 :          0 :         priv->sh->ct_aso_en = 1;
   10968                 :          0 :         return 0;
   10969                 :            : 
   10970                 :          0 : err:
   10971         [ #  # ]:          0 :         if (priv->hws_ctpool) {
   10972                 :          0 :                 flow_hw_ct_pool_destroy(dev, priv->hws_ctpool);
   10973                 :          0 :                 priv->hws_ctpool = NULL;
   10974                 :            :         }
   10975         [ #  # ]:          0 :         if (priv->ct_mng) {
   10976                 :          0 :                 flow_hw_ct_mng_destroy(dev, priv->ct_mng);
   10977                 :          0 :                 priv->ct_mng = NULL;
   10978                 :            :         }
   10979                 :            :         return ret;
   10980                 :            : }
   10981                 :            : 
   10982                 :            : static void
   10983                 :          0 : flow_hw_destroy_vlan(struct rte_eth_dev *dev)
   10984                 :            : {
   10985                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   10986                 :            :         enum mlx5dr_table_type i;
   10987                 :            : 
   10988         [ #  # ]:          0 :         for (i = MLX5DR_TABLE_TYPE_NIC_RX; i < MLX5DR_TABLE_TYPE_MAX; i++) {
   10989         [ #  # ]:          0 :                 if (priv->hw_pop_vlan[i]) {
   10990                 :          0 :                         mlx5dr_action_destroy(priv->hw_pop_vlan[i]);
   10991                 :          0 :                         priv->hw_pop_vlan[i] = NULL;
   10992                 :            :                 }
   10993         [ #  # ]:          0 :                 if (priv->hw_push_vlan[i]) {
   10994                 :          0 :                         mlx5dr_action_destroy(priv->hw_push_vlan[i]);
   10995                 :          0 :                         priv->hw_push_vlan[i] = NULL;
   10996                 :            :                 }
   10997                 :            :         }
   10998                 :          0 : }
   10999                 :            : 
   11000                 :            : static int
   11001                 :          0 : flow_hw_create_vlan(struct rte_eth_dev *dev)
   11002                 :            : {
   11003                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   11004                 :            :         enum mlx5dr_table_type i;
   11005                 :          0 :         const enum mlx5dr_action_flags flags[MLX5DR_TABLE_TYPE_MAX] = {
   11006                 :            :                 MLX5DR_ACTION_FLAG_HWS_RX,
   11007                 :            :                 MLX5DR_ACTION_FLAG_HWS_TX,
   11008                 :            :                 MLX5DR_ACTION_FLAG_HWS_FDB
   11009                 :            :         };
   11010                 :            : 
   11011                 :            :         /* rte_errno is set in the mlx5dr_action* functions. */
   11012         [ #  # ]:          0 :         for (i = MLX5DR_TABLE_TYPE_NIC_RX; i <= MLX5DR_TABLE_TYPE_NIC_TX; i++) {
   11013                 :          0 :                 priv->hw_pop_vlan[i] =
   11014                 :          0 :                         mlx5dr_action_create_pop_vlan(priv->dr_ctx, flags[i]);
   11015         [ #  # ]:          0 :                 if (!priv->hw_pop_vlan[i])
   11016                 :          0 :                         return -rte_errno;
   11017                 :          0 :                 priv->hw_push_vlan[i] =
   11018                 :          0 :                         mlx5dr_action_create_push_vlan(priv->dr_ctx, flags[i]);
   11019         [ #  # ]:          0 :                 if (!priv->hw_pop_vlan[i])
   11020                 :          0 :                         return -rte_errno;
   11021                 :            :         }
   11022   [ #  #  #  # ]:          0 :         if (priv->sh->config.dv_esw_en && priv->master) {
   11023                 :          0 :                 priv->hw_pop_vlan[MLX5DR_TABLE_TYPE_FDB] =
   11024                 :          0 :                         mlx5dr_action_create_pop_vlan
   11025                 :            :                                 (priv->dr_ctx, MLX5DR_ACTION_FLAG_HWS_FDB);
   11026         [ #  # ]:          0 :                 if (!priv->hw_pop_vlan[MLX5DR_TABLE_TYPE_FDB])
   11027                 :          0 :                         return -rte_errno;
   11028                 :          0 :                 priv->hw_push_vlan[MLX5DR_TABLE_TYPE_FDB] =
   11029                 :          0 :                         mlx5dr_action_create_push_vlan
   11030                 :            :                                 (priv->dr_ctx, MLX5DR_ACTION_FLAG_HWS_FDB);
   11031         [ #  # ]:          0 :                 if (!priv->hw_pop_vlan[MLX5DR_TABLE_TYPE_FDB])
   11032                 :          0 :                         return -rte_errno;
   11033                 :            :         }
   11034                 :            :         return 0;
   11035                 :            : }
   11036                 :            : 
   11037                 :            : static void
   11038                 :          0 : flow_hw_cleanup_ctrl_rx_tables(struct rte_eth_dev *dev)
   11039                 :            : {
   11040                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   11041                 :            :         unsigned int i;
   11042                 :            :         unsigned int j;
   11043                 :            : 
   11044         [ #  # ]:          0 :         if (!priv->hw_ctrl_rx)
   11045                 :            :                 return;
   11046         [ #  # ]:          0 :         for (i = 0; i < MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_MAX; ++i) {
   11047         [ #  # ]:          0 :                 for (j = 0; j < MLX5_FLOW_HW_CTRL_RX_EXPANDED_RSS_MAX; ++j) {
   11048                 :          0 :                         struct rte_flow_template_table *tbl = priv->hw_ctrl_rx->tables[i][j].tbl;
   11049                 :          0 :                         struct rte_flow_pattern_template *pt = priv->hw_ctrl_rx->tables[i][j].pt;
   11050                 :            : 
   11051         [ #  # ]:          0 :                         if (tbl)
   11052                 :          0 :                                 claim_zero(flow_hw_table_destroy(dev, tbl, NULL));
   11053         [ #  # ]:          0 :                         if (pt)
   11054                 :          0 :                                 claim_zero(flow_hw_pattern_template_destroy(dev, pt, NULL));
   11055                 :            :                 }
   11056                 :            :         }
   11057         [ #  # ]:          0 :         for (i = 0; i < MLX5_FLOW_HW_CTRL_RX_EXPANDED_RSS_MAX; ++i) {
   11058                 :          0 :                 struct rte_flow_actions_template *at = priv->hw_ctrl_rx->rss[i];
   11059                 :            : 
   11060         [ #  # ]:          0 :                 if (at)
   11061                 :          0 :                         claim_zero(flow_hw_actions_template_destroy(dev, at, NULL));
   11062                 :            :         }
   11063                 :          0 :         mlx5_free(priv->hw_ctrl_rx);
   11064                 :          0 :         priv->hw_ctrl_rx = NULL;
   11065                 :            : }
   11066                 :            : 
   11067                 :            : static uint64_t
   11068                 :            : flow_hw_ctrl_rx_rss_type_hash_types(const enum mlx5_flow_ctrl_rx_expanded_rss_type rss_type)
   11069                 :            : {
   11070                 :            :         switch (rss_type) {
   11071                 :            :         case MLX5_FLOW_HW_CTRL_RX_EXPANDED_RSS_NON_IP:
   11072                 :            :                 return 0;
   11073                 :            :         case MLX5_FLOW_HW_CTRL_RX_EXPANDED_RSS_IPV4:
   11074                 :            :                 return RTE_ETH_RSS_IPV4 | RTE_ETH_RSS_FRAG_IPV4 | RTE_ETH_RSS_NONFRAG_IPV4_OTHER;
   11075                 :            :         case MLX5_FLOW_HW_CTRL_RX_EXPANDED_RSS_IPV4_UDP:
   11076                 :            :                 return RTE_ETH_RSS_NONFRAG_IPV4_UDP;
   11077                 :            :         case MLX5_FLOW_HW_CTRL_RX_EXPANDED_RSS_IPV4_TCP:
   11078                 :            :                 return RTE_ETH_RSS_NONFRAG_IPV4_TCP;
   11079                 :            :         case MLX5_FLOW_HW_CTRL_RX_EXPANDED_RSS_IPV6:
   11080                 :            :                 return RTE_ETH_RSS_IPV6 | RTE_ETH_RSS_FRAG_IPV6 | RTE_ETH_RSS_NONFRAG_IPV6_OTHER;
   11081                 :            :         case MLX5_FLOW_HW_CTRL_RX_EXPANDED_RSS_IPV6_UDP:
   11082                 :            :                 return RTE_ETH_RSS_NONFRAG_IPV6_UDP | RTE_ETH_RSS_IPV6_UDP_EX;
   11083                 :            :         case MLX5_FLOW_HW_CTRL_RX_EXPANDED_RSS_IPV6_TCP:
   11084                 :            :                 return RTE_ETH_RSS_NONFRAG_IPV6_TCP | RTE_ETH_RSS_IPV6_TCP_EX;
   11085                 :            :         default:
   11086                 :            :                 /* Should not reach here. */
   11087                 :            :                 MLX5_ASSERT(false);
   11088                 :            :                 return 0;
   11089                 :            :         }
   11090                 :            : }
   11091                 :            : 
   11092                 :            : static struct rte_flow_actions_template *
   11093                 :          0 : flow_hw_create_ctrl_rx_rss_template(struct rte_eth_dev *dev,
   11094                 :            :                                     const enum mlx5_flow_ctrl_rx_expanded_rss_type rss_type)
   11095                 :            : {
   11096                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   11097                 :          0 :         struct rte_flow_actions_template_attr attr = {
   11098                 :            :                 .ingress = 1,
   11099                 :            :         };
   11100                 :            :         uint16_t queue[RTE_MAX_QUEUES_PER_PORT];
   11101                 :          0 :         struct rte_flow_action_rss rss_conf = {
   11102                 :            :                 .func = RTE_ETH_HASH_FUNCTION_DEFAULT,
   11103                 :            :                 .level = 0,
   11104                 :            :                 .types = 0,
   11105                 :          0 :                 .key_len = priv->rss_conf.rss_key_len,
   11106                 :          0 :                 .key = priv->rss_conf.rss_key,
   11107                 :          0 :                 .queue_num = priv->reta_idx_n,
   11108                 :            :                 .queue = queue,
   11109                 :            :         };
   11110                 :          0 :         struct rte_flow_action actions[] = {
   11111                 :            :                 {
   11112                 :            :                         .type = RTE_FLOW_ACTION_TYPE_RSS,
   11113                 :            :                         .conf = &rss_conf,
   11114                 :            :                 },
   11115                 :            :                 {
   11116                 :            :                         .type = RTE_FLOW_ACTION_TYPE_END,
   11117                 :            :                 }
   11118                 :            :         };
   11119         [ #  # ]:          0 :         struct rte_flow_action masks[] = {
   11120                 :            :                 {
   11121                 :            :                         .type = RTE_FLOW_ACTION_TYPE_RSS,
   11122                 :            :                         .conf = &rss_conf,
   11123                 :            :                 },
   11124                 :            :                 {
   11125                 :            :                         .type = RTE_FLOW_ACTION_TYPE_END,
   11126                 :            :                 }
   11127                 :            :         };
   11128                 :            :         struct rte_flow_actions_template *at;
   11129                 :            :         struct rte_flow_error error;
   11130                 :            :         unsigned int i;
   11131                 :            : 
   11132                 :            :         MLX5_ASSERT(priv->reta_idx_n > 0 && priv->reta_idx);
   11133                 :            :         /* Select proper RSS hash types and based on that configure the actions template. */
   11134                 :          0 :         rss_conf.types = flow_hw_ctrl_rx_rss_type_hash_types(rss_type);
   11135         [ #  # ]:          0 :         if (rss_conf.types) {
   11136         [ #  # ]:          0 :                 for (i = 0; i < priv->reta_idx_n; ++i)
   11137                 :          0 :                         queue[i] = (*priv->reta_idx)[i];
   11138                 :            :         } else {
   11139                 :          0 :                 rss_conf.queue_num = 1;
   11140                 :          0 :                 queue[0] = (*priv->reta_idx)[0];
   11141                 :            :         }
   11142                 :            :         at = flow_hw_actions_template_create(dev, &attr, actions, masks, &error);
   11143         [ #  # ]:          0 :         if (!at)
   11144         [ #  # ]:          0 :                 DRV_LOG(ERR,
   11145                 :            :                         "Failed to create ctrl flow actions template: rte_errno(%d), type(%d): %s",
   11146                 :            :                         rte_errno, error.type,
   11147                 :            :                         error.message ? error.message : "(no stated reason)");
   11148                 :          0 :         return at;
   11149                 :            : }
   11150                 :            : 
   11151                 :            : static uint32_t ctrl_rx_rss_priority_map[MLX5_FLOW_HW_CTRL_RX_EXPANDED_RSS_MAX] = {
   11152                 :            :         [MLX5_FLOW_HW_CTRL_RX_EXPANDED_RSS_NON_IP] = MLX5_HW_CTRL_RX_PRIO_L2,
   11153                 :            :         [MLX5_FLOW_HW_CTRL_RX_EXPANDED_RSS_IPV4] = MLX5_HW_CTRL_RX_PRIO_L3,
   11154                 :            :         [MLX5_FLOW_HW_CTRL_RX_EXPANDED_RSS_IPV4_UDP] = MLX5_HW_CTRL_RX_PRIO_L4,
   11155                 :            :         [MLX5_FLOW_HW_CTRL_RX_EXPANDED_RSS_IPV4_TCP] = MLX5_HW_CTRL_RX_PRIO_L4,
   11156                 :            :         [MLX5_FLOW_HW_CTRL_RX_EXPANDED_RSS_IPV6] = MLX5_HW_CTRL_RX_PRIO_L3,
   11157                 :            :         [MLX5_FLOW_HW_CTRL_RX_EXPANDED_RSS_IPV6_UDP] = MLX5_HW_CTRL_RX_PRIO_L4,
   11158                 :            :         [MLX5_FLOW_HW_CTRL_RX_EXPANDED_RSS_IPV6_TCP] = MLX5_HW_CTRL_RX_PRIO_L4,
   11159                 :            : };
   11160                 :            : 
   11161                 :            : static uint32_t ctrl_rx_nb_flows_map[MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_MAX] = {
   11162                 :            :         [MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_ALL] = 1,
   11163                 :            :         [MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_ALL_MCAST] = 1,
   11164                 :            :         [MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_BCAST] = 1,
   11165                 :            :         [MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_BCAST_VLAN] = MLX5_MAX_VLAN_IDS,
   11166                 :            :         [MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_IPV4_MCAST] = 1,
   11167                 :            :         [MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_IPV4_MCAST_VLAN] = MLX5_MAX_VLAN_IDS,
   11168                 :            :         [MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_IPV6_MCAST] = 1,
   11169                 :            :         [MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_IPV6_MCAST_VLAN] = MLX5_MAX_VLAN_IDS,
   11170                 :            :         [MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_DMAC] = MLX5_MAX_UC_MAC_ADDRESSES,
   11171                 :            :         [MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_DMAC_VLAN] =
   11172                 :            :                         MLX5_MAX_UC_MAC_ADDRESSES * MLX5_MAX_VLAN_IDS,
   11173                 :            : };
   11174                 :            : 
   11175                 :            : static struct rte_flow_template_table_attr
   11176                 :            : flow_hw_get_ctrl_rx_table_attr(enum mlx5_flow_ctrl_rx_eth_pattern_type eth_pattern_type,
   11177                 :            :                                const enum mlx5_flow_ctrl_rx_expanded_rss_type rss_type)
   11178                 :            : {
   11179                 :          0 :         return (struct rte_flow_template_table_attr){
   11180                 :            :                 .flow_attr = {
   11181                 :            :                         .group = 0,
   11182                 :          0 :                         .priority = ctrl_rx_rss_priority_map[rss_type],
   11183                 :            :                         .ingress = 1,
   11184                 :            :                 },
   11185                 :          0 :                 .nb_flows = ctrl_rx_nb_flows_map[eth_pattern_type],
   11186                 :            :         };
   11187                 :            : }
   11188                 :            : 
   11189                 :            : static struct rte_flow_item
   11190                 :            : flow_hw_get_ctrl_rx_eth_item(const enum mlx5_flow_ctrl_rx_eth_pattern_type eth_pattern_type)
   11191                 :            : {
   11192                 :            :         struct rte_flow_item item = {
   11193                 :            :                 .type = RTE_FLOW_ITEM_TYPE_ETH,
   11194                 :            :                 .mask = NULL,
   11195                 :            :         };
   11196                 :            : 
   11197                 :          0 :         switch (eth_pattern_type) {
   11198                 :            :         case MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_ALL:
   11199                 :            :                 item.mask = &ctrl_rx_eth_promisc_mask;
   11200                 :            :                 break;
   11201                 :          0 :         case MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_ALL_MCAST:
   11202                 :            :                 item.mask = &ctrl_rx_eth_mcast_mask;
   11203                 :          0 :                 break;
   11204                 :          0 :         case MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_BCAST:
   11205                 :            :         case MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_BCAST_VLAN:
   11206                 :            :         case MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_DMAC:
   11207                 :            :         case MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_DMAC_VLAN:
   11208                 :            :                 item.mask = &ctrl_rx_eth_dmac_mask;
   11209                 :          0 :                 break;
   11210                 :          0 :         case MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_IPV4_MCAST:
   11211                 :            :         case MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_IPV4_MCAST_VLAN:
   11212                 :            :                 item.mask = &ctrl_rx_eth_ipv4_mcast_mask;
   11213                 :          0 :                 break;
   11214                 :          0 :         case MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_IPV6_MCAST:
   11215                 :            :         case MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_IPV6_MCAST_VLAN:
   11216                 :            :                 item.mask = &ctrl_rx_eth_ipv6_mcast_mask;
   11217                 :          0 :                 break;
   11218                 :          0 :         default:
   11219                 :            :                 /* Should not reach here - ETH mask must be present. */
   11220                 :            :                 item.type = RTE_FLOW_ITEM_TYPE_END;
   11221                 :            :                 MLX5_ASSERT(false);
   11222                 :          0 :                 break;
   11223                 :            :         }
   11224                 :          0 :         return item;
   11225                 :            : }
   11226                 :            : 
   11227                 :            : static struct rte_flow_item
   11228                 :            : flow_hw_get_ctrl_rx_vlan_item(const enum mlx5_flow_ctrl_rx_eth_pattern_type eth_pattern_type)
   11229                 :            : {
   11230                 :            :         struct rte_flow_item item = {
   11231                 :            :                 .type = RTE_FLOW_ITEM_TYPE_VOID,
   11232                 :            :                 .mask = NULL,
   11233                 :            :         };
   11234                 :            : 
   11235         [ #  # ]:          0 :         switch (eth_pattern_type) {
   11236                 :          0 :         case MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_BCAST_VLAN:
   11237                 :            :         case MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_IPV4_MCAST_VLAN:
   11238                 :            :         case MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_IPV6_MCAST_VLAN:
   11239                 :            :         case MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_DMAC_VLAN:
   11240                 :            :                 item.type = RTE_FLOW_ITEM_TYPE_VLAN;
   11241                 :            :                 item.mask = &rte_flow_item_vlan_mask;
   11242                 :          0 :                 break;
   11243                 :            :         default:
   11244                 :            :                 /* Nothing to update. */
   11245                 :            :                 break;
   11246                 :            :         }
   11247                 :          0 :         return item;
   11248                 :            : }
   11249                 :            : 
   11250                 :            : static struct rte_flow_item
   11251                 :            : flow_hw_get_ctrl_rx_l3_item(const enum mlx5_flow_ctrl_rx_expanded_rss_type rss_type)
   11252                 :            : {
   11253                 :            :         struct rte_flow_item item = {
   11254                 :            :                 .type = RTE_FLOW_ITEM_TYPE_VOID,
   11255                 :            :                 .mask = NULL,
   11256                 :            :         };
   11257                 :            : 
   11258      [ #  #  # ]:          0 :         switch (rss_type) {
   11259                 :          0 :         case MLX5_FLOW_HW_CTRL_RX_EXPANDED_RSS_IPV4:
   11260                 :            :         case MLX5_FLOW_HW_CTRL_RX_EXPANDED_RSS_IPV4_UDP:
   11261                 :            :         case MLX5_FLOW_HW_CTRL_RX_EXPANDED_RSS_IPV4_TCP:
   11262                 :            :                 item.type = RTE_FLOW_ITEM_TYPE_IPV4;
   11263                 :          0 :                 break;
   11264                 :          0 :         case MLX5_FLOW_HW_CTRL_RX_EXPANDED_RSS_IPV6:
   11265                 :            :         case MLX5_FLOW_HW_CTRL_RX_EXPANDED_RSS_IPV6_UDP:
   11266                 :            :         case MLX5_FLOW_HW_CTRL_RX_EXPANDED_RSS_IPV6_TCP:
   11267                 :            :                 item.type = RTE_FLOW_ITEM_TYPE_IPV6;
   11268                 :          0 :                 break;
   11269                 :            :         default:
   11270                 :            :                 /* Nothing to update. */
   11271                 :            :                 break;
   11272                 :            :         }
   11273                 :          0 :         return item;
   11274                 :            : }
   11275                 :            : 
   11276                 :            : static struct rte_flow_item
   11277                 :            : flow_hw_get_ctrl_rx_l4_item(const enum mlx5_flow_ctrl_rx_expanded_rss_type rss_type)
   11278                 :            : {
   11279                 :            :         struct rte_flow_item item = {
   11280                 :            :                 .type = RTE_FLOW_ITEM_TYPE_VOID,
   11281                 :            :                 .mask = NULL,
   11282                 :            :         };
   11283                 :            : 
   11284      [ #  #  # ]:          0 :         switch (rss_type) {
   11285                 :          0 :         case MLX5_FLOW_HW_CTRL_RX_EXPANDED_RSS_IPV4_UDP:
   11286                 :            :         case MLX5_FLOW_HW_CTRL_RX_EXPANDED_RSS_IPV6_UDP:
   11287                 :            :                 item.type = RTE_FLOW_ITEM_TYPE_UDP;
   11288                 :          0 :                 break;
   11289                 :          0 :         case MLX5_FLOW_HW_CTRL_RX_EXPANDED_RSS_IPV4_TCP:
   11290                 :            :         case MLX5_FLOW_HW_CTRL_RX_EXPANDED_RSS_IPV6_TCP:
   11291                 :            :                 item.type = RTE_FLOW_ITEM_TYPE_TCP;
   11292                 :          0 :                 break;
   11293                 :            :         default:
   11294                 :            :                 /* Nothing to update. */
   11295                 :            :                 break;
   11296                 :            :         }
   11297                 :          0 :         return item;
   11298                 :            : }
   11299                 :            : 
   11300                 :            : static struct rte_flow_pattern_template *
   11301                 :          0 : flow_hw_create_ctrl_rx_pattern_template
   11302                 :            :                 (struct rte_eth_dev *dev,
   11303                 :            :                  const enum mlx5_flow_ctrl_rx_eth_pattern_type eth_pattern_type,
   11304                 :            :                  const enum mlx5_flow_ctrl_rx_expanded_rss_type rss_type)
   11305                 :            : {
   11306                 :          0 :         const struct rte_flow_pattern_template_attr attr = {
   11307                 :            :                 .relaxed_matching = 0,
   11308                 :            :                 .ingress = 1,
   11309                 :            :         };
   11310   [ #  #  #  #  :          0 :         struct rte_flow_item items[] = {
                   #  # ]
   11311                 :            :                 /* Matching patterns */
   11312                 :            :                 flow_hw_get_ctrl_rx_eth_item(eth_pattern_type),
   11313                 :            :                 flow_hw_get_ctrl_rx_vlan_item(eth_pattern_type),
   11314                 :            :                 flow_hw_get_ctrl_rx_l3_item(rss_type),
   11315                 :            :                 flow_hw_get_ctrl_rx_l4_item(rss_type),
   11316                 :            :                 /* Terminate pattern */
   11317                 :            :                 { .type = RTE_FLOW_ITEM_TYPE_END }
   11318                 :            :         };
   11319                 :            : 
   11320                 :          0 :         return flow_hw_pattern_template_create(dev, &attr, items, NULL);
   11321                 :            : }
   11322                 :            : 
   11323                 :            : static int
   11324                 :          0 : flow_hw_create_ctrl_rx_tables(struct rte_eth_dev *dev)
   11325                 :            : {
   11326                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   11327                 :            :         unsigned int i;
   11328                 :            :         unsigned int j;
   11329                 :            :         int ret;
   11330                 :            : 
   11331                 :            :         MLX5_ASSERT(!priv->hw_ctrl_rx);
   11332                 :          0 :         priv->hw_ctrl_rx = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*priv->hw_ctrl_rx),
   11333                 :          0 :                                        RTE_CACHE_LINE_SIZE, rte_socket_id());
   11334         [ #  # ]:          0 :         if (!priv->hw_ctrl_rx) {
   11335                 :          0 :                 DRV_LOG(ERR, "Failed to allocate memory for Rx control flow tables");
   11336                 :          0 :                 rte_errno = ENOMEM;
   11337                 :          0 :                 return -rte_errno;
   11338                 :            :         }
   11339                 :            :         /* Create all pattern template variants. */
   11340         [ #  # ]:          0 :         for (i = 0; i < MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_MAX; ++i) {
   11341                 :            :                 enum mlx5_flow_ctrl_rx_eth_pattern_type eth_pattern_type = i;
   11342                 :            : 
   11343         [ #  # ]:          0 :                 for (j = 0; j < MLX5_FLOW_HW_CTRL_RX_EXPANDED_RSS_MAX; ++j) {
   11344                 :            :                         const enum mlx5_flow_ctrl_rx_expanded_rss_type rss_type = j;
   11345                 :            :                         struct rte_flow_template_table_attr attr;
   11346                 :            :                         struct rte_flow_pattern_template *pt;
   11347                 :            : 
   11348                 :            :                         attr = flow_hw_get_ctrl_rx_table_attr(eth_pattern_type, rss_type);
   11349                 :          0 :                         pt = flow_hw_create_ctrl_rx_pattern_template(dev, eth_pattern_type,
   11350                 :            :                                                                      rss_type);
   11351         [ #  # ]:          0 :                         if (!pt)
   11352                 :          0 :                                 goto err;
   11353                 :          0 :                         priv->hw_ctrl_rx->tables[i][j].attr = attr;
   11354                 :          0 :                         priv->hw_ctrl_rx->tables[i][j].pt = pt;
   11355                 :            :                 }
   11356                 :            :         }
   11357                 :            :         return 0;
   11358                 :            : err:
   11359                 :          0 :         ret = rte_errno;
   11360                 :          0 :         flow_hw_cleanup_ctrl_rx_tables(dev);
   11361                 :          0 :         rte_errno = ret;
   11362                 :          0 :         return -ret;
   11363                 :            : }
   11364                 :            : 
   11365                 :            : void
   11366                 :          0 : mlx5_flow_hw_cleanup_ctrl_rx_templates(struct rte_eth_dev *dev)
   11367                 :            : {
   11368                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   11369                 :            :         struct mlx5_flow_hw_ctrl_rx *hw_ctrl_rx;
   11370                 :            :         unsigned int i;
   11371                 :            :         unsigned int j;
   11372                 :            : 
   11373         [ #  # ]:          0 :         if (!priv->dr_ctx)
   11374                 :            :                 return;
   11375         [ #  # ]:          0 :         if (!priv->hw_ctrl_rx)
   11376                 :            :                 return;
   11377                 :            :         hw_ctrl_rx = priv->hw_ctrl_rx;
   11378         [ #  # ]:          0 :         for (i = 0; i < MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_MAX; ++i) {
   11379         [ #  # ]:          0 :                 for (j = 0; j < MLX5_FLOW_HW_CTRL_RX_EXPANDED_RSS_MAX; ++j) {
   11380                 :            :                         struct mlx5_flow_hw_ctrl_rx_table *tmpls = &hw_ctrl_rx->tables[i][j];
   11381                 :            : 
   11382         [ #  # ]:          0 :                         if (tmpls->tbl) {
   11383                 :          0 :                                 claim_zero(flow_hw_table_destroy(dev, tmpls->tbl, NULL));
   11384                 :          0 :                                 tmpls->tbl = NULL;
   11385                 :            :                         }
   11386                 :            :                 }
   11387                 :            :         }
   11388         [ #  # ]:          0 :         for (j = 0; j < MLX5_FLOW_HW_CTRL_RX_EXPANDED_RSS_MAX; ++j) {
   11389         [ #  # ]:          0 :                 if (hw_ctrl_rx->rss[j]) {
   11390                 :          0 :                         claim_zero(flow_hw_actions_template_destroy(dev, hw_ctrl_rx->rss[j], NULL));
   11391                 :          0 :                         hw_ctrl_rx->rss[j] = NULL;
   11392                 :            :                 }
   11393                 :            :         }
   11394                 :            : }
   11395                 :            : 
   11396                 :            : /**
   11397                 :            :  * Copy the provided HWS configuration to a newly allocated buffer.
   11398                 :            :  *
   11399                 :            :  * @param[in] port_attr
   11400                 :            :  *   Port configuration attributes.
   11401                 :            :  * @param[in] nb_queue
   11402                 :            :  *   Number of queue.
   11403                 :            :  * @param[in] queue_attr
   11404                 :            :  *   Array that holds attributes for each flow queue.
   11405                 :            :  * @param[in] nt_mode
   11406                 :            :  *   Non template mode.
   11407                 :            :  *
   11408                 :            :  * @return
   11409                 :            :  *   Pointer to copied HWS configuration is returned on success.
   11410                 :            :  *   Otherwise, NULL is returned and rte_errno is set.
   11411                 :            :  */
   11412                 :            : static struct mlx5_flow_hw_attr *
   11413                 :          0 : flow_hw_alloc_copy_config(const struct rte_flow_port_attr *port_attr,
   11414                 :            :                           const uint16_t nb_queue,
   11415                 :            :                           const struct rte_flow_queue_attr *queue_attr[],
   11416                 :            :                           bool nt_mode,
   11417                 :            :                           struct rte_flow_error *error)
   11418                 :            : {
   11419                 :            :         struct mlx5_flow_hw_attr *hw_attr;
   11420                 :            :         size_t hw_attr_size;
   11421                 :            :         unsigned int i;
   11422                 :            : 
   11423                 :          0 :         hw_attr_size = sizeof(*hw_attr) + nb_queue * sizeof(*hw_attr->queue_attr);
   11424                 :          0 :         hw_attr = mlx5_malloc(MLX5_MEM_ZERO, hw_attr_size, 0, SOCKET_ID_ANY);
   11425         [ #  # ]:          0 :         if (!hw_attr) {
   11426                 :          0 :                 rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   11427                 :            :                                    "Not enough memory to store configuration");
   11428                 :          0 :                 return NULL;
   11429                 :            :         }
   11430                 :          0 :         memcpy(&hw_attr->port_attr, port_attr, sizeof(*port_attr));
   11431                 :          0 :         hw_attr->nb_queue = nb_queue;
   11432                 :            :         /* Queue attributes are placed after the mlx5_flow_hw_attr. */
   11433                 :          0 :         hw_attr->queue_attr = (struct rte_flow_queue_attr *)(hw_attr + 1);
   11434         [ #  # ]:          0 :         for (i = 0; i < nb_queue; ++i)
   11435                 :          0 :                 memcpy(&hw_attr->queue_attr[i], queue_attr[i], sizeof(hw_attr->queue_attr[i]));
   11436                 :          0 :         hw_attr->nt_mode = nt_mode;
   11437                 :          0 :         return hw_attr;
   11438                 :            : }
   11439                 :            : 
   11440                 :            : /**
   11441                 :            :  * Compares the preserved HWS configuration with the provided one.
   11442                 :            :  *
   11443                 :            :  * @param[in] hw_attr
   11444                 :            :  *   Pointer to preserved HWS configuration.
   11445                 :            :  * @param[in] new_pa
   11446                 :            :  *   Port configuration attributes to compare.
   11447                 :            :  * @param[in] new_nbq
   11448                 :            :  *   Number of queues to compare.
   11449                 :            :  * @param[in] new_qa
   11450                 :            :  *   Array that holds attributes for each flow queue.
   11451                 :            :  *
   11452                 :            :  * @return
   11453                 :            :  *   True if configurations are the same, false otherwise.
   11454                 :            :  */
   11455                 :            : static bool
   11456                 :          0 : flow_hw_compare_config(const struct mlx5_flow_hw_attr *hw_attr,
   11457                 :            :                        const struct rte_flow_port_attr *new_pa,
   11458                 :            :                        const uint16_t new_nbq,
   11459                 :            :                        const struct rte_flow_queue_attr *new_qa[])
   11460                 :            : {
   11461                 :            :         const struct rte_flow_port_attr *old_pa = &hw_attr->port_attr;
   11462                 :          0 :         const uint16_t old_nbq = hw_attr->nb_queue;
   11463                 :          0 :         const struct rte_flow_queue_attr *old_qa = hw_attr->queue_attr;
   11464                 :            :         unsigned int i;
   11465                 :            : 
   11466         [ #  # ]:          0 :         if (old_pa->nb_counters != new_pa->nb_counters ||
   11467         [ #  # ]:          0 :             old_pa->nb_aging_objects != new_pa->nb_aging_objects ||
   11468         [ #  # ]:          0 :             old_pa->nb_meters != new_pa->nb_meters ||
   11469         [ #  # ]:          0 :             old_pa->nb_conn_tracks != new_pa->nb_conn_tracks ||
   11470         [ #  # ]:          0 :             old_pa->flags != new_pa->flags)
   11471                 :            :                 return false;
   11472         [ #  # ]:          0 :         if (old_nbq != new_nbq)
   11473                 :            :                 return false;
   11474         [ #  # ]:          0 :         for (i = 0; i < old_nbq; ++i)
   11475         [ #  # ]:          0 :                 if (old_qa[i].size != new_qa[i]->size)
   11476                 :            :                         return false;
   11477                 :            :         return true;
   11478                 :            : }
   11479                 :            : 
   11480                 :            : /*
   11481                 :            :  * No need to explicitly release drop action templates on port stop.
   11482                 :            :  * Drop action templates release with other action templates during
   11483                 :            :  * mlx5_dev_close -> flow_hw_resource_release -> flow_hw_actions_template_destroy
   11484                 :            :  */
   11485                 :            : static void
   11486                 :          0 : flow_hw_action_template_drop_release(struct rte_eth_dev *dev)
   11487                 :            : {
   11488                 :            :         int i;
   11489                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   11490                 :            : 
   11491         [ #  # ]:          0 :         for (i = 0; i < MLX5DR_TABLE_TYPE_MAX; i++) {
   11492         [ #  # ]:          0 :                 if (!priv->action_template_drop[i])
   11493                 :          0 :                         continue;
   11494                 :          0 :                 flow_hw_actions_template_destroy(dev,
   11495                 :            :                                                  priv->action_template_drop[i],
   11496                 :            :                                                  NULL);
   11497                 :          0 :                 priv->action_template_drop[i] = NULL;
   11498                 :            :         }
   11499                 :          0 : }
   11500                 :            : 
   11501                 :            : static int
   11502                 :          0 : flow_hw_action_template_drop_init(struct rte_eth_dev *dev,
   11503                 :            :                           struct rte_flow_error *error)
   11504                 :            : {
   11505                 :          0 :         const struct rte_flow_action drop[2] = {
   11506                 :            :                 [0] = { .type = RTE_FLOW_ACTION_TYPE_DROP },
   11507                 :            :                 [1] = { .type = RTE_FLOW_ACTION_TYPE_END },
   11508                 :            :         };
   11509                 :            :         const struct rte_flow_action *actions = drop;
   11510                 :            :         const struct rte_flow_action *masks = drop;
   11511                 :          0 :         const struct rte_flow_actions_template_attr attr[MLX5DR_TABLE_TYPE_MAX] = {
   11512                 :            :                 [MLX5DR_TABLE_TYPE_NIC_RX] = { .ingress = 1 },
   11513                 :            :                 [MLX5DR_TABLE_TYPE_NIC_TX] = { .egress = 1 },
   11514                 :            :                 [MLX5DR_TABLE_TYPE_FDB] = { .transfer = 1 }
   11515                 :            :         };
   11516                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   11517                 :            : 
   11518                 :          0 :         priv->action_template_drop[MLX5DR_TABLE_TYPE_NIC_RX] =
   11519                 :            :                 flow_hw_actions_template_create(dev,
   11520                 :            :                                                 &attr[MLX5DR_TABLE_TYPE_NIC_RX],
   11521                 :            :                                                 actions, masks, error);
   11522         [ #  # ]:          0 :         if (!priv->action_template_drop[MLX5DR_TABLE_TYPE_NIC_RX])
   11523                 :            :                 return -1;
   11524                 :          0 :         priv->action_template_drop[MLX5DR_TABLE_TYPE_NIC_TX] =
   11525                 :            :                 flow_hw_actions_template_create(dev,
   11526                 :            :                                                 &attr[MLX5DR_TABLE_TYPE_NIC_TX],
   11527                 :            :                                                 actions, masks, error);
   11528         [ #  # ]:          0 :         if (!priv->action_template_drop[MLX5DR_TABLE_TYPE_NIC_TX])
   11529                 :            :                 return -1;
   11530   [ #  #  #  # ]:          0 :         if (priv->sh->config.dv_esw_en && priv->master) {
   11531                 :          0 :                 priv->action_template_drop[MLX5DR_TABLE_TYPE_FDB] =
   11532                 :            :                         flow_hw_actions_template_create(dev,
   11533                 :            :                                                         &attr[MLX5DR_TABLE_TYPE_FDB],
   11534                 :            :                                                         actions, masks, error);
   11535         [ #  # ]:          0 :                 if (!priv->action_template_drop[MLX5DR_TABLE_TYPE_FDB])
   11536                 :          0 :                         return -1;
   11537                 :            :         }
   11538                 :            :         return 0;
   11539                 :            : }
   11540                 :            : 
   11541                 :            : static void
   11542                 :          0 : __flow_hw_resource_release(struct rte_eth_dev *dev, bool ctx_close)
   11543                 :            : {
   11544                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   11545                 :            :         struct rte_flow_template_table *tbl, *temp_tbl;
   11546                 :            :         struct rte_flow_pattern_template *it, *temp_it;
   11547                 :            :         struct rte_flow_actions_template *at, *temp_at;
   11548                 :            :         struct mlx5_flow_group *grp, *temp_grp;
   11549                 :            :         uint32_t i;
   11550                 :            : 
   11551                 :          0 :         flow_hw_rxq_flag_set(dev, false);
   11552                 :          0 :         flow_hw_flush_all_ctrl_flows(dev);
   11553                 :          0 :         flow_hw_cleanup_ctrl_fdb_tables(dev);
   11554                 :          0 :         flow_hw_cleanup_tx_repr_tagging(dev);
   11555                 :          0 :         flow_hw_cleanup_ctrl_rx_tables(dev);
   11556                 :          0 :         flow_hw_action_template_drop_release(dev);
   11557                 :          0 :         grp = LIST_FIRST(&priv->flow_hw_grp);
   11558         [ #  # ]:          0 :         while (grp) {
   11559                 :          0 :                 temp_grp = LIST_NEXT(grp, next);
   11560                 :          0 :                 claim_zero(flow_hw_group_unset_miss_group(dev, grp, NULL));
   11561                 :            :                 grp = temp_grp;
   11562                 :            :         }
   11563                 :          0 :         tbl = LIST_FIRST(&priv->flow_hw_tbl_ongo);
   11564         [ #  # ]:          0 :         while (tbl) {
   11565                 :          0 :                 temp_tbl = LIST_NEXT(tbl, next);
   11566                 :          0 :                 claim_zero(flow_hw_table_destroy(dev, tbl, NULL));
   11567                 :            :                 tbl = temp_tbl;
   11568                 :            :         }
   11569                 :          0 :         tbl = LIST_FIRST(&priv->flow_hw_tbl);
   11570         [ #  # ]:          0 :         while (tbl) {
   11571                 :          0 :                 temp_tbl = LIST_NEXT(tbl, next);
   11572                 :          0 :                 claim_zero(flow_hw_table_destroy(dev, tbl, NULL));
   11573                 :            :                 tbl = temp_tbl;
   11574                 :            :         }
   11575                 :          0 :         it = LIST_FIRST(&priv->flow_hw_itt);
   11576         [ #  # ]:          0 :         while (it) {
   11577                 :          0 :                 temp_it = LIST_NEXT(it, next);
   11578                 :          0 :                 claim_zero(flow_hw_pattern_template_destroy(dev, it, NULL));
   11579                 :            :                 it = temp_it;
   11580                 :            :         }
   11581                 :          0 :         at = LIST_FIRST(&priv->flow_hw_at);
   11582         [ #  # ]:          0 :         while (at) {
   11583                 :          0 :                 temp_at = LIST_NEXT(at, next);
   11584                 :          0 :                 claim_zero(flow_hw_actions_template_destroy(dev, at, NULL));
   11585                 :            :                 at = temp_at;
   11586                 :            :         }
   11587         [ #  # ]:          0 :         for (i = 0; i < MLX5_HW_ACTION_FLAG_MAX; i++) {
   11588         [ #  # ]:          0 :                 if (priv->hw_drop[i])
   11589                 :          0 :                         mlx5dr_action_destroy(priv->hw_drop[i]);
   11590         [ #  # ]:          0 :                 if (priv->hw_tag[i])
   11591                 :          0 :                         mlx5dr_action_destroy(priv->hw_tag[i]);
   11592                 :            :         }
   11593         [ #  # ]:          0 :         if (priv->hw_def_miss)
   11594                 :          0 :                 mlx5dr_action_destroy(priv->hw_def_miss);
   11595                 :          0 :         flow_hw_destroy_nat64_actions(priv);
   11596                 :          0 :         flow_hw_destroy_vlan(dev);
   11597                 :          0 :         flow_hw_destroy_send_to_kernel_action(priv);
   11598                 :          0 :         flow_hw_free_vport_actions(priv);
   11599         [ #  # ]:          0 :         if (priv->acts_ipool) {
   11600                 :          0 :                 mlx5_ipool_destroy(priv->acts_ipool);
   11601                 :          0 :                 priv->acts_ipool = NULL;
   11602                 :            :         }
   11603         [ #  # ]:          0 :         if (priv->hws_age_req)
   11604                 :          0 :                 mlx5_hws_age_pool_destroy(priv);
   11605   [ #  #  #  # ]:          0 :         if (!priv->shared_host && priv->hws_cpool) {
   11606                 :          0 :                 mlx5_hws_cnt_pool_destroy(priv->sh, priv->hws_cpool);
   11607                 :          0 :                 priv->hws_cpool = NULL;
   11608                 :            :         }
   11609         [ #  # ]:          0 :         if (priv->hws_ctpool) {
   11610                 :          0 :                 flow_hw_ct_pool_destroy(dev, priv->hws_ctpool);
   11611                 :          0 :                 priv->hws_ctpool = NULL;
   11612                 :            :         }
   11613         [ #  # ]:          0 :         if (priv->ct_mng) {
   11614                 :          0 :                 flow_hw_ct_mng_destroy(dev, priv->ct_mng);
   11615                 :          0 :                 priv->ct_mng = NULL;
   11616                 :            :         }
   11617                 :          0 :         mlx5_flow_quota_destroy(dev);
   11618         [ #  # ]:          0 :         if (priv->hw_q) {
   11619         [ #  # ]:          0 :                 for (i = 0; i < priv->nb_queue; i++) {
   11620                 :          0 :                         struct mlx5_hw_q *hwq = &priv->hw_q[i];
   11621                 :          0 :                         rte_ring_free(hwq->indir_iq);
   11622                 :          0 :                         rte_ring_free(hwq->indir_cq);
   11623                 :          0 :                         rte_ring_free(hwq->flow_transfer_pending);
   11624                 :          0 :                         rte_ring_free(hwq->flow_transfer_completed);
   11625                 :            :                 }
   11626                 :          0 :                 mlx5_free(priv->hw_q);
   11627                 :          0 :                 priv->hw_q = NULL;
   11628                 :            :         }
   11629         [ #  # ]:          0 :         if (ctx_close) {
   11630         [ #  # ]:          0 :                 if (priv->dr_ctx) {
   11631                 :          0 :                         claim_zero(mlx5dr_context_close(priv->dr_ctx));
   11632                 :          0 :                         priv->dr_ctx = NULL;
   11633                 :            :                 }
   11634                 :            :         }
   11635         [ #  # ]:          0 :         if (priv->shared_host) {
   11636                 :          0 :                 struct mlx5_priv *host_priv = priv->shared_host->data->dev_private;
   11637                 :          0 :                 rte_atomic_fetch_sub_explicit(&host_priv->shared_refcnt, 1,
   11638                 :            :                                 rte_memory_order_relaxed);
   11639                 :          0 :                 priv->shared_host = NULL;
   11640                 :            :         }
   11641         [ #  # ]:          0 :         if (priv->hw_attr) {
   11642                 :          0 :                 mlx5_free(priv->hw_attr);
   11643                 :          0 :                 priv->hw_attr = NULL;
   11644                 :            :         }
   11645                 :          0 :         priv->nb_queue = 0;
   11646                 :          0 : }
   11647                 :            : 
   11648                 :            : static __rte_always_inline struct rte_ring *
   11649                 :            : mlx5_hwq_ring_create(uint16_t port_id, uint32_t queue, uint32_t size, const char *str)
   11650                 :            : {
   11651                 :            :         char mz_name[RTE_MEMZONE_NAMESIZE];
   11652                 :            : 
   11653                 :            :         snprintf(mz_name, sizeof(mz_name), "port_%u_%s_%u", port_id, str, queue);
   11654                 :          0 :         return rte_ring_create(mz_name, size, SOCKET_ID_ANY,
   11655                 :            :                                RING_F_SP_ENQ | RING_F_SC_DEQ | RING_F_EXACT_SZ);
   11656                 :            : }
   11657                 :            : 
   11658                 :            : static int
   11659                 :          0 : flow_hw_validate_attributes(const struct rte_flow_port_attr *port_attr,
   11660                 :            :                             uint16_t nb_queue,
   11661                 :            :                             const struct rte_flow_queue_attr *queue_attr[],
   11662                 :            :                             bool nt_mode, struct rte_flow_error *error)
   11663                 :            : {
   11664                 :            :         uint32_t size;
   11665                 :            :         unsigned int i;
   11666                 :            : 
   11667         [ #  # ]:          0 :         if (port_attr == NULL)
   11668                 :          0 :                 return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   11669                 :            :                                           "Port attributes must be non-NULL");
   11670                 :            : 
   11671         [ #  # ]:          0 :         if (nb_queue == 0 && !nt_mode)
   11672                 :          0 :                 return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   11673                 :            :                                           "At least one flow queue is required");
   11674                 :            : 
   11675         [ #  # ]:          0 :         if (queue_attr == NULL)
   11676                 :          0 :                 return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   11677                 :            :                                           "Queue attributes must be non-NULL");
   11678                 :            : 
   11679                 :          0 :         size = queue_attr[0]->size;
   11680         [ #  # ]:          0 :         for (i = 1; i < nb_queue; ++i) {
   11681         [ #  # ]:          0 :                 if (queue_attr[i]->size != size)
   11682                 :          0 :                         return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   11683                 :            :                                                   NULL,
   11684                 :            :                                                   "All flow queues must have the same size");
   11685                 :            :         }
   11686                 :            : 
   11687                 :            :         return 0;
   11688                 :            : }
   11689                 :            : 
   11690                 :            : /**
   11691                 :            :  * Configure port HWS resources.
   11692                 :            :  *
   11693                 :            :  * @param[in] dev
   11694                 :            :  *   Pointer to the rte_eth_dev structure.
   11695                 :            :  * @param[in] port_attr
   11696                 :            :  *   Port configuration attributes.
   11697                 :            :  * @param[in] nb_queue
   11698                 :            :  *   Number of queue.
   11699                 :            :  * @param[in] queue_attr
   11700                 :            :  *   Array that holds attributes for each flow queue.
   11701                 :            :  * @param[in] nt_mode
   11702                 :            :  *   Non-template mode.
   11703                 :            :  * @param[out] error
   11704                 :            :  *   Pointer to error structure.
   11705                 :            :  *
   11706                 :            :  * @return
   11707                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   11708                 :            :  */
   11709                 :            : static int
   11710                 :          0 : __flow_hw_configure(struct rte_eth_dev *dev,
   11711                 :            :                   const struct rte_flow_port_attr *port_attr,
   11712                 :            :                   uint16_t nb_queue,
   11713                 :            :                   const struct rte_flow_queue_attr *queue_attr[],
   11714                 :            :                   bool nt_mode,
   11715                 :            :                   struct rte_flow_error *error)
   11716                 :            : {
   11717                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   11718                 :            :         struct mlx5_priv *host_priv = NULL;
   11719                 :          0 :         struct mlx5dr_context_attr dr_ctx_attr = {0};
   11720                 :            :         struct mlx5_hw_q *hw_q;
   11721                 :            :         struct mlx5_hw_q_job *job = NULL;
   11722                 :            :         uint32_t mem_size, i, j;
   11723                 :          0 :         struct mlx5_indexed_pool_config cfg = {
   11724                 :            :                 .size = sizeof(struct mlx5_action_construct_data),
   11725                 :            :                 .trunk_size = 4096,
   11726                 :            :                 .need_lock = 1,
   11727                 :          0 :                 .release_mem_en = !!priv->sh->config.reclaim_mode,
   11728                 :            :                 .malloc = mlx5_malloc,
   11729                 :            :                 .free = mlx5_free,
   11730                 :            :                 .type = "mlx5_hw_action_construct_data",
   11731                 :            :         };
   11732                 :            :         /*
   11733                 :            :          * Adds one queue to be used by PMD.
   11734                 :            :          * The last queue will be used by the PMD.
   11735                 :            :          */
   11736                 :            :         uint16_t nb_q_updated = 0;
   11737                 :            :         struct rte_flow_queue_attr **_queue_attr = NULL;
   11738                 :          0 :         struct rte_flow_queue_attr ctrl_queue_attr = {0};
   11739   [ #  #  #  # ]:          0 :         bool is_proxy = !!(priv->sh->config.dv_esw_en && priv->master);
   11740                 :            :         int ret = 0;
   11741                 :            :         uint32_t action_flags;
   11742                 :            :         bool strict_queue = false;
   11743                 :            : 
   11744                 :          0 :         error->type = RTE_FLOW_ERROR_TYPE_NONE;
   11745         [ #  # ]:          0 :         if (mlx5dr_rule_get_handle_size() != MLX5_DR_RULE_SIZE) {
   11746                 :          0 :                 rte_errno = EINVAL;
   11747                 :          0 :                 goto err;
   11748                 :            :         }
   11749         [ #  # ]:          0 :         if (flow_hw_validate_attributes(port_attr, nb_queue, queue_attr, nt_mode, error))
   11750                 :          0 :                 return -rte_errno;
   11751                 :            :         /*
   11752                 :            :          * Calling rte_flow_configure() again is allowed if
   11753                 :            :          * provided configuration matches the initially provided one,
   11754                 :            :          * or previous configuration was default non template one.
   11755                 :            :          */
   11756         [ #  # ]:          0 :         if (priv->dr_ctx) {
   11757                 :            :                 MLX5_ASSERT(priv->hw_attr != NULL);
   11758         [ #  # ]:          0 :                 for (i = 0; i < priv->nb_queue; i++) {
   11759                 :          0 :                         hw_q = &priv->hw_q[i];
   11760                 :            :                         /* Make sure all queues are empty. */
   11761         [ #  # ]:          0 :                         if (hw_q->size != hw_q->job_idx) {
   11762                 :          0 :                                 rte_errno = EBUSY;
   11763                 :          0 :                                 goto err;
   11764                 :            :                         }
   11765                 :            :                 }
   11766                 :            :                 /* If previous configuration was not default non template mode config. */
   11767         [ #  # ]:          0 :                 if (!priv->hw_attr->nt_mode) {
   11768         [ #  # ]:          0 :                         if (flow_hw_compare_config(priv->hw_attr, port_attr, nb_queue, queue_attr))
   11769                 :            :                                 return 0;
   11770                 :            :                         else
   11771                 :          0 :                                 return rte_flow_error_set(error, ENOTSUP,
   11772                 :            :                                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   11773                 :            :                                                         "Changing HWS configuration attributes "
   11774                 :            :                                                         "is not supported");
   11775                 :            :                 }
   11776                 :            :                 /* Reconfiguration, need to release all resources from previous allocation. */
   11777                 :          0 :                 __flow_hw_resource_release(dev, true);
   11778                 :            :         }
   11779                 :          0 :         priv->hw_attr = flow_hw_alloc_copy_config(port_attr, nb_queue, queue_attr, nt_mode, error);
   11780         [ #  # ]:          0 :         if (!priv->hw_attr) {
   11781                 :          0 :                 ret = -rte_errno;
   11782                 :          0 :                 goto err;
   11783                 :            :         }
   11784                 :          0 :         ctrl_queue_attr.size = queue_attr[0]->size;
   11785                 :          0 :         nb_q_updated = nb_queue + 1;
   11786                 :          0 :         _queue_attr = mlx5_malloc(MLX5_MEM_ZERO,
   11787                 :            :                                   nb_q_updated *
   11788                 :            :                                   sizeof(struct rte_flow_queue_attr *),
   11789                 :            :                                   64, SOCKET_ID_ANY);
   11790         [ #  # ]:          0 :         if (!_queue_attr) {
   11791                 :          0 :                 rte_errno = ENOMEM;
   11792                 :          0 :                 goto err;
   11793                 :            :         }
   11794                 :            : 
   11795                 :          0 :         memcpy(_queue_attr, queue_attr, sizeof(void *) * nb_queue);
   11796                 :          0 :         _queue_attr[nb_queue] = &ctrl_queue_attr;
   11797                 :          0 :         priv->acts_ipool = mlx5_ipool_create(&cfg);
   11798         [ #  # ]:          0 :         if (!priv->acts_ipool)
   11799                 :          0 :                 goto err;
   11800                 :            :         /* Allocate the queue job descriptor LIFO. */
   11801                 :          0 :         mem_size = sizeof(priv->hw_q[0]) * nb_q_updated;
   11802         [ #  # ]:          0 :         for (i = 0; i < nb_q_updated; i++) {
   11803                 :          0 :                 mem_size += (sizeof(struct mlx5_hw_q_job *) +
   11804                 :          0 :                              sizeof(struct mlx5_hw_q_job)) * _queue_attr[i]->size;
   11805                 :            :         }
   11806                 :          0 :         priv->hw_q = mlx5_malloc(MLX5_MEM_ZERO, mem_size,
   11807                 :            :                                  64, SOCKET_ID_ANY);
   11808         [ #  # ]:          0 :         if (!priv->hw_q) {
   11809                 :          0 :                 rte_errno = ENOMEM;
   11810                 :          0 :                 goto err;
   11811                 :            :         }
   11812         [ #  # ]:          0 :         for (i = 0; i < nb_q_updated; i++) {
   11813                 :          0 :                 priv->hw_q[i].job_idx = _queue_attr[i]->size;
   11814                 :          0 :                 priv->hw_q[i].size = _queue_attr[i]->size;
   11815                 :          0 :                 priv->hw_q[i].ongoing_flow_ops = 0;
   11816         [ #  # ]:          0 :                 if (i == 0)
   11817                 :          0 :                         priv->hw_q[i].job = (struct mlx5_hw_q_job **)
   11818                 :          0 :                                             &priv->hw_q[nb_q_updated];
   11819                 :            :                 else
   11820                 :          0 :                         priv->hw_q[i].job = (struct mlx5_hw_q_job **)&job[_queue_attr[i - 1]->size];
   11821                 :          0 :                 job = (struct mlx5_hw_q_job *)
   11822                 :          0 :                       &priv->hw_q[i].job[_queue_attr[i]->size];
   11823         [ #  # ]:          0 :                 for (j = 0; j < _queue_attr[i]->size; j++)
   11824                 :          0 :                         priv->hw_q[i].job[j] = &job[j];
   11825                 :            :                 /* Notice ring name length is limited. */
   11826                 :          0 :                 priv->hw_q[i].indir_cq = mlx5_hwq_ring_create
   11827                 :          0 :                         (dev->data->port_id, i, _queue_attr[i]->size, "indir_act_cq");
   11828         [ #  # ]:          0 :                 if (!priv->hw_q[i].indir_cq)
   11829                 :          0 :                         goto err;
   11830                 :          0 :                 priv->hw_q[i].indir_iq = mlx5_hwq_ring_create
   11831                 :          0 :                         (dev->data->port_id, i, _queue_attr[i]->size, "indir_act_iq");
   11832         [ #  # ]:          0 :                 if (!priv->hw_q[i].indir_iq)
   11833                 :          0 :                         goto err;
   11834                 :          0 :                 priv->hw_q[i].flow_transfer_pending = mlx5_hwq_ring_create
   11835                 :          0 :                         (dev->data->port_id, i, _queue_attr[i]->size, "tx_pending");
   11836         [ #  # ]:          0 :                 if (!priv->hw_q[i].flow_transfer_pending)
   11837                 :          0 :                         goto err;
   11838                 :          0 :                 priv->hw_q[i].flow_transfer_completed = mlx5_hwq_ring_create
   11839                 :          0 :                         (dev->data->port_id, i, _queue_attr[i]->size, "tx_done");
   11840         [ #  # ]:          0 :                 if (!priv->hw_q[i].flow_transfer_completed)
   11841                 :          0 :                         goto err;
   11842                 :            :         }
   11843                 :          0 :         dr_ctx_attr.pd = priv->sh->cdev->pd;
   11844                 :          0 :         dr_ctx_attr.queues = nb_q_updated;
   11845                 :            :         /* Assign initial value of STC numbers for representors. */
   11846         [ #  # ]:          0 :         if (priv->representor)
   11847                 :          0 :                 dr_ctx_attr.initial_log_stc_memory = MLX5_REPR_STC_MEMORY_LOG;
   11848                 :            :         /* Queue size should all be the same. Take the first one. */
   11849                 :          0 :         dr_ctx_attr.queue_size = _queue_attr[0]->size;
   11850         [ #  # ]:          0 :         if (port_attr->flags & RTE_FLOW_PORT_FLAG_SHARE_INDIRECT) {
   11851                 :            :                 struct rte_eth_dev *host_dev = NULL;
   11852                 :            :                 uint16_t port_id;
   11853                 :            : 
   11854                 :            :                 MLX5_ASSERT(rte_eth_dev_is_valid_port(port_attr->host_port_id));
   11855         [ #  # ]:          0 :                 if (is_proxy) {
   11856                 :          0 :                         DRV_LOG(ERR, "cross vHCA shared mode not supported "
   11857                 :            :                                 "for E-Switch confgiurations");
   11858                 :          0 :                         rte_errno = ENOTSUP;
   11859                 :          0 :                         goto err;
   11860                 :            :                 }
   11861         [ #  # ]:          0 :                 MLX5_ETH_FOREACH_DEV(port_id, dev->device) {
   11862         [ #  # ]:          0 :                         if (port_id == port_attr->host_port_id) {
   11863                 :          0 :                                 host_dev = &rte_eth_devices[port_id];
   11864                 :          0 :                                 break;
   11865                 :            :                         }
   11866                 :            :                 }
   11867         [ #  # ]:          0 :                 if (!host_dev || host_dev == dev ||
   11868   [ #  #  #  # ]:          0 :                     !host_dev->data || !host_dev->data->dev_private) {
   11869                 :          0 :                         DRV_LOG(ERR, "Invalid cross vHCA host port %u",
   11870                 :            :                                 port_attr->host_port_id);
   11871                 :          0 :                         rte_errno = EINVAL;
   11872                 :          0 :                         goto err;
   11873                 :            :                 }
   11874                 :            :                 host_priv = host_dev->data->dev_private;
   11875         [ #  # ]:          0 :                 if (host_priv->sh->cdev->ctx == priv->sh->cdev->ctx) {
   11876                 :          0 :                         DRV_LOG(ERR, "Sibling ports %u and %u do not "
   11877                 :            :                                      "require cross vHCA sharing mode",
   11878                 :            :                                 dev->data->port_id, port_attr->host_port_id);
   11879                 :          0 :                         rte_errno = EINVAL;
   11880                 :          0 :                         goto err;
   11881                 :            :                 }
   11882         [ #  # ]:          0 :                 if (host_priv->shared_host) {
   11883                 :          0 :                         DRV_LOG(ERR, "Host port %u is not the sharing base",
   11884                 :            :                                 port_attr->host_port_id);
   11885                 :          0 :                         rte_errno = EINVAL;
   11886                 :          0 :                         goto err;
   11887                 :            :                 }
   11888         [ #  # ]:          0 :                 if (port_attr->nb_counters ||
   11889         [ #  # ]:          0 :                     port_attr->nb_aging_objects ||
   11890         [ #  # ]:          0 :                     port_attr->nb_meters ||
   11891         [ #  # ]:          0 :                     port_attr->nb_conn_tracks) {
   11892                 :          0 :                         DRV_LOG(ERR,
   11893                 :            :                                 "Object numbers on guest port must be zeros");
   11894                 :          0 :                         rte_errno = EINVAL;
   11895                 :          0 :                         goto err;
   11896                 :            :                 }
   11897                 :          0 :                 dr_ctx_attr.shared_ibv_ctx = host_priv->sh->cdev->ctx;
   11898                 :          0 :                 priv->shared_host = host_dev;
   11899                 :          0 :                 rte_atomic_fetch_add_explicit(&host_priv->shared_refcnt, 1,
   11900                 :            :                                 rte_memory_order_relaxed);
   11901                 :            :         }
   11902                 :            :         /* Set backward compatibale mode to support non template RTE FLOW API.*/
   11903                 :          0 :         dr_ctx_attr.bwc = true;
   11904                 :          0 :         priv->dr_ctx = mlx5dr_context_open(priv->sh->cdev->ctx, &dr_ctx_attr);
   11905                 :            :         /* rte_errno has been updated by HWS layer. */
   11906         [ #  # ]:          0 :         if (!priv->dr_ctx)
   11907                 :          0 :                 goto err;
   11908                 :          0 :         priv->nb_queue = nb_q_updated;
   11909                 :          0 :         ret = flow_hw_action_template_drop_init(dev, error);
   11910         [ #  # ]:          0 :         if (ret)
   11911                 :          0 :                 goto err;
   11912                 :          0 :         ret = flow_hw_create_ctrl_rx_tables(dev);
   11913         [ #  # ]:          0 :         if (ret) {
   11914                 :          0 :                 rte_flow_error_set(error, -ret, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   11915                 :            :                                    "Failed to set up Rx control flow templates");
   11916                 :          0 :                 goto err;
   11917                 :            :         }
   11918                 :            :         /* Initialize quotas */
   11919   [ #  #  #  #  :          0 :         if (port_attr->nb_quotas || (host_priv && host_priv->quota_ctx.devx_obj)) {
                   #  # ]
   11920                 :          0 :                 ret = mlx5_flow_quota_init(dev, port_attr->nb_quotas);
   11921         [ #  # ]:          0 :                 if (ret) {
   11922                 :          0 :                         rte_flow_error_set(error, -ret, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   11923                 :            :                                            "Failed to initialize quota.");
   11924                 :          0 :                         goto err;
   11925                 :            :                 }
   11926                 :            :         }
   11927                 :            :         /* Initialize meter library*/
   11928   [ #  #  #  #  :          0 :         if (port_attr->nb_meters || (host_priv && host_priv->hws_mpool))
                   #  # ]
   11929         [ #  # ]:          0 :                 if (mlx5_flow_meter_init(dev, port_attr->nb_meters, 0, 0, nb_q_updated))
   11930                 :          0 :                         goto err;
   11931                 :            :         /* Add global actions. */
   11932         [ #  # ]:          0 :         for (i = 0; i < MLX5_HW_ACTION_FLAG_MAX; i++) {
   11933                 :            :                 uint32_t act_flags = 0;
   11934                 :            : 
   11935                 :          0 :                 act_flags = mlx5_hw_act_flag[i][0] | mlx5_hw_act_flag[i][1];
   11936         [ #  # ]:          0 :                 if (is_proxy)
   11937                 :          0 :                         act_flags |= mlx5_hw_act_flag[i][2];
   11938                 :          0 :                 priv->hw_drop[i] = mlx5dr_action_create_dest_drop(priv->dr_ctx, act_flags);
   11939         [ #  # ]:          0 :                 if (!priv->hw_drop[i])
   11940                 :          0 :                         goto err;
   11941                 :          0 :                 priv->hw_tag[i] = mlx5dr_action_create_tag
   11942                 :            :                         (priv->dr_ctx, mlx5_hw_act_flag[i][0]);
   11943         [ #  # ]:          0 :                 if (!priv->hw_tag[i])
   11944                 :          0 :                         goto err;
   11945                 :            :         }
   11946   [ #  #  #  # ]:          0 :         if (priv->sh->config.dv_esw_en && priv->sh->config.repr_matching) {
   11947                 :          0 :                 ret = flow_hw_setup_tx_repr_tagging(dev, error);
   11948         [ #  # ]:          0 :                 if (ret)
   11949                 :          0 :                         goto err;
   11950                 :            :         }
   11951                 :            :         /*
   11952                 :            :          * DEFAULT_MISS action have different behaviors in different domains.
   11953                 :            :          * In FDB, it will steering the packets to the E-switch manager.
   11954                 :            :          * In NIC Rx root, it will steering the packet to the kernel driver stack.
   11955                 :            :          * An action with all bits set in the flag can be created and the HWS
   11956                 :            :          * layer will translate it properly when being used in different rules.
   11957                 :            :          */
   11958                 :            :         action_flags = MLX5DR_ACTION_FLAG_ROOT_RX | MLX5DR_ACTION_FLAG_HWS_RX |
   11959                 :            :                        MLX5DR_ACTION_FLAG_ROOT_TX | MLX5DR_ACTION_FLAG_HWS_TX;
   11960         [ #  # ]:          0 :         if (is_proxy)
   11961                 :            :                 action_flags |= (MLX5DR_ACTION_FLAG_ROOT_FDB | MLX5DR_ACTION_FLAG_HWS_FDB);
   11962                 :          0 :         priv->hw_def_miss = mlx5dr_action_create_default_miss(priv->dr_ctx, action_flags);
   11963         [ #  # ]:          0 :         if (!priv->hw_def_miss)
   11964                 :          0 :                 goto err;
   11965         [ #  # ]:          0 :         if (is_proxy) {
   11966                 :          0 :                 ret = flow_hw_create_vport_actions(priv);
   11967         [ #  # ]:          0 :                 if (ret) {
   11968                 :          0 :                         rte_flow_error_set(error, -ret, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   11969                 :            :                                            NULL, "Failed to create vport actions.");
   11970                 :          0 :                         goto err;
   11971                 :            :                 }
   11972                 :          0 :                 ret = flow_hw_create_ctrl_tables(dev, error);
   11973         [ #  # ]:          0 :                 if (ret) {
   11974                 :          0 :                         rte_errno = -ret;
   11975                 :          0 :                         goto err;
   11976                 :            :                 }
   11977                 :            :         }
   11978                 :            :         if (!priv->shared_host)
   11979                 :            :                 flow_hw_create_send_to_kernel_actions(priv);
   11980   [ #  #  #  #  :          0 :         if (port_attr->nb_conn_tracks || (host_priv && host_priv->hws_ctpool)) {
                   #  # ]
   11981         [ #  # ]:          0 :                 if (mlx5_flow_ct_init(dev, port_attr->nb_conn_tracks, nb_q_updated))
   11982                 :          0 :                         goto err;
   11983                 :            :         }
   11984   [ #  #  #  #  :          0 :         if (port_attr->nb_counters || (host_priv && host_priv->hws_cpool)) {
                   #  # ]
   11985         [ #  # ]:          0 :                 struct mlx5_hws_cnt_pool *hws_cpool = host_priv ? host_priv->hws_cpool : NULL;
   11986                 :            : 
   11987                 :          0 :                 ret = mlx5_hws_cnt_pool_create(dev, port_attr->nb_counters,
   11988                 :            :                                                nb_queue, hws_cpool, error);
   11989         [ #  # ]:          0 :                 if (ret)
   11990                 :          0 :                         goto err;
   11991                 :            :         }
   11992         [ #  # ]:          0 :         if (port_attr->nb_aging_objects) {
   11993         [ #  # ]:          0 :                 if (port_attr->nb_counters == 0) {
   11994                 :            :                         /*
   11995                 :            :                          * Aging management uses counter. Number counters
   11996                 :            :                          * requesting should take into account a counter for
   11997                 :            :                          * each flow rules containing AGE without counter.
   11998                 :            :                          */
   11999                 :          0 :                         DRV_LOG(ERR, "Port %u AGE objects are requested (%u) "
   12000                 :            :                                 "without counters requesting.",
   12001                 :            :                                 dev->data->port_id,
   12002                 :            :                                 port_attr->nb_aging_objects);
   12003                 :          0 :                         rte_errno = EINVAL;
   12004                 :          0 :                         goto err;
   12005                 :            :                 }
   12006         [ #  # ]:          0 :                 if (port_attr->flags & RTE_FLOW_PORT_FLAG_SHARE_INDIRECT) {
   12007                 :          0 :                         DRV_LOG(ERR, "Aging is not supported "
   12008                 :            :                                 "in cross vHCA sharing mode");
   12009                 :            :                         ret = -ENOTSUP;
   12010                 :          0 :                         goto err;
   12011                 :            :                 }
   12012                 :          0 :                 strict_queue = !!(port_attr->flags & RTE_FLOW_PORT_FLAG_STRICT_QUEUE);
   12013                 :          0 :                 ret = mlx5_hws_age_pool_init(dev, port_attr->nb_aging_objects,
   12014                 :            :                                                 nb_queue, strict_queue);
   12015         [ #  # ]:          0 :                 if (ret < 0)
   12016                 :          0 :                         goto err;
   12017                 :            :         }
   12018                 :          0 :         ret = flow_hw_create_vlan(dev);
   12019         [ #  # ]:          0 :         if (ret) {
   12020                 :          0 :                 rte_flow_error_set(error, -ret, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12021                 :            :                                    NULL, "Failed to VLAN actions.");
   12022                 :          0 :                 goto err;
   12023                 :            :         }
   12024         [ #  # ]:          0 :         if (flow_hw_create_nat64_actions(priv, error))
   12025                 :          0 :                 DRV_LOG(WARNING, "Cannot create NAT64 action on port %u, "
   12026                 :            :                         "please check the FW version", dev->data->port_id);
   12027                 :            :         if (_queue_attr)
   12028                 :          0 :                 mlx5_free(_queue_attr);
   12029         [ #  # ]:          0 :         if (port_attr->flags & RTE_FLOW_PORT_FLAG_STRICT_QUEUE)
   12030                 :          0 :                 priv->hws_strict_queue = 1;
   12031                 :          0 :         dev->flow_fp_ops = &mlx5_flow_hw_fp_ops;
   12032                 :          0 :         return 0;
   12033                 :          0 : err:
   12034                 :          0 :         __flow_hw_resource_release(dev, true);
   12035         [ #  # ]:          0 :         if (_queue_attr)
   12036                 :          0 :                 mlx5_free(_queue_attr);
   12037                 :            :         /* Do not overwrite the internal errno information. */
   12038   [ #  #  #  # ]:          0 :         if (ret && error->type != RTE_FLOW_ERROR_TYPE_NONE)
   12039                 :            :                 return ret;
   12040                 :          0 :         return rte_flow_error_set(error, rte_errno,
   12041                 :            :                                   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   12042                 :            :                                   "fail to configure port");
   12043                 :            : }
   12044                 :            : 
   12045                 :            : /**
   12046                 :            :  * Configure port HWS resources.
   12047                 :            :  *
   12048                 :            :  * @param[in] dev
   12049                 :            :  *   Pointer to the rte_eth_dev structure.
   12050                 :            :  * @param[in] port_attr
   12051                 :            :  *   Port configuration attributes.
   12052                 :            :  * @param[in] nb_queue
   12053                 :            :  *   Number of queue.
   12054                 :            :  * @param[in] queue_attr
   12055                 :            :  *   Array that holds attributes for each flow queue.
   12056                 :            :  * @param[out] error
   12057                 :            :  *   Pointer to error structure.
   12058                 :            :  *
   12059                 :            :  * @return
   12060                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   12061                 :            :  */
   12062                 :            : static int
   12063                 :          0 : flow_hw_configure(struct rte_eth_dev *dev,
   12064                 :            :                   const struct rte_flow_port_attr *port_attr,
   12065                 :            :                   uint16_t nb_queue,
   12066                 :            :                   const struct rte_flow_queue_attr *queue_attr[],
   12067                 :            :                   struct rte_flow_error *error)
   12068                 :            : {
   12069                 :          0 :         struct rte_flow_error shadow_error = {0, };
   12070                 :            : 
   12071         [ #  # ]:          0 :         if (!error)
   12072                 :            :                 error = &shadow_error;
   12073                 :          0 :         return __flow_hw_configure(dev, port_attr, nb_queue, queue_attr, false, error);
   12074                 :            : }
   12075                 :            : 
   12076                 :            : /**
   12077                 :            :  * Release HWS resources.
   12078                 :            :  *
   12079                 :            :  * @param[in] dev
   12080                 :            :  *   Pointer to the rte_eth_dev structure.
   12081                 :            :  */
   12082                 :            : void
   12083                 :          0 : flow_hw_resource_release(struct rte_eth_dev *dev)
   12084                 :            : {
   12085                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12086                 :            : 
   12087         [ #  # ]:          0 :         if (!priv->dr_ctx)
   12088                 :            :                 return;
   12089                 :          0 :         __flow_hw_resource_release(dev, false);
   12090                 :            : }
   12091                 :            : 
   12092                 :            : /* Sets vport tag and mask, for given port, used in HWS rules. */
   12093                 :            : void
   12094                 :          0 : flow_hw_set_port_info(struct rte_eth_dev *dev)
   12095                 :            : {
   12096                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12097                 :          0 :         uint16_t port_id = dev->data->port_id;
   12098                 :            :         struct flow_hw_port_info *info;
   12099                 :            : 
   12100                 :            :         MLX5_ASSERT(port_id < RTE_MAX_ETHPORTS);
   12101                 :          0 :         info = &mlx5_flow_hw_port_infos[port_id];
   12102                 :          0 :         info->regc_mask = priv->vport_meta_mask;
   12103         [ #  # ]:          0 :         info->regc_value = priv->vport_meta_tag;
   12104         [ #  # ]:          0 :         info->is_wire = mlx5_is_port_on_mpesw_device(priv) ? priv->mpesw_uplink : priv->master;
   12105                 :          0 : }
   12106                 :            : 
   12107                 :            : /* Clears vport tag and mask used for HWS rules. */
   12108                 :            : void
   12109                 :          0 : flow_hw_clear_port_info(struct rte_eth_dev *dev)
   12110                 :            : {
   12111                 :          0 :         uint16_t port_id = dev->data->port_id;
   12112                 :            :         struct flow_hw_port_info *info;
   12113                 :            : 
   12114                 :            :         MLX5_ASSERT(port_id < RTE_MAX_ETHPORTS);
   12115                 :          0 :         info = &mlx5_flow_hw_port_infos[port_id];
   12116                 :          0 :         info->regc_mask = 0;
   12117                 :          0 :         info->regc_value = 0;
   12118                 :          0 :         info->is_wire = 0;
   12119                 :          0 : }
   12120                 :            : 
   12121                 :            : static int
   12122                 :          0 : flow_hw_conntrack_destroy(struct rte_eth_dev *dev,
   12123                 :            :                           uint32_t idx,
   12124                 :            :                           struct rte_flow_error *error)
   12125                 :            : {
   12126                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12127                 :          0 :         struct mlx5_aso_ct_pool *pool = priv->hws_ctpool;
   12128                 :            :         struct mlx5_aso_ct_action *ct;
   12129                 :            : 
   12130         [ #  # ]:          0 :         if (priv->shared_host)
   12131                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
   12132                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12133                 :            :                                 NULL,
   12134                 :            :                                 "CT destruction is not allowed to guest port");
   12135                 :          0 :         ct = mlx5_ipool_get(pool->cts, idx);
   12136         [ #  # ]:          0 :         if (!ct) {
   12137                 :          0 :                 return rte_flow_error_set(error, EINVAL,
   12138                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12139                 :            :                                 NULL,
   12140                 :            :                                 "Invalid CT destruction index");
   12141                 :            :         }
   12142                 :          0 :         rte_atomic_store_explicit(&ct->state, ASO_CONNTRACK_FREE,
   12143                 :            :                                  rte_memory_order_relaxed);
   12144                 :          0 :         mlx5_ipool_free(pool->cts, idx);
   12145                 :          0 :         return 0;
   12146                 :            : }
   12147                 :            : 
   12148                 :            : static int
   12149                 :          0 : flow_hw_conntrack_query(struct rte_eth_dev *dev, uint32_t queue, uint32_t idx,
   12150                 :            :                         struct rte_flow_action_conntrack *profile,
   12151                 :            :                         void *user_data, bool push,
   12152                 :            :                         struct rte_flow_error *error)
   12153                 :            : {
   12154                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12155                 :          0 :         struct mlx5_aso_ct_pool *pool = priv->hws_ctpool;
   12156                 :            :         struct mlx5_aso_ct_action *ct;
   12157                 :            : 
   12158         [ #  # ]:          0 :         if (priv->shared_host)
   12159                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
   12160                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12161                 :            :                                 NULL,
   12162                 :            :                                 "CT query is not allowed to guest port");
   12163                 :          0 :         ct = mlx5_ipool_get(pool->cts, idx);
   12164         [ #  # ]:          0 :         if (!ct) {
   12165                 :          0 :                 return rte_flow_error_set(error, EINVAL,
   12166                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12167                 :            :                                 NULL,
   12168                 :            :                                 "Invalid CT query index");
   12169                 :            :         }
   12170                 :          0 :         profile->peer_port = ct->peer;
   12171                 :          0 :         profile->is_original_dir = ct->is_original;
   12172         [ #  # ]:          0 :         if (mlx5_aso_ct_query_by_wqe(priv->sh, queue, ct, profile, user_data, push))
   12173                 :          0 :                 return rte_flow_error_set(error, EIO,
   12174                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12175                 :            :                                 NULL,
   12176                 :            :                                 "Failed to query CT context");
   12177                 :            :         return 0;
   12178                 :            : }
   12179                 :            : 
   12180                 :            : 
   12181                 :            : static int
   12182                 :          0 : flow_hw_conntrack_update(struct rte_eth_dev *dev, uint32_t queue,
   12183                 :            :                          const struct rte_flow_modify_conntrack *action_conf,
   12184                 :            :                          uint32_t idx, void *user_data, bool push,
   12185                 :            :                          struct rte_flow_error *error)
   12186                 :            : {
   12187                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12188                 :          0 :         struct mlx5_aso_ct_pool *pool = priv->hws_ctpool;
   12189                 :            :         struct mlx5_aso_ct_action *ct;
   12190                 :            :         const struct rte_flow_action_conntrack *new_prf;
   12191                 :            :         int ret = 0;
   12192                 :            : 
   12193         [ #  # ]:          0 :         if (priv->shared_host)
   12194                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
   12195                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12196                 :            :                                 NULL,
   12197                 :            :                                 "CT update is not allowed to guest port");
   12198                 :          0 :         ct = mlx5_ipool_get(pool->cts, idx);
   12199         [ #  # ]:          0 :         if (!ct) {
   12200                 :          0 :                 return rte_flow_error_set(error, EINVAL,
   12201                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12202                 :            :                                 NULL,
   12203                 :            :                                 "Invalid CT update index");
   12204                 :            :         }
   12205                 :          0 :         new_prf = &action_conf->new_ct;
   12206         [ #  # ]:          0 :         if (action_conf->direction)
   12207                 :          0 :                 ct->is_original = !!new_prf->is_original_dir;
   12208         [ #  # ]:          0 :         if (action_conf->state) {
   12209                 :            :                 /* Only validate the profile when it needs to be updated. */
   12210                 :          0 :                 ret = mlx5_validate_action_ct(dev, new_prf, error);
   12211         [ #  # ]:          0 :                 if (ret)
   12212                 :            :                         return ret;
   12213                 :          0 :                 ret = mlx5_aso_ct_update_by_wqe(priv->sh, queue, ct, new_prf,
   12214                 :            :                                                 user_data, push);
   12215         [ #  # ]:          0 :                 if (ret)
   12216                 :          0 :                         return rte_flow_error_set(error, EIO,
   12217                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12218                 :            :                                         NULL,
   12219                 :            :                                         "Failed to send CT context update WQE");
   12220         [ #  # ]:          0 :                 if (queue != MLX5_HW_INV_QUEUE)
   12221                 :            :                         return 0;
   12222                 :            :                 /* Block until ready or a failure in synchronous mode. */
   12223                 :          0 :                 ret = mlx5_aso_ct_available(priv->sh, queue, ct);
   12224         [ #  # ]:          0 :                 if (ret)
   12225                 :          0 :                         rte_flow_error_set(error, rte_errno,
   12226                 :            :                                            RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12227                 :            :                                            NULL,
   12228                 :            :                                            "Timeout to get the CT update");
   12229                 :            :         }
   12230                 :            :         return ret;
   12231                 :            : }
   12232                 :            : 
   12233                 :            : static struct rte_flow_action_handle *
   12234                 :          0 : flow_hw_conntrack_create(struct rte_eth_dev *dev, uint32_t queue,
   12235                 :            :                          const struct rte_flow_action_conntrack *pro,
   12236                 :            :                          void *user_data, bool push,
   12237                 :            :                          struct rte_flow_error *error)
   12238                 :            : {
   12239                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12240                 :          0 :         struct mlx5_aso_ct_pool *pool = priv->hws_ctpool;
   12241                 :            :         struct mlx5_aso_ct_action *ct;
   12242                 :          0 :         uint32_t ct_idx = 0;
   12243                 :            :         int ret;
   12244                 :            :         bool async = !!(queue != MLX5_HW_INV_QUEUE);
   12245                 :            : 
   12246         [ #  # ]:          0 :         if (priv->shared_host) {
   12247                 :          0 :                 rte_flow_error_set(error, ENOTSUP,
   12248                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12249                 :            :                                 NULL,
   12250                 :            :                                 "CT create is not allowed to guest port");
   12251                 :          0 :                 return NULL;
   12252                 :            :         }
   12253         [ #  # ]:          0 :         if (!pool) {
   12254                 :          0 :                 rte_flow_error_set(error, EINVAL,
   12255                 :            :                                    RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   12256                 :            :                                    "CT is not enabled");
   12257                 :          0 :                 return 0;
   12258                 :            :         }
   12259                 :          0 :         ct = mlx5_ipool_zmalloc(pool->cts, &ct_idx);
   12260         [ #  # ]:          0 :         if (!ct) {
   12261                 :          0 :                 rte_flow_error_set(error, rte_errno,
   12262                 :            :                                    RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   12263                 :            :                                    "Failed to allocate CT object");
   12264                 :          0 :                 return 0;
   12265                 :            :         }
   12266                 :          0 :         ct->offset = ct_idx - 1;
   12267                 :          0 :         ct->is_original = !!pro->is_original_dir;
   12268                 :          0 :         ct->peer = pro->peer_port;
   12269                 :          0 :         ct->pool = pool;
   12270         [ #  # ]:          0 :         if (mlx5_aso_ct_update_by_wqe(priv->sh, queue, ct, pro, user_data, push)) {
   12271                 :          0 :                 mlx5_ipool_free(pool->cts, ct_idx);
   12272                 :          0 :                 rte_flow_error_set(error, EBUSY,
   12273                 :            :                                    RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   12274                 :            :                                    "Failed to update CT");
   12275                 :          0 :                 return 0;
   12276                 :            :         }
   12277         [ #  # ]:          0 :         if (!async) {
   12278                 :          0 :                 ret = mlx5_aso_ct_available(priv->sh, queue, ct);
   12279         [ #  # ]:          0 :                 if (ret) {
   12280                 :          0 :                         mlx5_ipool_free(pool->cts, ct_idx);
   12281                 :          0 :                         rte_flow_error_set(error, rte_errno,
   12282                 :            :                                            RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12283                 :            :                                            NULL,
   12284                 :            :                                            "Timeout to get the CT update");
   12285                 :          0 :                         return 0;
   12286                 :            :                 }
   12287                 :            :         }
   12288                 :          0 :         return MLX5_INDIRECT_ACT_HWS_CT_GEN_IDX(ct_idx);
   12289                 :            : }
   12290                 :            : 
   12291                 :            : /**
   12292                 :            :  * Validate shared action.
   12293                 :            :  *
   12294                 :            :  * @param[in] dev
   12295                 :            :  *   Pointer to the rte_eth_dev structure.
   12296                 :            :  * @param[in] queue
   12297                 :            :  *   Which queue to be used.
   12298                 :            :  * @param[in] attr
   12299                 :            :  *   Operation attribute.
   12300                 :            :  * @param[in] conf
   12301                 :            :  *   Indirect action configuration.
   12302                 :            :  * @param[in] action
   12303                 :            :  *   rte_flow action detail.
   12304                 :            :  * @param[in] user_data
   12305                 :            :  *   Pointer to the user_data.
   12306                 :            :  * @param[out] error
   12307                 :            :  *   Pointer to error structure.
   12308                 :            :  *
   12309                 :            :  * @return
   12310                 :            :  *   0 on success, otherwise negative errno value.
   12311                 :            :  */
   12312                 :            : static int
   12313                 :          0 : flow_hw_action_handle_validate(struct rte_eth_dev *dev, uint32_t queue,
   12314                 :            :                                const struct rte_flow_op_attr *attr,
   12315                 :            :                                const struct rte_flow_indir_action_conf *conf,
   12316                 :            :                                const struct rte_flow_action *action,
   12317                 :            :                                void *user_data,
   12318                 :            :                                struct rte_flow_error *error)
   12319                 :            : {
   12320                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12321                 :            : 
   12322                 :            :         RTE_SET_USED(attr);
   12323                 :            :         RTE_SET_USED(queue);
   12324                 :            :         RTE_SET_USED(user_data);
   12325   [ #  #  #  #  :          0 :         switch (action->type) {
                #  #  # ]
   12326                 :          0 :         case RTE_FLOW_ACTION_TYPE_AGE:
   12327         [ #  # ]:          0 :                 if (!priv->hws_age_req) {
   12328         [ #  # ]:          0 :                         if (flow_hw_allocate_actions(dev, MLX5_FLOW_ACTION_AGE,
   12329                 :            :                                                      error))
   12330                 :          0 :                                 return rte_flow_error_set
   12331                 :            :                                         (error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
   12332                 :            :                                          NULL, "aging pool not initialized");
   12333                 :            :                 }
   12334                 :            :                 break;
   12335                 :          0 :         case RTE_FLOW_ACTION_TYPE_COUNT:
   12336         [ #  # ]:          0 :                 if (!priv->hws_cpool) {
   12337         [ #  # ]:          0 :                         if (flow_hw_allocate_actions(dev, MLX5_FLOW_ACTION_COUNT,
   12338                 :            :                                                      error))
   12339                 :          0 :                                 return rte_flow_error_set
   12340                 :            :                                         (error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
   12341                 :            :                                          NULL, "counters pool not initialized");
   12342                 :            :                 }
   12343                 :            :                 break;
   12344                 :          0 :         case RTE_FLOW_ACTION_TYPE_CONNTRACK:
   12345         [ #  # ]:          0 :                 if (priv->hws_ctpool == NULL) {
   12346         [ #  # ]:          0 :                         if (flow_hw_allocate_actions(dev, MLX5_FLOW_ACTION_CT,
   12347                 :            :                                                      error))
   12348                 :          0 :                                 return rte_flow_error_set
   12349                 :            :                                         (error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
   12350                 :            :                                          NULL, "CT pool not initialized");
   12351                 :            :                 }
   12352                 :          0 :                 return mlx5_validate_action_ct(dev, action->conf, error);
   12353                 :          0 :         case RTE_FLOW_ACTION_TYPE_METER_MARK:
   12354                 :          0 :                 return flow_hw_validate_action_meter_mark(dev, action, true, error);
   12355                 :          0 :         case RTE_FLOW_ACTION_TYPE_RSS:
   12356                 :          0 :                 return flow_dv_action_validate(dev, conf, action, error);
   12357                 :            :         case RTE_FLOW_ACTION_TYPE_QUOTA:
   12358                 :            :                 return 0;
   12359                 :          0 :         default:
   12360                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
   12361                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   12362                 :            :                                           "action type not supported");
   12363                 :            :         }
   12364                 :            :         return 0;
   12365                 :            : }
   12366                 :            : 
   12367                 :            : static __rte_always_inline bool
   12368                 :            : flow_hw_action_push(const struct rte_flow_op_attr *attr)
   12369                 :            : {
   12370   [ #  #  #  #  :          0 :         return attr ? !attr->postpone : true;
          #  #  #  #  #  
             #  #  #  #  
                      # ]
   12371                 :            : }
   12372                 :            : 
   12373                 :            : static __rte_always_inline struct mlx5_hw_q_job *
   12374                 :            : flow_hw_action_job_init(struct mlx5_priv *priv, uint32_t queue,
   12375                 :            :                         const struct rte_flow_action_handle *handle,
   12376                 :            :                         void *user_data, void *query_data,
   12377                 :            :                         enum mlx5_hw_job_type type,
   12378                 :            :                         enum mlx5_hw_indirect_type indirect_type,
   12379                 :            :                         struct rte_flow_error *error)
   12380                 :            : {
   12381                 :            :         struct mlx5_hw_q_job *job;
   12382                 :            : 
   12383   [ #  #  #  #  :          0 :         if (queue == MLX5_HW_INV_QUEUE)
          #  #  #  #  #  
             #  #  #  #  
                      # ]
   12384   [ #  #  #  #  :          0 :                 queue = CTRL_QUEUE_ID(priv);
          #  #  #  #  #  
                #  #  # ]
   12385                 :            :         job = flow_hw_job_get(priv, queue);
   12386   [ #  #  #  #  :          0 :         if (!job) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
   12387                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   12388                 :            :                                    RTE_FLOW_ERROR_TYPE_ACTION_NUM, NULL,
   12389                 :            :                                    "Action destroy failed due to queue full.");
   12390                 :          0 :                 return NULL;
   12391                 :            :         }
   12392                 :          0 :         job->type = type;
   12393                 :          0 :         job->action = handle;
   12394                 :          0 :         job->user_data = user_data;
   12395                 :          0 :         job->query.user = query_data;
   12396   [ #  #  #  #  :          0 :         job->indirect_type = indirect_type;
          #  #  #  #  #  
                #  #  # ]
   12397                 :          0 :         return job;
   12398                 :            : }
   12399                 :            : 
   12400                 :            : struct mlx5_hw_q_job *
   12401         [ #  # ]:          0 : mlx5_flow_action_job_init(struct mlx5_priv *priv, uint32_t queue,
   12402                 :            :                           const struct rte_flow_action_handle *handle,
   12403                 :            :                           void *user_data, void *query_data,
   12404                 :            :                           enum mlx5_hw_job_type type,
   12405                 :            :                           struct rte_flow_error *error)
   12406                 :            : {
   12407                 :          0 :         return flow_hw_action_job_init(priv, queue, handle, user_data, query_data,
   12408                 :            :                                        type, MLX5_HW_INDIRECT_TYPE_LEGACY, error);
   12409                 :            : }
   12410                 :            : 
   12411                 :            : static __rte_always_inline void
   12412                 :            : flow_hw_action_finalize(struct rte_eth_dev *dev, uint32_t queue,
   12413                 :            :                         struct mlx5_hw_q_job *job,
   12414                 :            :                         bool push, bool aso, bool status)
   12415                 :            : {
   12416                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12417                 :            : 
   12418         [ #  # ]:          0 :         if (queue == MLX5_HW_INV_QUEUE)
   12419                 :          0 :                 queue = CTRL_QUEUE_ID(priv);
   12420   [ #  #  #  #  :          0 :         if (likely(status)) {
          #  #  #  #  #  
                #  #  # ]
   12421                 :            :                 /* 1. add new job to a queue */
   12422   [ #  #  #  #  :          0 :                 if (!aso)
          #  #  #  #  #  
                      # ]
   12423   [ #  #  #  #  :          0 :                         rte_ring_enqueue(push ?
          #  #  #  #  #  
             #  #  #  #  
                      # ]
   12424                 :          0 :                                          priv->hw_q[queue].indir_cq :
   12425                 :          0 :                                          priv->hw_q[queue].indir_iq,
   12426                 :            :                                          job);
   12427                 :            :                 /* 2. send pending jobs */
   12428   [ #  #  #  #  :          0 :                 if (push)
          #  #  #  #  #  
             #  #  #  #  
                      # ]
   12429                 :          0 :                         __flow_hw_push_action(dev, queue);
   12430                 :            :         } else {
   12431                 :            :                 flow_hw_job_put(priv, job, queue);
   12432                 :            :         }
   12433                 :            : }
   12434                 :            : 
   12435                 :            : /**
   12436                 :            :  * Create shared action.
   12437                 :            :  *
   12438                 :            :  * @param[in] dev
   12439                 :            :  *   Pointer to the rte_eth_dev structure.
   12440                 :            :  * @param[in] queue
   12441                 :            :  *   Which queue to be used.
   12442                 :            :  * @param[in] attr
   12443                 :            :  *   Operation attribute.
   12444                 :            :  * @param[in] conf
   12445                 :            :  *   Indirect action configuration.
   12446                 :            :  * @param[in] action
   12447                 :            :  *   rte_flow action detail.
   12448                 :            :  * @param[in] user_data
   12449                 :            :  *   Pointer to the user_data.
   12450                 :            :  * @param[out] error
   12451                 :            :  *   Pointer to error structure.
   12452                 :            :  *
   12453                 :            :  * @return
   12454                 :            :  *   Action handle on success, NULL otherwise and rte_errno is set.
   12455                 :            :  */
   12456                 :            : static struct rte_flow_action_handle *
   12457                 :          0 : flow_hw_action_handle_create(struct rte_eth_dev *dev, uint32_t queue,
   12458                 :            :                              const struct rte_flow_op_attr *attr,
   12459                 :            :                              const struct rte_flow_indir_action_conf *conf,
   12460                 :            :                              const struct rte_flow_action *action,
   12461                 :            :                              void *user_data,
   12462                 :            :                              struct rte_flow_error *error)
   12463                 :            : {
   12464                 :            :         struct rte_flow_action_handle *handle = NULL;
   12465                 :            :         struct mlx5_hw_q_job *job = NULL;
   12466         [ #  # ]:          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12467                 :            :         const struct rte_flow_action_age *age;
   12468                 :            :         struct mlx5_aso_mtr *aso_mtr;
   12469                 :            :         cnt_id_t cnt_id;
   12470                 :            :         uint32_t age_idx;
   12471                 :            :         bool push = flow_hw_action_push(attr);
   12472                 :            :         bool aso = false;
   12473                 :          0 :         bool force_job = action->type == RTE_FLOW_ACTION_TYPE_METER_MARK;
   12474                 :            : 
   12475         [ #  # ]:          0 :         if (!mlx5_hw_ctx_validate(dev, error))
   12476                 :            :                 return NULL;
   12477         [ #  # ]:          0 :         if (attr || force_job) {
   12478                 :            :                 job = flow_hw_action_job_init(priv, queue, NULL, user_data,
   12479                 :            :                                               NULL, MLX5_HW_Q_JOB_TYPE_CREATE,
   12480                 :            :                                               MLX5_HW_INDIRECT_TYPE_LEGACY, error);
   12481                 :            :                 if (!job)
   12482                 :          0 :                         return NULL;
   12483                 :            :         }
   12484   [ #  #  #  #  :          0 :         switch (action->type) {
                #  #  # ]
   12485                 :          0 :         case RTE_FLOW_ACTION_TYPE_AGE:
   12486         [ #  # ]:          0 :                 if (priv->hws_strict_queue) {
   12487                 :          0 :                         struct mlx5_age_info *info = GET_PORT_AGE_INFO(priv);
   12488                 :            : 
   12489         [ #  # ]:          0 :                         if (queue >= info->hw_q_age->nb_rings) {
   12490                 :          0 :                                 rte_flow_error_set(error, EINVAL,
   12491                 :            :                                                    RTE_FLOW_ERROR_TYPE_ACTION,
   12492                 :            :                                                    NULL,
   12493                 :            :                                                    "Invalid queue ID for indirect AGE.");
   12494                 :          0 :                                 rte_errno = EINVAL;
   12495                 :          0 :                                 return NULL;
   12496                 :            :                         }
   12497                 :            :                 }
   12498                 :          0 :                 age = action->conf;
   12499                 :          0 :                 age_idx = mlx5_hws_age_action_create(priv, queue, true, age,
   12500                 :            :                                                      0, error);
   12501         [ #  # ]:          0 :                 if (age_idx == 0) {
   12502                 :          0 :                         rte_flow_error_set(error, ENODEV,
   12503                 :            :                                            RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   12504                 :            :                                            "AGE are not configured!");
   12505                 :            :                 } else {
   12506                 :          0 :                         age_idx = (MLX5_INDIRECT_ACTION_TYPE_AGE <<
   12507                 :            :                                    MLX5_INDIRECT_ACTION_TYPE_OFFSET) | age_idx;
   12508                 :          0 :                         handle =
   12509                 :          0 :                             (struct rte_flow_action_handle *)(uintptr_t)age_idx;
   12510                 :            :                 }
   12511                 :            :                 break;
   12512                 :          0 :         case RTE_FLOW_ACTION_TYPE_COUNT:
   12513         [ #  # ]:          0 :                 if (mlx5_hws_cnt_shared_get(priv->hws_cpool, &cnt_id, 0))
   12514                 :          0 :                         rte_flow_error_set(error, ENODEV,
   12515                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION,
   12516                 :            :                                         NULL,
   12517                 :            :                                         "counter are not configured!");
   12518                 :            :                 else
   12519                 :          0 :                         handle = (struct rte_flow_action_handle *)
   12520                 :          0 :                                  (uintptr_t)cnt_id;
   12521                 :            :                 break;
   12522                 :          0 :         case RTE_FLOW_ACTION_TYPE_CONNTRACK:
   12523                 :            :                 aso = true;
   12524                 :          0 :                 handle = flow_hw_conntrack_create(dev, queue, action->conf, job,
   12525                 :            :                                                   push, error);
   12526                 :          0 :                 break;
   12527         [ #  # ]:          0 :         case RTE_FLOW_ACTION_TYPE_METER_MARK:
   12528                 :            :                 aso = true;
   12529                 :            :                 aso_mtr = flow_hw_meter_mark_alloc(dev, queue, action, job, push, error);
   12530                 :            :                 if (!aso_mtr)
   12531                 :            :                         break;
   12532                 :          0 :                 handle = (void *)(uintptr_t)job->action;
   12533                 :          0 :                 break;
   12534                 :          0 :         case RTE_FLOW_ACTION_TYPE_RSS:
   12535                 :          0 :                 handle = flow_dv_action_create(dev, conf, action, error);
   12536                 :          0 :                 break;
   12537                 :          0 :         case RTE_FLOW_ACTION_TYPE_QUOTA:
   12538                 :            :                 aso = true;
   12539                 :          0 :                 handle = mlx5_quota_alloc(dev, queue, action->conf,
   12540                 :            :                                           job, push, error);
   12541                 :          0 :                 break;
   12542                 :          0 :         default:
   12543                 :          0 :                 rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION,
   12544                 :            :                                    NULL, "action type not supported");
   12545                 :          0 :                 break;
   12546                 :            :         }
   12547         [ #  # ]:          0 :         if (job && !force_job) {
   12548                 :          0 :                 job->action = handle;
   12549         [ #  # ]:          0 :                 flow_hw_action_finalize(dev, queue, job, push, aso,
   12550                 :            :                                         handle != NULL);
   12551                 :            :         }
   12552                 :            :         return handle;
   12553                 :            : }
   12554                 :            : 
   12555                 :            : static int
   12556                 :          0 : mlx5_flow_update_meter_mark(struct rte_eth_dev *dev, uint32_t queue,
   12557                 :            :                             const struct rte_flow_update_meter_mark *upd_meter_mark,
   12558                 :            :                             uint32_t idx, bool push,
   12559                 :            :                             struct mlx5_hw_q_job *job, struct rte_flow_error *error)
   12560                 :            : {
   12561                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12562                 :          0 :         struct mlx5_aso_mtr_pool *pool = priv->hws_mpool;
   12563                 :            :         const struct rte_flow_action_meter_mark *meter_mark = &upd_meter_mark->meter_mark;
   12564                 :          0 :         struct mlx5_aso_mtr *aso_mtr = mlx5_ipool_get(pool->idx_pool, idx);
   12565                 :            :         struct mlx5_flow_meter_info *fm;
   12566                 :            : 
   12567         [ #  # ]:          0 :         if (!aso_mtr)
   12568                 :          0 :                 return rte_flow_error_set(error, EINVAL,
   12569                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12570                 :            :                                           NULL, "Invalid meter_mark update index");
   12571                 :            :         fm = &aso_mtr->fm;
   12572         [ #  # ]:          0 :         if (upd_meter_mark->profile_valid)
   12573                 :          0 :                 fm->profile = (struct mlx5_flow_meter_profile *)
   12574                 :          0 :                         (meter_mark->profile);
   12575         [ #  # ]:          0 :         if (upd_meter_mark->color_mode_valid)
   12576                 :          0 :                 fm->color_aware = meter_mark->color_mode;
   12577         [ #  # ]:          0 :         if (upd_meter_mark->state_valid)
   12578                 :          0 :                 fm->is_enable = meter_mark->state;
   12579         [ #  # ]:          0 :         aso_mtr->state = (queue == MLX5_HW_INV_QUEUE) ?
   12580                 :            :                          ASO_METER_WAIT : ASO_METER_WAIT_ASYNC;
   12581                 :            :         /* Update ASO flow meter by wqe. */
   12582         [ #  # ]:          0 :         if (mlx5_aso_meter_update_by_wqe(priv, queue,
   12583                 :            :                                          aso_mtr, &priv->mtr_bulk, job, push))
   12584                 :          0 :                 return rte_flow_error_set(error, EINVAL,
   12585                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12586                 :            :                                           NULL, "Unable to update ASO meter WQE");
   12587                 :            :         /* Wait for ASO object completion. */
   12588   [ #  #  #  # ]:          0 :         if (queue == MLX5_HW_INV_QUEUE &&
   12589                 :          0 :             mlx5_aso_mtr_wait(priv, aso_mtr, true))
   12590                 :          0 :                 return rte_flow_error_set(error, EINVAL,
   12591                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12592                 :            :                                           NULL, "Unable to wait for ASO meter CQE");
   12593                 :            :         return 0;
   12594                 :            : }
   12595                 :            : 
   12596                 :            : /**
   12597                 :            :  * Update shared action.
   12598                 :            :  *
   12599                 :            :  * @param[in] dev
   12600                 :            :  *   Pointer to the rte_eth_dev structure.
   12601                 :            :  * @param[in] queue
   12602                 :            :  *   Which queue to be used.
   12603                 :            :  * @param[in] attr
   12604                 :            :  *   Operation attribute.
   12605                 :            :  * @param[in] handle
   12606                 :            :  *   Action handle to be updated.
   12607                 :            :  * @param[in] update
   12608                 :            :  *   Update value.
   12609                 :            :  * @param[in] user_data
   12610                 :            :  *   Pointer to the user_data.
   12611                 :            :  * @param[out] error
   12612                 :            :  *   Pointer to error structure.
   12613                 :            :  *
   12614                 :            :  * @return
   12615                 :            :  *   0 on success, negative value otherwise and rte_errno is set.
   12616                 :            :  */
   12617                 :            : static int
   12618                 :          0 : flow_hw_action_handle_update(struct rte_eth_dev *dev, uint32_t queue,
   12619                 :            :                              const struct rte_flow_op_attr *attr,
   12620                 :            :                              struct rte_flow_action_handle *handle,
   12621                 :            :                              const void *update,
   12622                 :            :                              void *user_data,
   12623                 :            :                              struct rte_flow_error *error)
   12624                 :            : {
   12625                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12626                 :            :         const struct rte_flow_modify_conntrack *ct_conf =
   12627                 :            :                 (const struct rte_flow_modify_conntrack *)update;
   12628                 :            :         struct mlx5_hw_q_job *job = NULL;
   12629                 :          0 :         uint32_t act_idx = (uint32_t)(uintptr_t)handle;
   12630                 :          0 :         uint32_t type = act_idx >> MLX5_INDIRECT_ACTION_TYPE_OFFSET;
   12631         [ #  # ]:          0 :         uint32_t idx = act_idx & ((1u << MLX5_INDIRECT_ACTION_TYPE_OFFSET) - 1);
   12632                 :            :         int ret = 0;
   12633                 :            :         bool push = flow_hw_action_push(attr);
   12634                 :            :         bool aso = false;
   12635                 :          0 :         bool force_job = type == MLX5_INDIRECT_ACTION_TYPE_METER_MARK;
   12636                 :            : 
   12637         [ #  # ]:          0 :         if (attr || force_job) {
   12638                 :            :                 job = flow_hw_action_job_init(priv, queue, handle, user_data,
   12639                 :            :                                               NULL, MLX5_HW_Q_JOB_TYPE_UPDATE,
   12640                 :            :                                               MLX5_HW_INDIRECT_TYPE_LEGACY, error);
   12641                 :            :                 if (!job)
   12642                 :          0 :                         return -rte_errno;
   12643                 :            :         }
   12644   [ #  #  #  #  :          0 :         switch (type) {
                   #  # ]
   12645                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_AGE:
   12646                 :          0 :                 ret = mlx5_hws_age_action_update(priv, idx, update, error);
   12647                 :          0 :                 break;
   12648                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_CT:
   12649         [ #  # ]:          0 :                 if (ct_conf->state)
   12650                 :            :                         aso = true;
   12651                 :          0 :                 ret = flow_hw_conntrack_update(dev, queue, update, idx,
   12652                 :            :                                                job, push, error);
   12653                 :          0 :                 break;
   12654                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_METER_MARK:
   12655                 :            :                 aso = true;
   12656                 :          0 :                 ret = mlx5_flow_update_meter_mark(dev, queue, update, idx, push,
   12657                 :            :                                                   job, error);
   12658                 :          0 :                 break;
   12659                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_RSS:
   12660                 :          0 :                 ret = flow_dv_action_update(dev, handle, update, error);
   12661                 :          0 :                 break;
   12662                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_QUOTA:
   12663                 :            :                 aso = true;
   12664                 :          0 :                 ret = mlx5_quota_query_update(dev, queue, handle, update, NULL,
   12665                 :            :                                               job, push, error);
   12666                 :          0 :                 break;
   12667                 :          0 :         default:
   12668                 :            :                 ret = -ENOTSUP;
   12669                 :          0 :                 rte_flow_error_set(error, ENOTSUP,
   12670                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   12671                 :            :                                           "action type not supported");
   12672                 :          0 :                 break;
   12673                 :            :         }
   12674         [ #  # ]:          0 :         if (job && !force_job)
   12675         [ #  # ]:          0 :                 flow_hw_action_finalize(dev, queue, job, push, aso, ret == 0);
   12676                 :            :         return ret;
   12677                 :            : }
   12678                 :            : 
   12679                 :            : /**
   12680                 :            :  * Destroy shared action.
   12681                 :            :  *
   12682                 :            :  * @param[in] dev
   12683                 :            :  *   Pointer to the rte_eth_dev structure.
   12684                 :            :  * @param[in] queue
   12685                 :            :  *   Which queue to be used.
   12686                 :            :  * @param[in] attr
   12687                 :            :  *   Operation attribute.
   12688                 :            :  * @param[in] handle
   12689                 :            :  *   Action handle to be destroyed.
   12690                 :            :  * @param[in] user_data
   12691                 :            :  *   Pointer to the user_data.
   12692                 :            :  * @param[out] error
   12693                 :            :  *   Pointer to error structure.
   12694                 :            :  *
   12695                 :            :  * @return
   12696                 :            :  *   0 on success, negative value otherwise and rte_errno is set.
   12697                 :            :  */
   12698                 :            : static int
   12699                 :          0 : flow_hw_action_handle_destroy(struct rte_eth_dev *dev, uint32_t queue,
   12700                 :            :                               const struct rte_flow_op_attr *attr,
   12701                 :            :                               struct rte_flow_action_handle *handle,
   12702                 :            :                               void *user_data,
   12703                 :            :                               struct rte_flow_error *error)
   12704                 :            : {
   12705                 :          0 :         uint32_t act_idx = (uint32_t)(uintptr_t)handle;
   12706                 :          0 :         uint32_t type = act_idx >> MLX5_INDIRECT_ACTION_TYPE_OFFSET;
   12707                 :          0 :         uint32_t age_idx = act_idx & MLX5_HWS_AGE_IDX_MASK;
   12708                 :            :         uint32_t idx = act_idx & ((1u << MLX5_INDIRECT_ACTION_TYPE_OFFSET) - 1);
   12709                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12710         [ #  # ]:          0 :         struct mlx5_aso_mtr_pool *pool = priv->hws_mpool;
   12711                 :            :         struct mlx5_hw_q_job *job = NULL;
   12712                 :            :         struct mlx5_aso_mtr *aso_mtr;
   12713                 :            :         struct mlx5_flow_meter_info *fm;
   12714                 :            :         bool push = flow_hw_action_push(attr);
   12715                 :            :         bool aso = false;
   12716                 :            :         int ret = 0;
   12717                 :          0 :         bool force_job = type == MLX5_INDIRECT_ACTION_TYPE_METER_MARK;
   12718                 :            : 
   12719         [ #  # ]:          0 :         if (attr || force_job) {
   12720                 :            :                 job = flow_hw_action_job_init(priv, queue, handle, user_data,
   12721                 :            :                                               NULL, MLX5_HW_Q_JOB_TYPE_DESTROY,
   12722                 :            :                                               MLX5_HW_INDIRECT_TYPE_LEGACY, error);
   12723                 :            :                 if (!job)
   12724                 :          0 :                         return -rte_errno;
   12725                 :            :         }
   12726   [ #  #  #  #  :          0 :         switch (type) {
                #  #  # ]
   12727                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_AGE:
   12728                 :          0 :                 ret = mlx5_hws_age_action_destroy(priv, age_idx, error);
   12729                 :          0 :                 break;
   12730                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_COUNT:
   12731         [ #  # ]:          0 :                 age_idx = mlx5_hws_cnt_age_get(priv->hws_cpool, act_idx);
   12732         [ #  # ]:          0 :                 if (age_idx != 0)
   12733                 :            :                         /*
   12734                 :            :                          * If this counter belongs to indirect AGE, here is the
   12735                 :            :                          * time to update the AGE.
   12736                 :            :                          */
   12737                 :            :                         mlx5_hws_age_nb_cnt_decrease(priv, age_idx);
   12738         [ #  # ]:          0 :                 mlx5_hws_cnt_shared_put(priv->hws_cpool, &act_idx);
   12739                 :            :                 break;
   12740                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_CT:
   12741                 :          0 :                 ret = flow_hw_conntrack_destroy(dev, idx, error);
   12742                 :          0 :                 break;
   12743                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_METER_MARK:
   12744                 :          0 :                 aso_mtr = mlx5_ipool_get(pool->idx_pool, idx);
   12745         [ #  # ]:          0 :                 if (!aso_mtr) {
   12746                 :            :                         ret = -EINVAL;
   12747                 :          0 :                         rte_flow_error_set(error, EINVAL,
   12748                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12749                 :            :                                 NULL, "Invalid meter_mark destroy index");
   12750                 :          0 :                         break;
   12751                 :            :                 }
   12752                 :            :                 fm = &aso_mtr->fm;
   12753                 :          0 :                 fm->is_enable = 0;
   12754                 :            :                 /* Update ASO flow meter by wqe. */
   12755         [ #  # ]:          0 :                 if (mlx5_aso_meter_update_by_wqe(priv, queue, aso_mtr,
   12756                 :            :                                                  &priv->mtr_bulk, job, push)) {
   12757                 :            :                         ret = -EINVAL;
   12758                 :          0 :                         rte_flow_error_set(error, EINVAL,
   12759                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12760                 :            :                                 NULL, "Unable to update ASO meter WQE");
   12761                 :          0 :                         break;
   12762                 :            :                 }
   12763                 :            :                 /* Wait for ASO object completion. */
   12764   [ #  #  #  # ]:          0 :                 if (queue == MLX5_HW_INV_QUEUE &&
   12765                 :          0 :                     mlx5_aso_mtr_wait(priv, aso_mtr, true)) {
   12766                 :            :                         ret = -EINVAL;
   12767                 :          0 :                         rte_flow_error_set(error, EINVAL,
   12768                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12769                 :            :                                 NULL, "Unable to wait for ASO meter CQE");
   12770                 :          0 :                         break;
   12771                 :            :                 }
   12772                 :            :                 aso = true;
   12773                 :            :                 break;
   12774                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_RSS:
   12775                 :          0 :                 ret = flow_dv_action_destroy(dev, handle, error);
   12776                 :          0 :                 break;
   12777                 :            :         case MLX5_INDIRECT_ACTION_TYPE_QUOTA:
   12778                 :            :                 break;
   12779                 :          0 :         default:
   12780                 :            :                 ret = -ENOTSUP;
   12781                 :          0 :                 rte_flow_error_set(error, ENOTSUP,
   12782                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   12783                 :            :                                           "action type not supported");
   12784                 :          0 :                 break;
   12785                 :            :         }
   12786         [ #  # ]:          0 :         if (job && !force_job)
   12787         [ #  # ]:          0 :                 flow_hw_action_finalize(dev, queue, job, push, aso, ret == 0);
   12788                 :            :         return ret;
   12789                 :            : }
   12790                 :            : 
   12791                 :            : static int
   12792                 :          0 : flow_hw_query_counter(const struct rte_eth_dev *dev, uint32_t counter,
   12793                 :            :                       void *data, struct rte_flow_error *error)
   12794                 :            : {
   12795                 :            :         struct mlx5_hws_cnt_pool *hpool;
   12796         [ #  # ]:          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12797                 :            :         struct mlx5_hws_cnt *cnt;
   12798                 :            :         struct rte_flow_query_count *qc = data;
   12799                 :            :         uint32_t iidx;
   12800                 :            :         uint64_t pkts, bytes;
   12801                 :            : 
   12802         [ #  # ]:          0 :         if (!mlx5_hws_cnt_id_valid(counter))
   12803                 :          0 :                 return rte_flow_error_set(error, EINVAL,
   12804                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   12805                 :            :                                 "counter are not available");
   12806         [ #  # ]:          0 :         hpool = mlx5_hws_cnt_host_pool(priv->hws_cpool);
   12807                 :            :         iidx = mlx5_hws_cnt_iidx(hpool, counter);
   12808                 :          0 :         cnt = &hpool->pool[iidx];
   12809                 :            :         __hws_cnt_query_raw(priv->hws_cpool, counter, &pkts, &bytes);
   12810                 :          0 :         qc->hits_set = 1;
   12811                 :          0 :         qc->bytes_set = 1;
   12812                 :          0 :         qc->hits = pkts - cnt->reset.hits;
   12813                 :          0 :         qc->bytes = bytes - cnt->reset.bytes;
   12814         [ #  # ]:          0 :         if (qc->reset) {
   12815                 :          0 :                 cnt->reset.bytes = bytes;
   12816                 :          0 :                 cnt->reset.hits = pkts;
   12817                 :            :         }
   12818                 :            :         return 0;
   12819                 :            : }
   12820                 :            : 
   12821                 :            : /**
   12822                 :            :  * Query a flow rule AGE action for aging information.
   12823                 :            :  *
   12824                 :            :  * @param[in] dev
   12825                 :            :  *   Pointer to Ethernet device.
   12826                 :            :  * @param[in] age_idx
   12827                 :            :  *   Index of AGE action parameter.
   12828                 :            :  * @param[out] data
   12829                 :            :  *   Data retrieved by the query.
   12830                 :            :  * @param[out] error
   12831                 :            :  *   Perform verbose error reporting if not NULL.
   12832                 :            :  *
   12833                 :            :  * @return
   12834                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   12835                 :            :  */
   12836                 :            : static int
   12837                 :          0 : flow_hw_query_age(const struct rte_eth_dev *dev, uint32_t age_idx, void *data,
   12838                 :            :                   struct rte_flow_error *error)
   12839                 :            : {
   12840                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12841                 :          0 :         struct mlx5_age_info *age_info = GET_PORT_AGE_INFO(priv);
   12842                 :          0 :         struct mlx5_indexed_pool *ipool = age_info->ages_ipool;
   12843                 :          0 :         struct mlx5_hws_age_param *param = mlx5_ipool_get(ipool, age_idx);
   12844                 :            :         struct rte_flow_query_age *resp = data;
   12845                 :            : 
   12846   [ #  #  #  # ]:          0 :         if (!param || !param->timeout)
   12847                 :          0 :                 return rte_flow_error_set(error, EINVAL,
   12848                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12849                 :            :                                           NULL, "age data not available");
   12850      [ #  #  # ]:          0 :         switch (rte_atomic_load_explicit(&param->state, rte_memory_order_relaxed)) {
   12851                 :          0 :         case HWS_AGE_AGED_OUT_REPORTED:
   12852                 :            :         case HWS_AGE_AGED_OUT_NOT_REPORTED:
   12853                 :          0 :                 resp->aged = 1;
   12854                 :          0 :                 break;
   12855                 :          0 :         case HWS_AGE_CANDIDATE:
   12856                 :            :         case HWS_AGE_CANDIDATE_INSIDE_RING:
   12857                 :          0 :                 resp->aged = 0;
   12858                 :          0 :                 break;
   12859                 :            :         case HWS_AGE_FREE:
   12860                 :            :                 /*
   12861                 :            :                  * When state is FREE the flow itself should be invalid.
   12862                 :            :                  * Fall-through.
   12863                 :            :                  */
   12864                 :            :         default:
   12865                 :            :                 MLX5_ASSERT(0);
   12866                 :            :                 break;
   12867                 :            :         }
   12868                 :          0 :         resp->sec_since_last_hit_valid = !resp->aged;
   12869         [ #  # ]:          0 :         if (resp->sec_since_last_hit_valid)
   12870                 :          0 :                 resp->sec_since_last_hit = rte_atomic_load_explicit
   12871                 :            :                                  (&param->sec_since_last_hit, rte_memory_order_relaxed);
   12872                 :            :         return 0;
   12873                 :            : }
   12874                 :            : 
   12875                 :            : static int
   12876                 :          0 : flow_hw_query(struct rte_eth_dev *dev, struct rte_flow *flow,
   12877                 :            :               const struct rte_flow_action *actions, void *data,
   12878                 :            :               struct rte_flow_error *error)
   12879                 :            : {
   12880                 :            :         int ret = -EINVAL;
   12881                 :            :         struct rte_flow_hw *hw_flow = (struct rte_flow_hw *)flow;
   12882                 :            :         struct rte_flow_hw_aux *aux;
   12883                 :            : 
   12884         [ #  # ]:          0 :         for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
   12885   [ #  #  #  # ]:          0 :                 switch (actions->type) {
   12886                 :            :                 case RTE_FLOW_ACTION_TYPE_VOID:
   12887                 :            :                         break;
   12888                 :          0 :                 case RTE_FLOW_ACTION_TYPE_COUNT:
   12889         [ #  # ]:          0 :                         if (!(hw_flow->flags & MLX5_FLOW_HW_FLOW_FLAG_CNT_ID))
   12890                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
   12891                 :            :                                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   12892                 :            :                                                           "counter not defined in the rule");
   12893                 :          0 :                         ret = flow_hw_query_counter(dev, hw_flow->cnt_id, data,
   12894                 :            :                                                     error);
   12895                 :          0 :                         break;
   12896                 :          0 :                 case RTE_FLOW_ACTION_TYPE_AGE:
   12897         [ #  # ]:          0 :                         if (!(hw_flow->flags & MLX5_FLOW_HW_FLOW_FLAG_AGE_IDX))
   12898                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
   12899                 :            :                                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   12900                 :            :                                                           "age data not available");
   12901                 :          0 :                         aux = mlx5_flow_hw_aux(dev->data->port_id, hw_flow);
   12902                 :          0 :                         ret = flow_hw_query_age(dev, mlx5_flow_hw_aux_get_age_idx(hw_flow, aux),
   12903                 :            :                                                 data, error);
   12904                 :          0 :                         break;
   12905                 :          0 :                 default:
   12906                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
   12907                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
   12908                 :            :                                                   actions,
   12909                 :            :                                                   "action not supported");
   12910                 :            :                 }
   12911                 :            :         }
   12912                 :            :         return ret;
   12913                 :            : }
   12914                 :            : 
   12915                 :            : /**
   12916                 :            :  * Validate indirect action.
   12917                 :            :  *
   12918                 :            :  * @param[in] dev
   12919                 :            :  *   Pointer to the Ethernet device structure.
   12920                 :            :  * @param[in] conf
   12921                 :            :  *   Shared action configuration.
   12922                 :            :  * @param[in] action
   12923                 :            :  *   Action specification used to create indirect action.
   12924                 :            :  * @param[out] error
   12925                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   12926                 :            :  *   error only.
   12927                 :            :  *
   12928                 :            :  * @return
   12929                 :            :  *   0 on success, otherwise negative errno value.
   12930                 :            :  */
   12931                 :            : static int
   12932                 :          0 : flow_hw_action_validate(struct rte_eth_dev *dev,
   12933                 :            :                         const struct rte_flow_indir_action_conf *conf,
   12934                 :            :                         const struct rte_flow_action *action,
   12935                 :            :                         struct rte_flow_error *err)
   12936                 :            : {
   12937                 :          0 :         struct rte_flow_error shadow_error = {0, };
   12938                 :            : 
   12939         [ #  # ]:          0 :         if (!err)
   12940                 :            :                 err = &shadow_error;
   12941                 :          0 :         return flow_hw_action_handle_validate(dev, MLX5_HW_INV_QUEUE, NULL,
   12942                 :            :                                               conf, action, NULL, err);
   12943                 :            : }
   12944                 :            : 
   12945                 :            : /**
   12946                 :            :  * Create indirect action.
   12947                 :            :  *
   12948                 :            :  * @param[in] dev
   12949                 :            :  *   Pointer to the Ethernet device structure.
   12950                 :            :  * @param[in] conf
   12951                 :            :  *   Shared action configuration.
   12952                 :            :  * @param[in] action
   12953                 :            :  *   Action specification used to create indirect action.
   12954                 :            :  * @param[out] error
   12955                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   12956                 :            :  *   error only.
   12957                 :            :  *
   12958                 :            :  * @return
   12959                 :            :  *   A valid shared action handle in case of success, NULL otherwise and
   12960                 :            :  *   rte_errno is set.
   12961                 :            :  */
   12962                 :            : static struct rte_flow_action_handle *
   12963                 :          0 : flow_hw_action_create(struct rte_eth_dev *dev,
   12964                 :            :                        const struct rte_flow_indir_action_conf *conf,
   12965                 :            :                        const struct rte_flow_action *action,
   12966                 :            :                        struct rte_flow_error *err)
   12967                 :            : {
   12968                 :          0 :         return flow_hw_action_handle_create(dev, MLX5_HW_INV_QUEUE,
   12969                 :            :                                             NULL, conf, action, NULL, err);
   12970                 :            : }
   12971                 :            : 
   12972                 :            : /**
   12973                 :            :  * Destroy the indirect action.
   12974                 :            :  * Release action related resources on the NIC and the memory.
   12975                 :            :  * Lock free, (mutex should be acquired by caller).
   12976                 :            :  * Dispatcher for action type specific call.
   12977                 :            :  *
   12978                 :            :  * @param[in] dev
   12979                 :            :  *   Pointer to the Ethernet device structure.
   12980                 :            :  * @param[in] handle
   12981                 :            :  *   The indirect action object handle to be removed.
   12982                 :            :  * @param[out] error
   12983                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   12984                 :            :  *   error only.
   12985                 :            :  *
   12986                 :            :  * @return
   12987                 :            :  *   0 on success, otherwise negative errno value.
   12988                 :            :  */
   12989                 :            : static int
   12990                 :          0 : flow_hw_action_destroy(struct rte_eth_dev *dev,
   12991                 :            :                        struct rte_flow_action_handle *handle,
   12992                 :            :                        struct rte_flow_error *error)
   12993                 :            : {
   12994                 :          0 :         return flow_hw_action_handle_destroy(dev, MLX5_HW_INV_QUEUE,
   12995                 :            :                         NULL, handle, NULL, error);
   12996                 :            : }
   12997                 :            : 
   12998                 :            : /**
   12999                 :            :  * Updates in place shared action configuration.
   13000                 :            :  *
   13001                 :            :  * @param[in] dev
   13002                 :            :  *   Pointer to the Ethernet device structure.
   13003                 :            :  * @param[in] handle
   13004                 :            :  *   The indirect action object handle to be updated.
   13005                 :            :  * @param[in] update
   13006                 :            :  *   Action specification used to modify the action pointed by *handle*.
   13007                 :            :  *   *update* could be of same type with the action pointed by the *handle*
   13008                 :            :  *   handle argument, or some other structures like a wrapper, depending on
   13009                 :            :  *   the indirect action type.
   13010                 :            :  * @param[out] error
   13011                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   13012                 :            :  *   error only.
   13013                 :            :  *
   13014                 :            :  * @return
   13015                 :            :  *   0 on success, otherwise negative errno value.
   13016                 :            :  */
   13017                 :            : static int
   13018                 :          0 : flow_hw_action_update(struct rte_eth_dev *dev,
   13019                 :            :                       struct rte_flow_action_handle *handle,
   13020                 :            :                       const void *update,
   13021                 :            :                       struct rte_flow_error *err)
   13022                 :            : {
   13023                 :          0 :         return flow_hw_action_handle_update(dev, MLX5_HW_INV_QUEUE,
   13024                 :            :                         NULL, handle, update, NULL, err);
   13025                 :            : }
   13026                 :            : 
   13027                 :            : static int
   13028                 :          0 : flow_hw_action_handle_query(struct rte_eth_dev *dev, uint32_t queue,
   13029                 :            :                             const struct rte_flow_op_attr *attr,
   13030                 :            :                             const struct rte_flow_action_handle *handle,
   13031                 :            :                             void *data, void *user_data,
   13032                 :            :                             struct rte_flow_error *error)
   13033                 :            : {
   13034                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13035                 :            :         struct mlx5_hw_q_job *job = NULL;
   13036                 :          0 :         uint32_t act_idx = (uint32_t)(uintptr_t)handle;
   13037                 :          0 :         uint32_t type = act_idx >> MLX5_INDIRECT_ACTION_TYPE_OFFSET;
   13038         [ #  # ]:          0 :         uint32_t idx = MLX5_INDIRECT_ACTION_IDX_GET(handle);
   13039                 :            :         uint32_t age_idx = act_idx & MLX5_HWS_AGE_IDX_MASK;
   13040                 :            :         int ret;
   13041                 :            :         bool push = flow_hw_action_push(attr);
   13042                 :            :         bool aso = false;
   13043                 :            : 
   13044         [ #  # ]:          0 :         if (attr) {
   13045                 :            :                 job = flow_hw_action_job_init(priv, queue, handle, user_data,
   13046                 :            :                                               data, MLX5_HW_Q_JOB_TYPE_QUERY,
   13047                 :            :                                               MLX5_HW_INDIRECT_TYPE_LEGACY, error);
   13048                 :            :                 if (!job)
   13049                 :          0 :                         return -rte_errno;
   13050                 :            :         }
   13051   [ #  #  #  #  :          0 :         switch (type) {
                      # ]
   13052                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_AGE:
   13053                 :          0 :                 ret = flow_hw_query_age(dev, age_idx, data, error);
   13054                 :          0 :                 break;
   13055                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_COUNT:
   13056                 :          0 :                 ret = flow_hw_query_counter(dev, act_idx, data, error);
   13057                 :          0 :                 break;
   13058                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_CT:
   13059                 :            :                 aso = true;
   13060         [ #  # ]:          0 :                 if (job)
   13061                 :          0 :                         job->query.user = data;
   13062                 :          0 :                 ret = flow_hw_conntrack_query(dev, queue, idx, data,
   13063                 :            :                                               job, push, error);
   13064                 :          0 :                 break;
   13065                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_QUOTA:
   13066                 :            :                 aso = true;
   13067                 :          0 :                 ret = mlx5_quota_query(dev, queue, handle, data,
   13068                 :            :                                        job, push, error);
   13069                 :          0 :                 break;
   13070                 :          0 :         default:
   13071                 :            :                 ret = -ENOTSUP;
   13072                 :          0 :                 rte_flow_error_set(error, ENOTSUP,
   13073                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   13074                 :            :                                           "action type not supported");
   13075                 :          0 :                 break;
   13076                 :            :         }
   13077         [ #  # ]:          0 :         if (job)
   13078         [ #  # ]:          0 :                 flow_hw_action_finalize(dev, queue, job, push, aso, ret == 0);
   13079                 :            :         return ret;
   13080                 :            : }
   13081                 :            : 
   13082                 :            : static int
   13083                 :          0 : flow_hw_async_action_handle_query_update
   13084                 :            :                         (struct rte_eth_dev *dev, uint32_t queue,
   13085                 :            :                          const struct rte_flow_op_attr *attr,
   13086                 :            :                          struct rte_flow_action_handle *handle,
   13087                 :            :                          const void *update, void *query,
   13088                 :            :                          enum rte_flow_query_update_mode qu_mode,
   13089                 :            :                          void *user_data, struct rte_flow_error *error)
   13090                 :            : {
   13091         [ #  # ]:          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13092                 :            :         bool push = flow_hw_action_push(attr);
   13093                 :            :         bool aso = false;
   13094                 :            :         struct mlx5_hw_q_job *job = NULL;
   13095                 :            :         int ret = 0;
   13096                 :            : 
   13097         [ #  # ]:          0 :         if (attr) {
   13098                 :            :                 job = flow_hw_action_job_init(priv, queue, handle, user_data,
   13099                 :            :                                               query,
   13100                 :            :                                               MLX5_HW_Q_JOB_TYPE_UPDATE_QUERY,
   13101                 :            :                                               MLX5_HW_INDIRECT_TYPE_LEGACY, error);
   13102                 :            :                 if (!job)
   13103                 :          0 :                         return -rte_errno;
   13104                 :            :         }
   13105         [ #  # ]:          0 :         switch (MLX5_INDIRECT_ACTION_TYPE_GET(handle)) {
   13106                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_QUOTA:
   13107         [ #  # ]:          0 :                 if (qu_mode != RTE_FLOW_QU_QUERY_FIRST) {
   13108                 :          0 :                         ret = rte_flow_error_set
   13109                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION_CONF,
   13110                 :            :                                  NULL, "quota action must query before update");
   13111                 :          0 :                         break;
   13112                 :            :                 }
   13113                 :            :                 aso = true;
   13114                 :          0 :                 ret = mlx5_quota_query_update(dev, queue, handle,
   13115                 :            :                                               update, query, job, push, error);
   13116                 :          0 :                 break;
   13117                 :          0 :         default:
   13118                 :          0 :                 ret = rte_flow_error_set(error, ENOTSUP,
   13119                 :            :                                          RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL, "update and query not supportred");
   13120                 :            :         }
   13121         [ #  # ]:          0 :         if (job)
   13122         [ #  # ]:          0 :                 flow_hw_action_finalize(dev, queue, job, push, aso, ret == 0);
   13123                 :            :         return ret;
   13124                 :            : }
   13125                 :            : 
   13126                 :            : static int
   13127                 :          0 : flow_hw_action_query(struct rte_eth_dev *dev,
   13128                 :            :                      const struct rte_flow_action_handle *handle, void *data,
   13129                 :            :                      struct rte_flow_error *error)
   13130                 :            : {
   13131                 :          0 :         return flow_hw_action_handle_query(dev, MLX5_HW_INV_QUEUE, NULL,
   13132                 :            :                         handle, data, NULL, error);
   13133                 :            : }
   13134                 :            : 
   13135                 :            : static int
   13136                 :          0 : flow_hw_action_query_update(struct rte_eth_dev *dev,
   13137                 :            :                             struct rte_flow_action_handle *handle,
   13138                 :            :                             const void *update, void *query,
   13139                 :            :                             enum rte_flow_query_update_mode qu_mode,
   13140                 :            :                             struct rte_flow_error *error)
   13141                 :            : {
   13142                 :          0 :         return flow_hw_async_action_handle_query_update(dev, MLX5_HW_INV_QUEUE,
   13143                 :            :                                                         NULL, handle, update,
   13144                 :            :                                                         query, qu_mode, NULL,
   13145                 :            :                                                         error);
   13146                 :            : }
   13147                 :            : 
   13148                 :            : /**
   13149                 :            :  * Get aged-out flows of a given port on the given HWS flow queue.
   13150                 :            :  *
   13151                 :            :  * @param[in] dev
   13152                 :            :  *   Pointer to the Ethernet device structure.
   13153                 :            :  * @param[in] queue_id
   13154                 :            :  *   Flow queue to query. Ignored when RTE_FLOW_PORT_FLAG_STRICT_QUEUE not set.
   13155                 :            :  * @param[in, out] contexts
   13156                 :            :  *   The address of an array of pointers to the aged-out flows contexts.
   13157                 :            :  * @param[in] nb_contexts
   13158                 :            :  *   The length of context array pointers.
   13159                 :            :  * @param[out] error
   13160                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   13161                 :            :  *   error only.
   13162                 :            :  *
   13163                 :            :  * @return
   13164                 :            :  *   if nb_contexts is 0, return the amount of all aged contexts.
   13165                 :            :  *   if nb_contexts is not 0 , return the amount of aged flows reported
   13166                 :            :  *   in the context array, otherwise negative errno value.
   13167                 :            :  */
   13168                 :            : static int
   13169                 :          0 : flow_hw_get_q_aged_flows(struct rte_eth_dev *dev, uint32_t queue_id,
   13170                 :            :                          void **contexts, uint32_t nb_contexts,
   13171                 :            :                          struct rte_flow_error *error)
   13172                 :            : {
   13173                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13174                 :          0 :         struct mlx5_age_info *age_info = GET_PORT_AGE_INFO(priv);
   13175                 :            :         struct rte_ring *r;
   13176                 :            :         int nb_flows = 0;
   13177                 :            : 
   13178         [ #  # ]:          0 :         if (nb_contexts && !contexts)
   13179                 :          0 :                 return rte_flow_error_set(error, EINVAL,
   13180                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   13181                 :            :                                           NULL, "empty context");
   13182         [ #  # ]:          0 :         if (!priv->hws_age_req)
   13183                 :          0 :                 return rte_flow_error_set(error, ENOENT,
   13184                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   13185                 :            :                                           NULL, "No aging initialized");
   13186         [ #  # ]:          0 :         if (priv->hws_strict_queue) {
   13187         [ #  # ]:          0 :                 if (queue_id >= age_info->hw_q_age->nb_rings)
   13188                 :          0 :                         return rte_flow_error_set(error, EINVAL,
   13189                 :            :                                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   13190                 :            :                                                 NULL, "invalid queue id");
   13191                 :          0 :                 r = age_info->hw_q_age->aged_lists[queue_id];
   13192                 :            :         } else {
   13193                 :          0 :                 r = age_info->hw_age.aged_list;
   13194                 :          0 :                 MLX5_AGE_SET(age_info, MLX5_AGE_TRIGGER);
   13195                 :            :         }
   13196         [ #  # ]:          0 :         if (nb_contexts == 0)
   13197                 :          0 :                 return rte_ring_count(r);
   13198         [ #  # ]:          0 :         while ((uint32_t)nb_flows < nb_contexts) {
   13199                 :            :                 uint32_t age_idx;
   13200                 :            : 
   13201                 :            :                 if (rte_ring_dequeue_elem(r, &age_idx, sizeof(uint32_t)) < 0)
   13202                 :            :                         break;
   13203                 :            :                 /* get the AGE context if the aged-out index is still valid. */
   13204                 :          0 :                 contexts[nb_flows] = mlx5_hws_age_context_get(priv, age_idx);
   13205         [ #  # ]:          0 :                 if (!contexts[nb_flows])
   13206                 :          0 :                         continue;
   13207                 :          0 :                 nb_flows++;
   13208                 :            :         }
   13209                 :            :         return nb_flows;
   13210                 :            : }
   13211                 :            : 
   13212                 :            : /**
   13213                 :            :  * Get aged-out flows.
   13214                 :            :  *
   13215                 :            :  * This function is relevant only if RTE_FLOW_PORT_FLAG_STRICT_QUEUE isn't set.
   13216                 :            :  *
   13217                 :            :  * @param[in] dev
   13218                 :            :  *   Pointer to the Ethernet device structure.
   13219                 :            :  * @param[in] contexts
   13220                 :            :  *   The address of an array of pointers to the aged-out flows contexts.
   13221                 :            :  * @param[in] nb_contexts
   13222                 :            :  *   The length of context array pointers.
   13223                 :            :  * @param[out] error
   13224                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   13225                 :            :  *   error only.
   13226                 :            :  *
   13227                 :            :  * @return
   13228                 :            :  *   how many contexts get in success, otherwise negative errno value.
   13229                 :            :  *   if nb_contexts is 0, return the amount of all aged contexts.
   13230                 :            :  *   if nb_contexts is not 0 , return the amount of aged flows reported
   13231                 :            :  *   in the context array.
   13232                 :            :  */
   13233                 :            : static int
   13234                 :          0 : flow_hw_get_aged_flows(struct rte_eth_dev *dev, void **contexts,
   13235                 :            :                        uint32_t nb_contexts, struct rte_flow_error *error)
   13236                 :            : {
   13237                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13238                 :            : 
   13239         [ #  # ]:          0 :         if (priv->hws_strict_queue)
   13240                 :          0 :                 DRV_LOG(WARNING,
   13241                 :            :                         "port %u get aged flows called in strict queue mode.",
   13242                 :            :                         dev->data->port_id);
   13243                 :          0 :         return flow_hw_get_q_aged_flows(dev, 0, contexts, nb_contexts, error);
   13244                 :            : }
   13245                 :            : /**
   13246                 :            :  * Initialization function for non template API which calls
   13247                 :            :  * flow_hw_configure with default values.
   13248                 :            :  * Configure non queues cause 1 queue is configured by default for inner usage.
   13249                 :            :  *
   13250                 :            :  * @param[in] dev
   13251                 :            :  *   Pointer to the Ethernet device structure.
   13252                 :            :  * @param[out] error
   13253                 :            :  *   Pointer to the error structure.
   13254                 :            :  *
   13255                 :            :  * @return
   13256                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   13257                 :            :  */
   13258                 :            : int
   13259                 :          0 : flow_hw_init(struct rte_eth_dev *dev,
   13260                 :            :              struct rte_flow_error *error)
   13261                 :            : {
   13262                 :          0 :         const struct rte_flow_port_attr port_attr = {0};
   13263                 :          0 :         const struct rte_flow_queue_attr queue_attr = {.size = MLX5_NT_DEFAULT_QUEUE_SIZE};
   13264                 :          0 :         const struct rte_flow_queue_attr *attr_list = &queue_attr;
   13265                 :            : 
   13266                 :            :         /**
   13267                 :            :          * If user uses template and non template API:
   13268                 :            :          * User will call flow_hw_configure and non template
   13269                 :            :          * API will use the allocated actions.
   13270                 :            :          * Init function will not call flow_hw_configure.
   13271                 :            :          *
   13272                 :            :          * If user uses only non template API's:
   13273                 :            :          * Init function will call flow_hw_configure.
   13274                 :            :          * It will not allocate memory for actions.
   13275                 :            :          * When needed allocation, it will handle same as for SWS today,
   13276                 :            :          * meaning using bulk allocations and resize as needed.
   13277                 :            :          */
   13278                 :            :         /* Configure hws with default values. */
   13279                 :          0 :         DRV_LOG(DEBUG, "Apply default configuration, zero number of queues, inner control queue size is %u",
   13280                 :            :                 MLX5_NT_DEFAULT_QUEUE_SIZE);
   13281                 :          0 :         return __flow_hw_configure(dev, &port_attr, 0, &attr_list, true, error);
   13282                 :            : }
   13283                 :            : 
   13284                 :          0 : static int flow_hw_prepare(struct rte_eth_dev *dev,
   13285                 :            :                            const struct rte_flow_action actions[] __rte_unused,
   13286                 :            :                            enum mlx5_flow_type type,
   13287                 :            :                            struct rte_flow_hw **flow,
   13288                 :            :                            struct rte_flow_error *error)
   13289                 :            : {
   13290                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13291                 :          0 :         uint32_t idx = 0;
   13292                 :            : 
   13293                 :            :          /*
   13294                 :            :           * Notice pool idx size = (sizeof(struct rte_flow_hw)
   13295                 :            :           * + sizeof(struct rte_flow_nt2hws)) for HWS mode.
   13296                 :            :           */
   13297                 :          0 :         *flow = mlx5_ipool_zmalloc(priv->flows[type], &idx);
   13298         [ #  # ]:          0 :         if (!(*flow))
   13299                 :          0 :                 return rte_flow_error_set(error, ENOMEM,
   13300                 :            :                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   13301                 :            :                         "cannot allocate flow memory");
   13302                 :            :         /* Allocating 2 structures in one pool slot, updating nt2hw pointer.*/
   13303                 :          0 :         (*flow)->nt2hws = (struct rte_flow_nt2hws *)
   13304                 :          0 :                                 ((uintptr_t)(*flow) + sizeof(struct rte_flow_hw));
   13305                 :          0 :         (*flow)->idx = idx;
   13306                 :          0 :         (*flow)->nt2hws->flow_aux = mlx5_malloc(MLX5_MEM_ZERO, sizeof(struct rte_flow_hw_aux),
   13307                 :          0 :                                     RTE_CACHE_LINE_SIZE, rte_dev_numa_node(dev->device));
   13308         [ #  # ]:          0 :         if (!(*flow)->nt2hws->flow_aux)
   13309                 :          0 :                 return rte_flow_error_set(error, ENOMEM,
   13310                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   13311                 :            :                                 "cannot allocate flow aux memory");
   13312                 :            :         return 0;
   13313                 :            : }
   13314                 :            : 
   13315                 :            : #define FLOW_HW_SET_DV_FIELDS(flow_attr, root, dv_resource) {                                   \
   13316                 :            :         typeof(flow_attr) _flow_attr = (flow_attr);                                             \
   13317                 :            :         if (_flow_attr->transfer)                                                            \
   13318                 :            :                 dv_resource.ft_type = MLX5DV_FLOW_TABLE_TYPE_FDB;                               \
   13319                 :            :         else                                                                                    \
   13320                 :            :                 dv_resource.ft_type = _flow_attr->egress ? MLX5DV_FLOW_TABLE_TYPE_NIC_TX :   \
   13321                 :            :                                              MLX5DV_FLOW_TABLE_TYPE_NIC_RX;                     \
   13322                 :            :         root = _flow_attr->group ? 0 : 1;                                                    \
   13323                 :            :         dv_resource.flags =                                                                     \
   13324                 :            :                 mlx5_hw_act_flag[!!_flow_attr->group][get_mlx5dr_table_type(_flow_attr)];    \
   13325                 :            : }
   13326                 :            : 
   13327                 :            : static int
   13328                 :          0 : flow_hw_modify_hdr_resource_register
   13329                 :            :                         (struct rte_eth_dev *dev,
   13330                 :            :                          struct rte_flow_template_table *table,
   13331                 :            :                          struct mlx5_hw_actions *hw_acts,
   13332                 :            :                          struct rte_flow_hw *dev_flow,
   13333                 :            :                          struct rte_flow_error *error)
   13334                 :            : {
   13335                 :            :         struct rte_flow_attr *attr = &table->cfg.attr.flow_attr;
   13336                 :          0 :         struct mlx5_flow_dv_modify_hdr_resource *dv_resource_ptr = NULL;
   13337                 :            :         union {
   13338                 :            :                 struct mlx5_flow_dv_modify_hdr_resource dv_resource;
   13339                 :            :                 uint8_t data[sizeof(struct mlx5_flow_dv_modify_hdr_resource) +
   13340                 :            :                              sizeof(struct mlx5_modification_cmd) * MLX5_MHDR_MAX_CMD];
   13341                 :            :         } dummy;
   13342                 :            :         int ret;
   13343                 :            : 
   13344         [ #  # ]:          0 :         if (hw_acts->mhdr) {
   13345                 :          0 :                 dummy.dv_resource.actions_num = hw_acts->mhdr->mhdr_cmds_num;
   13346                 :          0 :                 memcpy(dummy.dv_resource.actions, hw_acts->mhdr->mhdr_cmds,
   13347         [ #  # ]:          0 :                         sizeof(struct mlx5_modification_cmd) * dummy.dv_resource.actions_num);
   13348                 :            :         } else {
   13349                 :            :                 return 0;
   13350                 :            :         }
   13351   [ #  #  #  # ]:          0 :         FLOW_HW_SET_DV_FIELDS(attr, dummy.dv_resource.root, dummy.dv_resource);
   13352                 :          0 :         dummy.dv_resource.flags |= MLX5DR_ACTION_FLAG_SHARED;
   13353                 :          0 :         ret = __flow_modify_hdr_resource_register(dev, &dummy.dv_resource,
   13354                 :            :                 &dv_resource_ptr, error);
   13355         [ #  # ]:          0 :         if (ret)
   13356                 :            :                 return ret;
   13357                 :            :         MLX5_ASSERT(dv_resource_ptr);
   13358                 :          0 :         dev_flow->nt2hws->modify_hdr = dv_resource_ptr;
   13359                 :            :         /* keep action for the rule construction. */
   13360                 :          0 :         hw_acts->rule_acts[hw_acts->mhdr->pos].action = dv_resource_ptr->action;
   13361                 :            :         /* Bulk size is 1, so index is 1. */
   13362                 :          0 :         dev_flow->res_idx = 1;
   13363                 :          0 :         return 0;
   13364                 :            : }
   13365                 :            : 
   13366                 :            : static int
   13367                 :          0 : flow_hw_encap_decap_resource_register
   13368                 :            :                         (struct rte_eth_dev *dev,
   13369                 :            :                          struct rte_flow_template_table *table,
   13370                 :            :                          struct mlx5_hw_actions *hw_acts,
   13371                 :            :                          struct rte_flow_hw *dev_flow,
   13372                 :            :                          struct rte_flow_error *error)
   13373                 :            : {
   13374                 :            :         struct rte_flow_attr *attr = &table->cfg.attr.flow_attr;
   13375                 :          0 :         struct mlx5_flow_dv_encap_decap_resource *dv_resource_ptr = NULL;
   13376                 :            :         struct mlx5_flow_dv_encap_decap_resource dv_resource;
   13377                 :            :         struct mlx5_tbl_multi_pattern_ctx *mpctx = &table->mpctx;
   13378                 :            :         int ret;
   13379                 :            :         bool is_root;
   13380                 :            :         int ix;
   13381                 :            : 
   13382         [ #  # ]:          0 :         if (hw_acts->encap_decap)
   13383                 :          0 :                 dv_resource.reformat_type = hw_acts->encap_decap->action_type;
   13384                 :            :         else
   13385                 :            :                 return 0;
   13386   [ #  #  #  # ]:          0 :         FLOW_HW_SET_DV_FIELDS(attr, is_root, dv_resource);
   13387         [ #  # ]:          0 :         ix = mlx5_bwc_multi_pattern_reformat_to_index((enum mlx5dr_action_type)
   13388                 :            :                         dv_resource.reformat_type);
   13389                 :            :         if (ix < 0)
   13390                 :          0 :                 return ix;
   13391         [ #  # ]:          0 :         if (hw_acts->encap_decap->shared) {
   13392                 :          0 :                 dv_resource.size = hw_acts->encap_decap->data_size;
   13393                 :            :                 MLX5_ASSERT(dv_resource.size <= MLX5_ENCAP_MAX_LEN);
   13394                 :          0 :                 memcpy(&dv_resource.buf, hw_acts->encap_decap->data, dv_resource.size);
   13395                 :          0 :                 dv_resource.flags |= MLX5DR_ACTION_FLAG_SHARED;
   13396                 :            :         } else {
   13397                 :          0 :                 typeof(mpctx->reformat[0]) *reformat = mpctx->reformat + ix;
   13398         [ #  # ]:          0 :                 if (!reformat->elements_num)
   13399                 :          0 :                         return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
   13400                 :            :                                         NULL, "No reformat action exist in the table.");
   13401                 :          0 :                 dv_resource.size = reformat->reformat_hdr->sz;
   13402                 :            :                 MLX5_ASSERT(dv_resource.size <= MLX5_ENCAP_MAX_LEN);
   13403                 :          0 :                 memcpy(&dv_resource.buf, reformat->reformat_hdr->data, dv_resource.size);
   13404                 :            :         }
   13405                 :          0 :         ret = __flow_encap_decap_resource_register(dev, &dv_resource, is_root,
   13406                 :            :                 &dv_resource_ptr, error);
   13407         [ #  # ]:          0 :         if (ret)
   13408                 :            :                 return ret;
   13409                 :            :         MLX5_ASSERT(dv_resource_ptr);
   13410                 :          0 :         dev_flow->nt2hws->rix_encap_decap = dv_resource_ptr->idx;
   13411                 :            :         /* keep action for the rule construction. */
   13412         [ #  # ]:          0 :         if (hw_acts->encap_decap->shared)
   13413                 :          0 :                 hw_acts->rule_acts[hw_acts->encap_decap_pos].action = dv_resource_ptr->action;
   13414                 :            :         else
   13415                 :          0 :                 mpctx->segments[0].reformat_action[ix] = dv_resource_ptr->action;
   13416                 :            :         /* Bulk size is 1, so index is 1. */
   13417                 :          0 :         dev_flow->res_idx = 1;
   13418                 :          0 :         return 0;
   13419                 :            : }
   13420                 :            : 
   13421                 :            : static enum rte_flow_action_type
   13422                 :            : flow_nta_get_indirect_action_type(const struct rte_flow_action *action)
   13423                 :            : {
   13424         [ #  # ]:          0 :         switch (MLX5_INDIRECT_ACTION_TYPE_GET(action->conf)) {
   13425                 :            :         case MLX5_INDIRECT_ACTION_TYPE_RSS:
   13426                 :            :                 return RTE_FLOW_ACTION_TYPE_RSS;
   13427                 :            :         case MLX5_INDIRECT_ACTION_TYPE_AGE:
   13428                 :            :                 return RTE_FLOW_ACTION_TYPE_AGE;
   13429                 :            :         case MLX5_INDIRECT_ACTION_TYPE_COUNT:
   13430                 :            :                 return RTE_FLOW_ACTION_TYPE_COUNT;
   13431                 :            :         case MLX5_INDIRECT_ACTION_TYPE_CT:
   13432                 :            :                 return RTE_FLOW_ACTION_TYPE_CONNTRACK;
   13433                 :            :         default:
   13434                 :            :                 break;
   13435                 :            :         }
   13436                 :            :         return RTE_FLOW_ACTION_TYPE_END;
   13437                 :            : }
   13438                 :            : 
   13439                 :            : static void
   13440                 :            : flow_nta_set_mh_mask_conf(const struct rte_flow_action_modify_field *action_conf,
   13441                 :            :                           struct rte_flow_action_modify_field *mask_conf)
   13442                 :            : {
   13443                 :            :         memset(mask_conf, 0xff, sizeof(*mask_conf));
   13444                 :          0 :         mask_conf->operation = action_conf->operation;
   13445                 :          0 :         mask_conf->dst.field = action_conf->dst.field;
   13446                 :          0 :         mask_conf->src.field = action_conf->src.field;
   13447                 :            : }
   13448                 :            : 
   13449                 :            : union actions_conf {
   13450                 :            :         struct rte_flow_action_modify_field modify_field;
   13451                 :            :         struct rte_flow_action_raw_encap raw_encap;
   13452                 :            :         struct rte_flow_action_vxlan_encap vxlan_encap;
   13453                 :            :         struct rte_flow_action_nvgre_encap nvgre_encap;
   13454                 :            : };
   13455                 :            : 
   13456                 :            : static int
   13457                 :          0 : flow_nta_build_template_mask(const struct rte_flow_action actions[],
   13458                 :            :                              struct rte_flow_action masks[MLX5_HW_MAX_ACTS],
   13459                 :            :                              union actions_conf mask_conf[MLX5_HW_MAX_ACTS])
   13460                 :            : {
   13461                 :            :         int i;
   13462                 :            : 
   13463   [ #  #  #  # ]:          0 :         for (i = 0; i == 0 || actions[i - 1].type != RTE_FLOW_ACTION_TYPE_END; i++) {
   13464                 :          0 :                 const struct rte_flow_action *action = &actions[i];
   13465                 :          0 :                 struct rte_flow_action *mask = &masks[i];
   13466                 :          0 :                 union actions_conf *conf = &mask_conf[i];
   13467                 :            : 
   13468                 :          0 :                 mask->type = action->type;
   13469   [ #  #  #  #  :          0 :                 switch (action->type) {
                   #  # ]
   13470                 :            :                 case RTE_FLOW_ACTION_TYPE_INDIRECT:
   13471                 :          0 :                         mask->type = flow_nta_get_indirect_action_type(action);
   13472         [ #  # ]:          0 :                         if (!mask->type)
   13473                 :            :                                 return -EINVAL;
   13474                 :            :                         break;
   13475                 :          0 :                 case RTE_FLOW_ACTION_TYPE_MODIFY_FIELD:
   13476                 :          0 :                         flow_nta_set_mh_mask_conf(action->conf, (void *)conf);
   13477                 :          0 :                         mask->conf = conf;
   13478                 :          0 :                         break;
   13479                 :            :                 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
   13480                 :            :                         /* This mask will set this action as shared. */
   13481                 :            :                         memset(conf, 0xff, sizeof(struct rte_flow_action_raw_encap));
   13482                 :          0 :                         mask->conf = conf;
   13483                 :          0 :                         break;
   13484                 :          0 :                 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
   13485                 :            :                         /* This mask will set this action as shared. */
   13486                 :          0 :                         conf->vxlan_encap.definition =
   13487                 :            :                                 ((const struct rte_flow_action_vxlan_encap *)
   13488                 :          0 :                                         action->conf)->definition;
   13489                 :          0 :                         mask->conf = conf;
   13490                 :          0 :                         break;
   13491                 :          0 :                 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
   13492                 :            :                         /* This mask will set this action as shared. */
   13493                 :          0 :                         conf->nvgre_encap.definition =
   13494                 :            :                                 ((const struct rte_flow_action_nvgre_encap *)
   13495                 :          0 :                                         action->conf)->definition;
   13496                 :          0 :                         mask->conf = conf;
   13497                 :          0 :                         break;
   13498                 :            :                 default:
   13499                 :            :                         break;
   13500                 :            :                 }
   13501                 :            :         }
   13502                 :            :         return 0;
   13503                 :            : #undef NTA_CHECK_CONF_BUF_SIZE
   13504                 :            : }
   13505                 :            : 
   13506                 :            : static int
   13507                 :          0 : flow_hw_translate_flow_actions(struct rte_eth_dev *dev,
   13508                 :            :                                const struct rte_flow_attr *attr,
   13509                 :            :                                const struct rte_flow_action actions[],
   13510                 :            :                                struct rte_flow_hw *flow,
   13511                 :            :                                struct mlx5_flow_hw_action_params *ap,
   13512                 :            :                                struct mlx5_hw_actions *hw_acts,
   13513                 :            :                                uint64_t item_flags, uint64_t action_flags,
   13514                 :            :                                bool external,
   13515                 :            :                                struct rte_flow_error *error)
   13516                 :            : {
   13517                 :            :         int ret = 0;
   13518                 :          0 :         uint32_t src_group = 0;
   13519                 :            :         enum mlx5dr_table_type table_type;
   13520                 :            :         struct mlx5_flow_group grp;
   13521                 :            :         struct rte_flow_actions_template *at = NULL;
   13522                 :          0 :         struct rte_flow_actions_template_attr template_attr = {
   13523                 :          0 :                 .egress = attr->egress,
   13524                 :          0 :                 .ingress = attr->ingress,
   13525                 :          0 :                 .transfer = attr->transfer,
   13526                 :            :         };
   13527                 :            :         struct rte_flow_action masks[MLX5_HW_MAX_ACTS];
   13528                 :            :         union actions_conf mask_conf[MLX5_HW_MAX_ACTS];
   13529                 :            : 
   13530                 :            :         RTE_SET_USED(action_flags);
   13531                 :            :         memset(masks, 0, sizeof(masks));
   13532                 :            :         memset(mask_conf, 0, sizeof(mask_conf));
   13533                 :            :         /* Only set the needed fields explicitly. */
   13534                 :          0 :         struct mlx5_flow_workspace *wks = mlx5_flow_push_thread_workspace();
   13535                 :            :         struct rte_flow_template_table *table;
   13536                 :            : 
   13537                 :            :         /*
   13538                 :            :          * Notice All direct actions will be unmasked,
   13539                 :            :          * except for modify header and encap,
   13540                 :            :          * and therefore will be parsed as part of action construct.
   13541                 :            :          * Modify header is always shared in HWS,
   13542                 :            :          * encap is masked such that it will be treated as shared.
   13543                 :            :          * shared actions will be parsed as part of template translation
   13544                 :            :          * and not during action construct.
   13545                 :            :          */
   13546         [ #  # ]:          0 :         if (!wks)
   13547                 :          0 :                 return rte_flow_error_set(error, ENOMEM,
   13548                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   13549                 :            :                                           NULL,
   13550                 :            :                                           "failed to push flow workspace");
   13551                 :          0 :         table = wks->table;
   13552                 :          0 :         flow_nta_build_template_mask(actions, masks, mask_conf);
   13553                 :            :         /* The group in the attribute translation was done in advance. */
   13554                 :          0 :         ret = __translate_group(dev, attr, external, attr->group, &src_group, error);
   13555         [ #  # ]:          0 :         if (ret)
   13556                 :            :                 return ret;
   13557         [ #  # ]:          0 :         if (attr->transfer)
   13558                 :            :                 table_type = MLX5DR_TABLE_TYPE_FDB;
   13559         [ #  # ]:          0 :         else if (attr->egress)
   13560                 :            :                 table_type = MLX5DR_TABLE_TYPE_NIC_TX;
   13561                 :            :         else
   13562                 :            :                 table_type = MLX5DR_TABLE_TYPE_NIC_RX;
   13563                 :          0 :         at = __flow_hw_actions_template_create(dev, &template_attr, actions, masks, true, error);
   13564         [ #  # ]:          0 :         if (!at) {
   13565                 :          0 :                 ret = -rte_errno;
   13566                 :          0 :                 goto end;
   13567                 :            :         }
   13568                 :          0 :         grp.group_id = src_group;
   13569                 :          0 :         table->grp = &grp;
   13570                 :          0 :         table->type = table_type;
   13571                 :          0 :         table->cfg.external = external;
   13572                 :          0 :         table->nb_action_templates = 1;
   13573                 :          0 :         memcpy(&table->cfg.attr.flow_attr, attr, sizeof(*attr));
   13574                 :          0 :         table->ats[0].action_template = at;
   13575                 :          0 :         ret = __flow_hw_translate_actions_template(dev, &table->cfg, hw_acts, at,
   13576                 :            :                                                    &table->mpctx, true, error);
   13577         [ #  # ]:          0 :         if (ret)
   13578                 :          0 :                 goto end;
   13579                 :            :         /* handle bulk actions register. */
   13580                 :          0 :         ret = flow_hw_encap_decap_resource_register(dev, table, hw_acts, flow, error);
   13581         [ #  # ]:          0 :         if (ret)
   13582                 :          0 :                 goto end;
   13583                 :          0 :         ret = flow_hw_modify_hdr_resource_register(dev, table, hw_acts, flow, error);
   13584         [ #  # ]:          0 :         if (ret)
   13585                 :          0 :                 goto end;
   13586                 :          0 :         table->ats[0].acts = *hw_acts;
   13587                 :          0 :         ret = flow_hw_actions_construct(dev, flow, ap,
   13588                 :            :                                         &table->ats[0], item_flags, table,
   13589         [ #  # ]:          0 :                                         actions, hw_acts->rule_acts, 0, error);
   13590                 :            :         if (ret)
   13591                 :          0 :                 goto end;
   13592                 :          0 :         goto end;
   13593                 :          0 : end:
   13594         [ #  # ]:          0 :         if (ret)
   13595                 :            :                 /* Make sure that there is no garbage in the actions. */
   13596                 :          0 :                 __flow_hw_action_template_destroy(dev, hw_acts);
   13597                 :            :         else
   13598                 :          0 :                 __flow_hw_act_data_flush(dev, hw_acts);
   13599         [ #  # ]:          0 :         if (at)
   13600                 :          0 :                 mlx5_free(at);
   13601                 :          0 :         mlx5_flow_pop_thread_workspace();
   13602                 :          0 :         return ret;
   13603                 :            : }
   13604                 :            : 
   13605                 :            : static int
   13606                 :          0 : flow_hw_unregister_matcher(struct rte_eth_dev *dev,
   13607                 :            :                            struct mlx5_flow_dv_matcher *matcher)
   13608                 :            : {
   13609                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13610                 :          0 :         struct mlx5_flow_group *group = matcher->group;
   13611                 :            :         int ret = 0;
   13612                 :            : 
   13613         [ #  # ]:          0 :         if (group) {
   13614         [ #  # ]:          0 :                 if (matcher->matcher_object)
   13615                 :          0 :                         ret |= mlx5_list_unregister(group->matchers, &matcher->entry);
   13616                 :          0 :                 ret |= mlx5_hlist_unregister(priv->sh->groups, &group->entry);
   13617                 :            :         }
   13618                 :          0 :         return ret;
   13619                 :            : }
   13620                 :            : 
   13621                 :          0 : static int flow_hw_register_matcher(struct rte_eth_dev *dev,
   13622                 :            :                                     const struct rte_flow_attr *attr,
   13623                 :            :                                     const struct rte_flow_item items[],
   13624                 :            :                                     bool external,
   13625                 :            :                                     struct rte_flow_hw *flow,
   13626                 :            :                                     struct mlx5_flow_dv_matcher *matcher,
   13627                 :            :                                     struct rte_flow_error *error)
   13628                 :            : {
   13629                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13630                 :          0 :         struct rte_flow_error sub_error = {
   13631                 :            :                 .type = RTE_FLOW_ERROR_TYPE_NONE,
   13632                 :            :                 .cause = NULL,
   13633                 :            :                 .message = NULL,
   13634                 :            :         };
   13635                 :          0 :         struct rte_flow_attr flow_attr = *attr;
   13636                 :          0 :         uint32_t specialize = 0; /* No unified FDB. */
   13637                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
   13638                 :            :                 .dev = dev,
   13639                 :            :                 .error = &sub_error,
   13640                 :            :                 .data = &flow_attr,
   13641                 :            :                 .data2 = &specialize,
   13642                 :            :         };
   13643                 :            :         void *items_ptr = &items;
   13644                 :          0 :         struct mlx5_flow_cb_ctx matcher_ctx = {
   13645                 :            :                 .error = &sub_error,
   13646                 :            :                 .data = matcher,
   13647                 :            :                 .data2 = items_ptr,
   13648                 :            :         };
   13649                 :            :         struct mlx5_list_entry *group_entry = NULL;
   13650                 :            :         struct mlx5_list_entry *matcher_entry = NULL;
   13651                 :            :         struct mlx5_flow_dv_matcher *resource;
   13652                 :            :         struct mlx5_list *matchers_list;
   13653                 :            :         struct mlx5_flow_group *flow_group;
   13654                 :            :         int ret;
   13655                 :            : 
   13656                 :            : 
   13657                 :          0 :         matcher->crc = rte_raw_cksum((const void *)matcher->mask.buf,
   13658                 :            :                                     matcher->mask.size);
   13659                 :          0 :         matcher->priority = attr->priority;
   13660                 :          0 :         ret = __translate_group(dev, attr, external, attr->group, &flow_attr.group, error);
   13661         [ #  # ]:          0 :         if (ret)
   13662                 :            :                 return ret;
   13663                 :            : 
   13664                 :            :         /* Register the flow group. */
   13665                 :          0 :         group_entry = mlx5_hlist_register(priv->sh->groups, flow_attr.group, &ctx);
   13666         [ #  # ]:          0 :         if (!group_entry)
   13667                 :          0 :                 goto error;
   13668                 :            :         flow_group = container_of(group_entry, struct mlx5_flow_group, entry);
   13669                 :            : 
   13670                 :          0 :         matchers_list = flow_group->matchers;
   13671                 :          0 :         matcher->group = flow_group;
   13672                 :          0 :         matcher_entry = mlx5_list_register(matchers_list, &matcher_ctx);
   13673         [ #  # ]:          0 :         if (!matcher_entry)
   13674                 :          0 :                 goto error;
   13675                 :            :         resource = container_of(matcher_entry, typeof(*resource), entry);
   13676                 :          0 :         flow->nt2hws->matcher = resource;
   13677                 :          0 :         return 0;
   13678                 :            : 
   13679                 :          0 : error:
   13680         [ #  # ]:          0 :         if (group_entry)
   13681                 :          0 :                 mlx5_hlist_unregister(priv->sh->groups, group_entry);
   13682         [ #  # ]:          0 :         if (error) {
   13683         [ #  # ]:          0 :                 if (sub_error.type != RTE_FLOW_ERROR_TYPE_NONE)
   13684                 :            :                         rte_memcpy(error, &sub_error, sizeof(sub_error));
   13685                 :            :         }
   13686                 :          0 :         return rte_flow_error_set(error, ENOMEM,
   13687                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   13688                 :            :                                         NULL, "fail to register matcher");
   13689                 :            : }
   13690                 :            : 
   13691                 :            : static int
   13692                 :          0 : flow_hw_allocate_actions(struct rte_eth_dev *dev,
   13693                 :            :                          uint64_t action_flags,
   13694                 :            :                          struct rte_flow_error *error)
   13695                 :            : {
   13696                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13697                 :            :         int ret;
   13698                 :            :         uint obj_num;
   13699                 :            : 
   13700                 :          0 :         error->type = RTE_FLOW_ERROR_TYPE_NONE;
   13701         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_AGE) {
   13702                 :            :                 /* If no age objects were previously allocated. */
   13703         [ #  # ]:          0 :                 if (!priv->hws_age_req) {
   13704                 :            :                         /* If no counters were previously allocated. */
   13705         [ #  # ]:          0 :                         if (!priv->hws_cpool) {
   13706                 :          0 :                                 obj_num = MLX5_CNT_NT_MAX(priv);
   13707                 :          0 :                                 ret = mlx5_hws_cnt_pool_create(dev, obj_num,
   13708                 :          0 :                                                                priv->nb_queue,
   13709                 :            :                                                                NULL, error);
   13710         [ #  # ]:          0 :                                 if (ret)
   13711                 :          0 :                                         goto err;
   13712                 :            :                         }
   13713                 :            :                         /* Allocate same number of counters. */
   13714                 :          0 :                         ret = mlx5_hws_age_pool_init(dev, priv->hws_cpool->cfg.request_num,
   13715                 :          0 :                                                      priv->nb_queue, false);
   13716         [ #  # ]:          0 :                         if (ret)
   13717                 :          0 :                                 goto err;
   13718                 :            :                 }
   13719                 :            :         }
   13720         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_COUNT) {
   13721                 :            :                 /* If no counters were previously allocated. */
   13722         [ #  # ]:          0 :                 if (!priv->hws_cpool) {
   13723                 :          0 :                         obj_num = MLX5_CNT_NT_MAX(priv);
   13724                 :          0 :                         ret = mlx5_hws_cnt_pool_create(dev, obj_num,
   13725                 :          0 :                                                        priv->nb_queue, NULL,
   13726                 :            :                                                        error);
   13727         [ #  # ]:          0 :                         if (ret)
   13728                 :          0 :                                 goto err;
   13729                 :            :                 }
   13730                 :            :         }
   13731         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_CT) {
   13732                 :            :                 /* If no CT were previously allocated. */
   13733         [ #  # ]:          0 :                 if (!priv->hws_ctpool) {
   13734                 :          0 :                         obj_num = MLX5_CT_NT_MAX(priv);
   13735                 :          0 :                         ret = mlx5_flow_ct_init(dev, obj_num, priv->nb_queue);
   13736         [ #  # ]:          0 :                         if (ret)
   13737                 :          0 :                                 goto err;
   13738                 :            :                 }
   13739                 :            :         }
   13740         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_METER) {
   13741                 :            :                 /* If no meters were previously allocated. */
   13742         [ #  # ]:          0 :                 if (!priv->hws_mpool) {
   13743                 :          0 :                         obj_num = MLX5_MTR_NT_MAX(priv);
   13744                 :          0 :                         ret = mlx5_flow_meter_init(dev, obj_num, 0, 0,
   13745                 :            :                                                    priv->nb_queue);
   13746         [ #  # ]:          0 :                         if (ret)
   13747                 :          0 :                                 goto err;
   13748                 :            :                 }
   13749                 :            :         }
   13750                 :            :         return 0;
   13751                 :          0 : err:
   13752         [ #  # ]:          0 :         if (ret && error->type != RTE_FLOW_ERROR_TYPE_NONE)
   13753                 :            :                 return ret;
   13754                 :          0 :         return rte_flow_error_set(error, ret,
   13755                 :            :                                   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   13756                 :            :                                   NULL, "fail to allocate actions");
   13757                 :            : }
   13758                 :            : 
   13759                 :          0 : static int flow_hw_apply(const struct rte_flow_item items[],
   13760                 :            :                          struct mlx5dr_rule_action rule_actions[],
   13761                 :            :                          struct rte_flow_hw *flow,
   13762                 :            :                          struct rte_flow_error *error)
   13763                 :            : {
   13764                 :            :         struct mlx5dr_bwc_rule *rule = NULL;
   13765                 :            : 
   13766                 :          0 :         rule = mlx5dr_bwc_rule_create((struct mlx5dr_bwc_matcher *)
   13767                 :          0 :                 flow->nt2hws->matcher->matcher_object,
   13768                 :            :                 items, rule_actions);
   13769                 :          0 :         flow->nt2hws->nt_rule = rule;
   13770         [ #  # ]:          0 :         if (!rule) {
   13771                 :          0 :                 return rte_flow_error_set(error, EINVAL,
   13772                 :            :                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   13773                 :            :                         NULL, "fail to create rte flow");
   13774                 :            :         }
   13775                 :            :         return 0;
   13776                 :            : }
   13777                 :            : 
   13778                 :            : #ifdef HAVE_MLX5_HWS_SUPPORT
   13779                 :            : /**
   13780                 :            :  * Create a flow.
   13781                 :            :  *
   13782                 :            :  * @param[in] dev
   13783                 :            :  *   Pointer to Ethernet device.
   13784                 :            :  * @param[in] type
   13785                 :            :  *   Flow type.
   13786                 :            :  * @param[in] attr
   13787                 :            :  *   Flow rule attributes.
   13788                 :            :  * @param[in] items
   13789                 :            :  *   Pattern specification (list terminated by the END pattern item).
   13790                 :            :  * @param[in] actions
   13791                 :            :  *   Associated actions (list terminated by the END action).
   13792                 :            :  * @param[in] external
   13793                 :            :  *   This flow rule is created by request external to PMD.
   13794                 :            :  * @param[out] flow
   13795                 :            :  *   Flow pointer
   13796                 :            :  * @param[out] error
   13797                 :            :  *   Perform verbose error reporting if not NULL.
   13798                 :            :  *
   13799                 :            :  * @return
   13800                 :            :  *   0 on success, negative errno value otherwise and rte_errno set.
   13801                 :            :  */
   13802                 :            : int
   13803                 :          0 : flow_hw_create_flow(struct rte_eth_dev *dev, enum mlx5_flow_type type,
   13804                 :            :                     const struct rte_flow_attr *attr,
   13805                 :            :                     const struct rte_flow_item items[],
   13806                 :            :                     const struct rte_flow_action actions[],
   13807                 :            :                     uint64_t item_flags, uint64_t action_flags, bool external,
   13808                 :            :                     struct rte_flow_hw **flow, struct rte_flow_error *error)
   13809                 :            : {
   13810                 :            :         int ret;
   13811                 :          0 :         struct mlx5_hw_actions hw_act = { { NULL } };
   13812                 :            :         struct mlx5_flow_hw_action_params ap;
   13813                 :          0 :         struct mlx5_flow_dv_matcher matcher = {
   13814                 :            :                 .mask = {
   13815                 :            :                         .size = sizeof(matcher.mask.buf),
   13816                 :            :                 },
   13817                 :            :         };
   13818                 :            :         uint32_t tbl_type;
   13819                 :            : 
   13820                 :          0 :         struct mlx5_flow_attr flow_attr = {
   13821                 :          0 :                 .port_id = dev->data->port_id,
   13822                 :          0 :                 .group = attr->group,
   13823                 :          0 :                 .priority = attr->priority,
   13824                 :            :                 .rss_level = 0,
   13825                 :            :                 .act_flags = action_flags,
   13826                 :            :                 .tbl_type = 0,
   13827                 :            :         };
   13828                 :            : 
   13829         [ #  # ]:          0 :         if (attr->transfer)
   13830                 :            :                 tbl_type = MLX5DR_TABLE_TYPE_FDB;
   13831         [ #  # ]:          0 :         else if (attr->egress)
   13832                 :            :                 tbl_type = MLX5DR_TABLE_TYPE_NIC_TX;
   13833                 :            :         else
   13834                 :            :                 tbl_type = MLX5DR_TABLE_TYPE_NIC_RX;
   13835                 :          0 :         flow_attr.tbl_type = tbl_type;
   13836                 :            : 
   13837                 :            :         /* Allocate needed memory. */
   13838                 :          0 :         ret = flow_hw_prepare(dev, actions, type, flow, error);
   13839         [ #  # ]:          0 :         if (ret)
   13840                 :          0 :                 goto error;
   13841                 :            : 
   13842                 :            :         /* TODO TBD flow_hw_handle_tunnel_offload(). */
   13843                 :          0 :         (*flow)->nt_rule = true;
   13844                 :          0 :         (*flow)->nt2hws->matcher = &matcher;
   13845                 :          0 :         ret = flow_dv_translate_items_hws(items, &flow_attr, &matcher.mask.buf,
   13846                 :            :                                         MLX5_SET_MATCHER_HS_M, NULL,
   13847                 :            :                                         NULL, error);
   13848                 :            : 
   13849         [ #  # ]:          0 :         if (ret)
   13850                 :          0 :                 goto error;
   13851                 :            : 
   13852                 :          0 :         ret = flow_hw_register_matcher(dev, attr, items, external, *flow, &matcher, error);
   13853         [ #  # ]:          0 :         if (ret)
   13854                 :          0 :                 goto error;
   13855                 :            : 
   13856                 :            :         /*
   13857                 :            :          * ASO allocation – iterating on actions list to allocate missing resources.
   13858                 :            :          * In the future when validate function in hws will be added,
   13859                 :            :          * The output actions bit mask instead of
   13860                 :            :          * looping on the actions array twice.
   13861                 :            :          */
   13862                 :          0 :         ret = flow_hw_allocate_actions(dev, action_flags, error);
   13863         [ #  # ]:          0 :         if (ret)
   13864                 :          0 :                 goto error;
   13865                 :            : 
   13866                 :            :         /* Note: the actions should be saved in the sub-flow rule itself for reference. */
   13867                 :          0 :         ret = flow_hw_translate_flow_actions(dev, attr, actions, *flow, &ap, &hw_act,
   13868                 :            :                                         item_flags, action_flags, external, error);
   13869         [ #  # ]:          0 :         if (ret)
   13870                 :          0 :                 goto error;
   13871                 :            : 
   13872                 :            :         /*
   13873                 :            :          * If the flow is external (from application) OR device is started,
   13874                 :            :          * OR mreg discover, then apply immediately.
   13875                 :            :          */
   13876   [ #  #  #  # ]:          0 :         if (external || dev->data->dev_started ||
   13877         [ #  # ]:          0 :             (attr->group == MLX5_FLOW_MREG_CP_TABLE_GROUP &&
   13878         [ #  # ]:          0 :              attr->priority == MLX5_FLOW_LOWEST_PRIO_INDICATOR)) {
   13879                 :          0 :                 ret = flow_hw_apply(items, hw_act.rule_acts, *flow, error);
   13880         [ #  # ]:          0 :                 if (ret)
   13881                 :          0 :                         goto error;
   13882                 :            :         }
   13883                 :            :         ret = 0;
   13884                 :          0 : error:
   13885                 :            :         /*
   13886                 :            :          * Release memory allocated.
   13887                 :            :          * Cannot use __flow_hw_actions_release(dev, &hw_act);
   13888                 :            :          * since it destroys the actions as well.
   13889                 :            :          */
   13890         [ #  # ]:          0 :         if (hw_act.encap_decap)
   13891                 :          0 :                 mlx5_free(hw_act.encap_decap);
   13892         [ #  # ]:          0 :         if (hw_act.push_remove)
   13893                 :          0 :                 mlx5_free(hw_act.push_remove);
   13894         [ #  # ]:          0 :         if (hw_act.mhdr)
   13895                 :          0 :                 mlx5_free(hw_act.mhdr);
   13896         [ #  # ]:          0 :         if (ret) {
   13897                 :            :                 /* release after actual error */
   13898   [ #  #  #  # ]:          0 :                 if ((*flow)->nt2hws && (*flow)->nt2hws->matcher)
   13899                 :          0 :                         flow_hw_unregister_matcher(dev, (*flow)->nt2hws->matcher);
   13900                 :            :         }
   13901                 :          0 :         return ret;
   13902                 :            : }
   13903                 :            : #endif
   13904                 :            : 
   13905                 :            : void
   13906                 :          0 : flow_hw_destroy(struct rte_eth_dev *dev, struct rte_flow_hw *flow)
   13907                 :            : {
   13908                 :            :         int ret;
   13909                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13910                 :            : 
   13911   [ #  #  #  # ]:          0 :         if (!flow || !flow->nt2hws)
   13912                 :            :                 return;
   13913                 :            : 
   13914         [ #  # ]:          0 :         if (flow->nt2hws->nt_rule) {
   13915                 :          0 :                 ret = mlx5dr_bwc_rule_destroy(flow->nt2hws->nt_rule);
   13916         [ #  # ]:          0 :                 if (ret)
   13917                 :          0 :                         DRV_LOG(ERR, "bwc rule destroy failed");
   13918                 :            :         }
   13919         [ #  # ]:          0 :         flow->operation_type = MLX5_FLOW_HW_FLOW_OP_TYPE_DESTROY;
   13920                 :            :         /* Notice this function does not handle shared/static actions. */
   13921                 :            :         hw_cmpl_flow_update_or_destroy(dev, flow, 0, NULL);
   13922                 :            : 
   13923                 :            :         /**
   13924                 :            :          * TODO: TBD - Release tunnel related memory allocations(mlx5_flow_tunnel_free)
   13925                 :            :          * – needed only if supporting tunnel offloads, notice update RX queue flags in SWS.
   13926                 :            :          */
   13927                 :            : 
   13928                 :            :          /**
   13929                 :            :           * Notice matcher destroy will take place when matcher's list is destroyed
   13930                 :            :           * , same as for DV.
   13931                 :            :           */
   13932         [ #  # ]:          0 :         if (flow->nt2hws->flow_aux)
   13933                 :          0 :                 mlx5_free(flow->nt2hws->flow_aux);
   13934                 :            : 
   13935         [ #  # ]:          0 :         if (flow->nt2hws->rix_encap_decap)
   13936                 :          0 :                 flow_encap_decap_resource_release(dev, flow->nt2hws->rix_encap_decap);
   13937         [ #  # ]:          0 :         if (flow->nt2hws->modify_hdr) {
   13938                 :            :                 MLX5_ASSERT(flow->nt2hws->modify_hdr->action);
   13939                 :          0 :                 mlx5_hlist_unregister(priv->sh->modify_cmds,
   13940                 :            :                                       &flow->nt2hws->modify_hdr->entry);
   13941                 :            :         }
   13942         [ #  # ]:          0 :         if (flow->nt2hws->matcher)
   13943                 :          0 :                 flow_hw_unregister_matcher(dev, flow->nt2hws->matcher);
   13944                 :            : }
   13945                 :            : 
   13946                 :            : #ifdef HAVE_MLX5_HWS_SUPPORT
   13947                 :            : /**
   13948                 :            :  * Destroy a flow.
   13949                 :            :  *
   13950                 :            :  * @param[in] dev
   13951                 :            :  *   Pointer to Ethernet device.
   13952                 :            :  * @param[in] type
   13953                 :            :  *   Flow type.
   13954                 :            :  * @param[in] flow_addr
   13955                 :            :  *   Address of flow to destroy.
   13956                 :            :  */
   13957                 :            : void
   13958                 :          0 : flow_hw_list_destroy(struct rte_eth_dev *dev, enum mlx5_flow_type type,
   13959                 :            :                      uintptr_t flow_addr)
   13960                 :            : {
   13961                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13962                 :          0 :         struct rte_flow_hw *flow = (struct rte_flow_hw *)flow_addr;
   13963                 :            :         struct mlx5_nta_rss_flow_head head = { .slh_first = flow };
   13964                 :            : 
   13965   [ #  #  #  #  :          0 :         if (!flow || !flow->nt2hws || flow->nt2hws->chaned_flow)
                   #  # ]
   13966                 :            :                 return;
   13967                 :          0 :         mlx5_flow_nta_del_copy_action(dev, flow->nt2hws->rix_mreg_copy);
   13968         [ #  # ]:          0 :         while (!SLIST_EMPTY(&head)) {
   13969                 :            :                 flow = SLIST_FIRST(&head);
   13970                 :          0 :                 SLIST_REMOVE_HEAD(&head, nt2hws->next);
   13971                 :          0 :                 flow_hw_destroy(dev, flow);
   13972                 :            :                 /* Release flow memory by idx */
   13973                 :          0 :                 mlx5_ipool_free(priv->flows[type], flow->idx);
   13974                 :            :         }
   13975                 :            : }
   13976                 :            : #endif
   13977                 :            : 
   13978                 :            : /**
   13979                 :            :  * Create a flow.
   13980                 :            :  *
   13981                 :            :  * @param[in] dev
   13982                 :            :  *   Pointer to Ethernet device.
   13983                 :            :  * @param[in] type
   13984                 :            :  *   Flow type.
   13985                 :            :  * @param[in] attr
   13986                 :            :  *   Flow rule attributes.
   13987                 :            :  * @param[in] items
   13988                 :            :  *   Pattern specification (list terminated by the END pattern item).
   13989                 :            :  * @param[in] actions
   13990                 :            :  *   Associated actions (list terminated by the END action).
   13991                 :            :  * @param[in] external
   13992                 :            :  *   This flow rule is created by request external to PMD.
   13993                 :            :  * @param[out] error
   13994                 :            :  *   Perform verbose error reporting if not NULL.
   13995                 :            :  *
   13996                 :            :  * @return
   13997                 :            :  *   A flow addr on success, 0 otherwise and rte_errno is set.
   13998                 :            :  */
   13999                 :          0 : static uintptr_t flow_hw_list_create(struct rte_eth_dev *dev,
   14000                 :            :                                      enum mlx5_flow_type type,
   14001                 :            :                                      const struct rte_flow_attr *attr,
   14002                 :            :                                      const struct rte_flow_item items[],
   14003                 :            :                                      const struct rte_flow_action actions[],
   14004                 :            :                                      bool external,
   14005                 :            :                                      struct rte_flow_error *error)
   14006                 :            : {
   14007                 :            :         int ret;
   14008                 :            :         int split;
   14009                 :            :         int encap_idx;
   14010                 :          0 :         uint32_t cpy_idx = 0;
   14011                 :          0 :         int actions_n = 0;
   14012                 :          0 :         struct rte_flow_hw *flow = NULL;
   14013                 :          0 :         struct rte_flow_hw *prfx_flow = NULL;
   14014                 :          0 :         const struct rte_flow_action *qrss = NULL;
   14015                 :          0 :         const struct rte_flow_action *mark = NULL;
   14016                 :          0 :         uint64_t item_flags = flow_hw_matching_item_flags_get(items);
   14017                 :          0 :         uint64_t action_flags = flow_hw_action_flags_get(actions, &qrss, &mark,
   14018                 :            :                                                          &encap_idx, &actions_n, error);
   14019                 :          0 :         struct mlx5_flow_hw_split_resource resource = {
   14020                 :            :                 .suffix = {
   14021                 :            :                         .attr = attr,
   14022                 :            :                         .items = items,
   14023                 :            :                         .actions = actions,
   14024                 :            :                 },
   14025                 :            :         };
   14026                 :          0 :         struct rte_flow_error shadow_error = {0, };
   14027                 :            : 
   14028                 :            :         /*
   14029                 :            :          * TODO: add a call to flow_hw_validate function once it exist.
   14030                 :            :          * and update mlx5_flow_hw_drv_ops accordingly.
   14031                 :            :          */
   14032                 :            : 
   14033                 :            :         RTE_SET_USED(encap_idx);
   14034         [ #  # ]:          0 :         if (!error)
   14035                 :            :                 error = &shadow_error;
   14036                 :          0 :         split = mlx5_flow_nta_split_metadata(dev, attr, actions, qrss, action_flags,
   14037                 :            :                                              actions_n, external, &resource, error);
   14038         [ #  # ]:          0 :         if (split < 0)
   14039                 :          0 :                 return split;
   14040                 :            : 
   14041                 :            :         /* Update the metadata copy table - MLX5_FLOW_MREG_CP_TABLE_GROUP */
   14042   [ #  #  #  #  :          0 :         if (((attr->ingress && attr->group != MLX5_FLOW_MREG_CP_TABLE_GROUP) ||
                   #  # ]
   14043         [ #  # ]:          0 :              attr->transfer) && external) {
   14044                 :          0 :                 ret = mlx5_flow_nta_update_copy_table(dev, &cpy_idx, mark,
   14045                 :            :                                                       action_flags, error);
   14046         [ #  # ]:          0 :                 if (ret)
   14047                 :          0 :                         goto free;
   14048                 :            :         }
   14049                 :            : 
   14050         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_RSS) {
   14051                 :            :                 const struct rte_flow_action_rss
   14052                 :          0 :                         *rss_conf = flow_nta_locate_rss(dev, actions, error);
   14053                 :          0 :                 flow = flow_nta_handle_rss(dev, attr, items, actions, rss_conf,
   14054                 :            :                                            item_flags, action_flags, external,
   14055                 :            :                                            type, error);
   14056         [ #  # ]:          0 :                 if (flow) {
   14057                 :          0 :                         flow->nt2hws->rix_mreg_copy = cpy_idx;
   14058                 :          0 :                         cpy_idx = 0;
   14059         [ #  # ]:          0 :                         if (!split)
   14060                 :          0 :                                 return (uintptr_t)flow;
   14061                 :          0 :                         goto prefix_flow;
   14062                 :            :                 }
   14063                 :          0 :                 goto free;
   14064                 :            :         }
   14065                 :            :         /* Create single flow. */
   14066                 :          0 :         ret = flow_hw_create_flow(dev, type, resource.suffix.attr, resource.suffix.items,
   14067                 :            :                                   resource.suffix.actions, item_flags, action_flags,
   14068                 :            :                                   external, &flow, error);
   14069         [ #  # ]:          0 :         if (ret)
   14070                 :          0 :                 goto free;
   14071         [ #  # ]:          0 :         if (flow) {
   14072                 :          0 :                 flow->nt2hws->rix_mreg_copy = cpy_idx;
   14073                 :          0 :                 cpy_idx = 0;
   14074         [ #  # ]:          0 :                 if (!split)
   14075                 :          0 :                         return (uintptr_t)flow;
   14076                 :            :                 /* Fall Through to prefix flow creation. */
   14077                 :            :         }
   14078                 :          0 : prefix_flow:
   14079                 :          0 :         ret = flow_hw_create_flow(dev, type, attr, items, resource.prefix.actions,
   14080                 :            :                                   item_flags, action_flags, external, &prfx_flow, error);
   14081         [ #  # ]:          0 :         if (ret)
   14082                 :          0 :                 goto free;
   14083         [ #  # ]:          0 :         if (prfx_flow) {
   14084                 :          0 :                 prfx_flow->nt2hws->rix_mreg_copy = flow->nt2hws->rix_mreg_copy;
   14085                 :          0 :                 flow->nt2hws->chaned_flow = 1;
   14086                 :          0 :                 SLIST_INSERT_AFTER(prfx_flow, flow, nt2hws->next);
   14087                 :          0 :                 mlx5_flow_nta_split_resource_free(dev, &resource);
   14088                 :          0 :                 return (uintptr_t)prfx_flow;
   14089                 :            :         }
   14090                 :          0 : free:
   14091         [ #  # ]:          0 :         if (prfx_flow)
   14092                 :          0 :                 flow_hw_list_destroy(dev, type, (uintptr_t)prfx_flow);
   14093         [ #  # ]:          0 :         if (flow)
   14094                 :          0 :                 flow_hw_list_destroy(dev, type, (uintptr_t)flow);
   14095         [ #  # ]:          0 :         if (cpy_idx)
   14096                 :          0 :                 mlx5_flow_nta_del_copy_action(dev, cpy_idx);
   14097         [ #  # ]:          0 :         if (split > 0)
   14098                 :          0 :                 mlx5_flow_nta_split_resource_free(dev, &resource);
   14099                 :            :         return 0;
   14100                 :            : }
   14101                 :            : 
   14102                 :            : static void
   14103                 :          0 : mlx5_mirror_destroy_clone(struct rte_eth_dev *dev,
   14104                 :            :                           struct mlx5_mirror_clone *clone)
   14105                 :            : {
   14106      [ #  #  # ]:          0 :         switch (clone->type) {
   14107                 :          0 :         case RTE_FLOW_ACTION_TYPE_RSS:
   14108                 :            :         case RTE_FLOW_ACTION_TYPE_QUEUE:
   14109                 :          0 :                 mlx5_hrxq_release(dev,
   14110                 :          0 :                                   ((struct mlx5_hrxq *)(clone->action_ctx))->idx);
   14111                 :          0 :                 break;
   14112                 :          0 :         case RTE_FLOW_ACTION_TYPE_JUMP:
   14113                 :          0 :                 flow_hw_jump_release(dev, clone->action_ctx);
   14114                 :            :                 break;
   14115                 :            :         case RTE_FLOW_ACTION_TYPE_JUMP_TO_TABLE_INDEX:
   14116                 :            :         case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
   14117                 :            :         case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR:
   14118                 :            :         case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
   14119                 :            :         case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
   14120                 :            :         case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
   14121                 :            :         case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
   14122                 :            :         default:
   14123                 :            :                 break;
   14124                 :            :         }
   14125                 :          0 : }
   14126                 :            : 
   14127                 :            : void
   14128         [ #  # ]:          0 : mlx5_hw_mirror_destroy(struct rte_eth_dev *dev, struct mlx5_mirror *mirror)
   14129                 :            : {
   14130                 :            :         uint32_t i;
   14131                 :            : 
   14132                 :            :         mlx5_indirect_list_remove_entry(&mirror->indirect);
   14133         [ #  # ]:          0 :         for (i = 0; i < mirror->clones_num; i++)
   14134                 :          0 :                 mlx5_mirror_destroy_clone(dev, &mirror->clone[i]);
   14135         [ #  # ]:          0 :         if (mirror->mirror_action)
   14136                 :          0 :                 mlx5dr_action_destroy(mirror->mirror_action);
   14137                 :          0 :         mlx5_free(mirror);
   14138                 :          0 : }
   14139                 :            : 
   14140                 :            : static __rte_always_inline bool
   14141                 :            : mlx5_mirror_terminal_action(const struct rte_flow_action *action)
   14142                 :            : {
   14143                 :          0 :         switch (action->type) {
   14144                 :            :         case RTE_FLOW_ACTION_TYPE_JUMP:
   14145                 :            :         case RTE_FLOW_ACTION_TYPE_RSS:
   14146                 :            :         case RTE_FLOW_ACTION_TYPE_QUEUE:
   14147                 :            :         case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
   14148                 :            :         case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR:
   14149                 :            :         case RTE_FLOW_ACTION_TYPE_JUMP_TO_TABLE_INDEX:
   14150                 :            :                 return true;
   14151                 :            :         default:
   14152                 :            :                 break;
   14153                 :            :         }
   14154                 :            :         return false;
   14155                 :            : }
   14156                 :            : 
   14157                 :            : static bool
   14158                 :          0 : mlx5_mirror_validate_sample_action(struct rte_eth_dev *dev,
   14159                 :            :                                    const struct rte_flow_attr *flow_attr,
   14160                 :            :                                    const struct rte_flow_action *action)
   14161                 :            : {
   14162                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   14163                 :            :         const struct rte_flow_action_ethdev *port = NULL;
   14164   [ #  #  #  # ]:          0 :         bool is_proxy = MLX5_HW_PORT_IS_PROXY(priv);
   14165                 :            : 
   14166         [ #  # ]:          0 :         if (!action)
   14167                 :            :                 return false;
   14168   [ #  #  #  #  :          0 :         switch (action->type) {
                      # ]
   14169                 :          0 :         case RTE_FLOW_ACTION_TYPE_QUEUE:
   14170                 :            :         case RTE_FLOW_ACTION_TYPE_RSS:
   14171         [ #  # ]:          0 :                 if (flow_attr->transfer)
   14172                 :            :                         return false;
   14173                 :            :                 break;
   14174                 :          0 :         case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR:
   14175   [ #  #  #  # ]:          0 :                 if (!is_proxy || !flow_attr->transfer)
   14176                 :            :                         return false;
   14177                 :          0 :                 port = action->conf;
   14178   [ #  #  #  # ]:          0 :                 if (!port || port->port_id != MLX5_REPRESENTED_PORT_ESW_MGR)
   14179                 :            :                         return false;
   14180                 :            :                 break;
   14181                 :          0 :         case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
   14182                 :            :         case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
   14183                 :            :         case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
   14184                 :            :         case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
   14185                 :            :         case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
   14186   [ #  #  #  # ]:          0 :                 if (!is_proxy || !flow_attr->transfer)
   14187                 :            :                         return false;
   14188         [ #  # ]:          0 :                 if (action[0].type == RTE_FLOW_ACTION_TYPE_RAW_DECAP &&
   14189         [ #  # ]:          0 :                     action[1].type != RTE_FLOW_ACTION_TYPE_RAW_ENCAP)
   14190                 :            :                         return false;
   14191                 :            :                 break;
   14192                 :            :         case RTE_FLOW_ACTION_TYPE_JUMP_TO_TABLE_INDEX:
   14193                 :            :                 break;
   14194                 :            :         default:
   14195                 :            :                 return false;
   14196                 :            :         }
   14197                 :          0 :         return true;
   14198                 :            : }
   14199                 :            : 
   14200                 :            : /**
   14201                 :            :  * Valid mirror actions list includes one or two SAMPLE actions
   14202                 :            :  * followed by JUMP.
   14203                 :            :  *
   14204                 :            :  * @return
   14205                 :            :  * Number of mirrors *action* list was valid.
   14206                 :            :  * -EINVAL otherwise.
   14207                 :            :  */
   14208                 :            : static int
   14209                 :          0 : mlx5_hw_mirror_actions_list_validate(struct rte_eth_dev *dev,
   14210                 :            :                                      const struct rte_flow_attr *flow_attr,
   14211                 :            :                                      const struct rte_flow_action *actions)
   14212                 :            : {
   14213         [ #  # ]:          0 :         if (actions[0].type == RTE_FLOW_ACTION_TYPE_SAMPLE) {
   14214                 :            :                 int i = 1;
   14215                 :            :                 bool valid;
   14216                 :          0 :                 const struct rte_flow_action_sample *sample = actions[0].conf;
   14217                 :          0 :                 valid = mlx5_mirror_validate_sample_action(dev, flow_attr,
   14218                 :          0 :                                                            sample->actions);
   14219         [ #  # ]:          0 :                 if (!valid)
   14220                 :            :                         return -EINVAL;
   14221         [ #  # ]:          0 :                 if (actions[1].type == RTE_FLOW_ACTION_TYPE_SAMPLE) {
   14222                 :            :                         i = 2;
   14223                 :          0 :                         sample = actions[1].conf;
   14224                 :          0 :                         valid = mlx5_mirror_validate_sample_action(dev, flow_attr,
   14225                 :          0 :                                                                    sample->actions);
   14226         [ #  # ]:          0 :                         if (!valid)
   14227                 :            :                                 return -EINVAL;
   14228                 :            :                 }
   14229         [ #  # ]:          0 :                 return mlx5_mirror_terminal_action(actions + i) ? i + 1 : -EINVAL;
   14230                 :            :         }
   14231                 :            :         return -EINVAL;
   14232                 :            : }
   14233                 :            : 
   14234                 :            : static int
   14235         [ #  # ]:          0 : mirror_format_tir(struct rte_eth_dev *dev,
   14236                 :            :                   struct mlx5_mirror_clone *clone,
   14237                 :            :                   const struct mlx5_flow_template_table_cfg *table_cfg,
   14238                 :            :                   const struct rte_flow_action *action,
   14239                 :            :                   struct mlx5dr_action_dest_attr *dest_attr,
   14240                 :            :                   struct rte_flow_error *error)
   14241                 :            : {
   14242                 :            :         uint32_t hws_flags;
   14243                 :            :         enum mlx5dr_table_type table_type;
   14244                 :            :         struct mlx5_hrxq *tir_ctx;
   14245                 :            : 
   14246                 :            :         table_type = get_mlx5dr_table_type(&table_cfg->attr.flow_attr);
   14247                 :          0 :         hws_flags = mlx5_hw_act_flag[MLX5_HW_ACTION_FLAG_NONE_ROOT][table_type];
   14248                 :          0 :         tir_ctx = flow_hw_tir_action_register(dev, hws_flags, action);
   14249         [ #  # ]:          0 :         if (!tir_ctx)
   14250                 :          0 :                 return rte_flow_error_set(error, EINVAL,
   14251                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
   14252                 :            :                                           action, "failed to create QUEUE action for mirror clone");
   14253                 :          0 :         dest_attr->dest = tir_ctx->action;
   14254                 :          0 :         clone->action_ctx = tir_ctx;
   14255                 :          0 :         return 0;
   14256                 :            : }
   14257                 :            : 
   14258                 :            : static int
   14259                 :          0 : mirror_format_jump(struct rte_eth_dev *dev,
   14260                 :            :                    struct mlx5_mirror_clone *clone,
   14261                 :            :                    const struct mlx5_flow_template_table_cfg *table_cfg,
   14262                 :            :                    const struct rte_flow_action *action,
   14263                 :            :                    struct mlx5dr_action_dest_attr *dest_attr,
   14264                 :            :                    struct rte_flow_error *error)
   14265                 :            : {
   14266                 :          0 :         const struct rte_flow_action_jump *jump_conf = action->conf;
   14267                 :          0 :         struct mlx5_hw_jump_action *jump = flow_hw_jump_action_register
   14268                 :            :                                                 (dev, table_cfg,
   14269                 :          0 :                                                  jump_conf->group, error);
   14270                 :            : 
   14271         [ #  # ]:          0 :         if (!jump)
   14272                 :          0 :                 return rte_flow_error_set(error, EINVAL,
   14273                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
   14274                 :            :                                           action, "failed to create JUMP action for mirror clone");
   14275                 :          0 :         dest_attr->dest = jump->hws_action;
   14276                 :          0 :         clone->action_ctx = jump;
   14277                 :          0 :         return 0;
   14278                 :            : }
   14279                 :            : 
   14280                 :            : static int
   14281                 :            : mirror_format_port(struct rte_eth_dev *dev,
   14282                 :            :                    const struct rte_flow_action *action,
   14283                 :            :                    struct mlx5dr_action_dest_attr *dest_attr,
   14284                 :            :                    struct rte_flow_error __rte_unused *error)
   14285                 :            : {
   14286                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   14287                 :          0 :         const struct rte_flow_action_ethdev *port_action = action->conf;
   14288                 :            : 
   14289                 :          0 :         dest_attr->dest = priv->hw_vport[port_action->port_id];
   14290                 :            :         return 0;
   14291                 :            : }
   14292                 :            : 
   14293                 :            : static int
   14294                 :          0 : hw_mirror_clone_reformat(const struct rte_flow_action *actions,
   14295                 :            :                          struct mlx5dr_action_dest_attr *dest_attr,
   14296                 :            :                          enum mlx5dr_action_type *action_type,
   14297                 :            :                          uint8_t *reformat_buf, bool decap)
   14298                 :            : {
   14299                 :            :         int ret;
   14300                 :            :         const struct rte_flow_item *encap_item = NULL;
   14301                 :            :         const struct rte_flow_action_raw_encap *encap_conf = NULL;
   14302                 :            :         typeof(dest_attr->reformat) *reformat = &dest_attr->reformat;
   14303                 :            : 
   14304   [ #  #  #  # ]:          0 :         switch (actions[0].type) {
   14305                 :          0 :         case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
   14306                 :          0 :                 encap_conf = actions[0].conf;
   14307                 :          0 :                 break;
   14308                 :          0 :         case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
   14309                 :          0 :                 encap_item = MLX5_CONST_ENCAP_ITEM(rte_flow_action_vxlan_encap,
   14310                 :            :                                                    actions);
   14311                 :          0 :                 break;
   14312                 :          0 :         case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
   14313                 :          0 :                 encap_item = MLX5_CONST_ENCAP_ITEM(rte_flow_action_nvgre_encap,
   14314                 :            :                                                    actions);
   14315                 :          0 :                 break;
   14316                 :            :         default:
   14317                 :            :                 return -EINVAL;
   14318                 :            :         }
   14319                 :          0 :         *action_type = decap ?
   14320         [ #  # ]:          0 :                        MLX5DR_ACTION_TYP_REFORMAT_L2_TO_TNL_L3 :
   14321                 :            :                        MLX5DR_ACTION_TYP_REFORMAT_L2_TO_TNL_L2;
   14322         [ #  # ]:          0 :         if (encap_item) {
   14323                 :          0 :                 ret = flow_dv_convert_encap_data(encap_item, reformat_buf,
   14324                 :            :                                                  &reformat->reformat_data_sz, NULL);
   14325         [ #  # ]:          0 :                 if (ret)
   14326                 :            :                         return -EINVAL;
   14327                 :          0 :                 reformat->reformat_data = reformat_buf;
   14328                 :            :         } else {
   14329                 :          0 :                 reformat->reformat_data = (void *)(uintptr_t)encap_conf->data;
   14330                 :          0 :                 reformat->reformat_data_sz = encap_conf->size;
   14331                 :            :         }
   14332                 :            :         return 0;
   14333                 :            : }
   14334                 :            : 
   14335                 :            : static int
   14336                 :          0 : hw_mirror_format_clone(struct rte_eth_dev *dev,
   14337                 :            :                         struct mlx5_mirror_clone *clone,
   14338                 :            :                         const struct mlx5_flow_template_table_cfg *table_cfg,
   14339                 :            :                         const struct rte_flow_action *actions,
   14340                 :            :                         struct mlx5dr_action_dest_attr *dest_attr,
   14341                 :            :                         uint8_t *reformat_buf, struct rte_flow_error *error)
   14342                 :            : {
   14343                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   14344                 :            :         int ret;
   14345                 :            :         uint32_t i;
   14346                 :            :         bool decap_seen = false;
   14347                 :            : 
   14348         [ #  # ]:          0 :         for (i = 0; actions[i].type != RTE_FLOW_ACTION_TYPE_END; i++) {
   14349                 :          0 :                 dest_attr->action_type[i] = mlx5_hw_dr_action_types[actions[i].type];
   14350   [ #  #  #  #  :          0 :                 switch (actions[i].type) {
                #  #  # ]
   14351                 :          0 :                 case RTE_FLOW_ACTION_TYPE_QUEUE:
   14352                 :            :                 case RTE_FLOW_ACTION_TYPE_RSS:
   14353                 :          0 :                         ret = mirror_format_tir(dev, clone, table_cfg,
   14354                 :            :                                                 &actions[i], dest_attr, error);
   14355         [ #  # ]:          0 :                         if (ret)
   14356                 :          0 :                                 return ret;
   14357                 :            :                         break;
   14358                 :          0 :                 case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
   14359                 :            :                         ret = mirror_format_port(dev, &actions[i],
   14360                 :            :                                                  dest_attr, error);
   14361                 :            :                         if (ret)
   14362                 :            :                                 return ret;
   14363                 :            :                         break;
   14364                 :          0 :                 case RTE_FLOW_ACTION_TYPE_JUMP:
   14365                 :          0 :                         ret = mirror_format_jump(dev, clone, table_cfg,
   14366                 :            :                                                  &actions[i], dest_attr, error);
   14367         [ #  # ]:          0 :                         if (ret)
   14368                 :          0 :                                 return ret;
   14369                 :            :                         break;
   14370                 :          0 :                 case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR:
   14371                 :          0 :                         dest_attr->dest = priv->hw_def_miss;
   14372                 :          0 :                         break;
   14373                 :            :                 case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
   14374                 :            :                         decap_seen = true;
   14375                 :            :                         break;
   14376                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
   14377                 :            :                 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
   14378                 :            :                 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
   14379                 :          0 :                         ret = hw_mirror_clone_reformat(&actions[i], dest_attr,
   14380                 :            :                                                        &dest_attr->action_type[i],
   14381                 :            :                                                        reformat_buf, decap_seen);
   14382         [ #  # ]:          0 :                         if (ret < 0)
   14383                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
   14384                 :            :                                                           RTE_FLOW_ERROR_TYPE_ACTION,
   14385                 :            :                                                           &actions[i],
   14386                 :            :                                                           "failed to create reformat action");
   14387                 :            :                         break;
   14388                 :          0 :                 default:
   14389                 :          0 :                         return rte_flow_error_set(error, EINVAL,
   14390                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
   14391                 :            :                                                   &actions[i], "unsupported sample action");
   14392                 :            :                 }
   14393                 :          0 :                 clone->type = actions->type;
   14394                 :            :         }
   14395                 :          0 :         dest_attr->action_type[i] = MLX5DR_ACTION_TYP_LAST;
   14396                 :          0 :         return 0;
   14397                 :            : }
   14398                 :            : 
   14399                 :            : static struct rte_flow_action_list_handle *
   14400                 :          0 : mlx5_hw_mirror_handle_create(struct rte_eth_dev *dev,
   14401                 :            :                              const struct mlx5_flow_template_table_cfg *table_cfg,
   14402                 :            :                              const struct rte_flow_action *actions,
   14403                 :            :                              struct rte_flow_error *error)
   14404                 :            : {
   14405                 :            :         uint32_t hws_flags;
   14406                 :            :         int ret = 0, i, clones_num;
   14407                 :            :         struct mlx5_mirror *mirror;
   14408                 :            :         enum mlx5dr_table_type table_type;
   14409                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   14410         [ #  # ]:          0 :         const struct rte_flow_attr *flow_attr = &table_cfg->attr.flow_attr;
   14411                 :            :         uint8_t reformat_buf[MLX5_MIRROR_MAX_CLONES_NUM][MLX5_ENCAP_MAX_LEN];
   14412                 :            :         struct mlx5dr_action_dest_attr mirror_attr[MLX5_MIRROR_MAX_CLONES_NUM + 1];
   14413                 :            :         enum mlx5dr_action_type array_action_types[MLX5_MIRROR_MAX_CLONES_NUM + 1]
   14414                 :            :                                                   [MLX5_MIRROR_MAX_SAMPLE_ACTIONS_LEN + 1];
   14415                 :            : 
   14416                 :            :         memset(mirror_attr, 0, sizeof(mirror_attr));
   14417                 :            :         memset(array_action_types, 0, sizeof(array_action_types));
   14418                 :            :         table_type = get_mlx5dr_table_type(flow_attr);
   14419                 :          0 :         hws_flags = mlx5_hw_act_flag[MLX5_HW_ACTION_FLAG_NONE_ROOT][table_type];
   14420                 :          0 :         clones_num = mlx5_hw_mirror_actions_list_validate(dev, flow_attr,
   14421                 :            :                                                           actions);
   14422         [ #  # ]:          0 :         if (clones_num < 0) {
   14423                 :          0 :                 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
   14424                 :            :                                    actions, "Invalid mirror list format");
   14425                 :          0 :                 return NULL;
   14426                 :            :         }
   14427                 :          0 :         mirror = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*mirror),
   14428                 :            :                              0, SOCKET_ID_ANY);
   14429         [ #  # ]:          0 :         if (!mirror) {
   14430                 :          0 :                 rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_ACTION,
   14431                 :            :                                    actions, "Failed to allocate mirror context");
   14432                 :          0 :                 return NULL;
   14433                 :            :         }
   14434                 :            : 
   14435                 :          0 :         mirror->indirect.type = MLX5_INDIRECT_ACTION_LIST_TYPE_MIRROR;
   14436                 :          0 :         mirror->clones_num = clones_num;
   14437         [ #  # ]:          0 :         for (i = 0; i < clones_num; i++) {
   14438                 :            :                 const struct rte_flow_action *clone_actions;
   14439                 :            : 
   14440                 :          0 :                 mirror_attr[i].action_type = array_action_types[i];
   14441         [ #  # ]:          0 :                 if (actions[i].type == RTE_FLOW_ACTION_TYPE_SAMPLE) {
   14442                 :          0 :                         const struct rte_flow_action_sample *sample = actions[i].conf;
   14443                 :            : 
   14444                 :          0 :                         clone_actions = sample->actions;
   14445                 :            :                 } else {
   14446                 :            :                         clone_actions = &actions[i];
   14447                 :            :                 }
   14448                 :          0 :                 ret = hw_mirror_format_clone(dev, &mirror->clone[i], table_cfg,
   14449                 :            :                                              clone_actions, &mirror_attr[i],
   14450                 :          0 :                                              reformat_buf[i], error);
   14451                 :            : 
   14452         [ #  # ]:          0 :                 if (ret)
   14453                 :          0 :                         goto error;
   14454                 :            :         }
   14455                 :          0 :         hws_flags |= MLX5DR_ACTION_FLAG_SHARED;
   14456                 :          0 :         mirror->mirror_action = mlx5dr_action_create_dest_array(priv->dr_ctx,
   14457                 :            :                                                                 clones_num,
   14458                 :            :                                                                 mirror_attr,
   14459                 :            :                                                                 hws_flags);
   14460         [ #  # ]:          0 :         if (!mirror->mirror_action) {
   14461                 :          0 :                 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
   14462                 :            :                                    actions, "Failed to create HWS mirror action");
   14463                 :          0 :                 goto error;
   14464                 :            :         }
   14465                 :            : 
   14466         [ #  # ]:          0 :         mlx5_indirect_list_add_entry(&priv->indirect_list_head, &mirror->indirect);
   14467                 :          0 :         return (struct rte_flow_action_list_handle *)mirror;
   14468                 :            : 
   14469                 :          0 : error:
   14470                 :          0 :         mlx5_hw_mirror_destroy(dev, mirror);
   14471                 :          0 :         return NULL;
   14472                 :            : }
   14473                 :            : 
   14474                 :            : void
   14475                 :          0 : mlx5_destroy_legacy_indirect(__rte_unused struct rte_eth_dev *dev,
   14476                 :            :                              struct mlx5_indirect_list *ptr)
   14477                 :            : {
   14478                 :            :         struct mlx5_indlst_legacy *obj = (typeof(obj))ptr;
   14479                 :            : 
   14480                 :            :         switch (obj->legacy_type) {
   14481                 :            :         case RTE_FLOW_ACTION_TYPE_METER_MARK:
   14482                 :            :                 break; /* ASO meters were released in mlx5_flow_meter_flush() */
   14483                 :            :         default:
   14484                 :            :                 break;
   14485                 :            :         }
   14486                 :          0 :         mlx5_free(obj);
   14487                 :          0 : }
   14488                 :            : 
   14489                 :            : static struct rte_flow_action_list_handle *
   14490                 :          0 : mlx5_create_legacy_indlst(struct rte_eth_dev *dev, uint32_t queue,
   14491                 :            :                           const struct rte_flow_op_attr *attr,
   14492                 :            :                           const struct rte_flow_indir_action_conf *conf,
   14493                 :            :                           const struct rte_flow_action *actions,
   14494                 :            :                           void *user_data, struct rte_flow_error *error)
   14495                 :            : {
   14496                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   14497                 :          0 :         struct mlx5_indlst_legacy *indlst_obj = mlx5_malloc(MLX5_MEM_ZERO,
   14498                 :            :                                                             sizeof(*indlst_obj),
   14499                 :            :                                                             0, SOCKET_ID_ANY);
   14500                 :            : 
   14501         [ #  # ]:          0 :         if (!indlst_obj)
   14502                 :            :                 return NULL;
   14503                 :          0 :         indlst_obj->handle = flow_hw_action_handle_create(dev, queue, attr, conf,
   14504                 :            :                                                           actions, user_data,
   14505                 :            :                                                           error);
   14506         [ #  # ]:          0 :         if (!indlst_obj->handle) {
   14507                 :          0 :                 mlx5_free(indlst_obj);
   14508                 :          0 :                 return NULL;
   14509                 :            :         }
   14510                 :          0 :         indlst_obj->legacy_type = actions[0].type;
   14511                 :          0 :         indlst_obj->indirect.type = MLX5_INDIRECT_ACTION_LIST_TYPE_LEGACY;
   14512         [ #  # ]:          0 :         mlx5_indirect_list_add_entry(&priv->indirect_list_head, &indlst_obj->indirect);
   14513                 :          0 :         return (struct rte_flow_action_list_handle *)indlst_obj;
   14514                 :            : }
   14515                 :            : 
   14516                 :            : static __rte_always_inline enum mlx5_indirect_list_type
   14517                 :            : flow_hw_inlist_type_get(const struct rte_flow_action *actions)
   14518                 :            : {
   14519   [ #  #  #  # ]:          0 :         switch (actions[0].type) {
   14520                 :            :         case RTE_FLOW_ACTION_TYPE_SAMPLE:
   14521                 :            :                 return MLX5_INDIRECT_ACTION_LIST_TYPE_MIRROR;
   14522                 :          0 :         case RTE_FLOW_ACTION_TYPE_METER_MARK:
   14523                 :          0 :                 return actions[1].type == RTE_FLOW_ACTION_TYPE_END ?
   14524                 :          0 :                        MLX5_INDIRECT_ACTION_LIST_TYPE_LEGACY :
   14525                 :            :                        MLX5_INDIRECT_ACTION_LIST_TYPE_ERR;
   14526                 :            :         case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
   14527                 :            :         case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
   14528                 :            :                 return MLX5_INDIRECT_ACTION_LIST_TYPE_REFORMAT;
   14529                 :            :         default:
   14530                 :            :                 break;
   14531                 :            :         }
   14532                 :            :         return MLX5_INDIRECT_ACTION_LIST_TYPE_ERR;
   14533                 :            : }
   14534                 :            : 
   14535                 :            : static struct rte_flow_action_list_handle*
   14536                 :          0 : mlx5_hw_decap_encap_handle_create(struct rte_eth_dev *dev,
   14537                 :            :                                   const struct mlx5_flow_template_table_cfg *table_cfg,
   14538                 :            :                                   const struct rte_flow_action *actions,
   14539                 :            :                                   struct rte_flow_error *error)
   14540                 :            : {
   14541                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   14542                 :            :         const struct rte_flow_attr *flow_attr = &table_cfg->attr.flow_attr;
   14543                 :            :         const struct rte_flow_action *encap = NULL;
   14544                 :            :         const struct rte_flow_action *decap = NULL;
   14545                 :          0 :         struct rte_flow_indir_action_conf indirect_conf = {
   14546                 :          0 :                 .ingress = flow_attr->ingress,
   14547                 :          0 :                 .egress = flow_attr->egress,
   14548                 :          0 :                 .transfer = flow_attr->transfer,
   14549                 :            :         };
   14550                 :            :         struct mlx5_hw_encap_decap_action *handle;
   14551                 :            :         uint64_t action_flags = 0;
   14552                 :            : 
   14553                 :            :         /*
   14554                 :            :          * Allow
   14555                 :            :          * 1. raw_decap / raw_encap / end
   14556                 :            :          * 2. raw_encap / end
   14557                 :            :          * 3. raw_decap / end
   14558                 :            :          */
   14559         [ #  # ]:          0 :         while (actions->type != RTE_FLOW_ACTION_TYPE_END) {
   14560         [ #  # ]:          0 :                 if (actions->type == RTE_FLOW_ACTION_TYPE_RAW_DECAP) {
   14561         [ #  # ]:          0 :                         if (action_flags) {
   14562                 :          0 :                                 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
   14563                 :            :                                                    actions, "Invalid indirect action list sequence");
   14564                 :          0 :                                 return NULL;
   14565                 :            :                         }
   14566                 :            :                         action_flags |= MLX5_FLOW_ACTION_DECAP;
   14567                 :            :                         decap = actions;
   14568         [ #  # ]:          0 :                 } else if (actions->type == RTE_FLOW_ACTION_TYPE_RAW_ENCAP) {
   14569         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_ENCAP) {
   14570                 :          0 :                                 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
   14571                 :            :                                                    actions, "Invalid indirect action list sequence");
   14572                 :          0 :                                 return NULL;
   14573                 :            :                         }
   14574                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_ENCAP;
   14575                 :            :                         encap = actions;
   14576                 :            :                 } else {
   14577                 :          0 :                         rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
   14578                 :            :                                            actions, "Invalid indirect action type in list");
   14579                 :          0 :                         return NULL;
   14580                 :            :                 }
   14581                 :          0 :                 actions++;
   14582                 :            :         }
   14583         [ #  # ]:          0 :         if (!decap && !encap) {
   14584                 :          0 :                 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
   14585                 :            :                                    actions, "Invalid indirect action combinations");
   14586                 :          0 :                 return NULL;
   14587                 :            :         }
   14588                 :          0 :         handle = mlx5_reformat_action_create(dev, &indirect_conf, encap, decap, error);
   14589         [ #  # ]:          0 :         if (!handle) {
   14590                 :          0 :                 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
   14591                 :            :                                    actions, "Failed to create HWS decap_encap action");
   14592                 :          0 :                 return NULL;
   14593                 :            :         }
   14594                 :          0 :         handle->indirect.type = MLX5_INDIRECT_ACTION_LIST_TYPE_REFORMAT;
   14595         [ #  # ]:          0 :         LIST_INSERT_HEAD(&priv->indirect_list_head, &handle->indirect, entry);
   14596                 :          0 :         return (struct rte_flow_action_list_handle *)handle;
   14597                 :            : }
   14598                 :            : 
   14599                 :            : static struct rte_flow_action_list_handle *
   14600         [ #  # ]:          0 : flow_hw_async_action_list_handle_create(struct rte_eth_dev *dev, uint32_t queue,
   14601                 :            :                                         const struct rte_flow_op_attr *attr,
   14602                 :            :                                         const struct rte_flow_indir_action_conf *conf,
   14603                 :            :                                         const struct rte_flow_action *actions,
   14604                 :            :                                         void *user_data,
   14605                 :            :                                         struct rte_flow_error *error)
   14606                 :            : {
   14607                 :            :         struct mlx5_hw_q_job *job = NULL;
   14608                 :            :         bool push = flow_hw_action_push(attr);
   14609                 :            :         enum mlx5_indirect_list_type list_type;
   14610                 :            :         struct rte_flow_action_list_handle *handle;
   14611                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   14612                 :          0 :         const struct mlx5_flow_template_table_cfg table_cfg = {
   14613                 :            :                 .external = true,
   14614                 :            :                 .attr = {
   14615                 :            :                         .flow_attr = {
   14616                 :          0 :                                 .ingress = conf->ingress,
   14617                 :          0 :                                 .egress = conf->egress,
   14618                 :          0 :                                 .transfer = conf->transfer
   14619                 :            :                         }
   14620                 :            :                 }
   14621                 :            :         };
   14622                 :            : 
   14623         [ #  # ]:          0 :         if (!mlx5_hw_ctx_validate(dev, error))
   14624                 :            :                 return NULL;
   14625         [ #  # ]:          0 :         if (!actions) {
   14626                 :          0 :                 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
   14627                 :            :                                    NULL, "No action list");
   14628                 :          0 :                 return NULL;
   14629                 :            :         }
   14630                 :            :         list_type = flow_hw_inlist_type_get(actions);
   14631         [ #  # ]:          0 :         if (list_type == MLX5_INDIRECT_ACTION_LIST_TYPE_LEGACY) {
   14632                 :            :                 /*
   14633                 :            :                  * Legacy indirect actions already have
   14634                 :            :                  * async resources management. No need to do it twice.
   14635                 :            :                  */
   14636                 :          0 :                 handle = mlx5_create_legacy_indlst(dev, queue, attr, conf,
   14637                 :            :                                                    actions, user_data, error);
   14638                 :          0 :                 goto end;
   14639                 :            :         }
   14640         [ #  # ]:          0 :         if (attr) {
   14641                 :            :                 job = flow_hw_action_job_init(priv, queue, NULL, user_data,
   14642                 :            :                                               NULL, MLX5_HW_Q_JOB_TYPE_CREATE,
   14643                 :            :                                               MLX5_HW_INDIRECT_TYPE_LIST, error);
   14644                 :            :                 if (!job)
   14645                 :          0 :                         return NULL;
   14646                 :            :         }
   14647      [ #  #  # ]:          0 :         switch (list_type) {
   14648                 :          0 :         case MLX5_INDIRECT_ACTION_LIST_TYPE_MIRROR:
   14649                 :          0 :                 handle = mlx5_hw_mirror_handle_create(dev, &table_cfg,
   14650                 :            :                                                       actions, error);
   14651                 :          0 :                 break;
   14652                 :          0 :         case MLX5_INDIRECT_ACTION_LIST_TYPE_REFORMAT:
   14653                 :          0 :                 handle = mlx5_hw_decap_encap_handle_create(dev, &table_cfg,
   14654                 :            :                                                            actions, error);
   14655                 :          0 :                 break;
   14656                 :          0 :         default:
   14657                 :            :                 handle = NULL;
   14658                 :          0 :                 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
   14659                 :            :                                    actions, "Invalid list");
   14660                 :            :         }
   14661         [ #  # ]:          0 :         if (job) {
   14662                 :          0 :                 job->action = handle;
   14663         [ #  # ]:          0 :                 flow_hw_action_finalize(dev, queue, job, push, false,
   14664                 :            :                                         handle != NULL);
   14665                 :            :         }
   14666                 :          0 : end:
   14667                 :            :         return handle;
   14668                 :            : }
   14669                 :            : 
   14670                 :            : static struct rte_flow_action_list_handle *
   14671                 :          0 : flow_hw_action_list_handle_create(struct rte_eth_dev *dev,
   14672                 :            :                                   const struct rte_flow_indir_action_conf *conf,
   14673                 :            :                                   const struct rte_flow_action *actions,
   14674                 :            :                                   struct rte_flow_error *error)
   14675                 :            : {
   14676                 :          0 :         return flow_hw_async_action_list_handle_create(dev, MLX5_HW_INV_QUEUE,
   14677                 :            :                                                        NULL, conf, actions,
   14678                 :            :                                                        NULL, error);
   14679                 :            : }
   14680                 :            : 
   14681                 :            : static int
   14682         [ #  # ]:          0 : flow_hw_async_action_list_handle_destroy
   14683                 :            :                         (struct rte_eth_dev *dev, uint32_t queue,
   14684                 :            :                          const struct rte_flow_op_attr *attr,
   14685                 :            :                          struct rte_flow_action_list_handle *handle,
   14686                 :            :                          void *user_data, struct rte_flow_error *error)
   14687                 :            : {
   14688                 :            :         int ret = 0;
   14689                 :            :         struct mlx5_hw_q_job *job = NULL;
   14690                 :            :         bool push = flow_hw_action_push(attr);
   14691         [ #  # ]:          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   14692                 :            :         enum mlx5_indirect_list_type type =
   14693                 :            :                 mlx5_get_indirect_list_type((void *)handle);
   14694                 :            : 
   14695         [ #  # ]:          0 :         if (type == MLX5_INDIRECT_ACTION_LIST_TYPE_LEGACY) {
   14696                 :            :                 struct mlx5_indlst_legacy *legacy = (typeof(legacy))handle;
   14697                 :            : 
   14698                 :          0 :                 ret = flow_hw_action_handle_destroy(dev, queue, attr,
   14699                 :            :                                                     legacy->handle,
   14700                 :            :                                                     user_data, error);
   14701                 :            :                 mlx5_indirect_list_remove_entry(&legacy->indirect);
   14702                 :          0 :                 goto end;
   14703                 :            :         }
   14704         [ #  # ]:          0 :         if (attr) {
   14705                 :            :                 job = flow_hw_action_job_init(priv, queue, NULL, user_data,
   14706                 :            :                                               NULL, MLX5_HW_Q_JOB_TYPE_DESTROY,
   14707                 :            :                                               MLX5_HW_INDIRECT_TYPE_LIST, error);
   14708                 :            :                 if (!job)
   14709                 :          0 :                         return rte_errno;
   14710                 :            :         }
   14711      [ #  #  # ]:          0 :         switch (type) {
   14712                 :          0 :         case MLX5_INDIRECT_ACTION_LIST_TYPE_MIRROR:
   14713                 :          0 :                 mlx5_hw_mirror_destroy(dev, (struct mlx5_mirror *)handle);
   14714                 :          0 :                 break;
   14715                 :          0 :         case MLX5_INDIRECT_ACTION_LIST_TYPE_REFORMAT:
   14716         [ #  # ]:          0 :                 LIST_REMOVE(&((struct mlx5_hw_encap_decap_action *)handle)->indirect,
   14717                 :            :                             entry);
   14718                 :          0 :                 mlx5_reformat_action_destroy(dev, handle, error);
   14719                 :          0 :                 break;
   14720                 :          0 :         default:
   14721                 :          0 :                 ret = rte_flow_error_set(error, EINVAL,
   14722                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
   14723                 :            :                                           NULL, "Invalid indirect list handle");
   14724                 :            :         }
   14725         [ #  # ]:          0 :         if (job) {
   14726                 :            :                 flow_hw_action_finalize(dev, queue, job, push, false, true);
   14727                 :            :         }
   14728                 :          0 : end:
   14729                 :            :         return ret;
   14730                 :            : }
   14731                 :            : 
   14732                 :            : static int
   14733                 :          0 : flow_hw_action_list_handle_destroy(struct rte_eth_dev *dev,
   14734                 :            :                                    struct rte_flow_action_list_handle *handle,
   14735                 :            :                                    struct rte_flow_error *error)
   14736                 :            : {
   14737                 :          0 :         return flow_hw_async_action_list_handle_destroy(dev, MLX5_HW_INV_QUEUE,
   14738                 :            :                                                         NULL, handle, NULL,
   14739                 :            :                                                         error);
   14740                 :            : }
   14741                 :            : 
   14742                 :            : static int
   14743         [ #  # ]:          0 : flow_hw_async_action_list_handle_query_update
   14744                 :            :                 (struct rte_eth_dev *dev, uint32_t queue_id,
   14745                 :            :                  const struct rte_flow_op_attr *attr,
   14746                 :            :                  const struct rte_flow_action_list_handle *handle,
   14747                 :            :                  const void **update, void **query,
   14748                 :            :                  enum rte_flow_query_update_mode mode,
   14749                 :            :                  void *user_data, struct rte_flow_error *error)
   14750                 :            : {
   14751                 :            :         enum mlx5_indirect_list_type type =
   14752                 :            :                 mlx5_get_indirect_list_type((const void *)handle);
   14753                 :            : 
   14754         [ #  # ]:          0 :         if (type == MLX5_INDIRECT_ACTION_LIST_TYPE_LEGACY) {
   14755                 :            :                 struct mlx5_indlst_legacy *legacy = (void *)(uintptr_t)handle;
   14756                 :            : 
   14757         [ #  # ]:          0 :                 if (update && query)
   14758                 :          0 :                         return flow_hw_async_action_handle_query_update
   14759                 :            :                                 (dev, queue_id, attr, legacy->handle,
   14760                 :            :                                  update, query, mode, user_data, error);
   14761   [ #  #  #  # ]:          0 :                 else if (update && update[0])
   14762                 :          0 :                         return flow_hw_action_handle_update(dev, queue_id, attr,
   14763                 :            :                                                             legacy->handle, update[0],
   14764                 :            :                                                             user_data, error);
   14765   [ #  #  #  # ]:          0 :                 else if (query && query[0])
   14766                 :          0 :                         return flow_hw_action_handle_query(dev, queue_id, attr,
   14767                 :          0 :                                                            legacy->handle, query[0],
   14768                 :            :                                                            user_data, error);
   14769                 :            :                 else
   14770                 :          0 :                         return rte_flow_error_set(error, EINVAL,
   14771                 :            :                                                   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   14772                 :            :                                                   NULL, "invalid legacy handle query_update parameters");
   14773                 :            :         }
   14774                 :            :         return -ENOTSUP;
   14775                 :            : }
   14776                 :            : 
   14777                 :            : static int
   14778                 :          0 : flow_hw_action_list_handle_query_update(struct rte_eth_dev *dev,
   14779                 :            :                                         const struct rte_flow_action_list_handle *handle,
   14780                 :            :                                         const void **update, void **query,
   14781                 :            :                                         enum rte_flow_query_update_mode mode,
   14782                 :            :                                         struct rte_flow_error *error)
   14783                 :            : {
   14784                 :          0 :         return flow_hw_async_action_list_handle_query_update
   14785                 :            :                                         (dev, MLX5_HW_INV_QUEUE, NULL, handle,
   14786                 :            :                                          update, query, mode, NULL, error);
   14787                 :            : }
   14788                 :            : 
   14789                 :            : static int
   14790                 :          0 : flow_hw_calc_table_hash(struct rte_eth_dev *dev,
   14791                 :            :                          const struct rte_flow_template_table *table,
   14792                 :            :                          const struct rte_flow_item pattern[],
   14793                 :            :                          uint8_t pattern_template_index,
   14794                 :            :                          uint32_t *hash, struct rte_flow_error *error)
   14795                 :            : {
   14796                 :            :         const struct rte_flow_item *items;
   14797                 :            :         struct mlx5_flow_hw_pattern_params pp;
   14798                 :            :         int res;
   14799                 :            : 
   14800                 :          0 :         items = flow_hw_get_rule_items(dev, table, pattern,
   14801                 :            :                                        pattern_template_index,
   14802                 :            :                                        &pp);
   14803                 :          0 :         res = mlx5dr_rule_hash_calculate(mlx5_table_matcher(table), items,
   14804                 :            :                                          pattern_template_index,
   14805                 :            :                                          MLX5DR_RULE_HASH_CALC_MODE_RAW,
   14806                 :            :                                          hash);
   14807         [ #  # ]:          0 :         if (res)
   14808                 :          0 :                 return rte_flow_error_set(error, res,
   14809                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   14810                 :            :                                           NULL,
   14811                 :            :                                           "hash could not be calculated");
   14812                 :            :         return 0;
   14813                 :            : }
   14814                 :            : 
   14815                 :            : static int
   14816                 :          0 : flow_hw_calc_encap_hash(struct rte_eth_dev *dev,
   14817                 :            :                         const struct rte_flow_item pattern[],
   14818                 :            :                         enum rte_flow_encap_hash_field dest_field,
   14819                 :            :                         uint8_t *hash,
   14820                 :            :                         struct rte_flow_error *error)
   14821                 :            : {
   14822                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   14823                 :            :         struct mlx5dr_crc_encap_entropy_hash_fields data;
   14824                 :          0 :         enum mlx5dr_crc_encap_entropy_hash_size res_size =
   14825                 :            :                         dest_field == RTE_FLOW_ENCAP_HASH_FIELD_SRC_PORT ?
   14826                 :          0 :                                 MLX5DR_CRC_ENCAP_ENTROPY_HASH_SIZE_16 :
   14827                 :            :                                 MLX5DR_CRC_ENCAP_ENTROPY_HASH_SIZE_8;
   14828                 :            :         int res;
   14829                 :            : 
   14830                 :            :         memset(&data, 0, sizeof(struct mlx5dr_crc_encap_entropy_hash_fields));
   14831                 :            : 
   14832         [ #  # ]:          0 :         for (; pattern->type != RTE_FLOW_ITEM_TYPE_END; pattern++) {
   14833   [ #  #  #  #  :          0 :                 switch (pattern->type) {
                #  #  # ]
   14834                 :          0 :                 case RTE_FLOW_ITEM_TYPE_IPV4:
   14835                 :          0 :                         data.dst.ipv4_addr =
   14836                 :          0 :                                 ((const struct rte_flow_item_ipv4 *)(pattern->spec))->hdr.dst_addr;
   14837                 :          0 :                         data.src.ipv4_addr =
   14838                 :          0 :                                 ((const struct rte_flow_item_ipv4 *)(pattern->spec))->hdr.src_addr;
   14839                 :          0 :                         break;
   14840                 :          0 :                 case RTE_FLOW_ITEM_TYPE_IPV6:
   14841                 :            :                         memcpy(data.dst.ipv6_addr,
   14842                 :          0 :                                &((const struct rte_flow_item_ipv6 *)(pattern->spec))->hdr.dst_addr,
   14843                 :            :                                sizeof(data.dst.ipv6_addr));
   14844                 :            :                         memcpy(data.src.ipv6_addr,
   14845                 :            :                                &((const struct rte_flow_item_ipv6 *)(pattern->spec))->hdr.src_addr,
   14846                 :            :                                sizeof(data.src.ipv6_addr));
   14847                 :            :                         break;
   14848                 :          0 :                 case RTE_FLOW_ITEM_TYPE_UDP:
   14849                 :          0 :                         data.next_protocol = IPPROTO_UDP;
   14850                 :          0 :                         data.dst_port =
   14851                 :          0 :                                 ((const struct rte_flow_item_udp *)(pattern->spec))->hdr.dst_port;
   14852                 :          0 :                         data.src_port =
   14853                 :          0 :                                 ((const struct rte_flow_item_udp *)(pattern->spec))->hdr.src_port;
   14854                 :          0 :                         break;
   14855                 :          0 :                 case RTE_FLOW_ITEM_TYPE_TCP:
   14856                 :          0 :                         data.next_protocol = IPPROTO_TCP;
   14857                 :          0 :                         data.dst_port =
   14858                 :          0 :                                 ((const struct rte_flow_item_tcp *)(pattern->spec))->hdr.dst_port;
   14859                 :          0 :                         data.src_port =
   14860                 :          0 :                                 ((const struct rte_flow_item_tcp *)(pattern->spec))->hdr.src_port;
   14861                 :          0 :                         break;
   14862                 :          0 :                 case RTE_FLOW_ITEM_TYPE_ICMP:
   14863                 :          0 :                         data.next_protocol = IPPROTO_ICMP;
   14864                 :          0 :                         break;
   14865                 :          0 :                 case RTE_FLOW_ITEM_TYPE_ICMP6:
   14866                 :          0 :                         data.next_protocol = IPPROTO_ICMPV6;
   14867                 :          0 :                         break;
   14868                 :            :                 default:
   14869                 :            :                         break;
   14870                 :            :                 }
   14871                 :            :         }
   14872                 :          0 :         res = mlx5dr_crc_encap_entropy_hash_calc(priv->dr_ctx, &data, hash, res_size);
   14873         [ #  # ]:          0 :         if (res)
   14874                 :          0 :                 return rte_flow_error_set(error, res,
   14875                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   14876                 :            :                                           NULL, "error while calculating encap hash");
   14877                 :            :         return 0;
   14878                 :            : }
   14879                 :            : 
   14880                 :            : static int
   14881                 :          0 : flow_hw_table_resize_multi_pattern_actions(struct rte_eth_dev *dev,
   14882                 :            :                                            struct rte_flow_template_table *table,
   14883                 :            :                                            uint32_t nb_flows,
   14884                 :            :                                            struct rte_flow_error *error)
   14885                 :            : {
   14886                 :          0 :         struct mlx5_multi_pattern_segment *segment = table->mpctx.segments;
   14887                 :            :         uint32_t bulk_size;
   14888                 :            :         int i, ret;
   14889                 :            : 
   14890                 :            :         /**
   14891                 :            :          * Segment always allocates Modify Header Argument Objects number in
   14892                 :            :          * powers of 2.
   14893                 :            :          * On resize, PMD adds minimal required argument objects number.
   14894                 :            :          * For example, if table size was 10, it allocated 16 argument objects.
   14895                 :            :          * Resize to 15 will not add new objects.
   14896                 :            :          */
   14897                 :          0 :         for (i = 1;
   14898   [ #  #  #  # ]:          0 :              i < MLX5_MAX_TABLE_RESIZE_NUM && segment->capacity;
   14899                 :          0 :              i++, segment++) {
   14900                 :            :                 /* keep the devtools/checkpatches.sh happy */
   14901                 :            :         }
   14902         [ #  # ]:          0 :         if (i == MLX5_MAX_TABLE_RESIZE_NUM)
   14903                 :          0 :                 return rte_flow_error_set(error, EINVAL,
   14904                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   14905                 :            :                                           table, "too many resizes");
   14906         [ #  # ]:          0 :         if (segment->head_index - 1 >= nb_flows)
   14907                 :            :                 return 0;
   14908         [ #  # ]:          0 :         bulk_size = rte_align32pow2(nb_flows - segment->head_index + 1);
   14909                 :          0 :         ret = mlx5_tbl_multi_pattern_process(dev, table, segment,
   14910                 :            :                                              rte_log2_u32(bulk_size),
   14911                 :            :                                              error);
   14912         [ #  # ]:          0 :         if (ret)
   14913                 :          0 :                 return rte_flow_error_set(error, EINVAL,
   14914                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   14915                 :            :                                           table, "too many resizes");
   14916                 :            :         return i;
   14917                 :            : }
   14918                 :            : 
   14919                 :            : static int
   14920                 :          0 : flow_hw_table_resize(struct rte_eth_dev *dev,
   14921                 :            :                      struct rte_flow_template_table *table,
   14922                 :            :                      uint32_t nb_flows,
   14923                 :            :                      struct rte_flow_error *error)
   14924                 :            : {
   14925                 :            :         struct mlx5dr_action_template *at[MLX5_HW_TBL_MAX_ACTION_TEMPLATE];
   14926                 :            :         struct mlx5dr_match_template *mt[MLX5_HW_TBL_MAX_ITEM_TEMPLATE];
   14927                 :          0 :         struct mlx5dr_matcher_attr matcher_attr = table->matcher_attr;
   14928                 :          0 :         struct mlx5dr_action_jump_to_matcher_attr jump_attr = {
   14929                 :            :                 .type = MLX5DR_ACTION_JUMP_TO_MATCHER_BY_INDEX,
   14930                 :            :                 .matcher = NULL,
   14931                 :            :         };
   14932                 :            :         struct mlx5_multi_pattern_segment *segment = NULL;
   14933                 :            :         struct mlx5dr_matcher *matcher = NULL;
   14934                 :            :         struct mlx5dr_action *jump = NULL;
   14935                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   14936                 :          0 :         uint32_t i, selector = table->matcher_selector;
   14937                 :          0 :         uint32_t other_selector = (selector + 1) & 1;
   14938                 :            :         int ret;
   14939                 :            : 
   14940         [ #  # ]:          0 :         if (!rte_flow_template_table_resizable(dev->data->port_id, &table->cfg.attr))
   14941                 :          0 :                 return rte_flow_error_set(error, EINVAL,
   14942                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   14943                 :            :                                           table, "no resizable attribute");
   14944         [ #  # ]:          0 :         if (table->matcher_info[other_selector].matcher)
   14945                 :          0 :                 return rte_flow_error_set(error, EINVAL,
   14946                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   14947                 :            :                                           table, "last table resize was not completed");
   14948         [ #  # ]:          0 :         if (nb_flows <= table->cfg.attr.nb_flows)
   14949                 :          0 :                 return rte_flow_error_set(error, EINVAL,
   14950                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   14951                 :            :                                           table, "shrinking table is not supported");
   14952                 :          0 :         ret = mlx5_ipool_resize(table->flow, nb_flows, error);
   14953         [ #  # ]:          0 :         if (ret)
   14954                 :            :                 return ret;
   14955                 :            :         /*
   14956                 :            :          * A resizable matcher doesn't support rule update. In this case, the ipool
   14957                 :            :          * for the resource is not created and there is no need to resize it.
   14958                 :            :          */
   14959                 :            :         MLX5_ASSERT(!table->resource);
   14960         [ #  # ]:          0 :         if (mlx5_is_multi_pattern_active(&table->mpctx)) {
   14961                 :          0 :                 ret = flow_hw_table_resize_multi_pattern_actions(dev, table, nb_flows, error);
   14962         [ #  # ]:          0 :                 if (ret < 0)
   14963                 :            :                         return ret;
   14964         [ #  # ]:          0 :                 if (ret > 0)
   14965                 :          0 :                         segment = table->mpctx.segments + ret;
   14966                 :            :         }
   14967         [ #  # ]:          0 :         for (i = 0; i < table->nb_item_templates; i++)
   14968                 :          0 :                 mt[i] = table->its[i]->mt;
   14969         [ #  # ]:          0 :         for (i = 0; i < table->nb_action_templates; i++)
   14970                 :          0 :                 at[i] = table->ats[i].action_template->tmpl;
   14971                 :            :         nb_flows = rte_align32pow2(nb_flows);
   14972                 :          0 :         matcher_attr.rule.num_log = rte_log2_u32(nb_flows);
   14973                 :          0 :         matcher = mlx5dr_matcher_create(table->grp->tbl, mt,
   14974                 :            :                                         table->nb_item_templates, at,
   14975                 :            :                                         table->nb_action_templates,
   14976                 :            :                                         &matcher_attr);
   14977         [ #  # ]:          0 :         if (!matcher) {
   14978                 :          0 :                 ret = rte_flow_error_set(error, rte_errno,
   14979                 :            :                                          RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   14980                 :            :                                          table, "failed to create new matcher");
   14981                 :          0 :                 goto error;
   14982                 :            :         }
   14983         [ #  # ]:          0 :         if (matcher_attr.isolated) {
   14984                 :          0 :                 jump_attr.matcher = matcher;
   14985                 :          0 :                 jump = mlx5dr_action_create_jump_to_matcher(priv->dr_ctx, &jump_attr,
   14986                 :          0 :                         mlx5_hw_act_flag[!!table->cfg.attr.flow_attr.group][table->type]);
   14987         [ #  # ]:          0 :                 if (!jump) {
   14988                 :          0 :                         ret = rte_flow_error_set(error, rte_errno,
   14989                 :            :                                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   14990                 :            :                                                 table, "failed to create jump to matcher action");
   14991                 :          0 :                         goto error;
   14992                 :            :                 }
   14993                 :            :         }
   14994                 :          0 :         rte_rwlock_write_lock(&table->matcher_replace_rwlk);
   14995                 :          0 :         ret = mlx5dr_matcher_resize_set_target
   14996                 :            :                         (table->matcher_info[selector].matcher, matcher);
   14997         [ #  # ]:          0 :         if (ret) {
   14998                 :            :                 rte_rwlock_write_unlock(&table->matcher_replace_rwlk);
   14999                 :          0 :                 ret = rte_flow_error_set(error, rte_errno,
   15000                 :            :                                          RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   15001                 :            :                                          table, "failed to initiate matcher swap");
   15002                 :          0 :                 goto error;
   15003                 :            :         }
   15004                 :          0 :         table->cfg.attr.nb_flows = nb_flows;
   15005                 :          0 :         table->matcher_info[other_selector].matcher = matcher;
   15006                 :          0 :         table->matcher_info[other_selector].jump = jump;
   15007                 :          0 :         table->matcher_selector = other_selector;
   15008                 :          0 :         rte_atomic_store_explicit(&table->matcher_info[other_selector].refcnt,
   15009                 :            :                                   0, rte_memory_order_relaxed);
   15010                 :            :         rte_rwlock_write_unlock(&table->matcher_replace_rwlk);
   15011                 :          0 :         return 0;
   15012                 :          0 : error:
   15013         [ #  # ]:          0 :         if (segment)
   15014                 :          0 :                 mlx5_destroy_multi_pattern_segment(segment);
   15015         [ #  # ]:          0 :         if (jump)
   15016                 :          0 :                 mlx5dr_action_destroy(jump);
   15017         [ #  # ]:          0 :         if (matcher) {
   15018                 :          0 :                 ret = mlx5dr_matcher_destroy(matcher);
   15019                 :          0 :                 return rte_flow_error_set(error, rte_errno,
   15020                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   15021                 :            :                                           table, "failed to destroy new matcher");
   15022                 :            :         }
   15023                 :            :         return ret;
   15024                 :            : }
   15025                 :            : 
   15026                 :            : static int
   15027                 :          0 : flow_hw_table_resize_complete(__rte_unused struct rte_eth_dev *dev,
   15028                 :            :                               struct rte_flow_template_table *table,
   15029                 :            :                               struct rte_flow_error *error)
   15030                 :            : {
   15031                 :            :         int ret;
   15032                 :          0 :         uint32_t selector = table->matcher_selector;
   15033                 :          0 :         uint32_t other_selector = (selector + 1) & 1;
   15034                 :            :         struct mlx5_matcher_info *matcher_info = &table->matcher_info[other_selector];
   15035                 :            :         uint32_t matcher_refcnt;
   15036                 :            : 
   15037         [ #  # ]:          0 :         if (!rte_flow_template_table_resizable(dev->data->port_id, &table->cfg.attr))
   15038                 :          0 :                 return rte_flow_error_set(error, EINVAL,
   15039                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   15040                 :            :                                           table, "no resizable attribute");
   15041                 :          0 :         matcher_refcnt = rte_atomic_load_explicit(&matcher_info->refcnt,
   15042                 :            :                                                   rte_memory_order_relaxed);
   15043   [ #  #  #  # ]:          0 :         if (!matcher_info->matcher || matcher_refcnt)
   15044                 :          0 :                 return rte_flow_error_set(error, EBUSY,
   15045                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   15046                 :            :                                           table, "cannot complete table resize");
   15047         [ #  # ]:          0 :         if (matcher_info->jump)
   15048                 :          0 :                 mlx5dr_action_destroy(matcher_info->jump);
   15049                 :          0 :         ret = mlx5dr_matcher_destroy(matcher_info->matcher);
   15050         [ #  # ]:          0 :         if (ret)
   15051                 :          0 :                 return rte_flow_error_set(error, rte_errno,
   15052                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   15053                 :            :                                           table, "failed to destroy retired matcher");
   15054                 :          0 :         matcher_info->matcher = NULL;
   15055                 :          0 :         return 0;
   15056                 :            : }
   15057                 :            : 
   15058                 :            : static int
   15059                 :          0 : flow_hw_update_resized(struct rte_eth_dev *dev, uint32_t queue,
   15060                 :            :                        const struct rte_flow_op_attr *attr,
   15061                 :            :                        struct rte_flow *flow, void *user_data,
   15062                 :            :                        struct rte_flow_error *error)
   15063                 :            : {
   15064                 :            :         int ret;
   15065                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   15066                 :            :         struct rte_flow_hw *hw_flow = (struct rte_flow_hw *)flow;
   15067                 :          0 :         struct rte_flow_template_table *table = hw_flow->table;
   15068                 :          0 :         struct rte_flow_hw_aux *aux = mlx5_flow_hw_aux(dev->data->port_id, hw_flow);
   15069                 :          0 :         uint32_t table_selector = table->matcher_selector;
   15070                 :          0 :         uint32_t rule_selector = aux->matcher_selector;
   15071                 :            :         uint32_t other_selector;
   15072                 :            :         struct mlx5dr_matcher *other_matcher;
   15073                 :          0 :         struct mlx5dr_rule_attr rule_attr = {
   15074                 :            :                 .queue_id = queue,
   15075                 :          0 :                 .burst = attr->postpone,
   15076                 :            :         };
   15077                 :            : 
   15078                 :            :         MLX5_ASSERT(hw_flow->flags & MLX5_FLOW_HW_FLOW_FLAG_MATCHER_SELECTOR);
   15079                 :            :         /**
   15080                 :            :          * mlx5dr_matcher_resize_rule_move() accepts original table matcher -
   15081                 :            :          * the one that was used BEFORE table resize.
   15082                 :            :          * Since the function is called AFTER table resize,
   15083                 :            :          * `table->matcher_selector` always points to the new matcher and
   15084                 :            :          * `aux->matcher_selector` points to a matcher used to create the flow.
   15085                 :            :          */
   15086                 :            :         other_selector = rule_selector == table_selector ?
   15087         [ #  # ]:          0 :                          (rule_selector + 1) & 1 : rule_selector;
   15088                 :          0 :         other_matcher = table->matcher_info[other_selector].matcher;
   15089         [ #  # ]:          0 :         if (!other_matcher)
   15090                 :          0 :                 return rte_flow_error_set(error, EINVAL,
   15091                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   15092                 :            :                                           "no active table resize");
   15093                 :          0 :         hw_flow->operation_type = MLX5_FLOW_HW_FLOW_OP_TYPE_RSZ_TBL_MOVE;
   15094                 :          0 :         hw_flow->user_data = user_data;
   15095                 :          0 :         rule_attr.user_data = hw_flow;
   15096         [ #  # ]:          0 :         if (rule_selector == table_selector) {
   15097                 :          0 :                 struct rte_ring *ring = !attr->postpone ?
   15098         [ #  # ]:          0 :                                         priv->hw_q[queue].flow_transfer_completed :
   15099                 :          0 :                                         priv->hw_q[queue].flow_transfer_pending;
   15100                 :          0 :                 rte_ring_enqueue(ring, hw_flow);
   15101                 :            :                 flow_hw_q_inc_flow_ops(priv, queue);
   15102                 :          0 :                 return 0;
   15103                 :            :         }
   15104                 :          0 :         ret = mlx5dr_matcher_resize_rule_move(other_matcher,
   15105                 :          0 :                                               (struct mlx5dr_rule *)hw_flow->rule,
   15106                 :            :                                               &rule_attr);
   15107         [ #  # ]:          0 :         if (ret) {
   15108                 :          0 :                 return rte_flow_error_set(error, rte_errno,
   15109                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   15110                 :            :                                           "flow transfer failed");
   15111                 :            :         }
   15112                 :            :         flow_hw_q_inc_flow_ops(priv, queue);
   15113                 :          0 :         return 0;
   15114                 :            : }
   15115                 :            : 
   15116                 :            : const struct mlx5_flow_driver_ops mlx5_flow_hw_drv_ops = {
   15117                 :            :         .list_create = flow_hw_list_create,
   15118                 :            :         .list_destroy = flow_hw_list_destroy,
   15119                 :            :         .validate = flow_dv_validate,
   15120                 :            :         .info_get = flow_hw_info_get,
   15121                 :            :         .configure = flow_hw_configure,
   15122                 :            :         .pattern_validate = flow_hw_pattern_validate,
   15123                 :            :         .pattern_template_create = flow_hw_pattern_template_create,
   15124                 :            :         .pattern_template_destroy = flow_hw_pattern_template_destroy,
   15125                 :            :         .actions_validate = flow_hw_actions_validate,
   15126                 :            :         .actions_template_create = flow_hw_actions_template_create,
   15127                 :            :         .actions_template_destroy = flow_hw_actions_template_destroy,
   15128                 :            :         .template_table_create = flow_hw_template_table_create,
   15129                 :            :         .template_table_destroy = flow_hw_table_destroy,
   15130                 :            :         .table_resize = flow_hw_table_resize,
   15131                 :            :         .group_set_miss_actions = flow_hw_group_set_miss_actions,
   15132                 :            :         .async_flow_create = flow_hw_async_flow_create,
   15133                 :            :         .async_flow_create_by_index = flow_hw_async_flow_create_by_index,
   15134                 :            :         .async_flow_update = flow_hw_async_flow_update,
   15135                 :            :         .async_flow_destroy = flow_hw_async_flow_destroy,
   15136                 :            :         .flow_update_resized = flow_hw_update_resized,
   15137                 :            :         .table_resize_complete = flow_hw_table_resize_complete,
   15138                 :            :         .pull = flow_hw_pull,
   15139                 :            :         .push = flow_hw_push,
   15140                 :            :         .async_action_create = flow_hw_action_handle_create,
   15141                 :            :         .async_action_destroy = flow_hw_action_handle_destroy,
   15142                 :            :         .async_action_update = flow_hw_action_handle_update,
   15143                 :            :         .async_action_query_update = flow_hw_async_action_handle_query_update,
   15144                 :            :         .async_action_query = flow_hw_action_handle_query,
   15145                 :            :         .action_validate = flow_hw_action_validate,
   15146                 :            :         .action_create = flow_hw_action_create,
   15147                 :            :         .action_destroy = flow_hw_action_destroy,
   15148                 :            :         .action_update = flow_hw_action_update,
   15149                 :            :         .action_query = flow_hw_action_query,
   15150                 :            :         .action_query_update = flow_hw_action_query_update,
   15151                 :            :         .action_list_handle_create = flow_hw_action_list_handle_create,
   15152                 :            :         .action_list_handle_destroy = flow_hw_action_list_handle_destroy,
   15153                 :            :         .action_list_handle_query_update =
   15154                 :            :                 flow_hw_action_list_handle_query_update,
   15155                 :            :         .async_action_list_handle_create =
   15156                 :            :                 flow_hw_async_action_list_handle_create,
   15157                 :            :         .async_action_list_handle_destroy =
   15158                 :            :                 flow_hw_async_action_list_handle_destroy,
   15159                 :            :         .async_action_list_handle_query_update =
   15160                 :            :                 flow_hw_async_action_list_handle_query_update,
   15161                 :            :         .query = flow_hw_query,
   15162                 :            :         .get_aged_flows = flow_hw_get_aged_flows,
   15163                 :            :         .get_q_aged_flows = flow_hw_get_q_aged_flows,
   15164                 :            :         .item_create = flow_dv_item_create,
   15165                 :            :         .item_release = flow_dv_item_release,
   15166                 :            :         .flow_calc_table_hash = flow_hw_calc_table_hash,
   15167                 :            :         .flow_calc_encap_hash = flow_hw_calc_encap_hash,
   15168                 :            : };
   15169                 :            : 
   15170                 :            : /**
   15171                 :            :  * Creates a control flow using flow template API on @p proxy_dev device,
   15172                 :            :  * on behalf of @p owner_dev device.
   15173                 :            :  *
   15174                 :            :  * This function uses locks internally to synchronize access to the
   15175                 :            :  * flow queue.
   15176                 :            :  *
   15177                 :            :  * Created flow is stored in private list associated with @p proxy_dev device.
   15178                 :            :  *
   15179                 :            :  * @param owner_dev
   15180                 :            :  *   Pointer to Ethernet device on behalf of which flow is created.
   15181                 :            :  * @param proxy_dev
   15182                 :            :  *   Pointer to Ethernet device on which flow is created.
   15183                 :            :  * @param table
   15184                 :            :  *   Pointer to flow table.
   15185                 :            :  * @param items
   15186                 :            :  *   Pointer to flow rule items.
   15187                 :            :  * @param item_template_idx
   15188                 :            :  *   Index of an item template associated with @p table.
   15189                 :            :  * @param actions
   15190                 :            :  *   Pointer to flow rule actions.
   15191                 :            :  * @param action_template_idx
   15192                 :            :  *   Index of an action template associated with @p table.
   15193                 :            :  * @param info
   15194                 :            :  *   Additional info about control flow rule.
   15195                 :            :  * @param external
   15196                 :            :  *   External ctrl flow.
   15197                 :            :  *
   15198                 :            :  * @return
   15199                 :            :  *   0 on success, negative errno value otherwise and rte_errno set.
   15200                 :            :  */
   15201                 :            : static __rte_unused int
   15202                 :          0 : flow_hw_create_ctrl_flow(struct rte_eth_dev *owner_dev,
   15203                 :            :                          struct rte_eth_dev *proxy_dev,
   15204                 :            :                          struct rte_flow_template_table *table,
   15205                 :            :                          struct rte_flow_item items[],
   15206                 :            :                          uint8_t item_template_idx,
   15207                 :            :                          struct rte_flow_action actions[],
   15208                 :            :                          uint8_t action_template_idx,
   15209                 :            :                          struct mlx5_ctrl_flow_info *info,
   15210                 :            :                          bool external)
   15211                 :            : {
   15212                 :          0 :         struct mlx5_priv *priv = proxy_dev->data->dev_private;
   15213                 :          0 :         uint32_t queue = CTRL_QUEUE_ID(priv);
   15214                 :          0 :         struct rte_flow_op_attr op_attr = {
   15215                 :            :                 .postpone = 0,
   15216                 :            :         };
   15217                 :            :         struct rte_flow *flow = NULL;
   15218                 :            :         struct mlx5_ctrl_flow_entry *entry = NULL;
   15219                 :            :         int ret;
   15220                 :            : 
   15221                 :          0 :         rte_spinlock_lock(&priv->hw_ctrl_lock);
   15222                 :          0 :         entry = mlx5_malloc(MLX5_MEM_ZERO | MLX5_MEM_SYS, sizeof(*entry),
   15223                 :            :                             0, SOCKET_ID_ANY);
   15224         [ #  # ]:          0 :         if (!entry) {
   15225                 :          0 :                 DRV_LOG(ERR, "port %u not enough memory to create control flows",
   15226                 :            :                         proxy_dev->data->port_id);
   15227                 :          0 :                 rte_errno = ENOMEM;
   15228                 :            :                 ret = -rte_errno;
   15229                 :          0 :                 goto error;
   15230                 :            :         }
   15231                 :          0 :         flow = flow_hw_async_flow_create(proxy_dev, queue, &op_attr, table,
   15232                 :            :                                          items, item_template_idx,
   15233                 :            :                                          actions, action_template_idx,
   15234                 :            :                                          NULL, NULL);
   15235         [ #  # ]:          0 :         if (!flow) {
   15236                 :          0 :                 DRV_LOG(ERR, "port %u failed to enqueue create control"
   15237                 :            :                         " flow operation", proxy_dev->data->port_id);
   15238                 :          0 :                 ret = -rte_errno;
   15239                 :          0 :                 goto error;
   15240                 :            :         }
   15241                 :          0 :         ret = __flow_hw_pull_comp(proxy_dev, queue, NULL);
   15242         [ #  # ]:          0 :         if (ret) {
   15243                 :          0 :                 DRV_LOG(ERR, "port %u failed to insert control flow",
   15244                 :            :                         proxy_dev->data->port_id);
   15245                 :          0 :                 rte_errno = EINVAL;
   15246                 :            :                 ret = -rte_errno;
   15247                 :          0 :                 goto error;
   15248                 :            :         }
   15249                 :          0 :         entry->owner_dev = owner_dev;
   15250                 :          0 :         entry->flow = flow;
   15251         [ #  # ]:          0 :         if (info)
   15252                 :          0 :                 entry->info = *info;
   15253                 :            :         else
   15254                 :          0 :                 entry->info.type = MLX5_CTRL_FLOW_TYPE_GENERAL;
   15255         [ #  # ]:          0 :         if (external)
   15256         [ #  # ]:          0 :                 LIST_INSERT_HEAD(&priv->hw_ext_ctrl_flows, entry, next);
   15257                 :            :         else
   15258         [ #  # ]:          0 :                 LIST_INSERT_HEAD(&priv->hw_ctrl_flows, entry, next);
   15259                 :            :         rte_spinlock_unlock(&priv->hw_ctrl_lock);
   15260                 :          0 :         return 0;
   15261                 :          0 : error:
   15262         [ #  # ]:          0 :         if (entry)
   15263                 :          0 :                 mlx5_free(entry);
   15264                 :            :         rte_spinlock_unlock(&priv->hw_ctrl_lock);
   15265                 :          0 :         return ret;
   15266                 :            : }
   15267                 :            : 
   15268                 :            : /**
   15269                 :            :  * Destroys a control flow @p flow using flow template API on @p dev device.
   15270                 :            :  *
   15271                 :            :  * This function uses locks internally to synchronize access to the
   15272                 :            :  * flow queue.
   15273                 :            :  *
   15274                 :            :  * If the @p flow is stored on any private list/pool, then caller must free up
   15275                 :            :  * the relevant resources.
   15276                 :            :  *
   15277                 :            :  * @param dev
   15278                 :            :  *   Pointer to Ethernet device.
   15279                 :            :  * @param flow
   15280                 :            :  *   Pointer to flow rule.
   15281                 :            :  *
   15282                 :            :  * @return
   15283                 :            :  *   0 on success, non-zero value otherwise.
   15284                 :            :  */
   15285                 :            : static int
   15286                 :          0 : flow_hw_destroy_ctrl_flow(struct rte_eth_dev *dev, struct rte_flow *flow)
   15287                 :            : {
   15288                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   15289                 :          0 :         uint32_t queue = CTRL_QUEUE_ID(priv);
   15290                 :          0 :         struct rte_flow_op_attr op_attr = {
   15291                 :            :                 .postpone = 0,
   15292                 :            :         };
   15293                 :            :         int ret;
   15294                 :            : 
   15295                 :          0 :         rte_spinlock_lock(&priv->hw_ctrl_lock);
   15296                 :          0 :         ret = flow_hw_async_flow_destroy(dev, queue, &op_attr, flow, NULL, NULL);
   15297         [ #  # ]:          0 :         if (ret) {
   15298                 :          0 :                 DRV_LOG(ERR, "port %u failed to enqueue destroy control"
   15299                 :            :                         " flow operation", dev->data->port_id);
   15300                 :          0 :                 goto exit;
   15301                 :            :         }
   15302                 :          0 :         ret = __flow_hw_pull_comp(dev, queue, NULL);
   15303         [ #  # ]:          0 :         if (ret) {
   15304                 :          0 :                 DRV_LOG(ERR, "port %u failed to destroy control flow",
   15305                 :            :                         dev->data->port_id);
   15306                 :          0 :                 rte_errno = EINVAL;
   15307                 :            :                 ret = -rte_errno;
   15308                 :          0 :                 goto exit;
   15309                 :            :         }
   15310                 :          0 : exit:
   15311                 :            :         rte_spinlock_unlock(&priv->hw_ctrl_lock);
   15312                 :          0 :         return ret;
   15313                 :            : }
   15314                 :            : 
   15315                 :            : /**
   15316                 :            :  * Destroys control flows created on behalf of @p owner device on @p dev device.
   15317                 :            :  *
   15318                 :            :  * @param dev
   15319                 :            :  *   Pointer to Ethernet device on which control flows were created.
   15320                 :            :  * @param owner
   15321                 :            :  *   Pointer to Ethernet device owning control flows.
   15322                 :            :  *
   15323                 :            :  * @return
   15324                 :            :  *   0 on success, otherwise negative error code is returned and
   15325                 :            :  *   rte_errno is set.
   15326                 :            :  */
   15327                 :            : static int
   15328                 :          0 : flow_hw_flush_ctrl_flows_owned_by(struct rte_eth_dev *dev, struct rte_eth_dev *owner)
   15329                 :            : {
   15330                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   15331                 :            :         struct mlx5_ctrl_flow_entry *cf;
   15332                 :            :         struct mlx5_ctrl_flow_entry *cf_next;
   15333                 :            :         int ret;
   15334                 :            : 
   15335                 :          0 :         cf = LIST_FIRST(&priv->hw_ctrl_flows);
   15336         [ #  # ]:          0 :         while (cf != NULL) {
   15337                 :          0 :                 cf_next = LIST_NEXT(cf, next);
   15338         [ #  # ]:          0 :                 if (cf->owner_dev == owner) {
   15339                 :          0 :                         ret = flow_hw_destroy_ctrl_flow(dev, cf->flow);
   15340         [ #  # ]:          0 :                         if (ret) {
   15341                 :          0 :                                 rte_errno = ret;
   15342                 :          0 :                                 return -ret;
   15343                 :            :                         }
   15344         [ #  # ]:          0 :                         LIST_REMOVE(cf, next);
   15345                 :          0 :                         mlx5_free(cf);
   15346                 :            :                 }
   15347                 :            :                 cf = cf_next;
   15348                 :            :         }
   15349                 :            :         return 0;
   15350                 :            : }
   15351                 :            : 
   15352                 :            : /**
   15353                 :            :  * Destroys control flows created for @p owner_dev device.
   15354                 :            :  *
   15355                 :            :  * @param owner_dev
   15356                 :            :  *   Pointer to Ethernet device owning control flows.
   15357                 :            :  *
   15358                 :            :  * @return
   15359                 :            :  *   0 on success, otherwise negative error code is returned and
   15360                 :            :  *   rte_errno is set.
   15361                 :            :  */
   15362                 :            : int
   15363                 :          0 : mlx5_flow_hw_flush_ctrl_flows(struct rte_eth_dev *owner_dev)
   15364                 :            : {
   15365                 :          0 :         struct mlx5_priv *owner_priv = owner_dev->data->dev_private;
   15366                 :            :         struct rte_eth_dev *proxy_dev;
   15367                 :          0 :         uint16_t owner_port_id = owner_dev->data->port_id;
   15368                 :          0 :         uint16_t proxy_port_id = owner_dev->data->port_id;
   15369                 :            :         int ret;
   15370                 :            : 
   15371                 :            :         /* Flush all flows created by this port for itself. */
   15372                 :          0 :         ret = flow_hw_flush_ctrl_flows_owned_by(owner_dev, owner_dev);
   15373         [ #  # ]:          0 :         if (ret)
   15374                 :            :                 return ret;
   15375                 :            :         /* Flush all flows created for this port on proxy port. */
   15376         [ #  # ]:          0 :         if (owner_priv->sh->config.dv_esw_en) {
   15377                 :          0 :                 ret = rte_flow_pick_transfer_proxy(owner_port_id, &proxy_port_id, NULL);
   15378         [ #  # ]:          0 :                 if (ret == -ENODEV) {
   15379                 :          0 :                         DRV_LOG(DEBUG, "Unable to find transfer proxy port for port %u. It was "
   15380                 :            :                                        "probably closed. Control flows were cleared.",
   15381                 :            :                                        owner_port_id);
   15382                 :          0 :                         rte_errno = 0;
   15383                 :          0 :                         return 0;
   15384         [ #  # ]:          0 :                 } else if (ret) {
   15385                 :          0 :                         DRV_LOG(ERR, "Unable to find proxy port for port %u (ret = %d)",
   15386                 :            :                                 owner_port_id, ret);
   15387                 :          0 :                         return ret;
   15388                 :            :                 }
   15389                 :          0 :                 proxy_dev = &rte_eth_devices[proxy_port_id];
   15390                 :            :         } else {
   15391                 :            :                 proxy_dev = owner_dev;
   15392                 :            :         }
   15393                 :          0 :         return flow_hw_flush_ctrl_flows_owned_by(proxy_dev, owner_dev);
   15394                 :            : }
   15395                 :            : 
   15396                 :            : /**
   15397                 :            :  * Destroys all control flows created on @p dev device.
   15398                 :            :  *
   15399                 :            :  * @param owner_dev
   15400                 :            :  *   Pointer to Ethernet device.
   15401                 :            :  *
   15402                 :            :  * @return
   15403                 :            :  *   0 on success, otherwise negative error code is returned and
   15404                 :            :  *   rte_errno is set.
   15405                 :            :  */
   15406                 :            : static int
   15407                 :          0 : flow_hw_flush_all_ctrl_flows(struct rte_eth_dev *dev)
   15408                 :            : {
   15409                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   15410                 :            :         struct mlx5_ctrl_flow_entry *cf;
   15411                 :            :         struct mlx5_ctrl_flow_entry *cf_next;
   15412                 :            :         int ret;
   15413                 :            : 
   15414                 :          0 :         cf = LIST_FIRST(&priv->hw_ctrl_flows);
   15415         [ #  # ]:          0 :         while (cf != NULL) {
   15416                 :          0 :                 cf_next = LIST_NEXT(cf, next);
   15417                 :          0 :                 ret = flow_hw_destroy_ctrl_flow(dev, cf->flow);
   15418         [ #  # ]:          0 :                 if (ret) {
   15419                 :          0 :                         rte_errno = ret;
   15420                 :          0 :                         return -ret;
   15421                 :            :                 }
   15422         [ #  # ]:          0 :                 LIST_REMOVE(cf, next);
   15423                 :          0 :                 mlx5_free(cf);
   15424                 :            :                 cf = cf_next;
   15425                 :            :         }
   15426                 :          0 :         cf = LIST_FIRST(&priv->hw_ext_ctrl_flows);
   15427         [ #  # ]:          0 :         while (cf != NULL) {
   15428                 :          0 :                 cf_next = LIST_NEXT(cf, next);
   15429                 :          0 :                 ret = flow_hw_destroy_ctrl_flow(dev, cf->flow);
   15430         [ #  # ]:          0 :                 if (ret) {
   15431                 :          0 :                         rte_errno = ret;
   15432                 :          0 :                         return -ret;
   15433                 :            :                 }
   15434         [ #  # ]:          0 :                 LIST_REMOVE(cf, next);
   15435                 :          0 :                 mlx5_free(cf);
   15436                 :            :                 cf = cf_next;
   15437                 :            :         }
   15438                 :            :         return 0;
   15439                 :            : }
   15440                 :            : 
   15441                 :            : int
   15442                 :          0 : mlx5_flow_hw_esw_create_sq_miss_flow(struct rte_eth_dev *dev, uint32_t sqn, bool external)
   15443                 :            : {
   15444                 :          0 :         uint16_t port_id = dev->data->port_id;
   15445                 :          0 :         struct rte_flow_item_ethdev esw_mgr_spec = {
   15446                 :            :                 .port_id = MLX5_REPRESENTED_PORT_ESW_MGR,
   15447                 :            :         };
   15448                 :          0 :         struct rte_flow_item_ethdev esw_mgr_mask = {
   15449                 :            :                 .port_id = MLX5_REPRESENTED_PORT_ESW_MGR,
   15450                 :            :         };
   15451                 :          0 :         struct rte_flow_item_tag reg_c0_spec = {
   15452                 :            :                 .index = (uint8_t)REG_C_0,
   15453                 :            :                 .data = flow_hw_esw_mgr_regc_marker(dev),
   15454                 :            :         };
   15455                 :          0 :         struct rte_flow_item_tag reg_c0_mask = {
   15456                 :            :                 .index = 0xff,
   15457                 :            :                 .data = flow_hw_esw_mgr_regc_marker_mask(dev),
   15458                 :            :         };
   15459                 :          0 :         struct mlx5_rte_flow_item_sq sq_spec = {
   15460                 :            :                 .queue = sqn,
   15461                 :            :         };
   15462                 :          0 :         struct rte_flow_action_ethdev port = {
   15463                 :            :                 .port_id = port_id,
   15464                 :            :         };
   15465                 :          0 :         struct rte_flow_item items[3] = { { 0 } };
   15466                 :          0 :         struct rte_flow_action actions[3] = { { 0 } };
   15467                 :          0 :         struct mlx5_ctrl_flow_info flow_info = {
   15468                 :            :                 .type = MLX5_CTRL_FLOW_TYPE_SQ_MISS_ROOT,
   15469                 :            :                 .esw_mgr_sq = sqn,
   15470                 :            :         };
   15471                 :            :         struct rte_eth_dev *proxy_dev;
   15472                 :            :         struct mlx5_priv *proxy_priv;
   15473                 :          0 :         uint16_t proxy_port_id = dev->data->port_id;
   15474                 :            :         int ret;
   15475                 :            : 
   15476                 :          0 :         ret = rte_flow_pick_transfer_proxy(port_id, &proxy_port_id, NULL);
   15477         [ #  # ]:          0 :         if (ret) {
   15478                 :          0 :                 DRV_LOG(ERR, "Unable to pick transfer proxy port for port %u. Transfer proxy "
   15479                 :            :                              "port must be present to create default SQ miss flows.",
   15480                 :            :                              port_id);
   15481                 :          0 :                 return ret;
   15482                 :            :         }
   15483                 :          0 :         proxy_dev = &rte_eth_devices[proxy_port_id];
   15484                 :          0 :         proxy_priv = proxy_dev->data->dev_private;
   15485         [ #  # ]:          0 :         if (!proxy_priv->dr_ctx) {
   15486                 :          0 :                 DRV_LOG(DEBUG, "Transfer proxy port (port %u) of port %u must be configured "
   15487                 :            :                                "for HWS to create default SQ miss flows. Default flows will "
   15488                 :            :                                "not be created.",
   15489                 :            :                                proxy_port_id, port_id);
   15490                 :          0 :                 return 0;
   15491                 :            :         }
   15492         [ #  # ]:          0 :         if (!proxy_priv->hw_ctrl_fdb ||
   15493         [ #  # ]:          0 :             !proxy_priv->hw_ctrl_fdb->hw_esw_sq_miss_root_tbl ||
   15494         [ #  # ]:          0 :             !proxy_priv->hw_ctrl_fdb->hw_esw_sq_miss_tbl) {
   15495                 :          0 :                 DRV_LOG(ERR, "Transfer proxy port (port %u) of port %u was configured, but "
   15496                 :            :                              "default flow tables were not created.",
   15497                 :            :                              proxy_port_id, port_id);
   15498                 :          0 :                 rte_errno = ENOMEM;
   15499                 :          0 :                 return -rte_errno;
   15500                 :            :         }
   15501                 :            :         /*
   15502                 :            :          * Create a root SQ miss flow rule - match E-Switch Manager and SQ,
   15503                 :            :          * and jump to group 1.
   15504                 :            :          */
   15505                 :          0 :         items[0] = (struct rte_flow_item){
   15506                 :            :                 .type = RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT,
   15507                 :            :                 .spec = &esw_mgr_spec,
   15508                 :            :                 .mask = &esw_mgr_mask,
   15509                 :            :         };
   15510                 :          0 :         items[1] = (struct rte_flow_item){
   15511                 :            :                 .type = (enum rte_flow_item_type)MLX5_RTE_FLOW_ITEM_TYPE_SQ,
   15512                 :            :                 .spec = &sq_spec,
   15513                 :            :         };
   15514                 :          0 :         items[2] = (struct rte_flow_item){
   15515                 :            :                 .type = RTE_FLOW_ITEM_TYPE_END,
   15516                 :            :         };
   15517                 :          0 :         actions[0] = (struct rte_flow_action){
   15518                 :            :                 .type = RTE_FLOW_ACTION_TYPE_MODIFY_FIELD,
   15519                 :            :         };
   15520                 :          0 :         actions[1] = (struct rte_flow_action){
   15521                 :            :                 .type = RTE_FLOW_ACTION_TYPE_JUMP,
   15522                 :            :         };
   15523                 :          0 :         actions[2] = (struct rte_flow_action) {
   15524                 :            :                 .type = RTE_FLOW_ACTION_TYPE_END,
   15525                 :            :         };
   15526                 :          0 :         ret = flow_hw_create_ctrl_flow(dev, proxy_dev,
   15527                 :            :                                        proxy_priv->hw_ctrl_fdb->hw_esw_sq_miss_root_tbl,
   15528                 :            :                                        items, 0, actions, 0, &flow_info, external);
   15529         [ #  # ]:          0 :         if (ret) {
   15530                 :          0 :                 DRV_LOG(ERR, "Port %u failed to create root SQ miss flow rule for SQ %u, ret %d",
   15531                 :            :                         port_id, sqn, ret);
   15532                 :          0 :                 return ret;
   15533                 :            :         }
   15534                 :            :         /*
   15535                 :            :          * Create a non-root SQ miss flow rule - match REG_C_0 marker and SQ,
   15536                 :            :          * and forward to port.
   15537                 :            :          */
   15538                 :          0 :         items[0] = (struct rte_flow_item){
   15539                 :            :                 .type = (enum rte_flow_item_type)MLX5_RTE_FLOW_ITEM_TYPE_TAG,
   15540                 :            :                 .spec = &reg_c0_spec,
   15541                 :            :                 .mask = &reg_c0_mask,
   15542                 :            :         };
   15543                 :          0 :         items[1] = (struct rte_flow_item){
   15544                 :            :                 .type = (enum rte_flow_item_type)MLX5_RTE_FLOW_ITEM_TYPE_SQ,
   15545                 :            :                 .spec = &sq_spec,
   15546                 :            :         };
   15547                 :          0 :         items[2] = (struct rte_flow_item){
   15548                 :            :                 .type = RTE_FLOW_ITEM_TYPE_END,
   15549                 :            :         };
   15550                 :          0 :         actions[0] = (struct rte_flow_action){
   15551                 :            :                 .type = RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT,
   15552                 :            :                 .conf = &port,
   15553                 :            :         };
   15554                 :          0 :         actions[1] = (struct rte_flow_action){
   15555                 :            :                 .type = RTE_FLOW_ACTION_TYPE_END,
   15556                 :            :         };
   15557                 :          0 :         flow_info.type = MLX5_CTRL_FLOW_TYPE_SQ_MISS;
   15558                 :          0 :         ret = flow_hw_create_ctrl_flow(dev, proxy_dev,
   15559                 :          0 :                                        proxy_priv->hw_ctrl_fdb->hw_esw_sq_miss_tbl,
   15560                 :            :                                        items, 0, actions, 0, &flow_info, external);
   15561         [ #  # ]:          0 :         if (ret) {
   15562                 :          0 :                 DRV_LOG(ERR, "Port %u failed to create HWS SQ miss flow rule for SQ %u, ret %d",
   15563                 :            :                         port_id, sqn, ret);
   15564                 :          0 :                 return ret;
   15565                 :            :         }
   15566                 :            :         return 0;
   15567                 :            : }
   15568                 :            : 
   15569                 :            : static bool
   15570                 :            : flow_hw_is_matching_sq_miss_flow(struct mlx5_ctrl_flow_entry *cf,
   15571                 :            :                                  struct rte_eth_dev *dev,
   15572                 :            :                                  uint32_t sqn)
   15573                 :            : {
   15574                 :          0 :         if (cf->owner_dev != dev)
   15575                 :            :                 return false;
   15576   [ #  #  #  # ]:          0 :         if (cf->info.type == MLX5_CTRL_FLOW_TYPE_SQ_MISS_ROOT && cf->info.esw_mgr_sq == sqn)
   15577                 :            :                 return true;
   15578   [ #  #  #  # ]:          0 :         if (cf->info.type == MLX5_CTRL_FLOW_TYPE_SQ_MISS && cf->info.esw_mgr_sq == sqn)
   15579                 :            :                 return true;
   15580                 :            :         return false;
   15581                 :            : }
   15582                 :            : 
   15583                 :            : int
   15584                 :          0 : mlx5_flow_hw_esw_destroy_sq_miss_flow(struct rte_eth_dev *dev, uint32_t sqn)
   15585                 :            : {
   15586                 :          0 :         uint16_t port_id = dev->data->port_id;
   15587                 :          0 :         uint16_t proxy_port_id = dev->data->port_id;
   15588                 :            :         struct rte_eth_dev *proxy_dev;
   15589                 :            :         struct mlx5_priv *proxy_priv;
   15590                 :            :         struct mlx5_ctrl_flow_entry *cf;
   15591                 :            :         struct mlx5_ctrl_flow_entry *cf_next;
   15592                 :            :         int ret;
   15593                 :            : 
   15594                 :          0 :         ret = rte_flow_pick_transfer_proxy(port_id, &proxy_port_id, NULL);
   15595         [ #  # ]:          0 :         if (ret) {
   15596                 :          0 :                 DRV_LOG(ERR, "Unable to pick transfer proxy port for port %u. Transfer proxy "
   15597                 :            :                              "port must be present for default SQ miss flow rules to exist.",
   15598                 :            :                              port_id);
   15599                 :          0 :                 return ret;
   15600                 :            :         }
   15601                 :          0 :         proxy_dev = &rte_eth_devices[proxy_port_id];
   15602                 :          0 :         proxy_priv = proxy_dev->data->dev_private;
   15603                 :            :         /* FDB default flow rules must be enabled. */
   15604                 :            :         MLX5_ASSERT(proxy_priv->sh->config.fdb_def_rule);
   15605         [ #  # ]:          0 :         if (!proxy_priv->dr_ctx)
   15606                 :            :                 return 0;
   15607         [ #  # ]:          0 :         if (!proxy_priv->hw_ctrl_fdb ||
   15608         [ #  # ]:          0 :             !proxy_priv->hw_ctrl_fdb->hw_esw_sq_miss_root_tbl ||
   15609         [ #  # ]:          0 :             !proxy_priv->hw_ctrl_fdb->hw_esw_sq_miss_tbl)
   15610                 :            :                 return 0;
   15611                 :          0 :         cf = LIST_FIRST(&proxy_priv->hw_ctrl_flows);
   15612         [ #  # ]:          0 :         while (cf != NULL) {
   15613         [ #  # ]:          0 :                 cf_next = LIST_NEXT(cf, next);
   15614                 :            :                 if (flow_hw_is_matching_sq_miss_flow(cf, dev, sqn)) {
   15615                 :          0 :                         claim_zero(flow_hw_destroy_ctrl_flow(proxy_dev, cf->flow));
   15616         [ #  # ]:          0 :                         LIST_REMOVE(cf, next);
   15617                 :          0 :                         mlx5_free(cf);
   15618                 :            :                 }
   15619                 :            :                 cf = cf_next;
   15620                 :            :         }
   15621                 :            :         return 0;
   15622                 :            : }
   15623                 :            : 
   15624                 :            : int
   15625                 :          0 : mlx5_flow_hw_esw_create_default_jump_flow(struct rte_eth_dev *dev)
   15626                 :            : {
   15627                 :          0 :         uint16_t port_id = dev->data->port_id;
   15628                 :          0 :         struct rte_flow_item_ethdev port_spec = {
   15629                 :            :                 .port_id = port_id,
   15630                 :            :         };
   15631                 :          0 :         struct rte_flow_item items[] = {
   15632                 :            :                 {
   15633                 :            :                         .type = RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT,
   15634                 :            :                         .spec = &port_spec,
   15635                 :            :                 },
   15636                 :            :                 {
   15637                 :            :                         .type = RTE_FLOW_ITEM_TYPE_END,
   15638                 :            :                 },
   15639                 :            :         };
   15640                 :          0 :         struct rte_flow_action_jump jump = {
   15641                 :            :                 .group = 1,
   15642                 :            :         };
   15643                 :          0 :         struct rte_flow_action actions[] = {
   15644                 :            :                 {
   15645                 :            :                         .type = RTE_FLOW_ACTION_TYPE_JUMP,
   15646                 :            :                         .conf = &jump,
   15647                 :            :                 },
   15648                 :            :                 {
   15649                 :            :                         .type = RTE_FLOW_ACTION_TYPE_END,
   15650                 :            :                 }
   15651                 :            :         };
   15652                 :          0 :         struct mlx5_ctrl_flow_info flow_info = {
   15653                 :            :                 .type = MLX5_CTRL_FLOW_TYPE_DEFAULT_JUMP,
   15654                 :            :         };
   15655                 :            :         struct rte_eth_dev *proxy_dev;
   15656                 :            :         struct mlx5_priv *proxy_priv;
   15657                 :          0 :         uint16_t proxy_port_id = dev->data->port_id;
   15658                 :            :         int ret;
   15659                 :            : 
   15660                 :          0 :         ret = rte_flow_pick_transfer_proxy(port_id, &proxy_port_id, NULL);
   15661         [ #  # ]:          0 :         if (ret) {
   15662                 :          0 :                 DRV_LOG(ERR, "Unable to pick transfer proxy port for port %u. Transfer proxy "
   15663                 :            :                              "port must be present to create default FDB jump rule.",
   15664                 :            :                              port_id);
   15665                 :          0 :                 return ret;
   15666                 :            :         }
   15667                 :          0 :         proxy_dev = &rte_eth_devices[proxy_port_id];
   15668                 :          0 :         proxy_priv = proxy_dev->data->dev_private;
   15669                 :            :         /* FDB default flow rules must be enabled. */
   15670                 :            :         MLX5_ASSERT(proxy_priv->sh->config.fdb_def_rule);
   15671         [ #  # ]:          0 :         if (!proxy_priv->dr_ctx) {
   15672                 :          0 :                 DRV_LOG(DEBUG, "Transfer proxy port (port %u) of port %u must be configured "
   15673                 :            :                                "for HWS to create default FDB jump rule. Default rule will "
   15674                 :            :                                "not be created.",
   15675                 :            :                                proxy_port_id, port_id);
   15676                 :          0 :                 return 0;
   15677                 :            :         }
   15678   [ #  #  #  # ]:          0 :         if (!proxy_priv->hw_ctrl_fdb || !proxy_priv->hw_ctrl_fdb->hw_esw_zero_tbl) {
   15679                 :          0 :                 DRV_LOG(ERR, "Transfer proxy port (port %u) of port %u was configured, but "
   15680                 :            :                              "default flow tables were not created.",
   15681                 :            :                              proxy_port_id, port_id);
   15682                 :          0 :                 rte_errno = EINVAL;
   15683                 :          0 :                 return -rte_errno;
   15684                 :            :         }
   15685                 :          0 :         return flow_hw_create_ctrl_flow(dev, proxy_dev,
   15686                 :            :                                         proxy_priv->hw_ctrl_fdb->hw_esw_zero_tbl,
   15687                 :            :                                         items, 0, actions, 0, &flow_info, false);
   15688                 :            : }
   15689                 :            : 
   15690                 :            : int
   15691                 :          0 : mlx5_flow_hw_create_tx_default_mreg_copy_flow(struct rte_eth_dev *dev)
   15692                 :            : {
   15693                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   15694                 :          0 :         struct rte_flow_item_eth promisc = {
   15695                 :            :                 .hdr.dst_addr.addr_bytes = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
   15696                 :            :                 .hdr.src_addr.addr_bytes = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
   15697                 :            :                 .hdr.ether_type = 0,
   15698                 :            :         };
   15699                 :          0 :         struct rte_flow_item eth_all[] = {
   15700                 :            :                 [0] = {
   15701                 :            :                         .type = RTE_FLOW_ITEM_TYPE_ETH,
   15702                 :            :                         .spec = &promisc,
   15703                 :            :                         .mask = &promisc,
   15704                 :            :                 },
   15705                 :            :                 [1] = {
   15706                 :            :                         .type = RTE_FLOW_ITEM_TYPE_END,
   15707                 :            :                 },
   15708                 :            :         };
   15709                 :          0 :         struct rte_flow_action_modify_field mreg_action = {
   15710                 :            :                 .operation = RTE_FLOW_MODIFY_SET,
   15711                 :            :                 .dst = {
   15712                 :            :                         .field = (enum rte_flow_field_id)MLX5_RTE_FLOW_FIELD_META_REG,
   15713                 :            :                         .tag_index = REG_C_1,
   15714                 :            :                 },
   15715                 :            :                 .src = {
   15716                 :            :                         .field = (enum rte_flow_field_id)MLX5_RTE_FLOW_FIELD_META_REG,
   15717                 :            :                         .tag_index = REG_A,
   15718                 :            :                 },
   15719                 :            :                 .width = 32,
   15720                 :            :         };
   15721                 :          0 :         struct rte_flow_action copy_reg_action[] = {
   15722                 :            :                 [0] = {
   15723                 :            :                         .type = RTE_FLOW_ACTION_TYPE_MODIFY_FIELD,
   15724                 :            :                         .conf = &mreg_action,
   15725                 :            :                 },
   15726                 :            :                 [1] = {
   15727                 :            :                         .type = RTE_FLOW_ACTION_TYPE_JUMP,
   15728                 :            :                 },
   15729                 :            :                 [2] = {
   15730                 :            :                         .type = RTE_FLOW_ACTION_TYPE_END,
   15731                 :            :                 },
   15732                 :            :         };
   15733                 :          0 :         struct mlx5_ctrl_flow_info flow_info = {
   15734                 :            :                 .type = MLX5_CTRL_FLOW_TYPE_TX_META_COPY,
   15735                 :            :         };
   15736                 :            : 
   15737                 :            :         MLX5_ASSERT(priv->master);
   15738         [ #  # ]:          0 :         if (!priv->dr_ctx ||
   15739         [ #  # ]:          0 :             !priv->hw_ctrl_fdb ||
   15740         [ #  # ]:          0 :             !priv->hw_ctrl_fdb->hw_tx_meta_cpy_tbl)
   15741                 :            :                 return 0;
   15742                 :          0 :         return flow_hw_create_ctrl_flow(dev, dev,
   15743                 :            :                                         priv->hw_ctrl_fdb->hw_tx_meta_cpy_tbl,
   15744                 :            :                                         eth_all, 0, copy_reg_action, 0, &flow_info, false);
   15745                 :            : }
   15746                 :            : 
   15747                 :            : int
   15748                 :          0 : mlx5_flow_hw_tx_repr_matching_flow(struct rte_eth_dev *dev, uint32_t sqn, bool external)
   15749                 :            : {
   15750                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   15751                 :          0 :         struct mlx5_rte_flow_item_sq sq_spec = {
   15752                 :            :                 .queue = sqn,
   15753                 :            :         };
   15754                 :          0 :         struct rte_flow_item items[] = {
   15755                 :            :                 {
   15756                 :            :                         .type = (enum rte_flow_item_type)MLX5_RTE_FLOW_ITEM_TYPE_SQ,
   15757                 :            :                         .spec = &sq_spec,
   15758                 :            :                 },
   15759                 :            :                 {
   15760                 :            :                         .type = RTE_FLOW_ITEM_TYPE_END,
   15761                 :            :                 },
   15762                 :            :         };
   15763                 :            :         /*
   15764                 :            :          * Allocate actions array suitable for all cases - extended metadata enabled or not.
   15765                 :            :          * With extended metadata there will be an additional MODIFY_FIELD action before JUMP.
   15766                 :            :          */
   15767                 :          0 :         struct rte_flow_action actions[] = {
   15768                 :            :                 { .type = RTE_FLOW_ACTION_TYPE_MODIFY_FIELD },
   15769                 :            :                 { .type = RTE_FLOW_ACTION_TYPE_JUMP },
   15770                 :            :                 { .type = RTE_FLOW_ACTION_TYPE_END },
   15771                 :            :                 { .type = RTE_FLOW_ACTION_TYPE_END },
   15772                 :            :         };
   15773                 :          0 :         struct mlx5_ctrl_flow_info flow_info = {
   15774                 :            :                 .type = MLX5_CTRL_FLOW_TYPE_TX_REPR_MATCH,
   15775                 :            :                 .tx_repr_sq = sqn,
   15776                 :            :         };
   15777                 :            : 
   15778                 :            :         /* It is assumed that caller checked for representor matching. */
   15779                 :            :         MLX5_ASSERT(priv->sh->config.repr_matching);
   15780         [ #  # ]:          0 :         if (!priv->dr_ctx) {
   15781                 :          0 :                 DRV_LOG(DEBUG, "Port %u must be configured for HWS, before creating "
   15782                 :            :                                "default egress flow rules. Omitting creation.",
   15783                 :            :                                dev->data->port_id);
   15784                 :          0 :                 return 0;
   15785                 :            :         }
   15786         [ #  # ]:          0 :         if (!priv->hw_tx_repr_tagging_tbl) {
   15787                 :          0 :                 DRV_LOG(ERR, "Port %u is configured for HWS, but table for default "
   15788                 :            :                              "egress flow rules does not exist.",
   15789                 :            :                              dev->data->port_id);
   15790                 :          0 :                 rte_errno = EINVAL;
   15791                 :          0 :                 return -rte_errno;
   15792                 :            :         }
   15793                 :            :         /*
   15794                 :            :          * If extended metadata mode is enabled, then an additional MODIFY_FIELD action must be
   15795                 :            :          * placed before terminating JUMP action.
   15796                 :            :          */
   15797         [ #  # ]:          0 :         if (priv->sh->config.dv_xmeta_en == MLX5_XMETA_MODE_META32_HWS) {
   15798                 :          0 :                 actions[1].type = RTE_FLOW_ACTION_TYPE_MODIFY_FIELD;
   15799                 :          0 :                 actions[2].type = RTE_FLOW_ACTION_TYPE_JUMP;
   15800                 :            :         }
   15801                 :          0 :         return flow_hw_create_ctrl_flow(dev, dev, priv->hw_tx_repr_tagging_tbl,
   15802                 :            :                                         items, 0, actions, 0, &flow_info, external);
   15803                 :            : }
   15804                 :            : 
   15805                 :            : int
   15806                 :          0 : mlx5_flow_hw_lacp_rx_flow(struct rte_eth_dev *dev)
   15807                 :            : {
   15808                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   15809                 :          0 :         struct rte_flow_item_eth lacp_item = {
   15810                 :            :                 .type = RTE_BE16(RTE_ETHER_TYPE_SLOW),
   15811                 :            :         };
   15812                 :          0 :         struct rte_flow_item eth_lacp[] = {
   15813                 :            :                 [0] = {
   15814                 :            :                         .type = RTE_FLOW_ITEM_TYPE_ETH,
   15815                 :            :                         .spec = &lacp_item,
   15816                 :            :                         .mask = &lacp_item,
   15817                 :            :                 },
   15818                 :            :                 [1] = {
   15819                 :            :                         .type = RTE_FLOW_ITEM_TYPE_END,
   15820                 :            :                 },
   15821                 :            :         };
   15822                 :          0 :         struct rte_flow_action miss_action[] = {
   15823                 :            :                 [0] = {
   15824                 :            :                         .type = (enum rte_flow_action_type)
   15825                 :            :                                 MLX5_RTE_FLOW_ACTION_TYPE_DEFAULT_MISS,
   15826                 :            :                 },
   15827                 :            :                 [1] = {
   15828                 :            :                         .type = RTE_FLOW_ACTION_TYPE_END,
   15829                 :            :                 },
   15830                 :            :         };
   15831                 :          0 :         struct mlx5_ctrl_flow_info flow_info = {
   15832                 :            :                 .type = MLX5_CTRL_FLOW_TYPE_LACP_RX,
   15833                 :            :         };
   15834                 :            : 
   15835   [ #  #  #  #  :          0 :         if (!priv->dr_ctx || !priv->hw_ctrl_fdb || !priv->hw_ctrl_fdb->hw_lacp_rx_tbl)
                   #  # ]
   15836                 :            :                 return 0;
   15837                 :          0 :         return flow_hw_create_ctrl_flow(dev, dev,
   15838                 :            :                                         priv->hw_ctrl_fdb->hw_lacp_rx_tbl,
   15839                 :            :                                         eth_lacp, 0, miss_action, 0, &flow_info, false);
   15840                 :            : }
   15841                 :            : 
   15842                 :            : static uint32_t
   15843                 :            : __calc_pattern_flags(const enum mlx5_flow_ctrl_rx_eth_pattern_type eth_pattern_type)
   15844                 :            : {
   15845                 :            :         switch (eth_pattern_type) {
   15846                 :            :         case MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_ALL:
   15847                 :            :                 return MLX5_CTRL_PROMISCUOUS;
   15848                 :            :         case MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_ALL_MCAST:
   15849                 :            :                 return MLX5_CTRL_ALL_MULTICAST;
   15850                 :            :         case MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_BCAST:
   15851                 :            :         case MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_BCAST_VLAN:
   15852                 :            :                 return MLX5_CTRL_BROADCAST;
   15853                 :            :         case MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_IPV4_MCAST:
   15854                 :            :         case MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_IPV4_MCAST_VLAN:
   15855                 :            :                 return MLX5_CTRL_IPV4_MULTICAST;
   15856                 :            :         case MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_IPV6_MCAST:
   15857                 :            :         case MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_IPV6_MCAST_VLAN:
   15858                 :            :                 return MLX5_CTRL_IPV6_MULTICAST;
   15859                 :            :         case MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_DMAC:
   15860                 :            :         case MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_DMAC_VLAN:
   15861                 :            :                 return MLX5_CTRL_DMAC;
   15862                 :            :         default:
   15863                 :            :                 /* Should not reach here. */
   15864                 :            :                 MLX5_ASSERT(false);
   15865                 :            :                 return 0;
   15866                 :            :         }
   15867                 :            : }
   15868                 :            : 
   15869                 :            : static uint32_t
   15870                 :            : __calc_vlan_flags(const enum mlx5_flow_ctrl_rx_eth_pattern_type eth_pattern_type)
   15871                 :            : {
   15872         [ #  # ]:          0 :         switch (eth_pattern_type) {
   15873                 :            :         case MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_BCAST_VLAN:
   15874                 :            :         case MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_IPV4_MCAST_VLAN:
   15875                 :            :         case MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_IPV6_MCAST_VLAN:
   15876                 :            :         case MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_DMAC_VLAN:
   15877                 :            :                 return MLX5_CTRL_VLAN_FILTER;
   15878                 :          0 :         default:
   15879                 :          0 :                 return 0;
   15880                 :            :         }
   15881                 :            : }
   15882                 :            : 
   15883                 :            : static bool
   15884         [ #  # ]:          0 : eth_pattern_type_is_requested(const enum mlx5_flow_ctrl_rx_eth_pattern_type eth_pattern_type,
   15885                 :            :                               uint32_t flags)
   15886                 :            : {
   15887                 :            :         uint32_t pattern_flags = __calc_pattern_flags(eth_pattern_type);
   15888                 :            :         uint32_t vlan_flags = __calc_vlan_flags(eth_pattern_type);
   15889                 :          0 :         bool pattern_requested = !!(pattern_flags & flags);
   15890   [ #  #  #  # ]:          0 :         bool consider_vlan = vlan_flags || (MLX5_CTRL_VLAN_FILTER & flags);
   15891                 :          0 :         bool vlan_requested = !!(vlan_flags & flags);
   15892                 :            : 
   15893         [ #  # ]:          0 :         if (consider_vlan)
   15894                 :          0 :                 return pattern_requested && vlan_requested;
   15895                 :            :         else
   15896                 :            :                 return pattern_requested;
   15897                 :            : }
   15898                 :            : 
   15899                 :            : static bool
   15900                 :            : rss_type_is_requested(struct mlx5_priv *priv,
   15901                 :            :                       const enum mlx5_flow_ctrl_rx_expanded_rss_type rss_type)
   15902                 :            : {
   15903                 :          0 :         struct rte_flow_actions_template *at = priv->hw_ctrl_rx->rss[rss_type];
   15904                 :            :         unsigned int i;
   15905                 :            : 
   15906   [ #  #  #  # ]:          0 :         for (i = 0; at->actions[i].type != RTE_FLOW_ACTION_TYPE_END; ++i) {
   15907   [ #  #  #  # ]:          0 :                 if (at->actions[i].type == RTE_FLOW_ACTION_TYPE_RSS) {
   15908                 :          0 :                         const struct rte_flow_action_rss *rss = at->actions[i].conf;
   15909                 :          0 :                         uint64_t rss_types = rss->types;
   15910                 :            : 
   15911   [ #  #  #  # ]:          0 :                         if ((rss_types & priv->rss_conf.rss_hf) != rss_types)
   15912                 :            :                                 return false;
   15913                 :            :                 }
   15914                 :            :         }
   15915                 :            :         return true;
   15916                 :            : }
   15917                 :            : 
   15918                 :            : static const struct rte_flow_item_eth *
   15919                 :            : __get_eth_spec(const enum mlx5_flow_ctrl_rx_eth_pattern_type pattern)
   15920                 :            : {
   15921                 :          0 :         switch (pattern) {
   15922                 :            :         case MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_ALL:
   15923                 :            :                 return &ctrl_rx_eth_promisc_spec;
   15924                 :          0 :         case MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_ALL_MCAST:
   15925                 :          0 :                 return &ctrl_rx_eth_mcast_spec;
   15926                 :          0 :         case MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_BCAST:
   15927                 :            :         case MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_BCAST_VLAN:
   15928                 :          0 :                 return &ctrl_rx_eth_bcast_spec;
   15929                 :          0 :         case MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_IPV4_MCAST:
   15930                 :            :         case MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_IPV4_MCAST_VLAN:
   15931                 :          0 :                 return &ctrl_rx_eth_ipv4_mcast_spec;
   15932                 :          0 :         case MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_IPV6_MCAST:
   15933                 :            :         case MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_IPV6_MCAST_VLAN:
   15934                 :          0 :                 return &ctrl_rx_eth_ipv6_mcast_spec;
   15935                 :          0 :         default:
   15936                 :            :                 /* This case should not be reached. */
   15937                 :            :                 MLX5_ASSERT(false);
   15938                 :          0 :                 return NULL;
   15939                 :            :         }
   15940                 :            : }
   15941                 :            : 
   15942                 :            : static int
   15943   [ #  #  #  #  :          0 : __flow_hw_ctrl_flows_single(struct rte_eth_dev *dev,
                   #  # ]
   15944                 :            :                             struct rte_flow_template_table *tbl,
   15945                 :            :                             const enum mlx5_flow_ctrl_rx_eth_pattern_type pattern_type,
   15946                 :            :                             const enum mlx5_flow_ctrl_rx_expanded_rss_type rss_type)
   15947                 :            : {
   15948                 :            :         const struct rte_flow_item_eth *eth_spec = __get_eth_spec(pattern_type);
   15949                 :            :         struct rte_flow_item items[5];
   15950                 :          0 :         struct rte_flow_action actions[] = {
   15951                 :            :                 { .type = RTE_FLOW_ACTION_TYPE_RSS },
   15952                 :            :                 { .type = RTE_FLOW_ACTION_TYPE_END },
   15953                 :            :         };
   15954                 :          0 :         struct mlx5_ctrl_flow_info flow_info = {
   15955                 :            :                 .type = MLX5_CTRL_FLOW_TYPE_DEFAULT_RX_RSS,
   15956                 :            :         };
   15957                 :            : 
   15958         [ #  # ]:          0 :         if (!eth_spec)
   15959                 :            :                 return -EINVAL;
   15960                 :            :         memset(items, 0, sizeof(items));
   15961                 :          0 :         items[0] = (struct rte_flow_item){
   15962                 :            :                 .type = RTE_FLOW_ITEM_TYPE_ETH,
   15963                 :            :                 .spec = eth_spec,
   15964                 :            :         };
   15965      [ #  #  # ]:          0 :         items[1] = (struct rte_flow_item){ .type = RTE_FLOW_ITEM_TYPE_VOID };
   15966      [ #  #  # ]:          0 :         items[2] = flow_hw_get_ctrl_rx_l3_item(rss_type);
   15967                 :          0 :         items[3] = flow_hw_get_ctrl_rx_l4_item(rss_type);
   15968                 :          0 :         items[4] = (struct rte_flow_item){ .type = RTE_FLOW_ITEM_TYPE_END };
   15969                 :            :         /* Without VLAN filtering, only a single flow rule must be created. */
   15970                 :          0 :         return flow_hw_create_ctrl_flow(dev, dev, tbl, items, 0, actions, 0, &flow_info, false);
   15971                 :            : }
   15972                 :            : 
   15973                 :            : static int
   15974                 :          0 : __flow_hw_ctrl_flows_single_vlan(struct rte_eth_dev *dev,
   15975                 :            :                                  struct rte_flow_template_table *tbl,
   15976                 :            :                                  const enum mlx5_flow_ctrl_rx_eth_pattern_type pattern_type,
   15977                 :            :                                  const enum mlx5_flow_ctrl_rx_expanded_rss_type rss_type)
   15978                 :            : {
   15979   [ #  #  #  #  :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
                   #  # ]
   15980                 :            :         const struct rte_flow_item_eth *eth_spec = __get_eth_spec(pattern_type);
   15981                 :            :         struct rte_flow_item items[5];
   15982                 :          0 :         struct rte_flow_action actions[] = {
   15983                 :            :                 { .type = RTE_FLOW_ACTION_TYPE_RSS },
   15984                 :            :                 { .type = RTE_FLOW_ACTION_TYPE_END },
   15985                 :            :         };
   15986                 :          0 :         struct mlx5_ctrl_flow_info flow_info = {
   15987                 :            :                 .type = MLX5_CTRL_FLOW_TYPE_DEFAULT_RX_RSS,
   15988                 :            :         };
   15989                 :            :         unsigned int i;
   15990                 :            : 
   15991         [ #  # ]:          0 :         if (!eth_spec)
   15992                 :            :                 return -EINVAL;
   15993                 :            :         memset(items, 0, sizeof(items));
   15994                 :          0 :         items[0] = (struct rte_flow_item){
   15995                 :            :                 .type = RTE_FLOW_ITEM_TYPE_ETH,
   15996                 :            :                 .spec = eth_spec,
   15997                 :            :         };
   15998                 :            :         /* Optional VLAN for now will be VOID - will be filled later. */
   15999      [ #  #  # ]:          0 :         items[1] = (struct rte_flow_item){ .type = RTE_FLOW_ITEM_TYPE_VLAN };
   16000      [ #  #  # ]:          0 :         items[2] = flow_hw_get_ctrl_rx_l3_item(rss_type);
   16001                 :          0 :         items[3] = flow_hw_get_ctrl_rx_l4_item(rss_type);
   16002                 :          0 :         items[4] = (struct rte_flow_item){ .type = RTE_FLOW_ITEM_TYPE_END };
   16003                 :            :         /* Since VLAN filtering is done, create a single flow rule for each registered vid. */
   16004         [ #  # ]:          0 :         for (i = 0; i < priv->vlan_filter_n; ++i) {
   16005                 :          0 :                 uint16_t vlan = priv->vlan_filter[i];
   16006                 :          0 :                 struct rte_flow_item_vlan vlan_spec = {
   16007         [ #  # ]:          0 :                         .hdr.vlan_tci = rte_cpu_to_be_16(vlan),
   16008                 :            :                 };
   16009                 :            : 
   16010                 :          0 :                 items[1].spec = &vlan_spec;
   16011         [ #  # ]:          0 :                 if (flow_hw_create_ctrl_flow(dev, dev,
   16012                 :            :                                              tbl, items, 0, actions, 0, &flow_info, false))
   16013                 :          0 :                         return -rte_errno;
   16014                 :            :         }
   16015                 :            :         return 0;
   16016                 :            : }
   16017                 :            : 
   16018                 :            : static int
   16019                 :          0 : __flow_hw_ctrl_flows_unicast_create(struct rte_eth_dev *dev,
   16020                 :            :                                     struct rte_flow_template_table *tbl,
   16021                 :            :                                     const enum mlx5_flow_ctrl_rx_expanded_rss_type rss_type,
   16022                 :            :                                     const struct rte_ether_addr *addr)
   16023                 :            : {
   16024                 :          0 :         struct rte_flow_item_eth eth_spec = {
   16025                 :            :                 .hdr.dst_addr = *addr,
   16026                 :            :         };
   16027                 :            :         struct rte_flow_item items[5];
   16028                 :          0 :         struct rte_flow_action actions[] = {
   16029                 :            :                 { .type = RTE_FLOW_ACTION_TYPE_RSS },
   16030                 :            :                 { .type = RTE_FLOW_ACTION_TYPE_END },
   16031                 :            :         };
   16032      [ #  #  # ]:          0 :         struct mlx5_ctrl_flow_info flow_info = {
   16033                 :            :                 .type = MLX5_CTRL_FLOW_TYPE_DEFAULT_RX_RSS_UNICAST_DMAC,
   16034                 :            :                 .uc = {
   16035                 :            :                         .dmac = *addr,
   16036                 :            :                 },
   16037                 :            :         };
   16038                 :            : 
   16039                 :            :         memset(items, 0, sizeof(items));
   16040                 :          0 :         items[0] = (struct rte_flow_item){
   16041                 :            :                 .type = RTE_FLOW_ITEM_TYPE_ETH,
   16042                 :            :                 .spec = &eth_spec,
   16043                 :            :         };
   16044      [ #  #  # ]:          0 :         items[1] = (struct rte_flow_item){ .type = RTE_FLOW_ITEM_TYPE_VOID };
   16045      [ #  #  # ]:          0 :         items[2] = flow_hw_get_ctrl_rx_l3_item(rss_type);
   16046                 :          0 :         items[3] = flow_hw_get_ctrl_rx_l4_item(rss_type);
   16047                 :          0 :         items[4] = (struct rte_flow_item){ .type = RTE_FLOW_ITEM_TYPE_END };
   16048                 :            : 
   16049         [ #  # ]:          0 :         if (flow_hw_create_ctrl_flow(dev, dev, tbl, items, 0, actions, 0, &flow_info, false))
   16050                 :          0 :                 return -rte_errno;
   16051                 :            : 
   16052                 :            :         return 0;
   16053                 :            : }
   16054                 :            : 
   16055                 :            : static int
   16056                 :          0 : __flow_hw_ctrl_flows_unicast(struct rte_eth_dev *dev,
   16057                 :            :                              struct rte_flow_template_table *tbl,
   16058                 :            :                              const enum mlx5_flow_ctrl_rx_expanded_rss_type rss_type)
   16059                 :            : {
   16060                 :            :         unsigned int i;
   16061                 :            :         int ret;
   16062                 :            : 
   16063         [ #  # ]:          0 :         for (i = 0; i < MLX5_MAX_MAC_ADDRESSES; ++i) {
   16064         [ #  # ]:          0 :                 struct rte_ether_addr *mac = &dev->data->mac_addrs[i];
   16065                 :            : 
   16066         [ #  # ]:          0 :                 if (rte_is_zero_ether_addr(mac))
   16067                 :          0 :                         continue;
   16068                 :            : 
   16069                 :          0 :                 ret = __flow_hw_ctrl_flows_unicast_create(dev, tbl, rss_type, mac);
   16070         [ #  # ]:          0 :                 if (ret < 0)
   16071                 :          0 :                         return ret;
   16072                 :            :         }
   16073                 :            :         return 0;
   16074                 :            : }
   16075                 :            : 
   16076                 :            : static int
   16077                 :          0 : __flow_hw_ctrl_flows_unicast_vlan_create(struct rte_eth_dev *dev,
   16078                 :            :                                          struct rte_flow_template_table *tbl,
   16079                 :            :                                          const enum mlx5_flow_ctrl_rx_expanded_rss_type rss_type,
   16080                 :            :                                          const struct rte_ether_addr *addr,
   16081                 :            :                                          const uint16_t vid)
   16082                 :            : {
   16083                 :          0 :         struct rte_flow_item_eth eth_spec = {
   16084                 :            :                 .hdr.dst_addr = *addr,
   16085                 :            :         };
   16086                 :          0 :         struct rte_flow_item_vlan vlan_spec = {
   16087         [ #  # ]:          0 :                 .tci = rte_cpu_to_be_16(vid),
   16088                 :            :         };
   16089                 :            :         struct rte_flow_item items[5];
   16090                 :          0 :         struct rte_flow_action actions[] = {
   16091                 :            :                 { .type = RTE_FLOW_ACTION_TYPE_RSS },
   16092                 :            :                 { .type = RTE_FLOW_ACTION_TYPE_END },
   16093                 :            :         };
   16094      [ #  #  # ]:          0 :         struct mlx5_ctrl_flow_info flow_info = {
   16095                 :            :                 .type = MLX5_CTRL_FLOW_TYPE_DEFAULT_RX_RSS_UNICAST_DMAC_VLAN,
   16096                 :            :                 .uc = {
   16097                 :            :                         .dmac = *addr,
   16098                 :            :                         .vlan = vid,
   16099                 :            :                 },
   16100                 :            :         };
   16101                 :            : 
   16102                 :            :         memset(items, 0, sizeof(items));
   16103                 :          0 :         items[0] = (struct rte_flow_item){
   16104                 :            :                 .type = RTE_FLOW_ITEM_TYPE_ETH,
   16105                 :            :                 .spec = &eth_spec,
   16106                 :            :         };
   16107      [ #  #  # ]:          0 :         items[1] = (struct rte_flow_item){
   16108                 :            :                 .type = RTE_FLOW_ITEM_TYPE_VLAN,
   16109                 :            :                 .spec = &vlan_spec,
   16110                 :            :         };
   16111      [ #  #  # ]:          0 :         items[2] = flow_hw_get_ctrl_rx_l3_item(rss_type);
   16112                 :          0 :         items[3] = flow_hw_get_ctrl_rx_l4_item(rss_type);
   16113                 :          0 :         items[4] = (struct rte_flow_item){ .type = RTE_FLOW_ITEM_TYPE_END };
   16114                 :            : 
   16115         [ #  # ]:          0 :         if (flow_hw_create_ctrl_flow(dev, dev, tbl, items, 0, actions, 0, &flow_info, false))
   16116                 :          0 :                 return -rte_errno;
   16117                 :            : 
   16118                 :            :         return 0;
   16119                 :            : }
   16120                 :            : 
   16121                 :            : static int
   16122                 :          0 : __flow_hw_ctrl_flows_unicast_vlan(struct rte_eth_dev *dev,
   16123                 :            :                                   struct rte_flow_template_table *tbl,
   16124                 :            :                                   const enum mlx5_flow_ctrl_rx_expanded_rss_type rss_type)
   16125                 :            : {
   16126                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16127                 :            :         unsigned int i;
   16128                 :            :         unsigned int j;
   16129                 :            : 
   16130         [ #  # ]:          0 :         for (i = 0; i < MLX5_MAX_MAC_ADDRESSES; ++i) {
   16131         [ #  # ]:          0 :                 struct rte_ether_addr *mac = &dev->data->mac_addrs[i];
   16132                 :            : 
   16133         [ #  # ]:          0 :                 if (rte_is_zero_ether_addr(mac))
   16134                 :          0 :                         continue;
   16135                 :            : 
   16136         [ #  # ]:          0 :                 for (j = 0; j < priv->vlan_filter_n; ++j) {
   16137                 :          0 :                         uint16_t vlan = priv->vlan_filter[j];
   16138                 :            :                         int ret;
   16139                 :            : 
   16140                 :          0 :                         ret = __flow_hw_ctrl_flows_unicast_vlan_create(dev, tbl, rss_type,
   16141                 :            :                                                                        mac, vlan);
   16142         [ #  # ]:          0 :                         if (ret < 0)
   16143                 :          0 :                                 return ret;
   16144                 :            :                 }
   16145                 :            :         }
   16146                 :            :         return 0;
   16147                 :            : }
   16148                 :            : 
   16149                 :            : static int
   16150                 :          0 : __flow_hw_ctrl_flows(struct rte_eth_dev *dev,
   16151                 :            :                      struct rte_flow_template_table *tbl,
   16152                 :            :                      const enum mlx5_flow_ctrl_rx_eth_pattern_type pattern_type,
   16153                 :            :                      const enum mlx5_flow_ctrl_rx_expanded_rss_type rss_type)
   16154                 :            : {
   16155   [ #  #  #  #  :          0 :         switch (pattern_type) {
                      # ]
   16156                 :          0 :         case MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_ALL:
   16157                 :            :         case MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_ALL_MCAST:
   16158                 :            :         case MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_BCAST:
   16159                 :            :         case MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_IPV4_MCAST:
   16160                 :            :         case MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_IPV6_MCAST:
   16161                 :          0 :                 return __flow_hw_ctrl_flows_single(dev, tbl, pattern_type, rss_type);
   16162                 :          0 :         case MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_BCAST_VLAN:
   16163                 :            :         case MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_IPV4_MCAST_VLAN:
   16164                 :            :         case MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_IPV6_MCAST_VLAN:
   16165                 :          0 :                 return __flow_hw_ctrl_flows_single_vlan(dev, tbl, pattern_type, rss_type);
   16166                 :          0 :         case MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_DMAC:
   16167                 :          0 :                 return __flow_hw_ctrl_flows_unicast(dev, tbl, rss_type);
   16168                 :          0 :         case MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_DMAC_VLAN:
   16169                 :          0 :                 return __flow_hw_ctrl_flows_unicast_vlan(dev, tbl, rss_type);
   16170                 :          0 :         default:
   16171                 :            :                 /* Should not reach here. */
   16172                 :            :                 MLX5_ASSERT(false);
   16173                 :          0 :                 rte_errno = EINVAL;
   16174                 :          0 :                 return -EINVAL;
   16175                 :            :         }
   16176                 :            : }
   16177                 :            : 
   16178                 :            : 
   16179                 :            : int
   16180                 :          0 : mlx5_flow_hw_ctrl_flows(struct rte_eth_dev *dev, uint32_t flags)
   16181                 :            : {
   16182                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16183                 :            :         struct mlx5_flow_hw_ctrl_rx *hw_ctrl_rx;
   16184                 :            :         unsigned int i;
   16185                 :            :         int j;
   16186                 :            :         int ret = 0;
   16187                 :            : 
   16188                 :            :         RTE_SET_USED(priv);
   16189                 :            :         RTE_SET_USED(flags);
   16190         [ #  # ]:          0 :         if (!priv->dr_ctx) {
   16191                 :          0 :                 DRV_LOG(DEBUG, "port %u Control flow rules will not be created. "
   16192                 :            :                                "HWS needs to be configured beforehand.",
   16193                 :            :                                dev->data->port_id);
   16194                 :          0 :                 return 0;
   16195                 :            :         }
   16196         [ #  # ]:          0 :         if (!priv->hw_ctrl_rx) {
   16197                 :          0 :                 DRV_LOG(ERR, "port %u Control flow rules templates were not created.",
   16198                 :            :                         dev->data->port_id);
   16199                 :          0 :                 rte_errno = EINVAL;
   16200                 :          0 :                 return -rte_errno;
   16201                 :            :         }
   16202                 :            :         hw_ctrl_rx = priv->hw_ctrl_rx;
   16203         [ #  # ]:          0 :         for (i = 0; i < MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_MAX; ++i) {
   16204                 :            :                 const enum mlx5_flow_ctrl_rx_eth_pattern_type eth_pattern_type = i;
   16205                 :            : 
   16206         [ #  # ]:          0 :                 if (!eth_pattern_type_is_requested(eth_pattern_type, flags))
   16207                 :          0 :                         continue;
   16208         [ #  # ]:          0 :                 for (j = 0; j < MLX5_FLOW_HW_CTRL_RX_EXPANDED_RSS_MAX; ++j) {
   16209                 :          0 :                         const enum mlx5_flow_ctrl_rx_expanded_rss_type rss_type = j;
   16210                 :            :                         struct rte_flow_actions_template *at;
   16211                 :            :                         struct mlx5_flow_hw_ctrl_rx_table *tmpls = &hw_ctrl_rx->tables[i][j];
   16212                 :          0 :                         const struct mlx5_flow_template_table_cfg cfg = {
   16213                 :            :                                 .attr = tmpls->attr,
   16214                 :            :                                 .external = 0,
   16215                 :            :                         };
   16216                 :            : 
   16217         [ #  # ]:          0 :                         if (!hw_ctrl_rx->rss[rss_type]) {
   16218                 :          0 :                                 at = flow_hw_create_ctrl_rx_rss_template(dev, rss_type);
   16219         [ #  # ]:          0 :                                 if (!at)
   16220                 :          0 :                                         return -rte_errno;
   16221                 :          0 :                                 hw_ctrl_rx->rss[rss_type] = at;
   16222                 :            :                         } else {
   16223                 :          0 :                                 at = hw_ctrl_rx->rss[rss_type];
   16224                 :            :                         }
   16225         [ #  # ]:          0 :                         if (!rss_type_is_requested(priv, rss_type))
   16226                 :          0 :                                 continue;
   16227         [ #  # ]:          0 :                         if (!tmpls->tbl) {
   16228                 :          0 :                                 tmpls->tbl = flow_hw_table_create(dev, &cfg,
   16229                 :            :                                                                   &tmpls->pt, 1, &at, 1, NULL);
   16230         [ #  # ]:          0 :                                 if (!tmpls->tbl) {
   16231                 :          0 :                                         DRV_LOG(ERR, "port %u Failed to create template table "
   16232                 :            :                                                      "for control flow rules. Unable to create "
   16233                 :            :                                                      "control flow rules.",
   16234                 :            :                                                      dev->data->port_id);
   16235                 :          0 :                                         return -rte_errno;
   16236                 :            :                                 }
   16237                 :            :                         }
   16238                 :            : 
   16239                 :          0 :                         ret = __flow_hw_ctrl_flows(dev, tmpls->tbl, eth_pattern_type, rss_type);
   16240         [ #  # ]:          0 :                         if (ret) {
   16241                 :          0 :                                 DRV_LOG(ERR, "port %u Failed to create control flow rule.",
   16242                 :            :                                         dev->data->port_id);
   16243                 :          0 :                                 return ret;
   16244                 :            :                         }
   16245                 :            :                 }
   16246                 :            :         }
   16247                 :            :         return 0;
   16248                 :            : }
   16249                 :            : 
   16250                 :            : static int
   16251                 :          0 : mlx5_flow_hw_ctrl_flow_single(struct rte_eth_dev *dev,
   16252                 :            :                               const enum mlx5_flow_ctrl_rx_eth_pattern_type eth_pattern_type,
   16253                 :            :                               const struct rte_ether_addr *addr,
   16254                 :            :                               const uint16_t vlan)
   16255                 :            : {
   16256                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16257                 :            :         struct mlx5_flow_hw_ctrl_rx *hw_ctrl_rx;
   16258                 :            :         unsigned int j;
   16259                 :            :         int ret = 0;
   16260                 :            : 
   16261         [ #  # ]:          0 :         if (!priv->dr_ctx) {
   16262                 :          0 :                 DRV_LOG(DEBUG, "port %u Control flow rules will not be created. "
   16263                 :            :                                "HWS needs to be configured beforehand.",
   16264                 :            :                                dev->data->port_id);
   16265                 :          0 :                 return 0;
   16266                 :            :         }
   16267         [ #  # ]:          0 :         if (!priv->hw_ctrl_rx) {
   16268                 :          0 :                 DRV_LOG(ERR, "port %u Control flow rules templates were not created.",
   16269                 :            :                         dev->data->port_id);
   16270                 :          0 :                 rte_errno = EINVAL;
   16271                 :          0 :                 return -rte_errno;
   16272                 :            :         }
   16273                 :            :         hw_ctrl_rx = priv->hw_ctrl_rx;
   16274                 :            : 
   16275                 :            :         /* TODO: this part should be somehow refactored. It's common with common flow creation. */
   16276         [ #  # ]:          0 :         for (j = 0; j < MLX5_FLOW_HW_CTRL_RX_EXPANDED_RSS_MAX; ++j) {
   16277                 :            :                 const enum mlx5_flow_ctrl_rx_expanded_rss_type rss_type = j;
   16278                 :            :                 const unsigned int pti = eth_pattern_type;
   16279                 :            :                 struct rte_flow_actions_template *at;
   16280                 :            :                 struct mlx5_flow_hw_ctrl_rx_table *tmpls = &hw_ctrl_rx->tables[pti][j];
   16281                 :          0 :                 const struct mlx5_flow_template_table_cfg cfg = {
   16282                 :            :                         .attr = tmpls->attr,
   16283                 :            :                         .external = 0,
   16284                 :            :                 };
   16285                 :            : 
   16286         [ #  # ]:          0 :                 if (!hw_ctrl_rx->rss[rss_type]) {
   16287                 :          0 :                         at = flow_hw_create_ctrl_rx_rss_template(dev, rss_type);
   16288         [ #  # ]:          0 :                         if (!at)
   16289                 :          0 :                                 return -rte_errno;
   16290                 :          0 :                         hw_ctrl_rx->rss[rss_type] = at;
   16291                 :            :                 } else {
   16292                 :          0 :                         at = hw_ctrl_rx->rss[rss_type];
   16293                 :            :                 }
   16294         [ #  # ]:          0 :                 if (!rss_type_is_requested(priv, rss_type))
   16295                 :          0 :                         continue;
   16296         [ #  # ]:          0 :                 if (!tmpls->tbl) {
   16297                 :          0 :                         tmpls->tbl = flow_hw_table_create(dev, &cfg,
   16298                 :            :                                                           &tmpls->pt, 1, &at, 1, NULL);
   16299         [ #  # ]:          0 :                         if (!tmpls->tbl) {
   16300                 :          0 :                                 DRV_LOG(ERR, "port %u Failed to create template table "
   16301                 :            :                                              "for control flow rules. Unable to create "
   16302                 :            :                                              "control flow rules.",
   16303                 :            :                                              dev->data->port_id);
   16304                 :          0 :                                 return -rte_errno;
   16305                 :            :                         }
   16306                 :            :                 }
   16307                 :            : 
   16308                 :            :                 MLX5_ASSERT(eth_pattern_type == MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_DMAC ||
   16309                 :            :                             eth_pattern_type == MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_DMAC_VLAN);
   16310                 :            : 
   16311         [ #  # ]:          0 :                 if (eth_pattern_type == MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_DMAC)
   16312                 :          0 :                         ret = __flow_hw_ctrl_flows_unicast_create(dev, tmpls->tbl, rss_type, addr);
   16313                 :            :                 else
   16314                 :          0 :                         ret = __flow_hw_ctrl_flows_unicast_vlan_create(dev, tmpls->tbl, rss_type,
   16315                 :            :                                                                        addr, vlan);
   16316         [ #  # ]:          0 :                 if (ret) {
   16317                 :          0 :                         DRV_LOG(ERR, "port %u Failed to create unicast control flow rule.",
   16318                 :            :                                 dev->data->port_id);
   16319                 :          0 :                         return ret;
   16320                 :            :                 }
   16321                 :            :         }
   16322                 :            : 
   16323                 :            :         return 0;
   16324                 :            : }
   16325                 :            : 
   16326                 :            : int
   16327                 :          0 : mlx5_flow_hw_ctrl_flow_dmac(struct rte_eth_dev *dev,
   16328                 :            :                             const struct rte_ether_addr *addr)
   16329                 :            : {
   16330                 :          0 :         return mlx5_flow_hw_ctrl_flow_single(dev, MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_DMAC,
   16331                 :            :                                              addr, 0);
   16332                 :            : }
   16333                 :            : 
   16334                 :            : int
   16335                 :          0 : mlx5_flow_hw_ctrl_flow_dmac_destroy(struct rte_eth_dev *dev,
   16336                 :            :                                     const struct rte_ether_addr *addr)
   16337                 :            : {
   16338                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16339                 :            :         struct mlx5_ctrl_flow_entry *entry;
   16340                 :            :         struct mlx5_ctrl_flow_entry *tmp;
   16341                 :            :         int ret;
   16342                 :            : 
   16343                 :            :         /*
   16344                 :            :          * HWS does not have automatic RSS flow expansion,
   16345                 :            :          * so each variant of the control flow rule is a separate entry in the list.
   16346                 :            :          * In that case, the whole list must be traversed.
   16347                 :            :          */
   16348                 :          0 :         entry = LIST_FIRST(&priv->hw_ctrl_flows);
   16349         [ #  # ]:          0 :         while (entry != NULL) {
   16350                 :          0 :                 tmp = LIST_NEXT(entry, next);
   16351                 :            : 
   16352   [ #  #  #  # ]:          0 :                 if (entry->info.type != MLX5_CTRL_FLOW_TYPE_DEFAULT_RX_RSS_UNICAST_DMAC ||
   16353                 :            :                     !rte_is_same_ether_addr(addr, &entry->info.uc.dmac)) {
   16354                 :            :                         entry = tmp;
   16355                 :          0 :                         continue;
   16356                 :            :                 }
   16357                 :            : 
   16358                 :          0 :                 ret = flow_hw_destroy_ctrl_flow(dev, entry->flow);
   16359         [ #  # ]:          0 :                 LIST_REMOVE(entry, next);
   16360                 :          0 :                 mlx5_free(entry);
   16361         [ #  # ]:          0 :                 if (ret)
   16362                 :          0 :                         return ret;
   16363                 :            : 
   16364                 :            :                 entry = tmp;
   16365                 :            :         }
   16366                 :            :         return 0;
   16367                 :            : }
   16368                 :            : 
   16369                 :            : int
   16370                 :          0 : mlx5_flow_hw_ctrl_flow_dmac_vlan(struct rte_eth_dev *dev,
   16371                 :            :                                  const struct rte_ether_addr *addr,
   16372                 :            :                                  const uint16_t vlan)
   16373                 :            : {
   16374                 :          0 :         return mlx5_flow_hw_ctrl_flow_single(dev, MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_DMAC_VLAN,
   16375                 :            :                                              addr, vlan);
   16376                 :            : }
   16377                 :            : 
   16378                 :            : int
   16379                 :          0 : mlx5_flow_hw_ctrl_flow_dmac_vlan_destroy(struct rte_eth_dev *dev,
   16380                 :            :                                          const struct rte_ether_addr *addr,
   16381                 :            :                                          const uint16_t vlan)
   16382                 :            : {
   16383                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16384                 :            :         struct mlx5_ctrl_flow_entry *entry;
   16385                 :            :         struct mlx5_ctrl_flow_entry *tmp;
   16386                 :            :         int ret;
   16387                 :            : 
   16388                 :            :         /*
   16389                 :            :          * HWS does not have automatic RSS flow expansion,
   16390                 :            :          * so each variant of the control flow rule is a separate entry in the list.
   16391                 :            :          * In that case, the whole list must be traversed.
   16392                 :            :          */
   16393                 :          0 :         entry = LIST_FIRST(&priv->hw_ctrl_flows);
   16394         [ #  # ]:          0 :         while (entry != NULL) {
   16395                 :          0 :                 tmp = LIST_NEXT(entry, next);
   16396                 :            : 
   16397   [ #  #  #  # ]:          0 :                 if (entry->info.type != MLX5_CTRL_FLOW_TYPE_DEFAULT_RX_RSS_UNICAST_DMAC_VLAN ||
   16398                 :          0 :                     !rte_is_same_ether_addr(addr, &entry->info.uc.dmac) ||
   16399         [ #  # ]:          0 :                     vlan != entry->info.uc.vlan) {
   16400                 :            :                         entry = tmp;
   16401                 :          0 :                         continue;
   16402                 :            :                 }
   16403                 :            : 
   16404                 :          0 :                 ret = flow_hw_destroy_ctrl_flow(dev, entry->flow);
   16405         [ #  # ]:          0 :                 LIST_REMOVE(entry, next);
   16406                 :          0 :                 mlx5_free(entry);
   16407         [ #  # ]:          0 :                 if (ret)
   16408                 :          0 :                         return ret;
   16409                 :            : 
   16410                 :            :                 entry = tmp;
   16411                 :            :         }
   16412                 :            :         return 0;
   16413                 :            : }
   16414                 :            : 
   16415                 :            : static __rte_always_inline uint32_t
   16416                 :            : mlx5_reformat_domain_to_tbl_type(const struct rte_flow_indir_action_conf *domain)
   16417                 :            : {
   16418                 :            :         uint32_t tbl_type;
   16419                 :            : 
   16420                 :          0 :         if (domain->transfer)
   16421                 :            :                 tbl_type = MLX5DR_ACTION_FLAG_HWS_FDB;
   16422         [ #  # ]:          0 :         else if (domain->egress)
   16423                 :            :                 tbl_type = MLX5DR_ACTION_FLAG_HWS_TX;
   16424         [ #  # ]:          0 :         else if (domain->ingress)
   16425                 :            :                 tbl_type = MLX5DR_ACTION_FLAG_HWS_RX;
   16426                 :            :         else
   16427                 :            :                 tbl_type = UINT32_MAX;
   16428                 :            :         return tbl_type;
   16429                 :            : }
   16430                 :            : 
   16431                 :            : static struct mlx5_hw_encap_decap_action *
   16432                 :          0 : __mlx5_reformat_create(struct rte_eth_dev *dev,
   16433                 :            :                        const struct rte_flow_action_raw_encap *encap_conf,
   16434                 :            :                        const struct rte_flow_indir_action_conf *domain,
   16435                 :            :                        enum mlx5dr_action_type type)
   16436                 :            : {
   16437         [ #  # ]:          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16438                 :            :         struct mlx5_hw_encap_decap_action *handle;
   16439                 :            :         struct mlx5dr_action_reformat_header hdr;
   16440                 :            :         uint32_t flags;
   16441                 :            : 
   16442                 :            :         flags = mlx5_reformat_domain_to_tbl_type(domain);
   16443                 :          0 :         flags |= (uint32_t)MLX5DR_ACTION_FLAG_SHARED;
   16444         [ #  # ]:          0 :         if (flags == UINT32_MAX) {
   16445                 :          0 :                 DRV_LOG(ERR, "Reformat: invalid indirect action configuration");
   16446                 :          0 :                 return NULL;
   16447                 :            :         }
   16448                 :            :         /* Allocate new list entry. */
   16449                 :          0 :         handle = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*handle), 0, SOCKET_ID_ANY);
   16450         [ #  # ]:          0 :         if (!handle) {
   16451                 :          0 :                 DRV_LOG(ERR, "Reformat: failed to allocate reformat entry");
   16452                 :          0 :                 return NULL;
   16453                 :            :         }
   16454                 :          0 :         handle->action_type = type;
   16455         [ #  # ]:          0 :         hdr.sz = encap_conf ? encap_conf->size : 0;
   16456         [ #  # ]:          0 :         hdr.data = encap_conf ? encap_conf->data : NULL;
   16457                 :          0 :         handle->action = mlx5dr_action_create_reformat(priv->dr_ctx,
   16458                 :            :                                         type, 1, &hdr, 0, flags);
   16459         [ #  # ]:          0 :         if (!handle->action) {
   16460                 :          0 :                 DRV_LOG(ERR, "Reformat: failed to create reformat action");
   16461                 :          0 :                 mlx5_free(handle);
   16462                 :          0 :                 return NULL;
   16463                 :            :         }
   16464                 :            :         return handle;
   16465                 :            : }
   16466                 :            : 
   16467                 :            : /**
   16468                 :            :  * Create mlx5 reformat action.
   16469                 :            :  *
   16470                 :            :  * @param[in] dev
   16471                 :            :  *   Pointer to rte_eth_dev structure.
   16472                 :            :  * @param[in] conf
   16473                 :            :  *   Pointer to the indirect action parameters.
   16474                 :            :  * @param[in] encap_action
   16475                 :            :  *   Pointer to the raw_encap action configuration.
   16476                 :            :  * @param[in] decap_action
   16477                 :            :  *   Pointer to the raw_decap action configuration.
   16478                 :            :  * @param[out] error
   16479                 :            :  *   Pointer to error structure.
   16480                 :            :  *
   16481                 :            :  * @return
   16482                 :            :  *   A valid shared action handle in case of success, NULL otherwise and
   16483                 :            :  *   rte_errno is set.
   16484                 :            :  */
   16485                 :            : struct mlx5_hw_encap_decap_action*
   16486                 :          0 : mlx5_reformat_action_create(struct rte_eth_dev *dev,
   16487                 :            :                             const struct rte_flow_indir_action_conf *conf,
   16488                 :            :                             const struct rte_flow_action *encap_action,
   16489                 :            :                             const struct rte_flow_action *decap_action,
   16490                 :            :                             struct rte_flow_error *error)
   16491                 :            : {
   16492                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16493                 :            :         struct mlx5_hw_encap_decap_action *handle;
   16494                 :            :         const struct rte_flow_action_raw_encap *encap = NULL;
   16495                 :            :         const struct rte_flow_action_raw_decap *decap = NULL;
   16496                 :            :         enum mlx5dr_action_type type = MLX5DR_ACTION_TYP_LAST;
   16497                 :            : 
   16498                 :            :         MLX5_ASSERT(!encap_action || encap_action->type == RTE_FLOW_ACTION_TYPE_RAW_ENCAP);
   16499                 :            :         MLX5_ASSERT(!decap_action || decap_action->type == RTE_FLOW_ACTION_TYPE_RAW_DECAP);
   16500         [ #  # ]:          0 :         if (priv->sh->config.dv_flow_en != 2) {
   16501                 :          0 :                 rte_flow_error_set(error, ENOTSUP,
   16502                 :            :                                    RTE_FLOW_ERROR_TYPE_ACTION, encap_action,
   16503                 :            :                                    "Reformat: hardware does not support");
   16504                 :          0 :                 return NULL;
   16505                 :            :         }
   16506   [ #  #  #  # ]:          0 :         if (!conf || (conf->transfer + conf->egress + conf->ingress != 1)) {
   16507                 :          0 :                 rte_flow_error_set(error, EINVAL,
   16508                 :            :                                    RTE_FLOW_ERROR_TYPE_ACTION, encap_action,
   16509                 :            :                                    "Reformat: domain should be specified");
   16510                 :          0 :                 return NULL;
   16511                 :            :         }
   16512   [ #  #  #  #  :          0 :         if ((encap_action && !encap_action->conf) || (decap_action && !decap_action->conf)) {
             #  #  #  # ]
   16513                 :          0 :                 rte_flow_error_set(error, EINVAL,
   16514                 :            :                                    RTE_FLOW_ERROR_TYPE_ACTION, encap_action,
   16515                 :            :                                    "Reformat: missed action configuration");
   16516                 :          0 :                 return NULL;
   16517                 :            :         }
   16518         [ #  # ]:          0 :         if (encap_action && !decap_action) {
   16519                 :          0 :                 encap = (const struct rte_flow_action_raw_encap *)encap_action->conf;
   16520         [ #  # ]:          0 :                 if (!encap->size || encap->size > MLX5_ENCAP_MAX_LEN ||
   16521                 :            :                     encap->size < MLX5_ENCAPSULATION_DECISION_SIZE) {
   16522                 :          0 :                         rte_flow_error_set(error, EINVAL,
   16523                 :            :                                            RTE_FLOW_ERROR_TYPE_ACTION, encap_action,
   16524                 :            :                                            "Reformat: Invalid encap length");
   16525                 :          0 :                         return NULL;
   16526                 :            :                 }
   16527                 :            :                 type = MLX5DR_ACTION_TYP_REFORMAT_L2_TO_TNL_L2;
   16528         [ #  # ]:          0 :         } else if (decap_action && !encap_action) {
   16529                 :          0 :                 decap = (const struct rte_flow_action_raw_decap *)decap_action->conf;
   16530         [ #  # ]:          0 :                 if (!decap->size || decap->size < MLX5_ENCAPSULATION_DECISION_SIZE) {
   16531                 :          0 :                         rte_flow_error_set(error, EINVAL,
   16532                 :            :                                            RTE_FLOW_ERROR_TYPE_ACTION, encap_action,
   16533                 :            :                                            "Reformat: Invalid decap length");
   16534                 :          0 :                         return NULL;
   16535                 :            :                 }
   16536                 :            :                 type = MLX5DR_ACTION_TYP_REFORMAT_TNL_L2_TO_L2;
   16537         [ #  # ]:          0 :         } else if (encap_action && decap_action) {
   16538                 :          0 :                 decap = (const struct rte_flow_action_raw_decap *)decap_action->conf;
   16539                 :          0 :                 encap = (const struct rte_flow_action_raw_encap *)encap_action->conf;
   16540         [ #  # ]:          0 :                 if (decap->size < MLX5_ENCAPSULATION_DECISION_SIZE &&
   16541   [ #  #  #  # ]:          0 :                     encap->size >= MLX5_ENCAPSULATION_DECISION_SIZE &&
   16542                 :            :                     encap->size <= MLX5_ENCAP_MAX_LEN) {
   16543                 :            :                         type = MLX5DR_ACTION_TYP_REFORMAT_L2_TO_TNL_L3;
   16544         [ #  # ]:          0 :                 } else if (decap->size >= MLX5_ENCAPSULATION_DECISION_SIZE &&
   16545         [ #  # ]:          0 :                            encap->size < MLX5_ENCAPSULATION_DECISION_SIZE) {
   16546                 :            :                         type = MLX5DR_ACTION_TYP_REFORMAT_TNL_L3_TO_L2;
   16547                 :            :                 } else {
   16548                 :          0 :                         rte_flow_error_set(error, EINVAL,
   16549                 :            :                                            RTE_FLOW_ERROR_TYPE_ACTION, encap_action,
   16550                 :            :                                            "Reformat: Invalid decap & encap length");
   16551                 :          0 :                         return NULL;
   16552                 :            :                 }
   16553         [ #  # ]:          0 :         } else if (!encap_action && !decap_action) {
   16554                 :          0 :                 rte_flow_error_set(error, EINVAL,
   16555                 :            :                                    RTE_FLOW_ERROR_TYPE_ACTION, encap_action,
   16556                 :            :                                    "Reformat: Invalid decap & encap configurations");
   16557                 :          0 :                 return NULL;
   16558                 :            :         }
   16559         [ #  # ]:          0 :         if (!priv->dr_ctx) {
   16560                 :          0 :                 rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION,
   16561                 :            :                                    encap_action, "Reformat: HWS not supported");
   16562                 :          0 :                 return NULL;
   16563                 :            :         }
   16564                 :          0 :         handle = __mlx5_reformat_create(dev, encap, conf, type);
   16565         [ #  # ]:          0 :         if (!handle) {
   16566                 :          0 :                 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION, encap_action,
   16567                 :            :                                    "Reformat: failed to create indirect action");
   16568                 :          0 :                 return NULL;
   16569                 :            :         }
   16570                 :            :         return handle;
   16571                 :            : }
   16572                 :            : 
   16573                 :            : /**
   16574                 :            :  * Destroy the indirect reformat action.
   16575                 :            :  * Release action related resources on the NIC and the memory.
   16576                 :            :  * Lock free, (mutex should be acquired by caller).
   16577                 :            :  *
   16578                 :            :  * @param[in] dev
   16579                 :            :  *   Pointer to the Ethernet device structure.
   16580                 :            :  * @param[in] handle
   16581                 :            :  *   The indirect action list handle to be removed.
   16582                 :            :  * @param[out] error
   16583                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   16584                 :            :  *   error only.
   16585                 :            :  *
   16586                 :            :  * @return
   16587                 :            :  *   0 on success, otherwise negative errno value.
   16588                 :            :  */
   16589                 :            : int
   16590                 :          0 : mlx5_reformat_action_destroy(struct rte_eth_dev *dev,
   16591                 :            :                              struct rte_flow_action_list_handle *handle,
   16592                 :            :                              struct rte_flow_error *error)
   16593                 :            : {
   16594                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16595                 :            :         struct mlx5_hw_encap_decap_action *action;
   16596                 :            : 
   16597                 :            :         action = (struct mlx5_hw_encap_decap_action *)handle;
   16598   [ #  #  #  # ]:          0 :         if (!priv->dr_ctx || !action)
   16599                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
   16600                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, handle,
   16601                 :            :                                           "Reformat: invalid action handle");
   16602                 :          0 :         mlx5dr_action_destroy(action->action);
   16603                 :          0 :         mlx5_free(handle);
   16604                 :          0 :         return 0;
   16605                 :            : }
   16606                 :            : 
   16607                 :            : static bool
   16608                 :          0 : flow_hw_is_item_masked(const struct rte_flow_item *item)
   16609                 :            : {
   16610                 :            :         const uint8_t *byte;
   16611                 :            :         int size;
   16612                 :            :         int i;
   16613                 :            : 
   16614         [ #  # ]:          0 :         if (item->mask == NULL)
   16615                 :            :                 return false;
   16616                 :            : 
   16617         [ #  # ]:          0 :         switch ((int)item->type) {
   16618                 :            :         case MLX5_RTE_FLOW_ITEM_TYPE_TAG:
   16619                 :            :                 size = sizeof(struct rte_flow_item_tag);
   16620                 :            :                 break;
   16621                 :            :         case MLX5_RTE_FLOW_ITEM_TYPE_SQ:
   16622                 :            :                 size = sizeof(struct mlx5_rte_flow_item_sq);
   16623                 :            :                 break;
   16624                 :          0 :         default:
   16625                 :          0 :                 size = rte_flow_conv(RTE_FLOW_CONV_OP_ITEM_MASK, NULL, 0, item, NULL);
   16626                 :            :                 /*
   16627                 :            :                  * Pattern template items are passed to this function.
   16628                 :            :                  * These items were already validated, so error is not expected.
   16629                 :            :                  * Also, if mask is NULL, then spec size is bigger than 0 always.
   16630                 :            :                  */
   16631                 :            :                 MLX5_ASSERT(size > 0);
   16632                 :            :         }
   16633                 :            : 
   16634                 :          0 :         byte = (const uint8_t *)item->mask;
   16635         [ #  # ]:          0 :         for (i = 0; i < size; ++i)
   16636         [ #  # ]:          0 :                 if (byte[i])
   16637                 :            :                         return true;
   16638                 :            : 
   16639                 :            :         return false;
   16640                 :            : }
   16641                 :            : 
   16642                 :            : static int
   16643                 :          0 : flow_hw_validate_rule_pattern(struct rte_eth_dev *dev,
   16644                 :            :                               const struct rte_flow_template_table *table,
   16645                 :            :                               const uint8_t pattern_template_idx,
   16646                 :            :                               const struct rte_flow_item items[],
   16647                 :            :                               struct rte_flow_error *error)
   16648                 :            : {
   16649                 :            :         const struct rte_flow_pattern_template *pt;
   16650                 :            :         const struct rte_flow_item *pt_item;
   16651                 :            : 
   16652         [ #  # ]:          0 :         if (pattern_template_idx >= table->nb_item_templates)
   16653                 :          0 :                 return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   16654                 :            :                                           "Pattern template index out of range");
   16655                 :            : 
   16656                 :          0 :         pt = table->its[pattern_template_idx];
   16657                 :          0 :         pt_item = pt->items;
   16658                 :            : 
   16659                 :            :         /* If any item was prepended, skip it. */
   16660         [ #  # ]:          0 :         if (pt->implicit_port || pt->implicit_tag)
   16661                 :          0 :                 pt_item++;
   16662                 :            : 
   16663         [ #  # ]:          0 :         for (; pt_item->type != RTE_FLOW_ITEM_TYPE_END; pt_item++, items++) {
   16664         [ #  # ]:          0 :                 if (pt_item->type != items->type)
   16665                 :          0 :                         return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
   16666                 :            :                                                   items, "Item type does not match the template");
   16667                 :            : 
   16668                 :            :                 /*
   16669                 :            :                  * Assumptions:
   16670                 :            :                  * - Currently mlx5dr layer contains info on which fields in masks are supported.
   16671                 :            :                  * - This info is not exposed to PMD directly.
   16672                 :            :                  * - Because of that, it is assumed that since pattern template is correct,
   16673                 :            :                  *   then, items' masks in pattern template have nonzero values only in
   16674                 :            :                  *   supported fields.
   16675                 :            :                  *   This is known, because a temporary mlx5dr matcher is created during pattern
   16676                 :            :                  *   template creation to validate the template.
   16677                 :            :                  * - As a result, it is safe to look for nonzero bytes in mask to determine if
   16678                 :            :                  *   item spec is needed in a flow rule.
   16679                 :            :                  */
   16680         [ #  # ]:          0 :                 if (!flow_hw_is_item_masked(pt_item))
   16681                 :          0 :                         continue;
   16682                 :            : 
   16683         [ #  # ]:          0 :                 if (items->spec == NULL)
   16684                 :          0 :                         return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
   16685                 :            :                                                   items, "Item spec is required");
   16686                 :            : 
   16687      [ #  #  # ]:          0 :                 switch (items->type) {
   16688                 :            :                 const struct rte_flow_item_ethdev *ethdev;
   16689                 :            :                 const struct rte_flow_item_tx_queue *tx_queue;
   16690                 :            :                 struct mlx5_txq_ctrl *txq;
   16691                 :            : 
   16692                 :          0 :                 case RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT:
   16693                 :            :                         ethdev = items->spec;
   16694         [ #  # ]:          0 :                         if (flow_hw_validate_target_port_id(dev, ethdev->port_id)) {
   16695                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
   16696                 :            :                                                           RTE_FLOW_ERROR_TYPE_ITEM_SPEC, items,
   16697                 :            :                                                           "Invalid port");
   16698                 :            :                         }
   16699                 :            :                         break;
   16700                 :          0 :                 case RTE_FLOW_ITEM_TYPE_TX_QUEUE:
   16701                 :            :                         tx_queue = items->spec;
   16702   [ #  #  #  # ]:          0 :                         if (mlx5_is_external_txq(dev, tx_queue->tx_queue))
   16703                 :          0 :                                 continue;
   16704                 :          0 :                         txq = mlx5_txq_get(dev, tx_queue->tx_queue);
   16705         [ #  # ]:          0 :                         if (!txq)
   16706                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
   16707                 :            :                                                           RTE_FLOW_ERROR_TYPE_ITEM_SPEC, items,
   16708                 :            :                                                           "Invalid Tx queue");
   16709                 :          0 :                         mlx5_txq_release(dev, tx_queue->tx_queue);
   16710                 :            :                 default:
   16711                 :            :                         break;
   16712                 :            :                 }
   16713                 :            :         }
   16714                 :            : 
   16715                 :            :         return 0;
   16716                 :            : }
   16717                 :            : 
   16718                 :            : static bool
   16719                 :          0 : flow_hw_valid_indirect_action_type(const struct rte_flow_action *user_action,
   16720                 :            :                                    const enum rte_flow_action_type expected_type)
   16721                 :            : {
   16722                 :          0 :         uint32_t user_indirect_type = MLX5_INDIRECT_ACTION_TYPE_GET(user_action->conf);
   16723                 :            :         uint32_t expected_indirect_type;
   16724                 :            : 
   16725   [ #  #  #  #  :          0 :         switch ((int)expected_type) {
                #  #  # ]
   16726                 :            :         case RTE_FLOW_ACTION_TYPE_RSS:
   16727                 :            :         case MLX5_RTE_FLOW_ACTION_TYPE_RSS:
   16728                 :            :                 expected_indirect_type = MLX5_INDIRECT_ACTION_TYPE_RSS;
   16729                 :            :                 break;
   16730                 :          0 :         case RTE_FLOW_ACTION_TYPE_COUNT:
   16731                 :            :         case MLX5_RTE_FLOW_ACTION_TYPE_COUNT:
   16732                 :            :                 expected_indirect_type = MLX5_INDIRECT_ACTION_TYPE_COUNT;
   16733                 :          0 :                 break;
   16734                 :          0 :         case RTE_FLOW_ACTION_TYPE_AGE:
   16735                 :            :                 expected_indirect_type = MLX5_INDIRECT_ACTION_TYPE_AGE;
   16736                 :          0 :                 break;
   16737                 :          0 :         case RTE_FLOW_ACTION_TYPE_CONNTRACK:
   16738                 :            :                 expected_indirect_type = MLX5_INDIRECT_ACTION_TYPE_CT;
   16739                 :          0 :                 break;
   16740                 :          0 :         case RTE_FLOW_ACTION_TYPE_METER_MARK:
   16741                 :            :         case MLX5_RTE_FLOW_ACTION_TYPE_METER_MARK:
   16742                 :            :                 expected_indirect_type = MLX5_INDIRECT_ACTION_TYPE_METER_MARK;
   16743                 :          0 :                 break;
   16744                 :          0 :         case RTE_FLOW_ACTION_TYPE_QUOTA:
   16745                 :            :                 expected_indirect_type = MLX5_INDIRECT_ACTION_TYPE_QUOTA;
   16746                 :          0 :                 break;
   16747                 :            :         default:
   16748                 :            :                 return false;
   16749                 :            :         }
   16750                 :            : 
   16751                 :          0 :         return user_indirect_type == expected_indirect_type;
   16752                 :            : }
   16753                 :            : 
   16754                 :            : static int
   16755                 :          0 : flow_hw_validate_rule_actions(struct rte_eth_dev *dev,
   16756                 :            :                               const struct rte_flow_template_table *table,
   16757                 :            :                               const uint8_t actions_template_idx,
   16758                 :            :                               const struct rte_flow_action actions[],
   16759                 :            :                               struct rte_flow_error *error)
   16760                 :            : {
   16761                 :            :         const struct rte_flow_actions_template *at;
   16762                 :            :         const struct mlx5_hw_actions *hw_acts;
   16763                 :            :         const struct mlx5_action_construct_data *act_data;
   16764                 :            :         unsigned int idx;
   16765                 :            : 
   16766         [ #  # ]:          0 :         if (actions_template_idx >= table->nb_action_templates)
   16767                 :          0 :                 return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   16768                 :            :                                           "Actions template index out of range");
   16769                 :            : 
   16770                 :          0 :         at = table->ats[actions_template_idx].action_template;
   16771                 :            :         hw_acts = &table->ats[actions_template_idx].acts;
   16772                 :            : 
   16773         [ #  # ]:          0 :         for (idx = 0; actions[idx].type != RTE_FLOW_ACTION_TYPE_END; ++idx) {
   16774                 :            :                 const struct rte_flow_action *user_action = &actions[idx];
   16775                 :          0 :                 const struct rte_flow_action *tmpl_action = &at->orig_actions[idx];
   16776                 :            : 
   16777         [ #  # ]:          0 :                 if (user_action->type != tmpl_action->type)
   16778                 :          0 :                         return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
   16779                 :            :                                                   user_action,
   16780                 :            :                                                   "Action type does not match type specified in "
   16781                 :            :                                                   "actions template");
   16782                 :            :         }
   16783                 :            : 
   16784                 :            :         /*
   16785                 :            :          * Only go through unmasked actions and check if configuration is provided.
   16786                 :            :          * Configuration of masked actions is ignored.
   16787                 :            :          */
   16788         [ #  # ]:          0 :         LIST_FOREACH(act_data, &hw_acts->act_list, next) {
   16789                 :            :                 const struct rte_flow_action *user_action;
   16790                 :            : 
   16791                 :          0 :                 user_action = &actions[act_data->action_src];
   16792                 :            : 
   16793                 :            :                 /* Skip actions which do not require conf. */
   16794         [ #  # ]:          0 :                 switch ((int)act_data->type) {
   16795                 :          0 :                 case RTE_FLOW_ACTION_TYPE_COUNT:
   16796                 :            :                 case MLX5_RTE_FLOW_ACTION_TYPE_COUNT:
   16797                 :            :                 case MLX5_RTE_FLOW_ACTION_TYPE_METER_MARK:
   16798                 :            :                 case MLX5_RTE_FLOW_ACTION_TYPE_RSS:
   16799                 :          0 :                         continue;
   16800                 :            :                 default:
   16801                 :            :                         break;
   16802                 :            :                 }
   16803                 :            : 
   16804         [ #  # ]:          0 :                 if (user_action->conf == NULL)
   16805                 :          0 :                         return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
   16806                 :            :                                                   user_action,
   16807                 :            :                                                   "Action requires configuration");
   16808                 :            : 
   16809   [ #  #  #  #  :          0 :                 switch ((int)user_action->type) {
                   #  # ]
   16810                 :            :                 enum rte_flow_action_type expected_type;
   16811                 :            :                 const struct rte_flow_action_ethdev *ethdev;
   16812                 :            :                 const struct rte_flow_action_modify_field *mf;
   16813                 :            : 
   16814                 :          0 :                 case RTE_FLOW_ACTION_TYPE_INDIRECT:
   16815                 :          0 :                         expected_type = act_data->indirect.expected_type;
   16816         [ #  # ]:          0 :                         if (!flow_hw_valid_indirect_action_type(user_action, expected_type))
   16817                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
   16818                 :            :                                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF,
   16819                 :            :                                                           user_action,
   16820                 :            :                                                           "Indirect action type does not match "
   16821                 :            :                                                           "the type specified in the mask");
   16822                 :            :                         break;
   16823                 :          0 :                 case RTE_FLOW_ACTION_TYPE_QUEUE:
   16824         [ #  # ]:          0 :                         if (mlx5_flow_validate_target_queue(dev, user_action, error))
   16825                 :          0 :                                 return -rte_errno;
   16826                 :            :                         break;
   16827                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RSS:
   16828         [ #  # ]:          0 :                         if (mlx5_validate_action_rss(dev, user_action, error))
   16829                 :          0 :                                 return -rte_errno;
   16830                 :            :                         break;
   16831                 :          0 :                 case RTE_FLOW_ACTION_TYPE_MODIFY_FIELD:
   16832                 :            :                         /* TODO: Compare other fields if needed. */
   16833                 :            :                         mf = user_action->conf;
   16834         [ #  # ]:          0 :                         if (mf->operation != act_data->modify_header.action.operation ||
   16835         [ #  # ]:          0 :                             mf->src.field != act_data->modify_header.action.src.field ||
   16836         [ #  # ]:          0 :                             mf->dst.field != act_data->modify_header.action.dst.field ||
   16837         [ #  # ]:          0 :                             mf->width != act_data->modify_header.action.width)
   16838                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
   16839                 :            :                                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF,
   16840                 :            :                                                           user_action,
   16841                 :            :                                                           "Modify field configuration does not "
   16842                 :            :                                                           "match configuration from actions "
   16843                 :            :                                                           "template");
   16844                 :            :                         break;
   16845                 :          0 :                 case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
   16846                 :            :                         ethdev = user_action->conf;
   16847         [ #  # ]:          0 :                         if (flow_hw_validate_target_port_id(dev, ethdev->port_id)) {
   16848                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
   16849                 :            :                                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF,
   16850                 :            :                                                           user_action, "Invalid port");
   16851                 :            :                         }
   16852                 :            :                         break;
   16853                 :            :                 default:
   16854                 :            :                         break;
   16855                 :            :                 }
   16856                 :            :         }
   16857                 :            : 
   16858                 :            :         return 0;
   16859                 :            : }
   16860                 :            : 
   16861                 :            : static int
   16862                 :          0 : flow_hw_async_op_validate(struct rte_eth_dev *dev,
   16863                 :            :                           const uint32_t queue,
   16864                 :            :                           const struct rte_flow_template_table *table,
   16865                 :            :                           struct rte_flow_error *error)
   16866                 :            : {
   16867                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16868                 :            : 
   16869                 :            :         MLX5_ASSERT(table != NULL);
   16870                 :            : 
   16871   [ #  #  #  # ]:          0 :         if (table->cfg.external && queue >= priv->hw_attr->nb_queue)
   16872                 :          0 :                 return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   16873                 :            :                                           "Incorrect queue");
   16874                 :            : 
   16875                 :            :         return 0;
   16876                 :            : }
   16877                 :            : 
   16878                 :            : /**
   16879                 :            :  * Validate user input for rte_flow_async_create() implementation.
   16880                 :            :  *
   16881                 :            :  * If RTE_LIBRTE_MLX5_DEBUG macro is not defined, this function is a no-op.
   16882                 :            :  *
   16883                 :            :  * @param[in] dev
   16884                 :            :  *   Pointer to the rte_eth_dev structure.
   16885                 :            :  * @param[in] queue
   16886                 :            :  *   The queue to create the flow.
   16887                 :            :  * @param[in] table
   16888                 :            :  *   Pointer to template table.
   16889                 :            :  * @param[in] rule_index
   16890                 :            :  *   The item pattern flow follows from the table.
   16891                 :            :  * @param[in] items
   16892                 :            :  *   Items with flow spec value.
   16893                 :            :  * @param[in] pattern_template_index
   16894                 :            :  *   The item pattern flow follows from the table.
   16895                 :            :  * @param[in] actions
   16896                 :            :  *   Action with flow spec value.
   16897                 :            :  * @param[in] action_template_index
   16898                 :            :  *   The action pattern flow follows from the table.
   16899                 :            :  * @param[out] error
   16900                 :            :  *   Pointer to error structure.
   16901                 :            :  *
   16902                 :            :  * @return
   16903                 :            :  *    0 if user input is valid.
   16904                 :            :  *    Negative errno otherwise, rte_errno and error struct is populated.
   16905                 :            :  */
   16906                 :            : static int
   16907                 :          0 : flow_hw_async_create_validate(struct rte_eth_dev *dev,
   16908                 :            :                               const uint32_t queue,
   16909                 :            :                               const struct rte_flow_template_table *table,
   16910                 :            :                               enum rte_flow_table_insertion_type insertion_type,
   16911                 :            :                               uint32_t rule_index,
   16912                 :            :                               const struct rte_flow_item items[],
   16913                 :            :                               const uint8_t pattern_template_index,
   16914                 :            :                               const struct rte_flow_action actions[],
   16915                 :            :                               const uint8_t action_template_index,
   16916                 :            :                               struct rte_flow_error *error)
   16917                 :            : {
   16918         [ #  # ]:          0 :         if (flow_hw_async_op_validate(dev, queue, table, error))
   16919                 :          0 :                 return -rte_errno;
   16920                 :            : 
   16921         [ #  # ]:          0 :         if (insertion_type != table->cfg.attr.insertion_type)
   16922                 :          0 :                 return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   16923                 :            :                                           NULL, "Flow rule insertion type mismatch with table configuration");
   16924                 :            : 
   16925         [ #  # ]:          0 :         if (table->cfg.attr.insertion_type != RTE_FLOW_TABLE_INSERTION_TYPE_PATTERN)
   16926         [ #  # ]:          0 :                 if (rule_index >= table->cfg.attr.nb_flows)
   16927                 :          0 :                         return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   16928                 :            :                                                   NULL, "Flow rule index exceeds table size");
   16929                 :            : 
   16930         [ #  # ]:          0 :         if (table->cfg.attr.insertion_type != RTE_FLOW_TABLE_INSERTION_TYPE_INDEX)
   16931         [ #  # ]:          0 :                 if (flow_hw_validate_rule_pattern(dev, table, pattern_template_index, items, error))
   16932                 :          0 :                         return -rte_errno;
   16933                 :            : 
   16934         [ #  # ]:          0 :         if (flow_hw_validate_rule_actions(dev, table, action_template_index, actions, error))
   16935                 :          0 :                 return -rte_errno;
   16936                 :            : 
   16937                 :            :         return 0;
   16938                 :            : }
   16939                 :            : 
   16940                 :            : /**
   16941                 :            :  * Validate user input for rte_flow_async_update() implementation.
   16942                 :            :  *
   16943                 :            :  * If RTE_LIBRTE_MLX5_DEBUG macro is not defined, this function is a no-op.
   16944                 :            :  *
   16945                 :            :  * @param[in] dev
   16946                 :            :  *   Pointer to the rte_eth_dev structure.
   16947                 :            :  * @param[in] queue
   16948                 :            :  *   The queue to create the flow.
   16949                 :            :  * @param[in] flow
   16950                 :            :  *   Flow rule to be updated.
   16951                 :            :  * @param[in] actions
   16952                 :            :  *   Action with flow spec value.
   16953                 :            :  * @param[in] action_template_index
   16954                 :            :  *   The action pattern flow follows from the table.
   16955                 :            :  * @param[out] error
   16956                 :            :  *   Pointer to error structure.
   16957                 :            :  *
   16958                 :            :  * @return
   16959                 :            :  *    0 if user input is valid.
   16960                 :            :  *    Negative errno otherwise, rte_errno and error struct is set.
   16961                 :            :  */
   16962                 :            : static int
   16963                 :          0 : flow_hw_async_update_validate(struct rte_eth_dev *dev,
   16964                 :            :                               const uint32_t queue,
   16965                 :            :                               const struct rte_flow_hw *flow,
   16966                 :            :                               const struct rte_flow_action actions[],
   16967                 :            :                               const uint8_t action_template_index,
   16968                 :            :                               struct rte_flow_error *error)
   16969                 :            : {
   16970         [ #  # ]:          0 :         if (flow_hw_async_op_validate(dev, queue, flow->table, error))
   16971                 :          0 :                 return -rte_errno;
   16972                 :            : 
   16973         [ #  # ]:          0 :         if (flow_hw_validate_rule_actions(dev, flow->table, action_template_index, actions, error))
   16974                 :          0 :                 return -rte_errno;
   16975                 :            : 
   16976                 :            :         return 0;
   16977                 :            : }
   16978                 :            : 
   16979                 :            : /**
   16980                 :            :  * Validate user input for rte_flow_async_destroy() implementation.
   16981                 :            :  *
   16982                 :            :  * If RTE_LIBRTE_MLX5_DEBUG macro is not defined, this function is a no-op.
   16983                 :            :  *
   16984                 :            :  * @param[in] dev
   16985                 :            :  *   Pointer to the rte_eth_dev structure.
   16986                 :            :  * @param[in] queue
   16987                 :            :  *   The queue to create the flow.
   16988                 :            :  * @param[in] flow
   16989                 :            :  *   Flow rule to be destroyed.
   16990                 :            :  * @param[out] error
   16991                 :            :  *   Pointer to error structure.
   16992                 :            :  *
   16993                 :            :  * @return
   16994                 :            :  *    0 if user input is valid.
   16995                 :            :  *    Negative errno otherwise, rte_errno and error struct is set.
   16996                 :            :  */
   16997                 :            : static int
   16998                 :            : flow_hw_async_destroy_validate(struct rte_eth_dev *dev,
   16999                 :            :                                const uint32_t queue,
   17000                 :            :                                const struct rte_flow_hw *flow,
   17001                 :            :                                struct rte_flow_error *error)
   17002                 :            : {
   17003                 :            :         if (flow_hw_async_op_validate(dev, queue, flow->table, error))
   17004                 :            :                 return -rte_errno;
   17005                 :            : 
   17006                 :            :         return 0;
   17007                 :            : }
   17008                 :            : 
   17009                 :            : static struct rte_flow_fp_ops mlx5_flow_hw_fp_ops = {
   17010                 :            :         .async_create = flow_hw_async_flow_create,
   17011                 :            :         .async_create_by_index = flow_hw_async_flow_create_by_index,
   17012                 :            :         .async_create_by_index_with_pattern = flow_hw_async_flow_create_by_index_with_pattern,
   17013                 :            :         .async_actions_update = flow_hw_async_flow_update,
   17014                 :            :         .async_destroy = flow_hw_async_flow_destroy,
   17015                 :            :         .push = flow_hw_push,
   17016                 :            :         .pull = flow_hw_pull,
   17017                 :            :         .async_action_handle_create = flow_hw_action_handle_create,
   17018                 :            :         .async_action_handle_destroy = flow_hw_action_handle_destroy,
   17019                 :            :         .async_action_handle_update = flow_hw_action_handle_update,
   17020                 :            :         .async_action_handle_query = flow_hw_action_handle_query,
   17021                 :            :         .async_action_handle_query_update = flow_hw_async_action_handle_query_update,
   17022                 :            :         .async_action_list_handle_create = flow_hw_async_action_list_handle_create,
   17023                 :            :         .async_action_list_handle_destroy = flow_hw_async_action_list_handle_destroy,
   17024                 :            :         .async_action_list_handle_query_update =
   17025                 :            :                 flow_hw_async_action_list_handle_query_update,
   17026                 :            : };
   17027                 :            : 
   17028                 :            : #endif

Generated by: LCOV version 1.14