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
|