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