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

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright (c) 2021 NVIDIA Corporation & Affiliates
       3                 :            :  */
       4                 :            : #include <rte_malloc.h>
       5                 :            : #include <mlx5_devx_cmds.h>
       6                 :            : #include <mlx5_malloc.h>
       7                 :            : #include "mlx5.h"
       8                 :            : #include "mlx5_flow.h"
       9                 :            : 
      10                 :            : static_assert(sizeof(uint32_t) * CHAR_BIT >= MLX5_PORT_FLEX_ITEM_NUM,
      11                 :            :               "Flex item maximal number exceeds uint32_t bit width");
      12                 :            : 
      13                 :            : /**
      14                 :            :  *  Routine called once on port initialization to init flex item
      15                 :            :  *  related infrastructure initialization
      16                 :            :  *
      17                 :            :  * @param dev
      18                 :            :  *   Ethernet device to perform flex item initialization
      19                 :            :  *
      20                 :            :  * @return
      21                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
      22                 :            :  */
      23                 :            : int
      24                 :          0 : mlx5_flex_item_port_init(struct rte_eth_dev *dev)
      25                 :            : {
      26                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
      27                 :            : 
      28                 :            :         rte_spinlock_init(&priv->flex_item_sl);
      29                 :            :         MLX5_ASSERT(!priv->flex_item_map);
      30                 :          0 :         return 0;
      31                 :            : }
      32                 :            : 
      33                 :            : /**
      34                 :            :  *  Routine called once on port close to perform flex item
      35                 :            :  *  related infrastructure cleanup.
      36                 :            :  *
      37                 :            :  * @param dev
      38                 :            :  *   Ethernet device to perform cleanup
      39                 :            :  */
      40                 :            : void
      41                 :          0 : mlx5_flex_item_port_cleanup(struct rte_eth_dev *dev)
      42                 :            : {
      43                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
      44                 :            :         uint32_t i;
      45                 :            : 
      46   [ #  #  #  # ]:          0 :         for (i = 0; i < MLX5_PORT_FLEX_ITEM_NUM && priv->flex_item_map ; i++) {
      47         [ #  # ]:          0 :                 if (priv->flex_item_map & (1 << i)) {
      48                 :            :                         struct mlx5_flex_item *flex = &priv->flex_item[i];
      49                 :            : 
      50                 :          0 :                         claim_zero(mlx5_list_unregister
      51                 :            :                                         (priv->sh->flex_parsers_dv,
      52                 :            :                                          &flex->devx_fp->entry));
      53                 :          0 :                         flex->devx_fp = NULL;
      54                 :          0 :                         flex->refcnt = 0;
      55                 :          0 :                         priv->flex_item_map &= ~(1 << i);
      56                 :            :                 }
      57                 :            :         }
      58                 :          0 : }
      59                 :            : 
      60                 :            : static int
      61                 :            : mlx5_flex_index(struct mlx5_priv *priv, struct mlx5_flex_item *item)
      62                 :            : {
      63                 :          0 :         uintptr_t start = (uintptr_t)&priv->flex_item[0];
      64                 :          0 :         uintptr_t entry = (uintptr_t)item;
      65                 :          0 :         uintptr_t idx = (entry - start) / sizeof(struct mlx5_flex_item);
      66                 :            : 
      67                 :          0 :         if (entry < start ||
      68         [ #  # ]:          0 :             idx >= MLX5_PORT_FLEX_ITEM_NUM ||
      69   [ #  #  #  #  :          0 :             (entry - start) % sizeof(struct mlx5_flex_item) ||
                   #  # ]
      70   [ #  #  #  #  :          0 :             !(priv->flex_item_map & (1u << idx)))
                   #  # ]
      71                 :            :                 return -1;
      72                 :          0 :         return (int)idx;
      73                 :            : }
      74                 :            : 
      75                 :            : static struct mlx5_flex_item *
      76                 :          0 : mlx5_flex_alloc(struct mlx5_priv *priv)
      77                 :            : {
      78                 :            :         struct mlx5_flex_item *item = NULL;
      79                 :            : 
      80                 :          0 :         rte_spinlock_lock(&priv->flex_item_sl);
      81         [ #  # ]:          0 :         if (~priv->flex_item_map) {
      82         [ #  # ]:          0 :                 uint32_t idx = rte_bsf32(~priv->flex_item_map);
      83                 :            : 
      84         [ #  # ]:          0 :                 if (idx < MLX5_PORT_FLEX_ITEM_NUM) {
      85                 :          0 :                         item = &priv->flex_item[idx];
      86                 :            :                         MLX5_ASSERT(!item->refcnt);
      87                 :            :                         MLX5_ASSERT(!item->devx_fp);
      88                 :          0 :                         item->devx_fp = NULL;
      89                 :          0 :                         rte_atomic_store_explicit(&item->refcnt, 0, rte_memory_order_release);
      90                 :          0 :                         priv->flex_item_map |= 1u << idx;
      91                 :            :                 }
      92                 :            :         }
      93                 :            :         rte_spinlock_unlock(&priv->flex_item_sl);
      94                 :          0 :         return item;
      95                 :            : }
      96                 :            : 
      97                 :            : static void
      98         [ #  # ]:          0 : mlx5_flex_free(struct mlx5_priv *priv, struct mlx5_flex_item *item)
      99                 :            : {
     100                 :            :         int idx = mlx5_flex_index(priv, item);
     101                 :            : 
     102                 :            :         MLX5_ASSERT(idx >= 0 &&
     103                 :            :                     idx < MLX5_PORT_FLEX_ITEM_NUM &&
     104                 :            :                     (priv->flex_item_map & (1u << idx)));
     105         [ #  # ]:          0 :         if (idx >= 0) {
     106                 :          0 :                 rte_spinlock_lock(&priv->flex_item_sl);
     107                 :            :                 MLX5_ASSERT(!item->refcnt);
     108                 :            :                 MLX5_ASSERT(!item->devx_fp);
     109                 :          0 :                 item->devx_fp = NULL;
     110                 :          0 :                 rte_atomic_store_explicit(&item->refcnt, 0, rte_memory_order_release);
     111                 :          0 :                 priv->flex_item_map &= ~(1u << idx);
     112                 :            :                 rte_spinlock_unlock(&priv->flex_item_sl);
     113                 :            :         }
     114                 :          0 : }
     115                 :            : 
     116                 :            : static uint32_t
     117                 :          0 : mlx5_flex_get_bitfield(const struct rte_flow_item_flex *item,
     118                 :            :                        uint32_t pos, uint32_t width, uint32_t shift)
     119                 :            : {
     120                 :          0 :         const uint8_t *ptr = item->pattern + pos / CHAR_BIT;
     121                 :          0 :         uint32_t val, vbits, skip = pos % CHAR_BIT;
     122                 :            : 
     123                 :            :         /* Proceed the bitfield start byte. */
     124                 :            :         MLX5_ASSERT(width <= sizeof(uint32_t) * CHAR_BIT && width);
     125                 :            :         MLX5_ASSERT(width + shift <= sizeof(uint32_t) * CHAR_BIT);
     126         [ #  # ]:          0 :         if (item->length <= pos / CHAR_BIT)
     127                 :            :                 return 0;
     128                 :            :         /* Bits are enumerated in byte in network order: 01234567 */
     129                 :          0 :         val = *ptr++;
     130                 :          0 :         vbits = CHAR_BIT - pos % CHAR_BIT;
     131                 :          0 :         pos = RTE_ALIGN_CEIL(pos, CHAR_BIT) / CHAR_BIT;
     132                 :          0 :         vbits = RTE_MIN(vbits, width);
     133                 :            :         /* Load bytes to cover the field width, checking pattern boundary */
     134   [ #  #  #  # ]:          0 :         while (vbits < width && pos < item->length) {
     135                 :          0 :                 uint32_t part = RTE_MIN(width - vbits, (uint32_t)CHAR_BIT);
     136                 :          0 :                 uint32_t tmp = *ptr++;
     137                 :            : 
     138                 :          0 :                 val |= tmp << RTE_ALIGN_CEIL(vbits, CHAR_BIT);
     139                 :          0 :                 vbits += part;
     140                 :          0 :                 pos++;
     141                 :            :         }
     142         [ #  # ]:          0 :         val = rte_cpu_to_be_32(val);
     143                 :          0 :         val <<= skip;
     144                 :          0 :         val >>= shift;
     145                 :          0 :         val &= (RTE_BIT64(width) - 1) << (sizeof(uint32_t) * CHAR_BIT - shift - width);
     146                 :          0 :         return val;
     147                 :            : }
     148                 :            : 
     149                 :            : #define SET_FP_MATCH_SAMPLE_ID(x, def, msk, val, sid) \
     150                 :            :         do { \
     151                 :            :                 uint32_t tmp, out = (def); \
     152                 :            :                 tmp = MLX5_GET(fte_match_set_misc4, misc4_v, \
     153                 :            :                                prog_sample_field_value_##x); \
     154                 :            :                 tmp = (tmp & ~out) | (val); \
     155                 :            :                 MLX5_SET(fte_match_set_misc4, misc4_v, \
     156                 :            :                          prog_sample_field_value_##x, tmp); \
     157                 :            :                 tmp = MLX5_GET(fte_match_set_misc4, misc4_m, \
     158                 :            :                                prog_sample_field_value_##x); \
     159                 :            :                 tmp = (tmp & ~out) | (msk); \
     160                 :            :                 MLX5_SET(fte_match_set_misc4, misc4_m, \
     161                 :            :                          prog_sample_field_value_##x, tmp); \
     162                 :            :                 tmp = tmp ? (sid) : 0; \
     163                 :            :                 MLX5_SET(fte_match_set_misc4, misc4_v, \
     164                 :            :                          prog_sample_field_id_##x, tmp);\
     165                 :            :                 MLX5_SET(fte_match_set_misc4, misc4_m, \
     166                 :            :                          prog_sample_field_id_##x, tmp); \
     167                 :            :         } while (0)
     168                 :            : 
     169                 :            : __rte_always_inline static void
     170                 :            : mlx5_flex_set_match_sample(void *misc4_m, void *misc4_v,
     171                 :            :                            uint32_t def, uint32_t mask, uint32_t value,
     172                 :            :                            uint32_t sample_id, uint32_t id)
     173                 :            : {
     174                 :          0 :         switch (id) {
     175                 :          0 :         case 0:
     176   [ #  #  #  #  :          0 :                 SET_FP_MATCH_SAMPLE_ID(0, def, mask, value, sample_id);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     177                 :          0 :                 break;
     178                 :          0 :         case 1:
     179   [ #  #  #  #  :          0 :                 SET_FP_MATCH_SAMPLE_ID(1, def, mask, value, sample_id);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     180                 :          0 :                 break;
     181                 :          0 :         case 2:
     182   [ #  #  #  #  :          0 :                 SET_FP_MATCH_SAMPLE_ID(2, def, mask, value, sample_id);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     183                 :          0 :                 break;
     184                 :          0 :         case 3:
     185   [ #  #  #  #  :          0 :                 SET_FP_MATCH_SAMPLE_ID(3, def, mask, value, sample_id);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     186                 :          0 :                 break;
     187                 :          0 :         case 4:
     188   [ #  #  #  #  :          0 :                 SET_FP_MATCH_SAMPLE_ID(4, def, mask, value, sample_id);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     189                 :          0 :                 break;
     190                 :          0 :         case 5:
     191   [ #  #  #  #  :          0 :                 SET_FP_MATCH_SAMPLE_ID(5, def, mask, value, sample_id);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     192                 :          0 :                 break;
     193                 :          0 :         case 6:
     194   [ #  #  #  #  :          0 :                 SET_FP_MATCH_SAMPLE_ID(6, def, mask, value, sample_id);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     195                 :          0 :                 break;
     196                 :          0 :         case 7:
     197   [ #  #  #  #  :          0 :                 SET_FP_MATCH_SAMPLE_ID(7, def, mask, value, sample_id);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     198                 :          0 :                 break;
     199                 :            :         default:
     200                 :            :                 MLX5_ASSERT(false);
     201                 :            :                 break;
     202                 :            :         }
     203                 :            : #undef SET_FP_MATCH_SAMPLE_ID
     204                 :            : }
     205                 :            : 
     206                 :            : /**
     207                 :            :  * Get the flex parser sample id and corresponding mask
     208                 :            :  * per shift and width information.
     209                 :            :  *
     210                 :            :  * @param[in] tp
     211                 :            :  *   Mlx5 flex item sample mapping handle.
     212                 :            :  * @param[in] idx
     213                 :            :  *   Mapping index.
     214                 :            :  * @param[in, out] pos
     215                 :            :  *   Where to search the value and mask.
     216                 :            :  * @param[in] is_inner
     217                 :            :  *   For inner matching or not.
     218                 :            :  *
     219                 :            :  * @return
     220                 :            :  *   0 on success, -1 to ignore.
     221                 :            :  */
     222                 :            : int
     223                 :          0 : mlx5_flex_get_sample_id(const struct mlx5_flex_item *tp,
     224                 :            :                         uint32_t idx, uint32_t *pos, bool is_inner)
     225                 :            : {
     226                 :          0 :         const struct mlx5_flex_pattern_field *map = tp->map + idx;
     227                 :          0 :         uint32_t id = map->reg_id;
     228                 :            : 
     229                 :            :         /* Skip placeholders for DUMMY fields. */
     230         [ #  # ]:          0 :         if (id == MLX5_INVALID_SAMPLE_REG_ID) {
     231                 :          0 :                 *pos += map->width;
     232                 :          0 :                 return -1;
     233                 :            :         }
     234                 :            :         MLX5_ASSERT(map->width);
     235                 :            :         MLX5_ASSERT(id < tp->devx_fp->num_samples);
     236   [ #  #  #  # ]:          0 :         if (tp->tunnel_mode == FLEX_TUNNEL_MODE_MULTI && is_inner) {
     237                 :          0 :                 uint32_t num_samples = tp->devx_fp->num_samples / 2;
     238                 :            : 
     239                 :            :                 MLX5_ASSERT(tp->devx_fp->num_samples % 2 == 0);
     240                 :            :                 MLX5_ASSERT(id < num_samples);
     241                 :          0 :                 id += num_samples;
     242                 :            :         }
     243                 :          0 :         return id;
     244                 :            : }
     245                 :            : 
     246                 :            : /**
     247                 :            :  * Get the flex parser mapping value per definer format_select_dw.
     248                 :            :  *
     249                 :            :  * @param[in] item
     250                 :            :  *   Rte flex item pointer.
     251                 :            :  * @param[in] flex
     252                 :            :  *   Mlx5 flex item sample mapping handle.
     253                 :            :  * @param[in] byte_off
     254                 :            :  *   Mlx5 flex item format_select_dw.
     255                 :            :  * @param[in] tunnel
     256                 :            :  *   Tunnel mode or not.
     257                 :            :  * @param[in, def] value
     258                 :            :  *   Value calculated for this flex parser, either spec or mask.
     259                 :            :  *
     260                 :            :  * @return
     261                 :            :  *   0 on success, -1 for error.
     262                 :            :  */
     263                 :            : int
     264                 :          0 : mlx5_flex_get_parser_value_per_byte_off(const struct rte_flow_item_flex *item,
     265                 :            :                                         void *flex, uint32_t byte_off,
     266                 :            :                                         bool tunnel, uint32_t *value)
     267                 :            : {
     268                 :            :         struct mlx5_flex_pattern_field *map;
     269                 :            :         struct mlx5_flex_item *tp = flex;
     270                 :            :         uint32_t i, pos, val;
     271                 :            :         int id;
     272                 :            : 
     273                 :          0 :         *value = 0;
     274   [ #  #  #  # ]:          0 :         for (i = 0, pos = 0; i < tp->mapnum && pos < item->length * CHAR_BIT; i++) {
     275                 :          0 :                 map = tp->map + i;
     276                 :          0 :                 id = mlx5_flex_get_sample_id(tp, i, &pos, tunnel);
     277         [ #  # ]:          0 :                 if (id == -1)
     278                 :          0 :                         continue;
     279   [ #  #  #  # ]:          0 :                 if (id >= (int)tp->devx_fp->num_samples || id >= MLX5_GRAPH_NODE_SAMPLE_NUM)
     280                 :            :                         return -1;
     281         [ #  # ]:          0 :                 if (byte_off == tp->devx_fp->sample_info[id].sample_dw_data * sizeof(uint32_t)) {
     282                 :          0 :                         val = mlx5_flex_get_bitfield(item, pos, map->width, map->shift);
     283                 :          0 :                         *value |= val;
     284                 :            :                 }
     285                 :          0 :                 pos += map->width;
     286                 :            :         }
     287                 :            :         return 0;
     288                 :            : }
     289                 :            : 
     290                 :            : /**
     291                 :            :  * Get the flex parser tunnel mode.
     292                 :            :  *
     293                 :            :  * @param[in] item
     294                 :            :  *   RTE Flex item.
     295                 :            :  * @param[in, out] tunnel_mode
     296                 :            :  *   Pointer to return tunnel mode.
     297                 :            :  *
     298                 :            :  * @return
     299                 :            :  *   0 on success, otherwise negative error code.
     300                 :            :  */
     301                 :            : int
     302                 :          0 : mlx5_flex_get_tunnel_mode(const struct rte_flow_item *item,
     303                 :            :                           enum rte_flow_item_flex_tunnel_mode *tunnel_mode)
     304                 :            : {
     305   [ #  #  #  #  :          0 :         if (item && item->spec && tunnel_mode) {
                   #  # ]
     306                 :            :                 const struct rte_flow_item_flex *spec = item->spec;
     307                 :          0 :                 struct mlx5_flex_item *flex = (struct mlx5_flex_item *)spec->handle;
     308                 :            : 
     309         [ #  # ]:          0 :                 if (flex) {
     310                 :          0 :                         *tunnel_mode = flex->tunnel_mode;
     311                 :          0 :                         return 0;
     312                 :            :                 }
     313                 :            :         }
     314                 :            :         return -EINVAL;
     315                 :            : }
     316                 :            : 
     317                 :            : /**
     318                 :            :  * Translate item pattern into matcher fields according to translation
     319                 :            :  * array.
     320                 :            :  *
     321                 :            :  * @param dev
     322                 :            :  *   Ethernet device to translate flex item on.
     323                 :            :  * @param[in, out] matcher
     324                 :            :  *   Flow matcher to configure
     325                 :            :  * @param[in, out] key
     326                 :            :  *   Flow matcher value.
     327                 :            :  * @param[in] item
     328                 :            :  *   Flow pattern to translate.
     329                 :            :  * @param[in] is_inner
     330                 :            :  *   Inner Flex Item (follows after tunnel header).
     331                 :            :  *
     332                 :            :  * @return
     333                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
     334                 :            :  */
     335                 :            : void
     336                 :          0 : mlx5_flex_flow_translate_item(struct rte_eth_dev *dev,
     337                 :            :                               void *matcher, void *key,
     338                 :            :                               const struct rte_flow_item *item,
     339                 :            :                               bool is_inner)
     340                 :            : {
     341                 :            :         const struct rte_flow_item_flex *spec, *mask;
     342                 :            :         void *misc4_m = MLX5_ADDR_OF(fte_match_param, matcher,
     343                 :            :                                      misc_parameters_4);
     344                 :            :         void *misc4_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_4);
     345                 :            :         struct mlx5_flex_item *tp;
     346                 :          0 :         uint32_t i, pos = 0;
     347                 :            :         uint32_t sample_id;
     348                 :            : 
     349                 :            :         RTE_SET_USED(dev);
     350                 :            :         MLX5_ASSERT(item->spec && item->mask);
     351                 :          0 :         spec = item->spec;
     352                 :          0 :         mask = item->mask;
     353                 :          0 :         tp = (struct mlx5_flex_item *)spec->handle;
     354   [ #  #  #  # ]:          0 :         for (i = 0; i < tp->mapnum && pos < (spec->length * CHAR_BIT); i++) {
     355                 :          0 :                 struct mlx5_flex_pattern_field *map = tp->map + i;
     356                 :            :                 uint32_t val, msk, def;
     357                 :          0 :                 int id = mlx5_flex_get_sample_id(tp, i, &pos, is_inner);
     358                 :            : 
     359         [ #  # ]:          0 :                 if (id == -1)
     360                 :          0 :                         continue;
     361                 :            :                 MLX5_ASSERT(id < (int)tp->devx_fp->num_samples);
     362   [ #  #  #  # ]:          0 :                 if (id >= (int)tp->devx_fp->num_samples ||
     363                 :            :                     id >= MLX5_GRAPH_NODE_SAMPLE_NUM)
     364                 :          0 :                         return;
     365                 :          0 :                 def = (uint32_t)(RTE_BIT64(map->width) - 1);
     366                 :          0 :                 def <<= (sizeof(uint32_t) * CHAR_BIT - map->shift - map->width);
     367                 :          0 :                 val = mlx5_flex_get_bitfield(spec, pos, map->width, map->shift);
     368                 :          0 :                 msk = pos < (mask->length * CHAR_BIT) ?
     369         [ #  # ]:          0 :                       mlx5_flex_get_bitfield(mask, pos, map->width, map->shift) : def;
     370                 :          0 :                 sample_id = tp->devx_fp->sample_ids[id];
     371   [ #  #  #  #  :          0 :                 mlx5_flex_set_match_sample(misc4_m, misc4_v,
             #  #  #  #  
                      # ]
     372                 :            :                                            def, msk, val & msk,
     373                 :            :                                            sample_id, id);
     374                 :          0 :                 pos += map->width;
     375                 :            :         }
     376                 :            : }
     377                 :            : 
     378                 :            : /**
     379                 :            :  * Convert flex item handle (from the RTE flow) to flex item index on port.
     380                 :            :  * Optionally can increment flex item object reference count.
     381                 :            :  *
     382                 :            :  * @param dev
     383                 :            :  *   Ethernet device to acquire flex item on.
     384                 :            :  * @param[in] handle
     385                 :            :  *   Flow item handle from item spec.
     386                 :            :  * @param[in] acquire
     387                 :            :  *   If set - increment reference counter.
     388                 :            :  *
     389                 :            :  * @return
     390                 :            :  *   >=0 - index on success, a negative errno value otherwise
     391                 :            :  *         and rte_errno is set.
     392                 :            :  */
     393                 :            : int
     394                 :          0 : mlx5_flex_acquire_index(struct rte_eth_dev *dev,
     395                 :            :                         struct rte_flow_item_flex_handle *handle,
     396                 :            :                         bool acquire)
     397                 :            : {
     398         [ #  # ]:          0 :         struct mlx5_priv *priv = dev->data->dev_private;
     399                 :            :         struct mlx5_flex_item *flex = (struct mlx5_flex_item *)handle;
     400                 :            :         int ret = mlx5_flex_index(priv, flex);
     401                 :            : 
     402         [ #  # ]:          0 :         if (ret < 0) {
     403                 :          0 :                 errno = -EINVAL;
     404                 :          0 :                 rte_errno = EINVAL;
     405                 :          0 :                 return ret;
     406                 :            :         }
     407         [ #  # ]:          0 :         if (acquire)
     408                 :          0 :                 rte_atomic_fetch_add_explicit(&flex->refcnt, 1, rte_memory_order_release);
     409                 :            :         return ret;
     410                 :            : }
     411                 :            : 
     412                 :            : /**
     413                 :            :  * Release flex item index on port - decrements reference counter by index.
     414                 :            :  *
     415                 :            :  * @param dev
     416                 :            :  *   Ethernet device to acquire flex item on.
     417                 :            :  * @param[in] index
     418                 :            :  *   Flow item index.
     419                 :            :  *
     420                 :            :  * @return
     421                 :            :  *   0 - on success, a negative errno value otherwise and rte_errno is set.
     422                 :            :  */
     423                 :            : int
     424                 :          0 : mlx5_flex_release_index(struct rte_eth_dev *dev,
     425                 :            :                         int index)
     426                 :            : {
     427                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
     428                 :            :         struct mlx5_flex_item *flex;
     429                 :            : 
     430         [ #  # ]:          0 :         if (index >= MLX5_PORT_FLEX_ITEM_NUM ||
     431         [ #  # ]:          0 :             !(priv->flex_item_map & (1u << index))) {
     432                 :          0 :                 errno = EINVAL;
     433                 :          0 :                 rte_errno = -EINVAL;
     434                 :          0 :                 return -EINVAL;
     435                 :            :         }
     436                 :          0 :         flex = priv->flex_item + index;
     437         [ #  # ]:          0 :         if (flex->refcnt <= 1) {
     438                 :            :                 MLX5_ASSERT(false);
     439                 :          0 :                 errno = EINVAL;
     440                 :          0 :                 rte_errno = -EINVAL;
     441                 :          0 :                 return -EINVAL;
     442                 :            :         }
     443                 :          0 :         rte_atomic_fetch_sub_explicit(&flex->refcnt, 1, rte_memory_order_release);
     444                 :          0 :         return 0;
     445                 :            : }
     446                 :            : 
     447                 :            : /*
     448                 :            :  * Calculate largest mask value for a given shift.
     449                 :            :  *
     450                 :            :  *   shift      mask
     451                 :            :  * ------- ---------------
     452                 :            :  *    0     b11111100  0x3C
     453                 :            :  *    1     b01111110  0x3E
     454                 :            :  *    2     b00111111  0x3F
     455                 :            :  *    3     b00011111  0x1F
     456                 :            :  *    4     b00001111  0x0F
     457                 :            :  *    5     b00000111  0x07
     458                 :            :  *    6     b00000011  0x03
     459                 :            :  *    7     b00000001  0x01
     460                 :            :  */
     461                 :            : static uint8_t
     462                 :            : mlx5_flex_hdr_len_mask(uint8_t shift,
     463                 :            :                        const struct mlx5_hca_flex_attr *attr)
     464                 :            : {
     465                 :            :         uint32_t base_mask;
     466         [ #  # ]:          0 :         int diff = shift - MLX5_PARSE_GRAPH_NODE_HDR_LEN_SHIFT_DWORD;
     467                 :            : 
     468                 :            :         base_mask = mlx5_hca_parse_graph_node_base_hdr_len_mask(attr);
     469         [ #  # ]:          0 :         return diff < 0 ? base_mask << -diff : base_mask >> diff;
     470                 :            : }
     471                 :            : 
     472                 :            : static int
     473                 :          0 : mlx5_flex_translate_length(struct mlx5_hca_flex_attr *attr,
     474                 :            :                            const struct rte_flow_item_flex_conf *conf,
     475                 :            :                            struct mlx5_flex_parser_devx *devx,
     476                 :            :                            struct rte_flow_error *error)
     477                 :            : {
     478                 :            :         const struct rte_flow_item_flex_field *field = &conf->next_header;
     479                 :            :         struct mlx5_devx_graph_node_attr *node = &devx->devx_conf;
     480                 :            : 
     481         [ #  # ]:          0 :         if (field->field_base % CHAR_BIT)
     482                 :          0 :                 return rte_flow_error_set
     483                 :            :                         (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     484                 :            :                          "not byte aligned header length field");
     485   [ #  #  #  #  :          0 :         switch (field->field_mode) {
                      # ]
     486                 :          0 :         case FIELD_MODE_DUMMY:
     487                 :          0 :                 return rte_flow_error_set
     488                 :            :                         (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     489                 :            :                          "invalid header length field mode (DUMMY)");
     490                 :          0 :         case FIELD_MODE_FIXED:
     491         [ #  # ]:          0 :                 if (!(attr->header_length_mode &
     492                 :            :                     RTE_BIT32(MLX5_GRAPH_NODE_LEN_FIXED)))
     493                 :          0 :                         return rte_flow_error_set
     494                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     495                 :            :                                  "unsupported header length field mode (FIXED)");
     496         [ #  # ]:          0 :                 if (field->field_size ||
     497   [ #  #  #  # ]:          0 :                     field->offset_mask || field->offset_shift)
     498                 :          0 :                         return rte_flow_error_set
     499                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     500                 :            :                                  "invalid fields for fixed mode");
     501         [ #  # ]:          0 :                 if (field->field_base < 0)
     502                 :          0 :                         return rte_flow_error_set
     503                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     504                 :            :                                  "negative header length field base (FIXED)");
     505                 :          0 :                 node->header_length_mode = MLX5_GRAPH_NODE_LEN_FIXED;
     506                 :          0 :                 break;
     507                 :          0 :         case FIELD_MODE_OFFSET: {
     508                 :            :                 uint32_t msb, lsb;
     509                 :          0 :                 int32_t shift = field->offset_shift;
     510                 :          0 :                 uint32_t offset = field->offset_base;
     511                 :          0 :                 uint32_t mask = field->offset_mask;
     512                 :          0 :                 uint32_t wmax = attr->header_length_mask_width +
     513                 :            :                                 MLX5_PARSE_GRAPH_NODE_HDR_LEN_SHIFT_DWORD;
     514                 :            : 
     515         [ #  # ]:          0 :                 if (!(attr->header_length_mode &
     516                 :            :                     RTE_BIT32(MLX5_GRAPH_NODE_LEN_FIELD)))
     517                 :          0 :                         return rte_flow_error_set
     518                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     519                 :            :                                  "unsupported header length field mode (OFFSET)");
     520         [ #  # ]:          0 :                 if (!field->field_size)
     521                 :          0 :                         return rte_flow_error_set
     522                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     523                 :            :                                  "field size is a must for offset mode");
     524         [ #  # ]:          0 :                 if ((offset ^ (field->field_size + offset)) >> 5)
     525                 :          0 :                         return rte_flow_error_set
     526                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     527                 :            :                                  "field crosses the 32-bit word boundary");
     528                 :            :                 /* Hardware counts in dwords, all shifts done by offset within mask */
     529         [ #  # ]:          0 :                 if (shift < 0 || (uint32_t)shift >= wmax)
     530                 :          0 :                         return rte_flow_error_set
     531                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     532                 :            :                                  "header length field shift exceeds limits (OFFSET)");
     533         [ #  # ]:          0 :                 if (!mask)
     534                 :          0 :                         return rte_flow_error_set
     535                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     536                 :            :                                  "zero length field offset mask (OFFSET)");
     537         [ #  # ]:          0 :                 msb = rte_fls_u32(mask) - 1;
     538                 :            :                 lsb = rte_bsf32(mask);
     539         [ #  # ]:          0 :                 if (!rte_is_power_of_2((mask >> lsb) + 1))
     540                 :          0 :                         return rte_flow_error_set
     541                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     542                 :            :                                  "length field offset mask not contiguous (OFFSET)");
     543         [ #  # ]:          0 :                 if (msb >= field->field_size)
     544                 :          0 :                         return rte_flow_error_set
     545                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     546                 :            :                                  "length field offset mask exceeds field size (OFFSET)");
     547         [ #  # ]:          0 :                 if (msb >= wmax)
     548                 :          0 :                         return rte_flow_error_set
     549                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     550                 :            :                                  "length field offset mask exceeds supported width (OFFSET)");
     551         [ #  # ]:          0 :                 if (mask & ~mlx5_flex_hdr_len_mask(shift, attr))
     552                 :          0 :                         return rte_flow_error_set
     553                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     554                 :            :                                  "mask and shift combination not supported (OFFSET)");
     555                 :            :                 msb++;
     556                 :          0 :                 offset += field->field_size - msb;
     557         [ #  # ]:          0 :                 if (msb < attr->header_length_mask_width) {
     558         [ #  # ]:          0 :                         if (attr->header_length_mask_width - msb > offset)
     559                 :          0 :                                 return rte_flow_error_set
     560                 :            :                                         (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     561                 :            :                                          "field size plus offset_base is too small");
     562                 :          0 :                         offset += msb;
     563                 :            :                         /*
     564                 :            :                          * Here we can move to preceding dword. Hardware does
     565                 :            :                          * cyclic left shift so we should avoid this and stay
     566                 :            :                          * at current dword offset.
     567                 :            :                          */
     568                 :          0 :                         offset = (offset & ~0x1Fu) |
     569                 :          0 :                                  ((offset - attr->header_length_mask_width) & 0x1F);
     570                 :            :                 }
     571                 :          0 :                 node->header_length_mode = MLX5_GRAPH_NODE_LEN_FIELD;
     572                 :          0 :                 node->header_length_field_mask = mask;
     573                 :          0 :                 node->header_length_field_shift = shift;
     574                 :          0 :                 node->header_length_field_offset = offset;
     575                 :          0 :                 break;
     576                 :            :         }
     577                 :          0 :         case FIELD_MODE_BITMASK:
     578         [ #  # ]:          0 :                 if (!(attr->header_length_mode &
     579                 :            :                     RTE_BIT32(MLX5_GRAPH_NODE_LEN_BITMASK)))
     580                 :          0 :                         return rte_flow_error_set
     581                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     582                 :            :                                  "unsupported header length field mode (BITMASK)");
     583         [ #  # ]:          0 :                 if (field->offset_shift > 15 || field->offset_shift < 0)
     584                 :          0 :                         return rte_flow_error_set
     585                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     586                 :            :                                  "header length field shift exceeds limit (BITMASK)");
     587                 :          0 :                 node->header_length_mode = MLX5_GRAPH_NODE_LEN_BITMASK;
     588                 :          0 :                 node->header_length_field_mask = field->offset_mask;
     589                 :          0 :                 node->header_length_field_shift = field->offset_shift;
     590                 :          0 :                 node->header_length_field_offset = field->offset_base;
     591                 :          0 :                 break;
     592                 :          0 :         default:
     593                 :          0 :                 return rte_flow_error_set
     594                 :            :                         (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     595                 :            :                          "unknown header length field mode");
     596                 :            :         }
     597         [ #  # ]:          0 :         if (field->field_base / CHAR_BIT >= 0 &&
     598         [ #  # ]:          0 :             field->field_base / CHAR_BIT > attr->max_base_header_length)
     599                 :          0 :                 return rte_flow_error_set
     600                 :            :                         (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     601                 :            :                          "header length field base exceeds limit");
     602                 :          0 :         node->header_length_base_value = field->field_base / CHAR_BIT;
     603                 :          0 :         return 0;
     604                 :            : }
     605                 :            : 
     606                 :            : static int
     607                 :          0 : mlx5_flex_translate_next(struct mlx5_hca_flex_attr *attr,
     608                 :            :                          const struct rte_flow_item_flex_conf *conf,
     609                 :            :                          struct mlx5_flex_parser_devx *devx,
     610                 :            :                          struct rte_flow_error *error)
     611                 :            : {
     612                 :            :         const struct rte_flow_item_flex_field *field = &conf->next_protocol;
     613                 :            :         struct mlx5_devx_graph_node_attr *node = &devx->devx_conf;
     614                 :            : 
     615   [ #  #  #  #  :          0 :         switch (field->field_mode) {
                      # ]
     616                 :          0 :         case FIELD_MODE_DUMMY:
     617         [ #  # ]:          0 :                 if (conf->nb_outputs)
     618                 :          0 :                         return rte_flow_error_set
     619                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     620                 :            :                                  "next protocol field is required (DUMMY)");
     621                 :            :                 return 0;
     622                 :            :         case FIELD_MODE_FIXED:
     623                 :            :                 break;
     624                 :          0 :         case FIELD_MODE_OFFSET:
     625                 :          0 :                 return rte_flow_error_set
     626                 :            :                         (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     627                 :            :                          "unsupported next protocol field mode (OFFSET)");
     628                 :            :                 break;
     629                 :          0 :         case FIELD_MODE_BITMASK:
     630                 :          0 :                 return rte_flow_error_set
     631                 :            :                         (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     632                 :            :                          "unsupported next protocol field mode (BITMASK)");
     633                 :          0 :         default:
     634                 :          0 :                 return rte_flow_error_set
     635                 :            :                         (error, EINVAL,
     636                 :            :                          RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     637                 :            :                          "unknown next protocol field mode");
     638                 :            :         }
     639                 :            :         MLX5_ASSERT(field->field_mode == FIELD_MODE_FIXED);
     640         [ #  # ]:          0 :         if (!conf->nb_outputs)
     641                 :          0 :                 return rte_flow_error_set
     642                 :            :                         (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     643                 :            :                          "out link(s) is required if next field present");
     644         [ #  # ]:          0 :         if (attr->max_next_header_offset < field->field_base)
     645                 :          0 :                 return rte_flow_error_set
     646                 :            :                         (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     647                 :            :                          "next protocol field base exceeds limit");
     648         [ #  # ]:          0 :         if (field->offset_shift)
     649                 :          0 :                 return rte_flow_error_set
     650                 :            :                         (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     651                 :            :                          "unsupported next protocol field shift");
     652                 :          0 :         node->next_header_field_offset = field->field_base;
     653                 :          0 :         node->next_header_field_size = field->field_size;
     654                 :          0 :         return 0;
     655                 :            : }
     656                 :            : 
     657                 :            : /* Helper structure to handle field bit intervals. */
     658                 :            : struct mlx5_flex_field_cover {
     659                 :            :         uint16_t num;
     660                 :            :         int32_t start[MLX5_FLEX_ITEM_MAPPING_NUM];
     661                 :            :         int32_t end[MLX5_FLEX_ITEM_MAPPING_NUM];
     662                 :            :         uint8_t mapped[MLX5_FLEX_ITEM_MAPPING_NUM / CHAR_BIT + 1];
     663                 :            : };
     664                 :            : 
     665                 :            : static void
     666                 :          0 : mlx5_flex_insert_field(struct mlx5_flex_field_cover *cover,
     667                 :            :                        uint16_t num, int32_t start, int32_t end)
     668                 :            : {
     669                 :            :         MLX5_ASSERT(num < MLX5_FLEX_ITEM_MAPPING_NUM);
     670                 :            :         MLX5_ASSERT(num <= cover->num);
     671         [ #  # ]:          0 :         if (num < cover->num) {
     672                 :          0 :                 memmove(&cover->start[num + 1],  &cover->start[num],
     673                 :          0 :                         (cover->num - num) * sizeof(int32_t));
     674                 :          0 :                 memmove(&cover->end[num + 1],    &cover->end[num],
     675                 :          0 :                         (cover->num - num) * sizeof(int32_t));
     676                 :            :         }
     677                 :          0 :         cover->start[num] = start;
     678                 :          0 :         cover->end[num] = end;
     679                 :          0 :         cover->num++;
     680                 :          0 : }
     681                 :            : 
     682                 :            : static void
     683                 :          0 : mlx5_flex_merge_field(struct mlx5_flex_field_cover *cover, uint16_t num)
     684                 :            : {
     685                 :            :         uint32_t i, del = 0;
     686                 :            :         int32_t end;
     687                 :            : 
     688                 :            :         MLX5_ASSERT(num < MLX5_FLEX_ITEM_MAPPING_NUM);
     689                 :            :         MLX5_ASSERT(num < (cover->num - 1));
     690                 :          0 :         end = cover->end[num];
     691         [ #  # ]:          0 :         for (i = num + 1; i < cover->num; i++) {
     692         [ #  # ]:          0 :                 if (end < cover->start[i])
     693                 :            :                         break;
     694                 :          0 :                 del++;
     695         [ #  # ]:          0 :                 if (end <= cover->end[i]) {
     696                 :          0 :                         cover->end[num] = cover->end[i];
     697                 :          0 :                         break;
     698                 :            :                 }
     699                 :            :         }
     700         [ #  # ]:          0 :         if (del) {
     701                 :            :                 MLX5_ASSERT(del < (cover->num - 1u - num));
     702                 :          0 :                 cover->num -= del;
     703                 :            :                 MLX5_ASSERT(cover->num > num);
     704         [ #  # ]:          0 :                 if ((cover->num - num) > 1) {
     705                 :          0 :                         memmove(&cover->start[num + 1],
     706                 :          0 :                                 &cover->start[num + 1 + del],
     707                 :          0 :                                 (cover->num - num - 1) * sizeof(int32_t));
     708                 :          0 :                         memmove(&cover->end[num + 1],
     709                 :          0 :                                 &cover->end[num + 1 + del],
     710                 :          0 :                                 (cover->num - num - 1) * sizeof(int32_t));
     711                 :            :                 }
     712                 :            :         }
     713                 :          0 : }
     714                 :            : 
     715                 :            : /*
     716                 :            :  * Validate the sample field and update interval array
     717                 :            :  * if parameters match with the 'match" field.
     718                 :            :  * Returns:
     719                 :            :  *    < 0  - error
     720                 :            :  *    == 0 - no match, interval array not updated
     721                 :            :  *    > 0  - match, interval array updated
     722                 :            :  */
     723                 :            : static int
     724                 :          0 : mlx5_flex_cover_sample(struct mlx5_flex_field_cover *cover,
     725                 :            :                        struct rte_flow_item_flex_field *field,
     726                 :            :                        struct rte_flow_item_flex_field *match,
     727                 :            :                        struct mlx5_hca_flex_attr *attr,
     728                 :            :                        struct rte_flow_error *error)
     729                 :            : {
     730                 :            :         int32_t start, end;
     731                 :            :         uint32_t i;
     732                 :            : 
     733   [ #  #  #  #  :          0 :         switch (field->field_mode) {
                      # ]
     734                 :            :         case FIELD_MODE_DUMMY:
     735                 :            :                 return 0;
     736                 :          0 :         case FIELD_MODE_FIXED:
     737         [ #  # ]:          0 :                 if (!(attr->sample_offset_mode &
     738                 :            :                     RTE_BIT32(MLX5_GRAPH_SAMPLE_OFFSET_FIXED)))
     739                 :          0 :                         return rte_flow_error_set
     740                 :            :                                 (error, EINVAL,
     741                 :            :                                  RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     742                 :            :                                  "unsupported sample field mode (FIXED)");
     743         [ #  # ]:          0 :                 if (field->offset_shift)
     744                 :          0 :                         return rte_flow_error_set
     745                 :            :                                 (error, EINVAL,
     746                 :            :                                  RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     747                 :            :                                  "invalid sample field shift (FIXED");
     748         [ #  # ]:          0 :                 if (field->field_base < 0)
     749                 :          0 :                         return rte_flow_error_set
     750                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     751                 :            :                                  "invalid sample field base (FIXED)");
     752         [ #  # ]:          0 :                 if (field->field_base / CHAR_BIT > attr->max_sample_base_offset)
     753                 :          0 :                         return rte_flow_error_set
     754                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     755                 :            :                                  "sample field base exceeds limit (FIXED)");
     756                 :            :                 break;
     757                 :          0 :         case FIELD_MODE_OFFSET:
     758         [ #  # ]:          0 :                 if (!(attr->sample_offset_mode &
     759                 :            :                     RTE_BIT32(MLX5_GRAPH_SAMPLE_OFFSET_FIELD)))
     760                 :          0 :                         return rte_flow_error_set
     761                 :            :                                 (error, EINVAL,
     762                 :            :                                  RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     763                 :            :                                  "unsupported sample field mode (OFFSET)");
     764         [ #  # ]:          0 :                 if (field->field_base / CHAR_BIT >= 0 &&
     765         [ #  # ]:          0 :                     field->field_base / CHAR_BIT > attr->max_sample_base_offset)
     766                 :          0 :                         return rte_flow_error_set
     767                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     768                 :            :                                 "sample field base exceeds limit");
     769                 :            :                 break;
     770                 :          0 :         case FIELD_MODE_BITMASK:
     771         [ #  # ]:          0 :                 if (!(attr->sample_offset_mode &
     772                 :            :                     RTE_BIT32(MLX5_GRAPH_SAMPLE_OFFSET_BITMASK)))
     773                 :          0 :                         return rte_flow_error_set
     774                 :            :                                 (error, EINVAL,
     775                 :            :                                  RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     776                 :            :                                  "unsupported sample field mode (BITMASK)");
     777         [ #  # ]:          0 :                 if (field->field_base / CHAR_BIT >= 0 &&
     778         [ #  # ]:          0 :                     field->field_base / CHAR_BIT > attr->max_sample_base_offset)
     779                 :          0 :                         return rte_flow_error_set
     780                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     781                 :            :                                 "sample field base exceeds limit");
     782                 :            :                 break;
     783                 :          0 :         default:
     784                 :          0 :                 return rte_flow_error_set
     785                 :            :                         (error, EINVAL,
     786                 :            :                          RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     787                 :            :                          "unknown data sample field mode");
     788                 :            :         }
     789         [ #  # ]:          0 :         if (!match) {
     790         [ #  # ]:          0 :                 if (!field->field_size)
     791                 :          0 :                         return rte_flow_error_set
     792                 :            :                                 (error, EINVAL,
     793                 :            :                                 RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     794                 :            :                                 "zero sample field width");
     795         [ #  # ]:          0 :                 if (field->field_id)
     796                 :          0 :                         DRV_LOG(DEBUG, "sample field id hint ignored");
     797                 :            :         } else {
     798         [ #  # ]:          0 :                 if (field->field_mode != match->field_mode ||
     799         [ #  # ]:          0 :                     field->offset_base | match->offset_base ||
     800         [ #  # ]:          0 :                     field->offset_mask | match->offset_mask ||
     801         [ #  # ]:          0 :                     field->offset_shift | match->offset_shift)
     802                 :            :                         return 0;
     803                 :            :         }
     804                 :          0 :         start = field->field_base;
     805                 :          0 :         end = start + field->field_size;
     806                 :            :         /* Add the new or similar field to interval array. */
     807         [ #  # ]:          0 :         if (!cover->num) {
     808                 :          0 :                 cover->start[cover->num] = start;
     809                 :          0 :                 cover->end[cover->num] = end;
     810                 :          0 :                 cover->num = 1;
     811                 :          0 :                 return 1;
     812                 :            :         }
     813         [ #  # ]:          0 :         for (i = 0; i < cover->num; i++) {
     814         [ #  # ]:          0 :                 if (start > cover->end[i]) {
     815         [ #  # ]:          0 :                         if (i >= (cover->num - 1u)) {
     816                 :          0 :                                 mlx5_flex_insert_field(cover, cover->num,
     817                 :            :                                                        start, end);
     818                 :          0 :                                 break;
     819                 :            :                         }
     820                 :            :                         continue;
     821                 :            :                 }
     822         [ #  # ]:          0 :                 if (end < cover->start[i]) {
     823                 :          0 :                         mlx5_flex_insert_field(cover, i, start, end);
     824                 :          0 :                         break;
     825                 :            :                 }
     826         [ #  # ]:          0 :                 if (start < cover->start[i])
     827                 :          0 :                         cover->start[i] = start;
     828         [ #  # ]:          0 :                 if (end > cover->end[i]) {
     829                 :          0 :                         cover->end[i] = end;
     830         [ #  # ]:          0 :                         if (i < (cover->num - 1u))
     831                 :          0 :                                 mlx5_flex_merge_field(cover, i);
     832                 :            :                 }
     833                 :            :                 break;
     834                 :            :         }
     835                 :            :         return 1;
     836                 :            : }
     837                 :            : 
     838                 :            : static void
     839      [ #  #  # ]:          0 : mlx5_flex_config_sample(struct mlx5_devx_match_sample_attr *na,
     840                 :            :                         struct rte_flow_item_flex_field *field,
     841                 :            :                         enum rte_flow_item_flex_tunnel_mode tunnel_mode)
     842                 :            : {
     843                 :            :         memset(na, 0, sizeof(struct mlx5_devx_match_sample_attr));
     844                 :          0 :         na->flow_match_sample_en = 1;
     845      [ #  #  # ]:          0 :         switch (field->field_mode) {
     846                 :            :         case FIELD_MODE_FIXED:
     847                 :            :                 na->flow_match_sample_offset_mode =
     848                 :            :                         MLX5_GRAPH_SAMPLE_OFFSET_FIXED;
     849                 :            :                 break;
     850                 :          0 :         case FIELD_MODE_OFFSET:
     851                 :          0 :                 na->flow_match_sample_offset_mode =
     852                 :            :                         MLX5_GRAPH_SAMPLE_OFFSET_FIELD;
     853                 :          0 :                 na->flow_match_sample_field_offset = field->offset_base;
     854                 :          0 :                 na->flow_match_sample_field_offset_mask = field->offset_mask;
     855                 :          0 :                 na->flow_match_sample_field_offset_shift = field->offset_shift;
     856                 :          0 :                 break;
     857                 :          0 :         case FIELD_MODE_BITMASK:
     858                 :          0 :                 na->flow_match_sample_offset_mode =
     859                 :            :                         MLX5_GRAPH_SAMPLE_OFFSET_BITMASK;
     860                 :          0 :                 na->flow_match_sample_field_offset = field->offset_base;
     861                 :          0 :                 na->flow_match_sample_field_offset_mask = field->offset_mask;
     862                 :          0 :                 na->flow_match_sample_field_offset_shift = field->offset_shift;
     863                 :          0 :                 break;
     864                 :            :         default:
     865                 :            :                 MLX5_ASSERT(false);
     866                 :            :                 break;
     867                 :            :         }
     868      [ #  #  # ]:          0 :         switch (tunnel_mode) {
     869                 :          0 :         case FLEX_TUNNEL_MODE_SINGLE:
     870                 :            :                 /* Fallthrough */
     871                 :            :         case FLEX_TUNNEL_MODE_TUNNEL:
     872                 :          0 :                 na->flow_match_sample_tunnel_mode =
     873                 :            :                         MLX5_GRAPH_SAMPLE_TUNNEL_FIRST;
     874                 :          0 :                 break;
     875                 :            :         case FLEX_TUNNEL_MODE_MULTI:
     876                 :            :                 /* Fallthrough */
     877                 :            :         case FLEX_TUNNEL_MODE_OUTER:
     878                 :            :                 na->flow_match_sample_tunnel_mode =
     879                 :            :                         MLX5_GRAPH_SAMPLE_TUNNEL_OUTER;
     880                 :            :                 break;
     881                 :          0 :         case FLEX_TUNNEL_MODE_INNER:
     882                 :          0 :                 na->flow_match_sample_tunnel_mode =
     883                 :            :                         MLX5_GRAPH_SAMPLE_TUNNEL_INNER;
     884                 :          0 :                 break;
     885                 :            :         default:
     886                 :            :                 MLX5_ASSERT(false);
     887                 :            :                 break;
     888                 :            :         }
     889                 :          0 : }
     890                 :            : 
     891                 :            : /* Map specified field to set/subset of allocated sample registers. */
     892                 :            : static int
     893                 :          0 : mlx5_flex_map_sample(struct rte_flow_item_flex_field *field,
     894                 :            :                      struct mlx5_flex_parser_devx *parser,
     895                 :            :                      struct mlx5_flex_item *item,
     896                 :            :                      struct rte_flow_error *error)
     897                 :            : {
     898                 :            :         struct mlx5_devx_match_sample_attr node;
     899                 :          0 :         int32_t start = field->field_base;
     900                 :          0 :         int32_t end = start + field->field_size;
     901                 :            :         struct mlx5_flex_pattern_field *trans;
     902                 :            :         uint32_t i, done_bits = 0;
     903                 :            : 
     904         [ #  # ]:          0 :         if (field->field_mode == FIELD_MODE_DUMMY) {
     905                 :            :                 done_bits = field->field_size;
     906         [ #  # ]:          0 :                 while (done_bits) {
     907                 :          0 :                         uint32_t part = RTE_MIN(done_bits,
     908                 :            :                                                 sizeof(uint32_t) * CHAR_BIT);
     909         [ #  # ]:          0 :                         if (item->mapnum >= MLX5_FLEX_ITEM_MAPPING_NUM)
     910                 :          0 :                                 return rte_flow_error_set
     911                 :            :                                         (error,
     912                 :            :                                          EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     913                 :            :                                          "too many flex item pattern translations");
     914                 :            :                         trans = &item->map[item->mapnum];
     915                 :          0 :                         trans->reg_id = MLX5_INVALID_SAMPLE_REG_ID;
     916                 :          0 :                         trans->shift = 0;
     917                 :          0 :                         trans->width = part;
     918                 :          0 :                         item->mapnum++;
     919                 :          0 :                         done_bits -= part;
     920                 :            :                 }
     921                 :            :                 return 0;
     922                 :            :         }
     923                 :          0 :         mlx5_flex_config_sample(&node, field, item->tunnel_mode);
     924         [ #  # ]:          0 :         for (i = 0; i < parser->num_samples; i++) {
     925                 :          0 :                 struct mlx5_devx_match_sample_attr *sample =
     926                 :            :                         &parser->devx_conf.sample[i];
     927                 :            :                 int32_t reg_start, reg_end;
     928                 :            :                 int32_t cov_start, cov_end;
     929                 :            : 
     930                 :            :                 MLX5_ASSERT(sample->flow_match_sample_en);
     931         [ #  # ]:          0 :                 if (!sample->flow_match_sample_en)
     932                 :            :                         break;
     933                 :          0 :                 node.flow_match_sample_field_base_offset =
     934                 :          0 :                         sample->flow_match_sample_field_base_offset;
     935         [ #  # ]:          0 :                 if (memcmp(&node, sample, sizeof(node)))
     936                 :          0 :                         continue;
     937                 :          0 :                 reg_start = (int8_t)sample->flow_match_sample_field_base_offset;
     938                 :          0 :                 reg_start *= CHAR_BIT;
     939                 :          0 :                 reg_end = reg_start + 32;
     940         [ #  # ]:          0 :                 if (end <= reg_start || start >= reg_end)
     941                 :          0 :                         continue;
     942                 :          0 :                 cov_start = RTE_MAX(reg_start, start);
     943                 :          0 :                 cov_end = RTE_MIN(reg_end, end);
     944                 :            :                 MLX5_ASSERT(cov_end > cov_start);
     945                 :          0 :                 done_bits += cov_end - cov_start;
     946         [ #  # ]:          0 :                 if (item->mapnum >= MLX5_FLEX_ITEM_MAPPING_NUM)
     947                 :          0 :                         return rte_flow_error_set
     948                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     949                 :            :                                  "too many flex item pattern translations");
     950                 :            :                 trans = &item->map[item->mapnum];
     951                 :          0 :                 item->mapnum++;
     952                 :          0 :                 trans->reg_id = i;
     953                 :          0 :                 trans->shift = cov_start - reg_start;
     954                 :          0 :                 trans->width = cov_end - cov_start;
     955                 :            :         }
     956         [ #  # ]:          0 :         if (done_bits != field->field_size) {
     957                 :            :                 MLX5_ASSERT(false);
     958                 :          0 :                 return rte_flow_error_set
     959                 :            :                         (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     960                 :            :                          "failed to map field to sample register");
     961                 :            :         }
     962                 :            :         return 0;
     963                 :            : }
     964                 :            : 
     965                 :            : /* Allocate sample registers for the specified field type and interval array. */
     966                 :            : static int
     967                 :          0 : mlx5_flex_alloc_sample(struct mlx5_flex_field_cover *cover,
     968                 :            :                        struct mlx5_flex_parser_devx *parser,
     969                 :            :                        struct mlx5_flex_item *item,
     970                 :            :                        struct rte_flow_item_flex_field *field,
     971                 :            :                        struct mlx5_hca_flex_attr *attr,
     972                 :            :                        struct rte_flow_error *error)
     973                 :            : {
     974                 :            :         struct mlx5_devx_match_sample_attr node;
     975                 :            :         uint32_t idx = 0;
     976                 :            : 
     977                 :          0 :         mlx5_flex_config_sample(&node, field, item->tunnel_mode);
     978         [ #  # ]:          0 :         while (idx < cover->num) {
     979                 :            :                 int32_t start, end;
     980                 :            : 
     981                 :            :                 /*
     982                 :            :                  * Sample base offsets are in bytes, should be aligned
     983                 :            :                  * to 32-bit as required by firmware for samples.
     984                 :            :                  */
     985                 :          0 :                 start = RTE_ALIGN_FLOOR(cover->start[idx],
     986                 :            :                                         sizeof(uint32_t) * CHAR_BIT);
     987                 :          0 :                 node.flow_match_sample_field_base_offset =
     988                 :          0 :                                                 (start / CHAR_BIT) & 0xFF;
     989                 :            :                 /* Allocate sample register. */
     990         [ #  # ]:          0 :                 if (parser->num_samples >= MLX5_GRAPH_NODE_SAMPLE_NUM ||
     991         [ #  # ]:          0 :                     parser->num_samples >= attr->max_num_sample ||
     992         [ #  # ]:          0 :                     parser->num_samples >= attr->max_num_prog_sample)
     993                 :          0 :                         return rte_flow_error_set
     994                 :            :                                 (error, EINVAL,
     995                 :            :                                  RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     996                 :            :                                  "no sample registers to handle all flex item fields");
     997                 :          0 :                 parser->devx_conf.sample[parser->num_samples] = node;
     998                 :          0 :                 parser->num_samples++;
     999                 :            :                 /* Remove or update covered intervals. */
    1000                 :          0 :                 end = start + 32;
    1001         [ #  # ]:          0 :                 while (idx < cover->num) {
    1002         [ #  # ]:          0 :                         if (end >= cover->end[idx]) {
    1003                 :          0 :                                 idx++;
    1004                 :          0 :                                 continue;
    1005                 :            :                         }
    1006         [ #  # ]:          0 :                         if (end > cover->start[idx])
    1007                 :          0 :                                 cover->start[idx] = end;
    1008                 :            :                         break;
    1009                 :            :                 }
    1010                 :            :         }
    1011                 :            :         return 0;
    1012                 :            : }
    1013                 :            : 
    1014                 :            : static int
    1015                 :          0 : mlx5_flex_translate_sample(struct mlx5_hca_flex_attr *attr,
    1016                 :            :                            const struct rte_flow_item_flex_conf *conf,
    1017                 :            :                            struct mlx5_flex_parser_devx *parser,
    1018                 :            :                            struct mlx5_flex_item *item,
    1019                 :            :                            struct rte_flow_error *error)
    1020                 :            : {
    1021                 :            :         struct mlx5_flex_field_cover cover;
    1022                 :            :         uint32_t i, j;
    1023                 :            :         int ret;
    1024                 :            : 
    1025         [ #  # ]:          0 :         switch (conf->tunnel) {
    1026                 :            :         case FLEX_TUNNEL_MODE_SINGLE:
    1027                 :            :                 /* Fallthrough */
    1028                 :            :         case FLEX_TUNNEL_MODE_OUTER:
    1029                 :            :                 /* Fallthrough */
    1030                 :            :         case FLEX_TUNNEL_MODE_INNER:
    1031                 :            :                 /* Fallthrough */
    1032                 :            :         case FLEX_TUNNEL_MODE_MULTI:
    1033                 :            :                 /* Fallthrough */
    1034                 :            :         case FLEX_TUNNEL_MODE_TUNNEL:
    1035                 :            :                 break;
    1036                 :          0 :         default:
    1037                 :          0 :                 return rte_flow_error_set
    1038                 :            :                         (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    1039                 :            :                          "unrecognized tunnel mode");
    1040                 :            :         }
    1041                 :          0 :         item->tunnel_mode = conf->tunnel;
    1042         [ #  # ]:          0 :         if (conf->nb_samples > MLX5_FLEX_ITEM_MAPPING_NUM)
    1043                 :          0 :                 return rte_flow_error_set
    1044                 :            :                         (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    1045                 :            :                          "sample field number exceeds limit");
    1046                 :            :         /*
    1047                 :            :          * The application can specify fields smaller or bigger than 32 bits
    1048                 :            :          * covered with single sample register and it can specify field
    1049                 :            :          * offsets in any order.
    1050                 :            :          *
    1051                 :            :          * Gather all similar fields together, build array of bit intervals
    1052                 :            :          * in ascending order and try to cover with the smallest set of sample
    1053                 :            :          * registers.
    1054                 :            :          */
    1055                 :            :         memset(&cover, 0, sizeof(cover));
    1056         [ #  # ]:          0 :         for (i = 0; i < conf->nb_samples; i++) {
    1057                 :          0 :                 struct rte_flow_item_flex_field *fl = conf->sample_data + i;
    1058                 :            : 
    1059                 :            :                 /* Check whether field was covered in the previous iteration. */
    1060         [ #  # ]:          0 :                 if (cover.mapped[i / CHAR_BIT] & (1u << (i % CHAR_BIT)))
    1061                 :          0 :                         continue;
    1062         [ #  # ]:          0 :                 if (fl->field_mode == FIELD_MODE_DUMMY)
    1063                 :          0 :                         continue;
    1064                 :            :                 /* Build an interval array for the field and similar ones */
    1065                 :          0 :                 cover.num = 0;
    1066                 :            :                 /* Add the first field to array unconditionally. */
    1067                 :          0 :                 ret = mlx5_flex_cover_sample(&cover, fl, NULL, attr, error);
    1068         [ #  # ]:          0 :                 if (ret < 0)
    1069                 :          0 :                         return ret;
    1070                 :            :                 MLX5_ASSERT(ret > 0);
    1071                 :          0 :                 cover.mapped[i / CHAR_BIT] |= 1u << (i % CHAR_BIT);
    1072         [ #  # ]:          0 :                 for (j = i + 1; j < conf->nb_samples; j++) {
    1073                 :            :                         struct rte_flow_item_flex_field *ft;
    1074                 :            : 
    1075                 :            :                         /* Add field to array if its type matches. */
    1076                 :          0 :                         ft = conf->sample_data + j;
    1077                 :          0 :                         ret = mlx5_flex_cover_sample(&cover, ft, fl,
    1078                 :            :                                                      attr, error);
    1079         [ #  # ]:          0 :                         if (ret < 0)
    1080                 :          0 :                                 return ret;
    1081         [ #  # ]:          0 :                         if (!ret)
    1082                 :          0 :                                 continue;
    1083                 :          0 :                         cover.mapped[j / CHAR_BIT] |= 1u << (j % CHAR_BIT);
    1084                 :            :                 }
    1085                 :            :                 /* Allocate sample registers to cover array of intervals. */
    1086                 :          0 :                 ret = mlx5_flex_alloc_sample(&cover, parser, item,
    1087                 :            :                                              fl, attr, error);
    1088         [ #  # ]:          0 :                 if (ret)
    1089                 :          0 :                         return ret;
    1090                 :            :         }
    1091                 :            :         /* Build the item pattern translating data on flow creation. */
    1092                 :          0 :         item->mapnum = 0;
    1093                 :          0 :         memset(&item->map, 0, sizeof(item->map));
    1094         [ #  # ]:          0 :         for (i = 0; i < conf->nb_samples; i++) {
    1095                 :          0 :                 struct rte_flow_item_flex_field *fl = conf->sample_data + i;
    1096                 :            : 
    1097                 :          0 :                 ret = mlx5_flex_map_sample(fl, parser, item, error);
    1098         [ #  # ]:          0 :                 if (ret) {
    1099                 :            :                         MLX5_ASSERT(false);
    1100                 :          0 :                         return ret;
    1101                 :            :                 }
    1102                 :            :         }
    1103         [ #  # ]:          0 :         if (conf->tunnel == FLEX_TUNNEL_MODE_MULTI) {
    1104                 :            :                 /*
    1105                 :            :                  * In FLEX_TUNNEL_MODE_MULTI tunnel mode PMD creates 2 sets
    1106                 :            :                  * of samples. The first set is for outer and the second set
    1107                 :            :                  * for inner flex flow item. Outer and inner samples differ
    1108                 :            :                  * only in tunnel_mode.
    1109                 :            :                  */
    1110         [ #  # ]:          0 :                 if (parser->num_samples > MLX5_GRAPH_NODE_SAMPLE_NUM / 2)
    1111                 :          0 :                         return rte_flow_error_set
    1112                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    1113                 :            :                                  "no sample registers for inner");
    1114                 :          0 :                 rte_memcpy(parser->devx_conf.sample + parser->num_samples,
    1115                 :          0 :                            parser->devx_conf.sample,
    1116         [ #  # ]:          0 :                            parser->num_samples *
    1117                 :            :                                         sizeof(parser->devx_conf.sample[0]));
    1118         [ #  # ]:          0 :                 for (i = 0; i < parser->num_samples; i++) {
    1119                 :          0 :                         struct mlx5_devx_match_sample_attr *sm = i +
    1120                 :          0 :                                 parser->devx_conf.sample + parser->num_samples;
    1121                 :            : 
    1122                 :          0 :                         sm->flow_match_sample_tunnel_mode =
    1123                 :            :                                                 MLX5_GRAPH_SAMPLE_TUNNEL_INNER;
    1124                 :            :                 }
    1125                 :          0 :                 parser->num_samples *= 2;
    1126                 :            :         }
    1127                 :            :         return 0;
    1128                 :            : }
    1129                 :            : 
    1130                 :            : static int
    1131                 :          0 : mlx5_flex_arc_type(enum rte_flow_item_type type, int in)
    1132                 :            : {
    1133   [ #  #  #  #  :          0 :         switch (type) {
          #  #  #  #  #  
                   #  # ]
    1134                 :            :         case RTE_FLOW_ITEM_TYPE_ETH:
    1135                 :            :                 return  MLX5_GRAPH_ARC_NODE_MAC;
    1136                 :          0 :         case RTE_FLOW_ITEM_TYPE_IPV4:
    1137         [ #  # ]:          0 :                 return in ? MLX5_GRAPH_ARC_NODE_IP : MLX5_GRAPH_ARC_NODE_IPV4;
    1138                 :          0 :         case RTE_FLOW_ITEM_TYPE_IPV6:
    1139         [ #  # ]:          0 :                 return in ? MLX5_GRAPH_ARC_NODE_IP : MLX5_GRAPH_ARC_NODE_IPV6;
    1140                 :          0 :         case RTE_FLOW_ITEM_TYPE_UDP:
    1141                 :          0 :                 return MLX5_GRAPH_ARC_NODE_UDP;
    1142                 :          0 :         case RTE_FLOW_ITEM_TYPE_TCP:
    1143                 :          0 :                 return MLX5_GRAPH_ARC_NODE_TCP;
    1144                 :          0 :         case RTE_FLOW_ITEM_TYPE_MPLS:
    1145                 :          0 :                 return MLX5_GRAPH_ARC_NODE_MPLS;
    1146                 :          0 :         case RTE_FLOW_ITEM_TYPE_GRE:
    1147                 :          0 :                 return MLX5_GRAPH_ARC_NODE_GRE;
    1148                 :          0 :         case RTE_FLOW_ITEM_TYPE_GENEVE:
    1149                 :          0 :                 return MLX5_GRAPH_ARC_NODE_GENEVE;
    1150                 :          0 :         case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
    1151                 :          0 :                 return MLX5_GRAPH_ARC_NODE_VXLAN_GPE;
    1152                 :          0 :         case RTE_FLOW_ITEM_TYPE_ESP:
    1153                 :          0 :                 return MLX5_GRAPH_ARC_NODE_IPSEC_ESP;
    1154                 :          0 :         default:
    1155                 :          0 :                 return -EINVAL;
    1156                 :            :         }
    1157                 :            : }
    1158                 :            : 
    1159                 :            : static int
    1160                 :          0 : mlx5_flex_arc_in_eth(const struct rte_flow_item *item,
    1161                 :            :                      struct rte_flow_error *error)
    1162                 :            : {
    1163                 :          0 :         const struct rte_flow_item_eth *spec = item->spec;
    1164                 :          0 :         const struct rte_flow_item_eth *mask = item->mask;
    1165                 :          0 :         struct rte_flow_item_eth eth = { .hdr.ether_type = RTE_BE16(0xFFFF) };
    1166                 :            : 
    1167         [ #  # ]:          0 :         if (memcmp(mask, &eth, sizeof(struct rte_flow_item_eth))) {
    1168                 :          0 :                 return rte_flow_error_set
    1169                 :            :                         (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, item,
    1170                 :            :                          "invalid eth item mask");
    1171                 :            :         }
    1172         [ #  # ]:          0 :         return rte_be_to_cpu_16(spec->hdr.ether_type);
    1173                 :            : }
    1174                 :            : 
    1175                 :            : static int
    1176                 :          0 : mlx5_flex_arc_in_udp(const struct rte_flow_item *item,
    1177                 :            :                      struct rte_flow_error *error)
    1178                 :            : {
    1179                 :          0 :         const struct rte_flow_item_udp *spec = item->spec;
    1180                 :          0 :         const struct rte_flow_item_udp *mask = item->mask;
    1181                 :          0 :         struct rte_flow_item_udp udp = { .hdr.dst_port = RTE_BE16(0xFFFF) };
    1182                 :            : 
    1183         [ #  # ]:          0 :         if (memcmp(mask, &udp, sizeof(struct rte_flow_item_udp))) {
    1184                 :          0 :                 return rte_flow_error_set
    1185                 :            :                         (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, item,
    1186                 :            :                          "invalid eth item mask");
    1187                 :            :         }
    1188         [ #  # ]:          0 :         return rte_be_to_cpu_16(spec->hdr.dst_port);
    1189                 :            : }
    1190                 :            : 
    1191                 :            : static int
    1192                 :          0 : mlx5_flex_arc_in_ipv4(const struct rte_flow_item *item,
    1193                 :            :                       struct rte_flow_error *error)
    1194                 :            : {
    1195                 :          0 :         const struct rte_flow_item_ipv4 *spec = item->spec;
    1196                 :          0 :         const struct rte_flow_item_ipv4 *mask = item->mask;
    1197                 :          0 :         struct rte_flow_item_ipv4 ip = { .hdr.next_proto_id = 0xff };
    1198                 :            : 
    1199         [ #  # ]:          0 :         if (memcmp(mask, &ip, sizeof(struct rte_flow_item_ipv4))) {
    1200                 :          0 :                 return rte_flow_error_set
    1201                 :            :                         (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, item,
    1202                 :            :                          "invalid ipv4 item mask, full mask is desired");
    1203                 :            :         }
    1204                 :          0 :         return spec->hdr.next_proto_id;
    1205                 :            : }
    1206                 :            : 
    1207                 :            : static int
    1208                 :          0 : mlx5_flex_arc_in_ipv6(const struct rte_flow_item *item,
    1209                 :            :                       struct rte_flow_error *error)
    1210                 :            : {
    1211                 :          0 :         const struct rte_flow_item_ipv6 *spec = item->spec;
    1212                 :          0 :         const struct rte_flow_item_ipv6 *mask = item->mask;
    1213                 :          0 :         struct rte_flow_item_ipv6 ip = { .hdr.proto = 0xff };
    1214                 :            : 
    1215         [ #  # ]:          0 :         if (memcmp(mask, &ip, sizeof(struct rte_flow_item_ipv6))) {
    1216                 :          0 :                 return rte_flow_error_set
    1217                 :            :                         (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, item,
    1218                 :            :                          "invalid ipv6 item mask, full mask is desired");
    1219                 :            :         }
    1220                 :          0 :         return spec->hdr.proto;
    1221                 :            : }
    1222                 :            : 
    1223                 :            : static int
    1224                 :          0 : mlx5_flex_translate_arc_in(struct mlx5_hca_flex_attr *attr,
    1225                 :            :                            const struct rte_flow_item_flex_conf *conf,
    1226                 :            :                            struct mlx5_flex_parser_devx *devx,
    1227                 :            :                            struct mlx5_flex_item *item,
    1228                 :            :                            struct rte_flow_error *error)
    1229                 :            : {
    1230                 :            :         struct mlx5_devx_graph_node_attr *node = &devx->devx_conf;
    1231                 :            :         uint32_t i;
    1232                 :            : 
    1233                 :            :         RTE_SET_USED(item);
    1234         [ #  # ]:          0 :         if (conf->nb_inputs > attr->max_num_arc_in)
    1235                 :          0 :                 return rte_flow_error_set
    1236                 :            :                         (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    1237                 :            :                          "too many input links");
    1238         [ #  # ]:          0 :         for (i = 0; i < conf->nb_inputs; i++) {
    1239                 :          0 :                 struct mlx5_devx_graph_arc_attr *arc = node->in + i;
    1240                 :          0 :                 struct rte_flow_item_flex_link *link = conf->input_link + i;
    1241                 :          0 :                 const struct rte_flow_item *rte_item = &link->item;
    1242                 :            :                 int arc_type;
    1243                 :            :                 int ret;
    1244                 :            : 
    1245   [ #  #  #  #  :          0 :                 if (!rte_item->spec || !rte_item->mask || rte_item->last)
                   #  # ]
    1246                 :          0 :                         return rte_flow_error_set
    1247                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    1248                 :            :                                  "invalid flex item IN arc format");
    1249                 :          0 :                 arc_type = mlx5_flex_arc_type(rte_item->type, true);
    1250   [ #  #  #  # ]:          0 :                 if (arc_type < 0 || !(attr->node_in & RTE_BIT32(arc_type)))
    1251                 :          0 :                         return rte_flow_error_set
    1252                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    1253                 :            :                                  "unsupported flex item IN arc type");
    1254                 :          0 :                 arc->arc_parse_graph_node = arc_type;
    1255                 :          0 :                 arc->start_inner_tunnel = 0;
    1256                 :            :                 /*
    1257                 :            :                  * Configure arc IN condition value. The value location depends
    1258                 :            :                  * on protocol. Current FW version supports IP & UDP for IN
    1259                 :            :                  * arcs only, and locations for these protocols are defined.
    1260                 :            :                  * Add more protocols when available.
    1261                 :            :                  */
    1262   [ #  #  #  #  :          0 :                 switch (rte_item->type) {
                      # ]
    1263                 :          0 :                 case RTE_FLOW_ITEM_TYPE_ETH:
    1264                 :          0 :                         ret = mlx5_flex_arc_in_eth(rte_item, error);
    1265                 :          0 :                         break;
    1266                 :          0 :                 case RTE_FLOW_ITEM_TYPE_UDP:
    1267                 :          0 :                         ret = mlx5_flex_arc_in_udp(rte_item, error);
    1268                 :          0 :                         break;
    1269                 :          0 :                 case RTE_FLOW_ITEM_TYPE_IPV4:
    1270                 :          0 :                         ret = mlx5_flex_arc_in_ipv4(rte_item, error);
    1271                 :          0 :                         break;
    1272                 :          0 :                 case RTE_FLOW_ITEM_TYPE_IPV6:
    1273                 :          0 :                         ret = mlx5_flex_arc_in_ipv6(rte_item, error);
    1274                 :          0 :                         break;
    1275                 :          0 :                 default:
    1276                 :            :                         MLX5_ASSERT(false);
    1277                 :          0 :                         return rte_flow_error_set
    1278                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    1279                 :            :                                  "unsupported flex item IN arc type");
    1280                 :            :                 }
    1281         [ #  # ]:          0 :                 if (ret < 0)
    1282                 :          0 :                         return ret;
    1283                 :          0 :                 arc->compare_condition_value = (uint16_t)ret;
    1284                 :            :         }
    1285                 :            :         return 0;
    1286                 :            : }
    1287                 :            : 
    1288                 :            : static int
    1289                 :          0 : mlx5_flex_translate_arc_out(struct mlx5_hca_flex_attr *attr,
    1290                 :            :                             const struct rte_flow_item_flex_conf *conf,
    1291                 :            :                             struct mlx5_flex_parser_devx *devx,
    1292                 :            :                             struct mlx5_flex_item *item,
    1293                 :            :                             struct rte_flow_error *error)
    1294                 :            : {
    1295                 :            :         struct mlx5_devx_graph_node_attr *node = &devx->devx_conf;
    1296                 :          0 :         bool is_tunnel = conf->tunnel == FLEX_TUNNEL_MODE_TUNNEL;
    1297                 :            :         uint32_t i;
    1298                 :            : 
    1299                 :            :         RTE_SET_USED(item);
    1300         [ #  # ]:          0 :         if (conf->nb_outputs > attr->max_num_arc_out)
    1301                 :          0 :                 return rte_flow_error_set
    1302                 :            :                         (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    1303                 :            :                          "too many output links");
    1304         [ #  # ]:          0 :         for (i = 0; i < conf->nb_outputs; i++) {
    1305                 :          0 :                 struct mlx5_devx_graph_arc_attr *arc = node->out + i;
    1306                 :          0 :                 struct rte_flow_item_flex_link *link = conf->output_link + i;
    1307                 :            :                 const struct rte_flow_item *rte_item = &link->item;
    1308                 :            :                 int arc_type;
    1309                 :            : 
    1310   [ #  #  #  #  :          0 :                 if (rte_item->spec || rte_item->mask || rte_item->last)
                   #  # ]
    1311                 :          0 :                         return rte_flow_error_set
    1312                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    1313                 :            :                                  "flex node: invalid OUT arc format");
    1314                 :          0 :                 arc_type = mlx5_flex_arc_type(rte_item->type, false);
    1315   [ #  #  #  # ]:          0 :                 if (arc_type < 0 || !(attr->node_out & RTE_BIT32(arc_type)))
    1316                 :          0 :                         return rte_flow_error_set
    1317                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    1318                 :            :                                  "unsupported flex item OUT arc type");
    1319                 :          0 :                 arc->arc_parse_graph_node = arc_type;
    1320                 :          0 :                 arc->start_inner_tunnel = !!is_tunnel;
    1321                 :          0 :                 arc->compare_condition_value = link->next;
    1322                 :            :         }
    1323                 :            :         return 0;
    1324                 :            : }
    1325                 :            : 
    1326                 :            : /* Translate RTE flex item API configuration into flaex parser settings. */
    1327                 :            : static int
    1328                 :          0 : mlx5_flex_translate_conf(struct rte_eth_dev *dev,
    1329                 :            :                          const struct rte_flow_item_flex_conf *conf,
    1330                 :            :                          struct mlx5_flex_parser_devx *devx,
    1331                 :            :                          struct mlx5_flex_item *item,
    1332                 :            :                          struct rte_flow_error *error)
    1333                 :            : {
    1334                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    1335                 :          0 :         struct mlx5_hca_flex_attr *attr = &priv->sh->cdev->config.hca_attr.flex;
    1336                 :            :         int ret;
    1337                 :            : 
    1338                 :          0 :         ret = mlx5_flex_translate_length(attr, conf, devx, error);
    1339         [ #  # ]:          0 :         if (ret)
    1340                 :            :                 return ret;
    1341                 :          0 :         ret = mlx5_flex_translate_next(attr, conf, devx, error);
    1342         [ #  # ]:          0 :         if (ret)
    1343                 :            :                 return ret;
    1344                 :          0 :         ret = mlx5_flex_translate_sample(attr, conf, devx, item, error);
    1345         [ #  # ]:          0 :         if (ret)
    1346                 :            :                 return ret;
    1347                 :          0 :         ret = mlx5_flex_translate_arc_in(attr, conf, devx, item, error);
    1348         [ #  # ]:          0 :         if (ret)
    1349                 :            :                 return ret;
    1350                 :          0 :         ret = mlx5_flex_translate_arc_out(attr, conf, devx, item, error);
    1351         [ #  # ]:          0 :         if (ret)
    1352                 :          0 :                 return ret;
    1353                 :            :         return 0;
    1354                 :            : }
    1355                 :            : 
    1356                 :            : /**
    1357                 :            :  * Create the flex item with specified configuration over the Ethernet device.
    1358                 :            :  *
    1359                 :            :  * @param dev
    1360                 :            :  *   Ethernet device to create flex item on.
    1361                 :            :  * @param[in] conf
    1362                 :            :  *   Flex item configuration.
    1363                 :            :  * @param[out] error
    1364                 :            :  *   Perform verbose error reporting if not NULL. PMDs initialize this
    1365                 :            :  *   structure in case of error only.
    1366                 :            :  *
    1367                 :            :  * @return
    1368                 :            :  *   Non-NULL opaque pointer on success, NULL otherwise and rte_errno is set.
    1369                 :            :  */
    1370                 :            : struct rte_flow_item_flex_handle *
    1371                 :          0 : flow_dv_item_create(struct rte_eth_dev *dev,
    1372                 :            :                     const struct rte_flow_item_flex_conf *conf,
    1373                 :            :                     struct rte_flow_error *error)
    1374                 :            : {
    1375                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    1376                 :          0 :         struct mlx5_flex_parser_devx devx_config = { .devx_obj = NULL };
    1377                 :            :         struct mlx5_flex_item *flex;
    1378                 :            :         struct mlx5_list_entry *ent;
    1379                 :            : 
    1380                 :            :         MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY);
    1381                 :          0 :         flex = mlx5_flex_alloc(priv);
    1382         [ #  # ]:          0 :         if (!flex) {
    1383                 :          0 :                 rte_flow_error_set(error, ENOMEM,
    1384                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    1385                 :            :                                    "too many flex items created on the port");
    1386                 :          0 :                 return NULL;
    1387                 :            :         }
    1388         [ #  # ]:          0 :         if (mlx5_flex_translate_conf(dev, conf, &devx_config, flex, error))
    1389                 :          0 :                 goto error;
    1390                 :          0 :         ent = mlx5_list_register(priv->sh->flex_parsers_dv, &devx_config);
    1391         [ #  # ]:          0 :         if (!ent) {
    1392                 :          0 :                 rte_flow_error_set(error, ENOMEM,
    1393                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    1394                 :            :                                    "flex item creation failure");
    1395                 :          0 :                 goto error;
    1396                 :            :         }
    1397                 :          0 :         flex->devx_fp = container_of(ent, struct mlx5_flex_parser_devx, entry);
    1398                 :            :         /* Mark initialized flex item valid. */
    1399                 :          0 :         rte_atomic_fetch_add_explicit(&flex->refcnt, 1, rte_memory_order_release);
    1400                 :          0 :         return (struct rte_flow_item_flex_handle *)flex;
    1401                 :            : 
    1402                 :          0 : error:
    1403                 :          0 :         mlx5_flex_free(priv, flex);
    1404                 :          0 :         return NULL;
    1405                 :            : }
    1406                 :            : 
    1407                 :            : /**
    1408                 :            :  * Release the flex item on the specified Ethernet device.
    1409                 :            :  *
    1410                 :            :  * @param dev
    1411                 :            :  *   Ethernet device to destroy flex item on.
    1412                 :            :  * @param[in] handle
    1413                 :            :  *   Handle of the item existing on the specified device.
    1414                 :            :  * @param[out] error
    1415                 :            :  *   Perform verbose error reporting if not NULL. PMDs initialize this
    1416                 :            :  *   structure in case of error only.
    1417                 :            :  *
    1418                 :            :  * @return
    1419                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    1420                 :            :  */
    1421                 :            : int
    1422                 :          0 : flow_dv_item_release(struct rte_eth_dev *dev,
    1423                 :            :                      const struct rte_flow_item_flex_handle *handle,
    1424                 :            :                      struct rte_flow_error *error)
    1425                 :            : {
    1426                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    1427                 :            :         struct mlx5_flex_item *flex =
    1428                 :            :                 (struct mlx5_flex_item *)(uintptr_t)handle;
    1429                 :            :         uint32_t old_refcnt = 1;
    1430                 :            :         int rc;
    1431                 :            : 
    1432                 :            :         MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY);
    1433                 :          0 :         rte_spinlock_lock(&priv->flex_item_sl);
    1434         [ #  # ]:          0 :         if (mlx5_flex_index(priv, flex) < 0) {
    1435                 :            :                 rte_spinlock_unlock(&priv->flex_item_sl);
    1436                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    1437                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    1438                 :            :                                           "invalid flex item handle value");
    1439                 :            :         }
    1440         [ #  # ]:          0 :         if (!rte_atomic_compare_exchange_strong_explicit(&flex->refcnt, &old_refcnt, 0,
    1441                 :            :                                          rte_memory_order_acquire, rte_memory_order_relaxed)) {
    1442                 :            :                 rte_spinlock_unlock(&priv->flex_item_sl);
    1443                 :          0 :                 return rte_flow_error_set(error, EBUSY,
    1444                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    1445                 :            :                                           "flex item has flow references");
    1446                 :            :         }
    1447                 :            :         /* Flex item is marked as invalid, we can leave locked section. */
    1448                 :            :         rte_spinlock_unlock(&priv->flex_item_sl);
    1449                 :            :         MLX5_ASSERT(flex->devx_fp);
    1450                 :          0 :         rc = mlx5_list_unregister(priv->sh->flex_parsers_dv,
    1451                 :          0 :                                   &flex->devx_fp->entry);
    1452                 :          0 :         flex->devx_fp = NULL;
    1453                 :          0 :         mlx5_flex_free(priv, flex);
    1454         [ #  # ]:          0 :         if (rc < 0)
    1455                 :          0 :                 return rte_flow_error_set(error, EBUSY,
    1456                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    1457                 :            :                                           "flex item release failure");
    1458                 :            :         return 0;
    1459                 :            : }
    1460                 :            : 
    1461                 :            : /* DevX flex parser list callbacks. */
    1462                 :            : struct mlx5_list_entry *
    1463                 :          0 : mlx5_flex_parser_create_cb(void *list_ctx, void *ctx)
    1464                 :            : {
    1465                 :            :         struct mlx5_dev_ctx_shared *sh = list_ctx;
    1466                 :            :         struct mlx5_flex_parser_devx *fp, *conf = ctx;
    1467                 :            :         uint32_t i;
    1468                 :          0 :         uint8_t sample_info = sh->cdev->config.hca_attr.flex.query_match_sample_info;
    1469                 :            :         int ret;
    1470                 :            : 
    1471                 :          0 :         fp = mlx5_malloc(MLX5_MEM_ZERO, sizeof(struct mlx5_flex_parser_devx),
    1472                 :            :                          0, SOCKET_ID_ANY);
    1473         [ #  # ]:          0 :         if (!fp)
    1474                 :            :                 return NULL;
    1475                 :            :         /* Copy the requested configurations. */
    1476                 :          0 :         fp->num_samples = conf->num_samples;
    1477                 :          0 :         memcpy(&fp->devx_conf, &conf->devx_conf, sizeof(fp->devx_conf));
    1478                 :            :         /* Create DevX flex parser. */
    1479                 :          0 :         fp->devx_obj = mlx5_devx_cmd_create_flex_parser(sh->cdev->ctx,
    1480                 :            :                                                         &fp->devx_conf);
    1481         [ #  # ]:          0 :         if (!fp->devx_obj)
    1482                 :          0 :                 goto error;
    1483                 :            :         /* Query the firmware assigned sample ids. */
    1484                 :          0 :         ret = mlx5_devx_cmd_query_parse_samples(fp->devx_obj,
    1485                 :          0 :                                                 fp->sample_ids,
    1486                 :            :                                                 fp->num_samples,
    1487                 :            :                                                 &fp->anchor_id);
    1488         [ #  # ]:          0 :         if (ret)
    1489                 :          0 :                 goto error;
    1490                 :            :         /* Query sample information per ID. */
    1491   [ #  #  #  # ]:          0 :         for (i = 0; i < fp->num_samples && sample_info; i++) {
    1492                 :          0 :                 ret = mlx5_devx_cmd_match_sample_info_query(sh->cdev->ctx, fp->sample_ids[i],
    1493                 :            :                                                             &fp->sample_info[i]);
    1494         [ #  # ]:          0 :                 if (ret)
    1495                 :          0 :                         goto error;
    1496                 :            :         }
    1497                 :          0 :         DRV_LOG(DEBUG, "DEVx flex parser %p created, samples num: %u",
    1498                 :            :                 (const void *)fp, fp->num_samples);
    1499                 :          0 :         return &fp->entry;
    1500                 :          0 : error:
    1501         [ #  # ]:          0 :         if (fp->devx_obj)
    1502                 :          0 :                 mlx5_devx_cmd_destroy((void *)(uintptr_t)fp->devx_obj);
    1503                 :            :         if (fp)
    1504                 :          0 :                 mlx5_free(fp);
    1505                 :          0 :         return NULL;
    1506                 :            : }
    1507                 :            : 
    1508                 :            : int
    1509                 :          0 : mlx5_flex_parser_match_cb(void *list_ctx,
    1510                 :            :                           struct mlx5_list_entry *iter, void *ctx)
    1511                 :            : {
    1512                 :            :         struct mlx5_flex_parser_devx *fp =
    1513                 :            :                 container_of(iter, struct mlx5_flex_parser_devx, entry);
    1514                 :            :         struct mlx5_flex_parser_devx *org =
    1515                 :            :                 container_of(ctx, struct mlx5_flex_parser_devx, entry);
    1516                 :            : 
    1517                 :            :         RTE_SET_USED(list_ctx);
    1518         [ #  # ]:          0 :         return !iter || !ctx || memcmp(&fp->devx_conf,
    1519         [ #  # ]:          0 :                                        &org->devx_conf,
    1520                 :            :                                        sizeof(fp->devx_conf));
    1521                 :            : }
    1522                 :            : 
    1523                 :            : void
    1524                 :          0 : mlx5_flex_parser_remove_cb(void *list_ctx, struct mlx5_list_entry *entry)
    1525                 :            : {
    1526                 :            :         struct mlx5_flex_parser_devx *fp =
    1527                 :            :                 container_of(entry, struct mlx5_flex_parser_devx, entry);
    1528                 :            : 
    1529                 :            :         RTE_SET_USED(list_ctx);
    1530                 :            :         MLX5_ASSERT(fp->devx_obj);
    1531                 :          0 :         claim_zero(mlx5_devx_cmd_destroy(fp->devx_obj));
    1532                 :          0 :         DRV_LOG(DEBUG, "DEVx flex parser %p destroyed", (const void *)fp);
    1533                 :          0 :         mlx5_free(entry);
    1534                 :          0 : }
    1535                 :            : 
    1536                 :            : struct mlx5_list_entry *
    1537                 :          0 : mlx5_flex_parser_clone_cb(void *list_ctx,
    1538                 :            :                           struct mlx5_list_entry *entry, void *ctx)
    1539                 :            : {
    1540                 :            :         struct mlx5_flex_parser_devx *fp;
    1541                 :            : 
    1542                 :            :         RTE_SET_USED(list_ctx);
    1543                 :            :         RTE_SET_USED(entry);
    1544                 :          0 :         fp = mlx5_malloc(0, sizeof(struct mlx5_flex_parser_devx),
    1545                 :            :                          0, SOCKET_ID_ANY);
    1546         [ #  # ]:          0 :         if (!fp)
    1547                 :            :                 return NULL;
    1548                 :            :         memcpy(fp, ctx, sizeof(struct mlx5_flex_parser_devx));
    1549                 :          0 :         return &fp->entry;
    1550                 :            : }
    1551                 :            : 
    1552                 :            : void
    1553                 :          0 : mlx5_flex_parser_clone_free_cb(void *list_ctx, struct mlx5_list_entry *entry)
    1554                 :            : {
    1555                 :            :         struct mlx5_flex_parser_devx *fp =
    1556                 :            :                 container_of(entry, struct mlx5_flex_parser_devx, entry);
    1557                 :            :         RTE_SET_USED(list_ctx);
    1558                 :          0 :         mlx5_free(fp);
    1559                 :          0 : }

Generated by: LCOV version 1.14