LCOV - code coverage report
Current view: top level - drivers/net/mlx5 - mlx5_nta_split.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 155 0.0 %
Date: 2024-12-01 18:57:19 Functions: 0 10 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 58 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright (c) 2024 NVIDIA Corporation & Affiliates
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <rte_common.h>
       6                 :            : #include <rte_flow.h>
       7                 :            : 
       8                 :            : #include "mlx5_malloc.h"
       9                 :            : #include "mlx5.h"
      10                 :            : #include "mlx5_defs.h"
      11                 :            : #include "mlx5_flow.h"
      12                 :            : #include "mlx5_rx.h"
      13                 :            : 
      14                 :            : #ifdef HAVE_MLX5_HWS_SUPPORT
      15                 :            : 
      16                 :            : /*
      17                 :            :  * Generate new actions lists for prefix and suffix flows.
      18                 :            :  *
      19                 :            :  * @param[in] dev
      20                 :            :  *   Pointer to rte_eth_dev structure.
      21                 :            :  * @param[in] prefix_act
      22                 :            :  *   Pointer to actions for prefix flow rule.
      23                 :            :  * @param[in] suffix_act
      24                 :            :  *   Pointer to actions for suffix flow rule.
      25                 :            :  * @param[in] actions
      26                 :            :  *   Pointer to the original actions list.
      27                 :            :  * @param[in] qrss
      28                 :            :  *   Pointer to the action of QUEUE / RSS.
      29                 :            :  * @param[in] actions_n
      30                 :            :  *   Number of the actions in the original list.
      31                 :            :  * @param[out] error
      32                 :            :  *   Pointer to error structure.
      33                 :            :  *
      34                 :            :  * @return
      35                 :            :  *   Positive prefix flow ID on success, zero on failure.
      36                 :            :  */
      37                 :            : static uint32_t
      38                 :          0 : mlx5_flow_nta_split_qrss_actions_prep(struct rte_eth_dev *dev,
      39                 :            :                                       struct rte_flow_action *prefix_act,
      40                 :            :                                       struct rte_flow_action *suffix_act,
      41                 :            :                                       const struct rte_flow_action *actions,
      42                 :            :                                       const struct rte_flow_action *qrss,
      43                 :            :                                       int actions_n,
      44                 :            :                                       struct rte_flow_error *error)
      45                 :            : {
      46                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
      47                 :            :         struct mlx5_rte_flow_action_set_tag *set_tag;
      48                 :            :         struct rte_flow_action_jump *jump;
      49                 :          0 :         const int qrss_idx = qrss - actions;
      50                 :          0 :         uint32_t flow_id = 0;
      51                 :            :         int ret = 0;
      52                 :            : 
      53                 :            :         /* Allocate the new subflow ID and used to be matched later. */
      54                 :          0 :         mlx5_ipool_malloc(priv->sh->ipool[MLX5_IPOOL_RSS_EXPANTION_FLOW_ID], &flow_id);
      55         [ #  # ]:          0 :         if (!flow_id) {
      56                 :          0 :                 rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_ACTION, NULL,
      57                 :            :                                    "can't allocate id for split Q/RSS subflow");
      58                 :          0 :                 return 0;
      59                 :            :         }
      60                 :            :         /*
      61                 :            :          * Given actions will be split
      62                 :            :          * - Replace QUEUE/RSS action with SET_TAG to set flow ID.
      63                 :            :          * - Add jump to mreg CP_TBL.
      64                 :            :          * As a result, there will be one more action.
      65                 :            :          */
      66                 :          0 :         memcpy(prefix_act, actions, sizeof(struct rte_flow_action) * actions_n);
      67                 :            :         /* Count MLX5_RTE_FLOW_ACTION_TYPE_TAG. */
      68                 :          0 :         actions_n++;
      69                 :          0 :         set_tag = (void *)(prefix_act + actions_n);
      70                 :            :         /* Reuse ASO reg, should always succeed. Consider to use REG_C_6. */
      71                 :            :         ret = flow_hw_get_reg_id_by_domain(dev, RTE_FLOW_ITEM_TYPE_METER_COLOR,
      72                 :            :                                            MLX5DR_TABLE_TYPE_NIC_RX, 0);
      73                 :            :         MLX5_ASSERT(ret != (int)REG_NON);
      74                 :          0 :         set_tag->id = (enum modify_reg)ret;
      75                 :            :         /* Internal SET_TAG action to set flow ID. */
      76                 :          0 :         set_tag->data = flow_id;
      77                 :            :         /* Construct new actions array and replace QUEUE/RSS action. */
      78                 :          0 :         prefix_act[qrss_idx] = (struct rte_flow_action) {
      79                 :            :                 .type = (enum rte_flow_action_type)MLX5_RTE_FLOW_ACTION_TYPE_TAG,
      80                 :            :                 .conf = set_tag,
      81                 :            :         };
      82                 :            :         /* JUMP action to jump to mreg copy table (CP_TBL). */
      83                 :          0 :         jump = (void *)(set_tag + 1);
      84                 :          0 :         *jump = (struct rte_flow_action_jump) {
      85                 :            :                 .group = MLX5_FLOW_MREG_CP_TABLE_GROUP,
      86                 :            :         };
      87                 :          0 :         prefix_act[actions_n - 2] = (struct rte_flow_action) {
      88                 :            :                 .type = RTE_FLOW_ACTION_TYPE_JUMP,
      89                 :            :                 .conf = jump,
      90                 :            :         };
      91                 :          0 :         prefix_act[actions_n - 1] = (struct rte_flow_action) {
      92                 :            :                 .type = RTE_FLOW_ACTION_TYPE_END,
      93                 :            :         };
      94                 :            :         /* Copy the suffix Q/RSS action, can also be indirect RSS. */
      95                 :          0 :         suffix_act[0] = (struct rte_flow_action) {
      96                 :          0 :                 .type = qrss->type,
      97                 :          0 :                 .conf = qrss->conf,
      98                 :            :         };
      99                 :          0 :         suffix_act[1] = (struct rte_flow_action) {
     100                 :            :                 .type = RTE_FLOW_ACTION_TYPE_END,
     101                 :            :         };
     102                 :          0 :         return flow_id;
     103                 :            : }
     104                 :            : 
     105                 :            : /*
     106                 :            :  * Generate new attribute and items for suffix flows.
     107                 :            :  *
     108                 :            :  * @param[in] dev
     109                 :            :  *   Pointer to rte_eth_dev structure.
     110                 :            :  * @param[in] split_attr
     111                 :            :  *   Pointer to attribute for prefix flow rule.
     112                 :            :  * @param[in] split_items
     113                 :            :  *   Pointer to actions for suffix flow rule.
     114                 :            :  * @param[in] qrss_id
     115                 :            :  *   Prefix flow ID to match.
     116                 :            :  */
     117                 :            : static void
     118                 :            : mlx5_flow_nta_split_qrss_items_prep(struct rte_eth_dev *dev,
     119                 :            :                                     struct rte_flow_attr *split_attr,
     120                 :            :                                     struct rte_flow_item *split_items,
     121                 :            :                                     uint32_t qrss_id)
     122                 :            : {
     123                 :            :         struct mlx5_rte_flow_item_tag *q_tag_spec;
     124                 :            : 
     125                 :            :         /* MLX5_FLOW_MREG_CP_TABLE_GROUP -> MLX5_FLOW_MREG_ACT_TABLE_GROUP(Q/RSS base) */
     126                 :          0 :         split_attr->ingress = 1;
     127                 :          0 :         split_attr->group = MLX5_FLOW_MREG_ACT_TABLE_GROUP;
     128                 :            :         /* Only internal tag will be used, together with the item flags for RSS. */
     129                 :          0 :         q_tag_spec = (void *)((char *)split_items + 2 * sizeof(struct rte_flow_item));
     130                 :          0 :         split_items[0].type = (enum rte_flow_item_type)MLX5_RTE_FLOW_ITEM_TYPE_TAG;
     131                 :          0 :         split_items[0].spec = q_tag_spec;
     132                 :          0 :         split_items[1].type = RTE_FLOW_ITEM_TYPE_END;
     133                 :          0 :         q_tag_spec->data = qrss_id;
     134                 :          0 :         q_tag_spec->id = (enum modify_reg)
     135                 :            :                          flow_hw_get_reg_id_by_domain(dev, RTE_FLOW_ITEM_TYPE_METER_COLOR,
     136                 :            :                                                       MLX5DR_TABLE_TYPE_NIC_RX, 0);
     137                 :            :         MLX5_ASSERT(q_tag_spec->id != REG_NON);
     138                 :            : }
     139                 :            : 
     140                 :            : /*
     141                 :            :  * Checking the split information and split the actions, items, attributes into
     142                 :            :  * prefix and suffix to connect the flows after passing the copy tables.
     143                 :            :  *
     144                 :            :  * @param[in] dev
     145                 :            :  *   Pointer to rte_eth_dev structure.
     146                 :            :  * @param[in] attr
     147                 :            :  *   Pointer to the flow attributes.
     148                 :            :  * @param[in] actions
     149                 :            :  *   Pointer to the original actions list.
     150                 :            :  * @param[in] qrss
     151                 :            :  *   Pointer to the action of QUEUE / RSS.
     152                 :            :  * @param[in] action_flags
     153                 :            :  *   Holds the actions detected.
     154                 :            :  * @param[in] actions_n
     155                 :            :  *   Number of original actions.
     156                 :            :  * @param[in] external
     157                 :            :  *   This flow rule is created by request external to PMD.
     158                 :            :  * @param[out] res
     159                 :            :  *   Pointer to the resource to store the split result.
     160                 :            :  * @param[out] error
     161                 :            :  *   Pointer to error structure.
     162                 :            :  *
     163                 :            :  * @return
     164                 :            :  *   - Positive 1 on succeed.
     165                 :            :  *   - 0 on no split.
     166                 :            :  *   - negative errno value on error.
     167                 :            :  */
     168                 :            : int
     169                 :          0 : mlx5_flow_nta_split_metadata(struct rte_eth_dev *dev,
     170                 :            :                              const struct rte_flow_attr *attr,
     171                 :            :                              const struct rte_flow_action actions[],
     172                 :            :                              const struct rte_flow_action *qrss,
     173                 :            :                              uint64_t action_flags,
     174                 :            :                              int actions_n,
     175                 :            :                              bool external,
     176                 :            :                              struct mlx5_flow_hw_split_resource *res,
     177                 :            :                              struct rte_flow_error *error)
     178                 :            : {
     179                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
     180                 :          0 :         struct mlx5_sh_config *config = &priv->sh->config;
     181                 :            :         const struct rte_flow_action_queue *queue;
     182                 :            :         const struct rte_flow_action_rss *rss;
     183                 :            :         struct rte_flow_action *prfx_actions;
     184                 :            :         struct rte_flow_action *sfx_actions;
     185                 :            :         struct rte_flow_attr *sfx_attr;
     186                 :            :         struct rte_flow_item *sfx_items;
     187                 :            :         size_t pefx_act_size, sfx_act_size;
     188                 :            :         size_t attr_size, item_size;
     189                 :            :         size_t total_size;
     190                 :            :         uint32_t qrss_id;
     191                 :            : 
     192                 :            :         /*
     193                 :            :          * The metadata copy flow should be created:
     194                 :            :          *   1. only on NIC Rx domain with Q / RSS
     195                 :            :          *   2. only when extended metadata mode is enabled
     196                 :            :          *   3. only on HWS, should always be "config->dv_flow_en == 2", this
     197                 :            :          *      checking can be skipped
     198                 :            :          * Note:
     199                 :            :          *   1. Even if metadata is not enabled in the data-path, it can still
     200                 :            :          *      be used to match on the Rx side.
     201                 :            :          *   2. The HWS Tx default copy rule or SQ rules already have the metadata
     202                 :            :          *      copy on the root table. The user's rule will always be inserted
     203                 :            :          *      and executed after the root table steering.
     204                 :            :          */
     205   [ #  #  #  # ]:          0 :         if (config->dv_xmeta_en == MLX5_XMETA_MODE_LEGACY || attr->transfer ||
     206         [ #  # ]:          0 :             attr->egress || !external || !qrss)
     207                 :            :                 return 0;
     208         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_QUEUE) {
     209                 :          0 :                 queue = (const struct rte_flow_action_queue *)actions->conf;
     210         [ #  # ]:          0 :                 if (mlx5_rxq_is_hairpin(dev, queue->index))
     211                 :            :                         return 0;
     212         [ #  # ]:          0 :         } else if (action_flags & MLX5_FLOW_ACTION_RSS) {
     213                 :          0 :                 rss = (const struct rte_flow_action_rss *)actions->conf;
     214         [ #  # ]:          0 :                 if (mlx5_rxq_is_hairpin(dev, rss->queue[0]))
     215                 :            :                         return 0;
     216                 :            :         }
     217                 :            :         /* The prefix and suffix flows' actions. */
     218                 :          0 :         pefx_act_size = sizeof(struct rte_flow_action) * (actions_n + 1) +
     219                 :          0 :                         sizeof(struct rte_flow_action_set_tag) +
     220                 :            :                         sizeof(struct rte_flow_action_jump);
     221                 :            :         sfx_act_size = sizeof(struct rte_flow_action) * 2;
     222                 :            :         /* The suffix attribute. */
     223                 :            :         attr_size = sizeof(struct rte_flow_attr);
     224                 :            :         /* The suffix items - mlx5_tag + end. */
     225                 :            :         item_size = sizeof(struct rte_flow_item) * 2 +
     226                 :            :                     sizeof(struct mlx5_rte_flow_item_tag);
     227                 :          0 :         total_size = pefx_act_size + sfx_act_size + attr_size + item_size;
     228                 :          0 :         prfx_actions = mlx5_malloc(MLX5_MEM_ZERO, total_size, 0, SOCKET_ID_ANY);
     229         [ #  # ]:          0 :         if (!prfx_actions)
     230                 :          0 :                 return rte_flow_error_set(error, ENOMEM,
     231                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
     232                 :            :                                           NULL, "no memory to split "
     233                 :            :                                           "metadata flow");
     234                 :          0 :         sfx_actions = (void *)((char *)prfx_actions + pefx_act_size);
     235                 :          0 :         qrss_id = mlx5_flow_nta_split_qrss_actions_prep(dev, prfx_actions,
     236                 :            :                                                         sfx_actions, actions,
     237                 :            :                                                         qrss, actions_n, error);
     238         [ #  # ]:          0 :         if (!qrss_id) {
     239                 :          0 :                 mlx5_free(prfx_actions);
     240                 :          0 :                 return -rte_errno;
     241                 :            :         }
     242                 :          0 :         sfx_attr = (void *)((char *)sfx_actions + sfx_act_size);
     243                 :          0 :         sfx_items = (void *)((char *)sfx_attr + attr_size);
     244                 :            :         mlx5_flow_nta_split_qrss_items_prep(dev, sfx_attr, sfx_items, qrss_id);
     245                 :          0 :         res->prefix.actions = prfx_actions;
     246                 :          0 :         res->suffix.actions = sfx_actions;
     247                 :          0 :         res->suffix.items = sfx_items;
     248                 :          0 :         res->suffix.attr = sfx_attr;
     249                 :          0 :         res->buf_start = prfx_actions;
     250                 :          0 :         res->flow_idx = qrss_id;
     251                 :          0 :         return 1;
     252                 :            : }
     253                 :            : 
     254                 :            : /*
     255                 :            :  * Release the buffer and flow ID.
     256                 :            :  *
     257                 :            :  * @param[in] dev
     258                 :            :  *   Pointer to rte_eth_dev structure.
     259                 :            :  * @param[in] res
     260                 :            :  *   Pointer to the resource to release.
     261                 :            :  */
     262                 :            : void
     263                 :          0 : mlx5_flow_nta_split_resource_free(struct rte_eth_dev *dev,
     264                 :            :                                   struct mlx5_flow_hw_split_resource *res)
     265                 :            : {
     266                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
     267                 :            : 
     268                 :          0 :         mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_RSS_EXPANTION_FLOW_ID], res->flow_idx);
     269                 :          0 :         mlx5_free(res->buf_start);
     270                 :          0 : }
     271                 :            : 
     272                 :            : /*
     273                 :            :  * Callback functions for the metadata copy and mark / flag set flow.
     274                 :            :  * The create and remove cannot reuse the DV since the flow opaque and structure
     275                 :            :  * are different, and the action used to copy the metadata is also different.
     276                 :            :  */
     277                 :            : struct mlx5_list_entry *
     278                 :          0 : flow_nta_mreg_create_cb(void *tool_ctx, void *cb_ctx)
     279                 :            : {
     280                 :            :         struct rte_eth_dev *dev = tool_ctx;
     281                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
     282                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
     283                 :            :         struct mlx5_flow_mreg_copy_resource *mcp_res;
     284                 :          0 :         struct rte_flow_error *error = ctx->error;
     285                 :          0 :         uint32_t idx = 0;
     286                 :          0 :         uint32_t mark_id = *(uint32_t *)(ctx->data);
     287                 :          0 :         struct rte_flow_attr attr = {
     288                 :            :                 .group = MLX5_FLOW_MREG_CP_TABLE_GROUP,
     289                 :            :                 .ingress = 1,
     290                 :            :         };
     291                 :          0 :         struct mlx5_rte_flow_item_tag tag_spec = {
     292                 :            :                 .id = REG_C_0,
     293                 :            :                 .data = mark_id,
     294                 :            :         };
     295                 :          0 :         struct mlx5_rte_flow_item_tag tag_mask = {
     296                 :          0 :                 .data = priv->sh->dv_mark_mask,
     297                 :            :         };
     298                 :          0 :         struct rte_flow_action_mark ftag = {
     299                 :            :                 .id = mark_id,
     300                 :            :         };
     301                 :          0 :         struct rte_flow_action_modify_field rx_meta = {
     302                 :            :                 .operation = RTE_FLOW_MODIFY_SET,
     303                 :            :                 .dst = {
     304                 :            :                         .field = (enum rte_flow_field_id)MLX5_RTE_FLOW_FIELD_META_REG,
     305                 :            :                         .tag_index = REG_B,
     306                 :            :                 },
     307                 :            :                 .src = {
     308                 :            :                         .field = (enum rte_flow_field_id)MLX5_RTE_FLOW_FIELD_META_REG,
     309                 :            :                         .tag_index = REG_C_1,
     310                 :            :                 },
     311                 :            :                 .width = 32,
     312                 :            :         };
     313                 :          0 :         struct rte_flow_action_jump jump = {
     314                 :            :                 .group = MLX5_FLOW_MREG_ACT_TABLE_GROUP,
     315                 :            :         };
     316                 :            :         struct rte_flow_item items[2];
     317                 :            :         struct rte_flow_action actions[4];
     318                 :            : 
     319                 :            :         /* Provide the full width of FLAG specific value. */
     320         [ #  # ]:          0 :         if (mark_id == (priv->sh->dv_regc0_mask & MLX5_FLOW_MARK_DEFAULT))
     321                 :          0 :                 tag_spec.data = MLX5_FLOW_MARK_DEFAULT;
     322                 :            :         /* Build a new flow. */
     323         [ #  # ]:          0 :         if (mark_id != MLX5_DEFAULT_COPY_ID) {
     324                 :          0 :                 items[0] = (struct rte_flow_item) {
     325                 :            :                         .type = (enum rte_flow_item_type)MLX5_RTE_FLOW_ITEM_TYPE_TAG,
     326                 :            :                         .spec = &tag_spec,
     327                 :            :                         .mask = &tag_mask,
     328                 :            :                 };
     329                 :          0 :                 actions[0] = (struct rte_flow_action) {
     330                 :            :                         .type = RTE_FLOW_ACTION_TYPE_MARK,
     331                 :            :                         .conf = &ftag,
     332                 :            :                 };
     333                 :            :         } else {
     334                 :            :                 /* Default rule, wildcard match with lowest priority. */
     335                 :          0 :                 attr.priority = MLX5_FLOW_LOWEST_PRIO_INDICATOR;
     336                 :          0 :                 items[0] = (struct rte_flow_item) {
     337                 :            :                         .type = RTE_FLOW_ITEM_TYPE_ETH,
     338                 :            :                 };
     339                 :          0 :                 actions[0] = (struct rte_flow_action) {
     340                 :            :                         .type = RTE_FLOW_ACTION_TYPE_VOID,
     341                 :            :                 };
     342                 :            :         }
     343                 :            :         /* (match REG 'tag') or all. */
     344                 :          0 :         items[1].type = RTE_FLOW_ITEM_TYPE_END;
     345                 :            :         /* (Mark) or void + copy to Rx meta + jump to the MREG_ACT_TABLE_GROUP. */
     346                 :          0 :         actions[1].type = RTE_FLOW_ACTION_TYPE_MODIFY_FIELD,
     347                 :          0 :         actions[1].conf = &rx_meta,
     348                 :          0 :         actions[2].type = RTE_FLOW_ACTION_TYPE_JUMP;
     349                 :          0 :         actions[2].conf = &jump;
     350                 :          0 :         actions[3].type = RTE_FLOW_ACTION_TYPE_END;
     351                 :            :         /* Build a new entry. */
     352                 :          0 :         mcp_res = mlx5_ipool_zmalloc(priv->sh->ipool[MLX5_IPOOL_MCP], &idx);
     353         [ #  # ]:          0 :         if (!mcp_res) {
     354                 :          0 :                 rte_errno = ENOMEM;
     355                 :          0 :                 return NULL;
     356                 :            :         }
     357                 :          0 :         mcp_res->idx = idx;
     358                 :          0 :         mcp_res->mark_id = mark_id;
     359                 :            :         /*
     360                 :            :          * The copy flows are not included in any list. There
     361                 :            :          * ones are referenced from other flows and cannot
     362                 :            :          * be applied, removed, deleted in arbitrary order
     363                 :            :          * by list traversing.
     364                 :            :          */
     365                 :          0 :         mcp_res->hw_flow = mlx5_flow_list_create(dev, MLX5_FLOW_TYPE_MCP, &attr,
     366                 :            :                                                  items, actions, false, error);
     367         [ #  # ]:          0 :         if (!mcp_res->hw_flow) {
     368                 :          0 :                 mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MCP], idx);
     369                 :          0 :                 return NULL;
     370                 :            :         }
     371                 :          0 :         return &mcp_res->hlist_ent;
     372                 :            : }
     373                 :            : 
     374                 :            : void
     375                 :          0 : flow_nta_mreg_remove_cb(void *tool_ctx, struct mlx5_list_entry *entry)
     376                 :            : {
     377                 :            :         struct mlx5_flow_mreg_copy_resource *mcp_res =
     378                 :            :                                container_of(entry, typeof(*mcp_res), hlist_ent);
     379                 :            :         struct rte_eth_dev *dev = tool_ctx;
     380                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
     381                 :            : 
     382                 :            :         MLX5_ASSERT(mcp_res->hw_flow);
     383                 :          0 :         mlx5_flow_list_destroy(dev, MLX5_FLOW_TYPE_MCP, mcp_res->hw_flow);
     384                 :          0 :         mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MCP], mcp_res->idx);
     385                 :          0 : }
     386                 :            : 
     387                 :            : /*
     388                 :            :  * Add a flow of copying flow metadata registers in RX_CP_TBL.
     389                 :            :  * @see flow_mreg_add_copy_action
     390                 :            :  *
     391                 :            :  * @param[in] dev
     392                 :            :  *   Pointer to Ethernet device.
     393                 :            :  * @param[in] mark_id
     394                 :            :  *   ID of MARK action, zero means default flow for META.
     395                 :            :  * @param[out] error
     396                 :            :  *   Perform verbose error reporting if not NULL.
     397                 :            :  *
     398                 :            :  * @return
     399                 :            :  *   Associated resource on success, NULL otherwise and rte_errno is set.
     400                 :            :  */
     401                 :            : static struct mlx5_flow_mreg_copy_resource *
     402                 :          0 : mlx5_flow_nta_add_copy_action(struct rte_eth_dev *dev,
     403                 :            :                               uint32_t mark_id,
     404                 :            :                               struct rte_flow_error *error)
     405                 :            : {
     406                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
     407                 :            :         struct mlx5_list_entry *entry;
     408                 :          0 :         uint32_t specialize = 0;
     409                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
     410                 :            :                 .dev = dev,
     411                 :            :                 .error = error,
     412                 :            :                 .data = &mark_id,
     413                 :            :                 .data2 = &specialize,
     414                 :            :         };
     415                 :            : 
     416                 :            :         /* Check if already registered. */
     417                 :            :         MLX5_ASSERT(priv->sh->mreg_cp_tbl);
     418                 :          0 :         entry = mlx5_hlist_register(priv->sh->mreg_cp_tbl, mark_id, &ctx);
     419         [ #  # ]:          0 :         if (!entry)
     420                 :          0 :                 return NULL;
     421                 :            :         return container_of(entry, struct mlx5_flow_mreg_copy_resource, hlist_ent);
     422                 :            : }
     423                 :            : 
     424                 :            : /*
     425                 :            :  * Release flow in RX_CP_TBL.
     426                 :            :  *
     427                 :            :  * @param[in] dev
     428                 :            :  *   Pointer to Ethernet device.
     429                 :            :  * @param[in] idx
     430                 :            :  *   Index in the pool to store the copy flow.
     431                 :            :  */
     432                 :            : void
     433                 :          0 : mlx5_flow_nta_del_copy_action(struct rte_eth_dev *dev, uint32_t idx)
     434                 :            : {
     435                 :            :         struct mlx5_flow_mreg_copy_resource *mcp_res;
     436                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
     437                 :            : 
     438         [ #  # ]:          0 :         if (!idx)
     439                 :            :                 return;
     440                 :          0 :         mcp_res = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_MCP], idx);
     441   [ #  #  #  # ]:          0 :         if (!mcp_res || !priv->sh->mreg_cp_tbl)
     442                 :            :                 return;
     443                 :            :         MLX5_ASSERT(mcp_res->hw_flow);
     444                 :          0 :         mlx5_hlist_unregister(priv->sh->mreg_cp_tbl, &mcp_res->hlist_ent);
     445                 :            : }
     446                 :            : 
     447                 :            : /*
     448                 :            :  * Remove the default copy action from RX_CP_TBL.
     449                 :            :  * @see flow_mreg_del_default_copy_action
     450                 :            :  *
     451                 :            :  * This functions is called in the mlx5_dev_start(). No thread safe
     452                 :            :  * is guaranteed.
     453                 :            :  *
     454                 :            :  * @param[in] dev
     455                 :            :  *   Pointer to Ethernet device.
     456                 :            :  */
     457                 :            : void
     458                 :          0 : mlx5_flow_nta_del_default_copy_action(struct rte_eth_dev *dev)
     459                 :            : {
     460                 :            :         struct mlx5_list_entry *entry;
     461                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
     462                 :            :         struct mlx5_flow_cb_ctx ctx;
     463                 :            :         uint32_t mark_id;
     464                 :            : 
     465                 :            :         /* Check if default flow is registered. */
     466         [ #  # ]:          0 :         if (!priv->sh->mreg_cp_tbl)
     467                 :          0 :                 return;
     468                 :          0 :         mark_id = MLX5_DEFAULT_COPY_ID;
     469                 :          0 :         ctx.data = &mark_id;
     470                 :          0 :         entry = mlx5_hlist_lookup(priv->sh->mreg_cp_tbl, mark_id, &ctx);
     471         [ #  # ]:          0 :         if (!entry)
     472                 :            :                 return;
     473                 :          0 :         mlx5_hlist_unregister(priv->sh->mreg_cp_tbl, entry);
     474                 :            : }
     475                 :            : 
     476                 :            : /*
     477                 :            :  * Add the default copy action in RX_CP_TBL.
     478                 :            :  *
     479                 :            :  * This functions is called in the mlx5_dev_start(). No thread safe
     480                 :            :  * is guaranteed.
     481                 :            :  * @see flow_mreg_add_default_copy_action
     482                 :            :  *
     483                 :            :  * @param[in] dev
     484                 :            :  *   Pointer to Ethernet device.
     485                 :            :  * @param[out] error
     486                 :            :  *   Perform verbose error reporting if not NULL.
     487                 :            :  *
     488                 :            :  * @return
     489                 :            :  *   0 for success, negative value otherwise and rte_errno is set.
     490                 :            :  */
     491                 :            : int
     492                 :          0 : mlx5_flow_nta_add_default_copy_action(struct rte_eth_dev *dev,
     493                 :            :                                       struct rte_flow_error *error)
     494                 :            : {
     495                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
     496                 :          0 :         struct mlx5_sh_config *config = &priv->sh->config;
     497                 :            :         struct mlx5_flow_mreg_copy_resource *mcp_res;
     498                 :            :         struct mlx5_flow_cb_ctx ctx;
     499                 :            :         uint32_t mark_id;
     500                 :            : 
     501         [ #  # ]:          0 :         if (config->dv_xmeta_en == MLX5_XMETA_MODE_LEGACY ||
     502         [ #  # ]:          0 :             !priv->sh->dv_regc0_mask)
     503                 :            :                 return 0;
     504                 :            :         /*
     505                 :            :          * Add default mreg copy flow may be called multiple time, but
     506                 :            :          * only be called once in stop. Avoid register it twice.
     507                 :            :          */
     508                 :          0 :         mark_id = MLX5_DEFAULT_COPY_ID;
     509                 :          0 :         ctx.data = &mark_id;
     510         [ #  # ]:          0 :         if (mlx5_hlist_lookup(priv->sh->mreg_cp_tbl, mark_id, &ctx))
     511                 :            :                 return 0;
     512                 :          0 :         mcp_res = mlx5_flow_nta_add_copy_action(dev, mark_id, error);
     513         [ #  # ]:          0 :         if (!mcp_res)
     514                 :          0 :                 return -rte_errno;
     515                 :            :         return 0;
     516                 :            : }
     517                 :            : 
     518                 :            : /*
     519                 :            :  * Add a flow of copying flow metadata registers in RX_CP_TBL.
     520                 :            :  * @see flow_mreg_update_copy_table
     521                 :            :  *
     522                 :            :  * @param[in] dev
     523                 :            :  *   Pointer to Ethernet device.
     524                 :            :  * @param[out] idx
     525                 :            :  *   Pointer to store the index of flow in the pool.
     526                 :            :  * @param[in] mark
     527                 :            :  *   Pointer to mark or flag action.
     528                 :            :  * @param[in] action_flags
     529                 :            :  *   Holds the actions detected.
     530                 :            :  * @param[out] error
     531                 :            :  *   Perform verbose error reporting if not NULL.
     532                 :            :  *
     533                 :            :  * @return
     534                 :            :  *   0 on success, negative value otherwise and rte_errno is set.
     535                 :            :  */
     536                 :            : int
     537                 :          0 : mlx5_flow_nta_update_copy_table(struct rte_eth_dev *dev,
     538                 :            :                                 uint32_t *idx,
     539                 :            :                                 const struct rte_flow_action *mark,
     540                 :            :                                 uint64_t action_flags,
     541                 :            :                                 struct rte_flow_error *error)
     542                 :            : {
     543                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
     544                 :          0 :         struct mlx5_sh_config *config = &priv->sh->config;
     545                 :            :         struct mlx5_flow_mreg_copy_resource *mcp_res;
     546                 :            :         const struct rte_flow_action_mark *mark_conf;
     547                 :            :         uint32_t mark_id;
     548                 :            : 
     549         [ #  # ]:          0 :         if (config->dv_xmeta_en == MLX5_XMETA_MODE_LEGACY ||
     550         [ #  # ]:          0 :             !priv->sh->dv_regc0_mask)
     551                 :            :                 return 0;
     552                 :            :         /* Find MARK action. */
     553         [ #  # ]:          0 :         if (action_flags & (MLX5_FLOW_ACTION_FLAG | MLX5_FLOW_ACTION_MARK)) {
     554         [ #  # ]:          0 :                 if (mark) {
     555                 :          0 :                         mark_conf = (const struct rte_flow_action_mark *)mark->conf;
     556                 :          0 :                         mark_id = mark_conf->id;
     557                 :            :                 } else {
     558                 :            :                         mark_id = MLX5_FLOW_MARK_DEFAULT;
     559                 :            :                 }
     560                 :          0 :                 mcp_res = mlx5_flow_nta_add_copy_action(dev, mark_id, error);
     561         [ #  # ]:          0 :                 if (!mcp_res)
     562                 :          0 :                         return -rte_errno;
     563                 :          0 :                 *idx = mcp_res->idx;
     564                 :            :         }
     565                 :            :         return 0;
     566                 :            : }
     567                 :            : 
     568                 :            : #endif

Generated by: LCOV version 1.14