Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (c) 2022 NVIDIA Corporation & Affiliates
3 : : */
4 : :
5 : : #include "mlx5dr_internal.h"
6 : :
7 : 0 : static void mlx5dr_rule_skip(struct mlx5dr_matcher *matcher,
8 : : struct mlx5dr_match_template *mt,
9 : : const struct rte_flow_item *items,
10 : : bool *skip_rx, bool *skip_tx)
11 : : {
12 : : const struct flow_hw_port_info *vport;
13 : : const struct rte_flow_item_ethdev *v;
14 : : enum mlx5dr_table_type type;
15 : :
16 : : /* By default FDB rules are added to both RX and TX */
17 : 0 : *skip_rx = false;
18 : 0 : *skip_tx = false;
19 : :
20 : 0 : type = matcher->tbl->type;
21 [ # # ]: 0 : if (type == MLX5DR_TABLE_TYPE_FDB_RX || type == MLX5DR_TABLE_TYPE_FDB_UNIFIED) {
22 : 0 : *skip_tx = true;
23 : 0 : return;
24 [ # # ]: 0 : } else if (type == MLX5DR_TABLE_TYPE_FDB_TX) {
25 : 0 : *skip_rx = true;
26 : 0 : return;
27 : : }
28 : :
29 : : /* Flow_src is the 1st priority after table type */
30 [ # # ]: 0 : if (matcher->attr.optimize_flow_src) {
31 : 0 : *skip_tx = matcher->attr.optimize_flow_src == MLX5DR_MATCHER_FLOW_SRC_WIRE;
32 : 0 : *skip_rx = matcher->attr.optimize_flow_src == MLX5DR_MATCHER_FLOW_SRC_VPORT;
33 : 0 : return;
34 : : }
35 : :
36 [ # # ]: 0 : if (unlikely(mlx5dr_matcher_is_insert_by_idx(matcher)))
37 : : return;
38 : :
39 [ # # ]: 0 : if (mt->item_flags & MLX5_FLOW_ITEM_REPRESENTED_PORT) {
40 : 0 : v = items[mt->vport_item_id].spec;
41 [ # # ]: 0 : vport = flow_hw_conv_port_id(matcher->tbl->ctx, v->port_id);
42 [ # # ]: 0 : if (unlikely(!vport)) {
43 : 0 : DR_LOG(ERR, "Fail to map port ID %d, ignoring", v->port_id);
44 : 0 : return;
45 : : }
46 : :
47 [ # # ]: 0 : if (!vport->is_wire)
48 : : /* Match vport ID is not WIRE -> Skip RX */
49 : 0 : *skip_rx = true;
50 : : else
51 : : /* Match vport ID is WIRE -> Skip TX */
52 : 0 : *skip_tx = true;
53 : : }
54 : : }
55 : :
56 : : static void
57 : 0 : mlx5dr_rule_update_copy_tag(struct mlx5dr_rule *rule,
58 : : struct mlx5dr_wqe_gta_data_seg_ste *wqe_data,
59 : : bool is_jumbo)
60 : : {
61 [ # # ]: 0 : if (is_jumbo)
62 : 0 : memcpy(wqe_data->jumbo, rule->tag.jumbo, MLX5DR_JUMBO_TAG_SZ);
63 : : else
64 : 0 : memcpy(wqe_data->tag, rule->tag.match, MLX5DR_MATCH_TAG_SZ);
65 : 0 : }
66 : :
67 : 0 : static void mlx5dr_rule_init_dep_wqe(struct mlx5dr_send_ring_dep_wqe *dep_wqe,
68 : : struct mlx5dr_rule *rule,
69 : : const struct rte_flow_item *items,
70 : : struct mlx5dr_match_template *mt,
71 : : struct mlx5dr_rule_attr *attr)
72 : : {
73 : 0 : struct mlx5dr_matcher *matcher = rule->matcher;
74 : 0 : struct mlx5dr_table *tbl = matcher->tbl;
75 : : bool skip_rx, skip_tx;
76 : :
77 : 0 : dep_wqe->rule = rule;
78 [ # # ]: 0 : dep_wqe->user_data = attr->user_data;
79 : 0 : dep_wqe->direct_index = mlx5dr_matcher_is_insert_by_idx(matcher) ?
80 [ # # ]: 0 : attr->rule_idx : 0;
81 : :
82 [ # # ]: 0 : if (!items) { /* rule update */
83 : 0 : dep_wqe->rtc_0 = rule->rtc_0;
84 : 0 : dep_wqe->rtc_1 = rule->rtc_1;
85 : 0 : dep_wqe->retry_rtc_1 = 0;
86 : 0 : dep_wqe->retry_rtc_0 = 0;
87 : 0 : return;
88 : : }
89 : :
90 [ # # # ]: 0 : switch (tbl->type) {
91 : 0 : case MLX5DR_TABLE_TYPE_NIC_RX:
92 : : case MLX5DR_TABLE_TYPE_NIC_TX:
93 : 0 : dep_wqe->rtc_0 = matcher->match_ste.rtc_0->id;
94 : 0 : dep_wqe->retry_rtc_0 = matcher->col_matcher ?
95 [ # # ]: 0 : matcher->col_matcher->match_ste.rtc_0->id : 0;
96 : 0 : dep_wqe->rtc_1 = 0;
97 : 0 : dep_wqe->retry_rtc_1 = 0;
98 : 0 : break;
99 : :
100 : 0 : case MLX5DR_TABLE_TYPE_FDB:
101 : : case MLX5DR_TABLE_TYPE_FDB_RX:
102 : : case MLX5DR_TABLE_TYPE_FDB_TX:
103 : : case MLX5DR_TABLE_TYPE_FDB_UNIFIED:
104 : 0 : mlx5dr_rule_skip(matcher, mt, items, &skip_rx, &skip_tx);
105 : :
106 [ # # ]: 0 : if (!skip_rx) {
107 : 0 : dep_wqe->rtc_0 = matcher->match_ste.rtc_0->id;
108 : 0 : dep_wqe->retry_rtc_0 = matcher->col_matcher ?
109 [ # # ]: 0 : matcher->col_matcher->match_ste.rtc_0->id : 0;
110 : : } else {
111 : 0 : dep_wqe->rtc_0 = 0;
112 : 0 : dep_wqe->retry_rtc_0 = 0;
113 : : }
114 : :
115 [ # # ]: 0 : if (!skip_tx) {
116 : 0 : dep_wqe->rtc_1 = matcher->match_ste.rtc_1->id;
117 : 0 : dep_wqe->retry_rtc_1 = matcher->col_matcher ?
118 [ # # ]: 0 : matcher->col_matcher->match_ste.rtc_1->id : 0;
119 : : } else {
120 : 0 : dep_wqe->rtc_1 = 0;
121 : 0 : dep_wqe->retry_rtc_1 = 0;
122 : : }
123 : :
124 : : break;
125 : :
126 : 0 : default:
127 : 0 : assert(false);
128 : : break;
129 : : }
130 : : }
131 : :
132 : 0 : static void mlx5dr_rule_move_get_rtc(struct mlx5dr_rule *rule,
133 : : struct mlx5dr_send_ste_attr *ste_attr)
134 : : {
135 : 0 : struct mlx5dr_matcher *dst_matcher = rule->matcher->resize_dst;
136 : :
137 [ # # ]: 0 : if (rule->resize_info->rtc_0) {
138 : 0 : ste_attr->rtc_0 = dst_matcher->match_ste.rtc_0->id;
139 : 0 : ste_attr->retry_rtc_0 = dst_matcher->col_matcher ?
140 [ # # ]: 0 : dst_matcher->col_matcher->match_ste.rtc_0->id : 0;
141 : : }
142 [ # # ]: 0 : if (rule->resize_info->rtc_1) {
143 : 0 : ste_attr->rtc_1 = dst_matcher->match_ste.rtc_1->id;
144 : 0 : ste_attr->retry_rtc_1 = dst_matcher->col_matcher ?
145 [ # # ]: 0 : dst_matcher->col_matcher->match_ste.rtc_1->id : 0;
146 : : }
147 : 0 : }
148 : :
149 : : static void mlx5dr_rule_gen_comp(struct mlx5dr_send_engine *queue,
150 : : struct mlx5dr_rule *rule,
151 : : bool err,
152 : : void *user_data,
153 : : enum mlx5dr_rule_status rule_status_on_succ)
154 : : {
155 : : enum rte_flow_op_status comp_status;
156 : :
157 : 0 : if (!err) {
158 : : comp_status = RTE_FLOW_OP_SUCCESS;
159 : 0 : rule->status = rule_status_on_succ;
160 : : } else {
161 : : comp_status = RTE_FLOW_OP_ERROR;
162 : 0 : rule->status = MLX5DR_RULE_STATUS_FAILED;
163 : : }
164 : :
165 : : mlx5dr_send_engine_inc_rule(queue);
166 : : mlx5dr_send_engine_gen_comp(queue, user_data, comp_status);
167 : : }
168 : :
169 : : static void
170 : 0 : mlx5dr_rule_save_resize_info(struct mlx5dr_rule *rule,
171 : : struct mlx5dr_send_ste_attr *ste_attr)
172 : : {
173 [ # # ]: 0 : if (likely(!mlx5dr_matcher_is_resizable(rule->matcher)))
174 : : return;
175 : :
176 : 0 : rule->resize_info = simple_calloc(1, sizeof(*rule->resize_info));
177 [ # # ]: 0 : if (unlikely(!rule->resize_info)) {
178 [ # # ]: 0 : assert(rule->resize_info);
179 : 0 : rte_errno = ENOMEM;
180 : : }
181 : :
182 [ # # ]: 0 : memcpy(rule->resize_info->ctrl_seg, ste_attr->wqe_ctrl,
183 : : sizeof(rule->resize_info->ctrl_seg));
184 : 0 : memcpy(rule->resize_info->data_seg, ste_attr->wqe_data,
185 : : sizeof(rule->resize_info->data_seg));
186 : :
187 : 0 : rule->resize_info->max_stes = rule->matcher->action_ste.max_stes;
188 : 0 : rule->resize_info->action_ste_pool = rule->matcher->action_ste.max_stes ?
189 [ # # ]: 0 : rule->matcher->action_ste.pool :
190 : : NULL;
191 : : }
192 : :
193 : 0 : void mlx5dr_rule_clear_resize_info(struct mlx5dr_rule *rule)
194 : : {
195 [ # # # # ]: 0 : if (unlikely(mlx5dr_matcher_is_resizable(rule->matcher) &&
196 : : rule->resize_info)) {
197 : : simple_free(rule->resize_info);
198 : 0 : rule->resize_info = NULL;
199 : : }
200 : 0 : }
201 : :
202 : : static void
203 : 0 : mlx5dr_rule_save_delete_info(struct mlx5dr_rule *rule,
204 : : struct mlx5dr_send_ste_attr *ste_attr)
205 : : {
206 [ # # ]: 0 : struct mlx5dr_match_template *mt = rule->matcher->mt;
207 : : bool is_jumbo = mlx5dr_matcher_mt_is_jumbo(mt);
208 : :
209 [ # # ]: 0 : if (unlikely(mlx5dr_matcher_req_fw_wqe(rule->matcher))) {
210 : : uint8_t *src_tag;
211 : :
212 : : /* Save match definer id and tag for delete */
213 : 0 : rule->tag_ptr = simple_calloc(2, sizeof(*rule->tag_ptr));
214 [ # # ]: 0 : assert(rule->tag_ptr);
215 : :
216 [ # # ]: 0 : if (is_jumbo)
217 : 0 : memcpy(rule->tag_ptr[0].jumbo, ste_attr->wqe_data->action,
218 : : MLX5DR_JUMBO_TAG_SZ);
219 : : else
220 : 0 : memcpy(rule->tag_ptr[0].match, ste_attr->wqe_data->tag,
221 : : MLX5DR_MATCH_TAG_SZ);
222 : :
223 : 0 : rule->tag_ptr[1].reserved[0] = ste_attr->send_attr.match_definer_id;
224 : :
225 : : /* Save range definer id and tag for delete */
226 [ # # ]: 0 : if (ste_attr->range_wqe_data) {
227 : 0 : src_tag = (uint8_t *)ste_attr->range_wqe_data->tag;
228 : 0 : memcpy(rule->tag_ptr[1].match, src_tag, MLX5DR_MATCH_TAG_SZ);
229 : 0 : rule->tag_ptr[1].reserved[1] = ste_attr->send_attr.range_definer_id;
230 : : }
231 : 0 : return;
232 : : }
233 : :
234 [ # # ]: 0 : if (likely(!mlx5dr_matcher_is_resizable(rule->matcher))) {
235 [ # # ]: 0 : if (is_jumbo)
236 : 0 : memcpy(&rule->tag.jumbo, ste_attr->wqe_data->action, MLX5DR_JUMBO_TAG_SZ);
237 : : else
238 : 0 : memcpy(&rule->tag.match, ste_attr->wqe_data->tag, MLX5DR_MATCH_TAG_SZ);
239 : 0 : return;
240 : : }
241 : : }
242 : :
243 : : static void
244 : : mlx5dr_rule_clear_delete_info(struct mlx5dr_rule *rule)
245 : : {
246 [ # # # # ]: 0 : if (unlikely(mlx5dr_matcher_req_fw_wqe(rule->matcher))) {
247 : 0 : simple_free(rule->tag_ptr);
248 : 0 : return;
249 : : }
250 : : }
251 : :
252 : : static void
253 : 0 : mlx5dr_rule_load_delete_info(struct mlx5dr_rule *rule,
254 : : struct mlx5dr_send_ste_attr *ste_attr)
255 : : {
256 [ # # ]: 0 : if (unlikely(mlx5dr_matcher_req_fw_wqe(rule->matcher))) {
257 : : /* Load match definer id and tag for delete */
258 : 0 : ste_attr->wqe_tag = &rule->tag_ptr[0];
259 : 0 : ste_attr->send_attr.match_definer_id = rule->tag_ptr[1].reserved[0];
260 : :
261 : : /* Load range definer id and tag for delete */
262 [ # # ]: 0 : if (rule->matcher->flags & MLX5DR_MATCHER_FLAGS_RANGE_DEFINER) {
263 : 0 : ste_attr->range_wqe_tag = &rule->tag_ptr[1];
264 : 0 : ste_attr->send_attr.range_definer_id = rule->tag_ptr[1].reserved[1];
265 : : }
266 [ # # ]: 0 : } else if (likely(!mlx5dr_matcher_is_resizable(rule->matcher))) {
267 : 0 : ste_attr->wqe_tag = &rule->tag;
268 : : } else {
269 : 0 : ste_attr->wqe_tag = (struct mlx5dr_rule_match_tag *)
270 : 0 : &rule->resize_info->data_seg[MLX5DR_STE_CTRL_SZ];
271 : : }
272 : 0 : }
273 : :
274 : 0 : static int mlx5dr_rule_alloc_action_ste(struct mlx5dr_rule *rule,
275 : : struct mlx5dr_rule_attr *attr)
276 : : {
277 : 0 : struct mlx5dr_matcher *matcher = rule->matcher;
278 : : int ret;
279 : :
280 : : /* Use rule_idx for locking optimzation, otherwise allocate from pool */
281 [ # # # # ]: 0 : if (matcher->attr.optimize_using_rule_idx ||
282 : : mlx5dr_matcher_is_insert_by_idx(matcher)) {
283 : 0 : rule->action_ste_idx = attr->rule_idx * matcher->action_ste.max_stes;
284 : : } else {
285 : 0 : struct mlx5dr_pool_chunk ste = {0};
286 : :
287 [ # # ]: 0 : ste.order = rte_log2_u32(matcher->action_ste.max_stes);
288 : 0 : ret = mlx5dr_pool_chunk_alloc(matcher->action_ste.pool, &ste);
289 [ # # ]: 0 : if (ret) {
290 : 0 : DR_LOG(ERR, "Failed to allocate STE for rule actions");
291 : 0 : return ret;
292 : : }
293 : 0 : rule->action_ste_idx = ste.offset;
294 : : }
295 : : return 0;
296 : : }
297 : :
298 : 0 : void mlx5dr_rule_free_action_ste_idx(struct mlx5dr_rule *rule)
299 : : {
300 : 0 : struct mlx5dr_matcher *matcher = rule->matcher;
301 : : struct mlx5dr_pool *pool;
302 : : uint8_t max_stes;
303 : :
304 [ # # ]: 0 : if (rule->action_ste_idx > -1 &&
305 [ # # # # ]: 0 : !matcher->attr.optimize_using_rule_idx &&
306 : : !mlx5dr_matcher_is_insert_by_idx(matcher)) {
307 [ # # ]: 0 : struct mlx5dr_pool_chunk ste = {0};
308 : :
309 [ # # ]: 0 : if (unlikely(mlx5dr_matcher_is_resizable(matcher))) {
310 : : /* Free the original action pool if rule was resized */
311 : 0 : max_stes = rule->resize_info->max_stes;
312 : 0 : pool = rule->resize_info->action_ste_pool;
313 : : } else {
314 : 0 : max_stes = matcher->action_ste.max_stes;
315 : 0 : pool = matcher->action_ste.pool;
316 : : }
317 : :
318 : : /* This release is safe only when the rule match part was deleted */
319 [ # # ]: 0 : ste.order = rte_log2_u32(max_stes);
320 : 0 : ste.offset = rule->action_ste_idx;
321 : :
322 : 0 : mlx5dr_pool_chunk_free(pool, &ste);
323 : : }
324 : 0 : }
325 : :
326 : : static void mlx5dr_rule_create_init(struct mlx5dr_rule *rule,
327 : : struct mlx5dr_send_ste_attr *ste_attr,
328 : : struct mlx5dr_actions_apply_data *apply,
329 : : bool is_update)
330 : : {
331 : : struct mlx5dr_matcher *matcher = rule->matcher;
332 : : struct mlx5dr_table *tbl = matcher->tbl;
333 : : struct mlx5dr_context *ctx = tbl->ctx;
334 : :
335 : : /* Init rule before reuse */
336 [ # # ]: 0 : if (!is_update) {
337 : : /* In update we use these rtc's */
338 : 0 : rule->rtc_0 = 0;
339 : 0 : rule->rtc_1 = 0;
340 : : }
341 : :
342 : 0 : rule->pending_wqes = 0;
343 : 0 : rule->action_ste_idx = -1;
344 : 0 : rule->status = MLX5DR_RULE_STATUS_CREATING;
345 : :
346 : : /* Init default send STE attributes */
347 : : ste_attr->gta_opcode = MLX5DR_WQE_GTA_OP_ACTIVATE;
348 : : ste_attr->send_attr.opmod = MLX5DR_WQE_GTA_OPMOD_STE;
349 : 0 : ste_attr->send_attr.opcode = MLX5DR_WQE_OPCODE_TBL_ACCESS;
350 : 0 : ste_attr->send_attr.len = MLX5DR_WQE_SZ_GTA_CTRL + MLX5DR_WQE_SZ_GTA_DATA;
351 : :
352 : : /* Init default action apply */
353 : 0 : apply->tbl_type = tbl->type;
354 : 0 : apply->common_res = &ctx->common_res[tbl->type];
355 : 0 : apply->jump_to_action_stc = matcher->action_ste.stc.offset;
356 : 0 : apply->require_dep = 0;
357 : : }
358 : :
359 : : static void mlx5dr_rule_move_init(struct mlx5dr_rule *rule,
360 : : struct mlx5dr_rule_attr *attr)
361 : : {
362 : : /* Save the old RTC IDs to be later used in match STE delete */
363 : 0 : rule->resize_info->rtc_0 = rule->rtc_0;
364 : 0 : rule->resize_info->rtc_1 = rule->rtc_1;
365 : 0 : rule->resize_info->rule_idx = attr->rule_idx;
366 : :
367 : 0 : rule->rtc_0 = 0;
368 : 0 : rule->rtc_1 = 0;
369 : :
370 : 0 : rule->pending_wqes = 0;
371 : 0 : rule->action_ste_idx = -1;
372 : 0 : rule->status = MLX5DR_RULE_STATUS_CREATING;
373 : 0 : rule->resize_info->state = MLX5DR_RULE_RESIZE_STATE_WRITING;
374 : : }
375 : :
376 : 0 : bool mlx5dr_rule_move_in_progress(struct mlx5dr_rule *rule)
377 : : {
378 [ # # ]: 0 : return mlx5dr_matcher_is_in_resize(rule->matcher) &&
379 [ # # # # ]: 0 : rule->resize_info &&
380 [ # # ]: 0 : rule->resize_info->state != MLX5DR_RULE_RESIZE_STATE_IDLE;
381 : : }
382 : :
383 : 0 : static int mlx5dr_rule_create_hws_fw_wqe(struct mlx5dr_rule *rule,
384 : : struct mlx5dr_rule_attr *attr,
385 : : uint8_t mt_idx,
386 : : const struct rte_flow_item items[],
387 : : uint8_t at_idx,
388 : : struct mlx5dr_rule_action rule_actions[])
389 : : {
390 : 0 : struct mlx5dr_action_template *at = &rule->matcher->at[at_idx];
391 : 0 : struct mlx5dr_match_template *mt = &rule->matcher->mt[mt_idx];
392 : 0 : struct mlx5dr_send_ring_dep_wqe range_wqe = {{0}};
393 [ # # ]: 0 : struct mlx5dr_send_ring_dep_wqe match_wqe = {{0}};
394 : : bool is_range = mlx5dr_matcher_mt_is_range(mt);
395 : : bool is_jumbo = mlx5dr_matcher_mt_is_jumbo(mt);
396 : : struct mlx5dr_matcher *matcher = rule->matcher;
397 : 0 : struct mlx5dr_context *ctx = matcher->tbl->ctx;
398 : 0 : struct mlx5dr_send_ste_attr ste_attr = {0};
399 : : struct mlx5dr_actions_apply_data apply;
400 : : struct mlx5dr_send_engine *queue;
401 : :
402 [ # # ]: 0 : queue = &ctx->send_queue[attr->queue_id];
403 [ # # ]: 0 : if (unlikely(mlx5dr_send_engine_err(queue))) {
404 : 0 : rte_errno = EIO;
405 : 0 : return rte_errno;
406 : : }
407 : :
408 : : mlx5dr_rule_create_init(rule, &ste_attr, &apply, false);
409 : 0 : mlx5dr_rule_init_dep_wqe(&match_wqe, rule, items, mt, attr);
410 : 0 : mlx5dr_rule_init_dep_wqe(&range_wqe, rule, items, mt, attr);
411 : :
412 : 0 : ste_attr.direct_index = 0;
413 : 0 : ste_attr.rtc_0 = match_wqe.rtc_0;
414 : 0 : ste_attr.rtc_1 = match_wqe.rtc_1;
415 : 0 : ste_attr.used_id_rtc_0 = &rule->rtc_0;
416 : 0 : ste_attr.used_id_rtc_1 = &rule->rtc_1;
417 : 0 : ste_attr.retry_rtc_0 = match_wqe.retry_rtc_0;
418 : 0 : ste_attr.retry_rtc_1 = match_wqe.retry_rtc_1;
419 : 0 : ste_attr.send_attr.rule = match_wqe.rule;
420 : 0 : ste_attr.send_attr.user_data = match_wqe.user_data;
421 : :
422 : 0 : ste_attr.send_attr.fence = 1;
423 : 0 : ste_attr.send_attr.notify_hw = 1;
424 : 0 : ste_attr.wqe_tag_is_jumbo = is_jumbo;
425 : :
426 : : /* Prepare match STE TAG */
427 : 0 : ste_attr.wqe_ctrl = &match_wqe.wqe_ctrl;
428 : 0 : ste_attr.wqe_data = &match_wqe.wqe_data;
429 : 0 : ste_attr.send_attr.match_definer_id = mlx5dr_definer_get_id(mt->definer);
430 : :
431 : 0 : mlx5dr_definer_create_tag(items,
432 : : mt->fc,
433 : 0 : mt->fc_sz,
434 : : (uint8_t *)match_wqe.wqe_data.action);
435 : :
436 : : /* Prepare range STE TAG */
437 [ # # ]: 0 : if (is_range) {
438 : 0 : ste_attr.range_wqe_data = &range_wqe.wqe_data;
439 : 0 : ste_attr.send_attr.len += MLX5DR_WQE_SZ_GTA_DATA;
440 : 0 : ste_attr.send_attr.range_definer_id = mlx5dr_definer_get_id(mt->range_definer);
441 : :
442 : 0 : mlx5dr_definer_create_tag_range(items,
443 : : mt->fcr,
444 : 0 : mt->fcr_sz,
445 : : (uint8_t *)range_wqe.wqe_data.action);
446 : : }
447 : :
448 : : /* Apply the actions on the last STE */
449 : 0 : apply.queue = queue;
450 : 0 : apply.next_direct_idx = 0;
451 : 0 : apply.rule_action = rule_actions;
452 : 0 : apply.wqe_ctrl = &match_wqe.wqe_ctrl;
453 [ # # ]: 0 : apply.wqe_data = (uint32_t *)(is_range ?
454 : : &range_wqe.wqe_data :
455 : : &match_wqe.wqe_data);
456 : :
457 : : /* Skip setters[0] used for jumbo STE since not support with FW WQE */
458 : 0 : mlx5dr_action_apply_setter(&apply, &at->setters[1], 0);
459 : :
460 : : /* Send WQEs to FW */
461 : 0 : mlx5dr_send_stes_fw(queue, &ste_attr);
462 : :
463 : : /* Backup TAG on the rule for deletion */
464 : 0 : mlx5dr_rule_save_delete_info(rule, &ste_attr);
465 : : mlx5dr_send_engine_inc_rule(queue);
466 : :
467 : : /* Send dependent WQEs */
468 [ # # ]: 0 : if (!attr->burst)
469 : 0 : mlx5dr_send_all_dep_wqe(queue);
470 : :
471 : : return 0;
472 : : }
473 : :
474 : 0 : static int mlx5dr_rule_create_hws(struct mlx5dr_rule *rule,
475 : : struct mlx5dr_rule_attr *attr,
476 : : uint8_t mt_idx,
477 : : const struct rte_flow_item items[],
478 : : uint8_t at_idx,
479 : : struct mlx5dr_rule_action rule_actions[])
480 : : {
481 : 0 : struct mlx5dr_action_template *at = &rule->matcher->at[at_idx];
482 [ # # ]: 0 : struct mlx5dr_match_template *mt = &rule->matcher->mt[mt_idx];
483 : : bool is_jumbo = mlx5dr_matcher_mt_is_jumbo(mt);
484 : : struct mlx5dr_matcher *matcher = rule->matcher;
485 : 0 : struct mlx5dr_context *ctx = matcher->tbl->ctx;
486 : 0 : struct mlx5dr_send_ste_attr ste_attr = {0};
487 : : struct mlx5dr_send_ring_dep_wqe *dep_wqe;
488 : : struct mlx5dr_actions_wqe_setter *setter;
489 : : struct mlx5dr_actions_apply_data apply;
490 : : struct mlx5dr_send_engine *queue;
491 : : uint8_t total_stes, action_stes;
492 : : bool is_update;
493 : : int i, ret;
494 : :
495 [ # # ]: 0 : is_update = (items == NULL);
496 : :
497 : : /* Insert rule using FW WQE if cannot use GTA WQE */
498 [ # # # # ]: 0 : if (unlikely(mlx5dr_matcher_req_fw_wqe(matcher) && !is_update))
499 : 0 : return mlx5dr_rule_create_hws_fw_wqe(rule, attr, mt_idx, items,
500 : : at_idx, rule_actions);
501 : :
502 [ # # ]: 0 : queue = &ctx->send_queue[attr->queue_id];
503 [ # # ]: 0 : if (unlikely(mlx5dr_send_engine_err(queue))) {
504 : 0 : rte_errno = EIO;
505 : 0 : return rte_errno;
506 : : }
507 : :
508 : : mlx5dr_rule_create_init(rule, &ste_attr, &apply, is_update);
509 : :
510 : : /* Allocate dependent match WQE since rule might have dependent writes.
511 : : * The queued dependent WQE can be later aborted or kept as a dependency.
512 : : * dep_wqe buffers (ctrl, data) are also reused for all STE writes.
513 : : */
514 : 0 : dep_wqe = mlx5dr_send_add_new_dep_wqe(queue);
515 : 0 : mlx5dr_rule_init_dep_wqe(dep_wqe, rule, items, mt, attr);
516 : :
517 : 0 : ste_attr.wqe_ctrl = &dep_wqe->wqe_ctrl;
518 : 0 : ste_attr.wqe_data = &dep_wqe->wqe_data;
519 : 0 : apply.wqe_ctrl = &dep_wqe->wqe_ctrl;
520 : 0 : apply.wqe_data = (uint32_t *)&dep_wqe->wqe_data;
521 : 0 : apply.rule_action = rule_actions;
522 : 0 : apply.queue = queue;
523 : :
524 : 0 : setter = &at->setters[at->num_of_action_stes];
525 [ # # # # ]: 0 : total_stes = at->num_of_action_stes + (is_jumbo && !at->only_term);
526 : 0 : action_stes = total_stes - 1;
527 : :
528 [ # # ]: 0 : if (action_stes) {
529 : : /* Allocate action STEs for complex rules */
530 : 0 : ret = mlx5dr_rule_alloc_action_ste(rule, attr);
531 [ # # ]: 0 : if (ret) {
532 : 0 : DR_LOG(ERR, "Failed to allocate action memory %d", ret);
533 : 0 : mlx5dr_send_abort_new_dep_wqe(queue);
534 : 0 : return ret;
535 : : }
536 : : /* Skip RX/TX based on the dep_wqe init */
537 [ # # ]: 0 : ste_attr.rtc_0 = dep_wqe->rtc_0 ? matcher->action_ste.rtc_0->id : 0;
538 [ # # ]: 0 : ste_attr.rtc_1 = dep_wqe->rtc_1 ? matcher->action_ste.rtc_1->id : 0;
539 : : /* Action STEs are written to a specific index last to first */
540 : 0 : ste_attr.direct_index = rule->action_ste_idx + action_stes;
541 : 0 : apply.next_direct_idx = ste_attr.direct_index;
542 : : } else {
543 : 0 : apply.next_direct_idx = 0;
544 : : }
545 : :
546 [ # # ]: 0 : for (i = total_stes; i-- > 0;) {
547 : 0 : mlx5dr_action_apply_setter(&apply, setter--, !i && is_jumbo);
548 : :
549 [ # # ]: 0 : if (i == 0) {
550 : : /* Handle last match STE.
551 : : * For hash split / linear lookup RTCs, packets reaching any STE
552 : : * will always match and perform the specified actions, which
553 : : * makes the tag irrelevant.
554 : : */
555 [ # # # # ]: 0 : if (likely(!mlx5dr_matcher_is_always_hit(matcher) && !is_update))
556 : 0 : mlx5dr_definer_create_tag(items, mt->fc, mt->fc_sz,
557 : 0 : (uint8_t *)dep_wqe->wqe_data.action);
558 [ # # ]: 0 : else if (unlikely(is_update))
559 : 0 : mlx5dr_rule_update_copy_tag(rule, &dep_wqe->wqe_data, is_jumbo);
560 : :
561 : : /* Rule has dependent WQEs, match dep_wqe is queued */
562 [ # # # # ]: 0 : if (action_stes || apply.require_dep)
563 : : break;
564 : :
565 : : /* Rule has no dependencies, abort dep_wqe and send WQE now */
566 : 0 : mlx5dr_send_abort_new_dep_wqe(queue);
567 : 0 : ste_attr.wqe_tag_is_jumbo = is_jumbo;
568 : 0 : ste_attr.send_attr.notify_hw = !attr->burst;
569 : 0 : ste_attr.send_attr.user_data = dep_wqe->user_data;
570 : 0 : ste_attr.send_attr.rule = dep_wqe->rule;
571 : 0 : ste_attr.rtc_0 = dep_wqe->rtc_0;
572 : 0 : ste_attr.rtc_1 = dep_wqe->rtc_1;
573 : 0 : ste_attr.used_id_rtc_0 = &rule->rtc_0;
574 : 0 : ste_attr.used_id_rtc_1 = &rule->rtc_1;
575 : 0 : ste_attr.retry_rtc_0 = dep_wqe->retry_rtc_0;
576 : 0 : ste_attr.retry_rtc_1 = dep_wqe->retry_rtc_1;
577 : 0 : ste_attr.direct_index = dep_wqe->direct_index;
578 : : } else {
579 : 0 : apply.next_direct_idx = --ste_attr.direct_index;
580 : : }
581 : :
582 : 0 : mlx5dr_send_ste(queue, &ste_attr);
583 : : }
584 : :
585 : : /* Backup TAG on the rule for deletion and resize info for
586 : : * moving rules to a new matcher, only after insertion.
587 : : */
588 [ # # ]: 0 : if (!is_update) {
589 : 0 : mlx5dr_rule_save_delete_info(rule, &ste_attr);
590 : 0 : mlx5dr_rule_save_resize_info(rule, &ste_attr);
591 : : }
592 : :
593 : : mlx5dr_send_engine_inc_rule(queue);
594 : :
595 : : /* Send dependent WQEs */
596 [ # # ]: 0 : if (!attr->burst)
597 : 0 : mlx5dr_send_all_dep_wqe(queue);
598 : :
599 : : return 0;
600 : : }
601 : :
602 : 0 : static void mlx5dr_rule_destroy_failed_hws(struct mlx5dr_rule *rule,
603 : : struct mlx5dr_rule_attr *attr)
604 : : {
605 : 0 : struct mlx5dr_context *ctx = rule->matcher->tbl->ctx;
606 : : struct mlx5dr_send_engine *queue;
607 : :
608 : 0 : queue = &ctx->send_queue[attr->queue_id];
609 : :
610 : 0 : mlx5dr_rule_gen_comp(queue, rule, false,
611 : : attr->user_data, MLX5DR_RULE_STATUS_DELETED);
612 : :
613 : : /* Rule failed now we can safely release action STEs */
614 : 0 : mlx5dr_rule_free_action_ste_idx(rule);
615 : :
616 : : /* Clear complex tag */
617 : : mlx5dr_rule_clear_delete_info(rule);
618 : :
619 : : /* Clear info that was saved for resizing */
620 : 0 : mlx5dr_rule_clear_resize_info(rule);
621 : :
622 : : /* If a rule that was indicated as burst (need to trigger HW) has failed
623 : : * insertion we won't ring the HW as nothing is being written to the WQ.
624 : : * In such case update the last WQE and ring the HW with that work
625 : : */
626 [ # # ]: 0 : if (attr->burst)
627 : : return;
628 : :
629 : 0 : mlx5dr_send_all_dep_wqe(queue);
630 : 0 : mlx5dr_send_engine_flush_queue(queue);
631 : : }
632 : :
633 : 0 : static int mlx5dr_rule_destroy_hws(struct mlx5dr_rule *rule,
634 : : struct mlx5dr_rule_attr *attr)
635 : : {
636 [ # # ]: 0 : struct mlx5dr_context *ctx = rule->matcher->tbl->ctx;
637 : : struct mlx5dr_matcher *matcher = rule->matcher;
638 : : bool fw_wqe = mlx5dr_matcher_req_fw_wqe(matcher);
639 [ # # ]: 0 : bool is_range = mlx5dr_matcher_mt_is_range(matcher->mt);
640 : : bool is_jumbo = mlx5dr_matcher_mt_is_jumbo(matcher->mt);
641 : 0 : struct mlx5dr_wqe_gta_ctrl_seg wqe_ctrl = {0};
642 : 0 : struct mlx5dr_send_ste_attr ste_attr = {0};
643 : : struct mlx5dr_send_engine *queue;
644 : :
645 [ # # ]: 0 : queue = &ctx->send_queue[attr->queue_id];
646 : :
647 [ # # ]: 0 : if (unlikely(mlx5dr_send_engine_err(queue))) {
648 : 0 : mlx5dr_rule_destroy_failed_hws(rule, attr);
649 : 0 : return 0;
650 : : }
651 : :
652 : : /* Rule is not completed yet */
653 [ # # ]: 0 : if (rule->status == MLX5DR_RULE_STATUS_CREATING) {
654 : 0 : DR_LOG(NOTICE, "Cannot destroy, rule creation still in progress");
655 : 0 : rte_errno = EBUSY;
656 : 0 : return rte_errno;
657 : : }
658 : :
659 : : /* Rule failed and doesn't require cleanup */
660 [ # # ]: 0 : if (rule->status == MLX5DR_RULE_STATUS_FAILED) {
661 : 0 : mlx5dr_rule_destroy_failed_hws(rule, attr);
662 : 0 : return 0;
663 : : }
664 : :
665 : : mlx5dr_send_engine_inc_rule(queue);
666 : :
667 : : /* Send dependent WQE */
668 [ # # ]: 0 : if (!attr->burst)
669 : 0 : mlx5dr_send_all_dep_wqe(queue);
670 : :
671 : 0 : rule->status = MLX5DR_RULE_STATUS_DELETING;
672 : :
673 : 0 : ste_attr.send_attr.opmod = MLX5DR_WQE_GTA_OPMOD_STE;
674 : 0 : ste_attr.send_attr.opcode = MLX5DR_WQE_OPCODE_TBL_ACCESS;
675 : 0 : ste_attr.send_attr.len = MLX5DR_WQE_SZ_GTA_CTRL + MLX5DR_WQE_SZ_GTA_DATA;
676 [ # # ]: 0 : if (unlikely(is_range))
677 : 0 : ste_attr.send_attr.len += MLX5DR_WQE_SZ_GTA_DATA;
678 : :
679 : 0 : ste_attr.send_attr.rule = rule;
680 : 0 : ste_attr.send_attr.notify_hw = !attr->burst;
681 : 0 : ste_attr.send_attr.user_data = attr->user_data;
682 : :
683 : 0 : ste_attr.rtc_0 = rule->rtc_0;
684 : 0 : ste_attr.rtc_1 = rule->rtc_1;
685 : 0 : ste_attr.used_id_rtc_0 = &rule->rtc_0;
686 : 0 : ste_attr.used_id_rtc_1 = &rule->rtc_1;
687 : 0 : ste_attr.wqe_ctrl = &wqe_ctrl;
688 : 0 : ste_attr.wqe_tag_is_jumbo = is_jumbo;
689 [ # # ]: 0 : ste_attr.gta_opcode = MLX5DR_WQE_GTA_OP_DEACTIVATE;
690 [ # # ]: 0 : if (unlikely(mlx5dr_matcher_is_insert_by_idx(matcher)))
691 : 0 : ste_attr.direct_index = attr->rule_idx;
692 : :
693 : 0 : mlx5dr_rule_load_delete_info(rule, &ste_attr);
694 : :
695 [ # # ]: 0 : if (unlikely(fw_wqe))
696 : 0 : mlx5dr_send_stes_fw(queue, &ste_attr);
697 : : else
698 : 0 : mlx5dr_send_ste(queue, &ste_attr);
699 : :
700 : : mlx5dr_rule_clear_delete_info(rule);
701 : :
702 : : return 0;
703 : : }
704 : :
705 : 0 : int mlx5dr_rule_create_root_no_comp(struct mlx5dr_rule *rule,
706 : : const struct rte_flow_item items[],
707 : : uint8_t num_actions,
708 : : struct mlx5dr_rule_action rule_actions[])
709 : : {
710 : 0 : struct mlx5dv_flow_matcher *dv_matcher = rule->matcher->dv_matcher;
711 : 0 : struct mlx5dr_context *ctx = rule->matcher->tbl->ctx;
712 : : struct mlx5dv_flow_match_parameters *value;
713 : 0 : struct mlx5_flow_attr flow_attr = {0};
714 : : struct mlx5dv_flow_action_attr *attr;
715 : : struct rte_flow_error error;
716 : : uint8_t match_criteria;
717 : : int ret;
718 : :
719 : : ret = flow_hw_get_port_id_from_ctx(ctx, &flow_attr.port_id);
720 : : if (ret) {
721 : 0 : DR_LOG(ERR, "Failed to get port id for dev %s", ctx->ibv_ctx->device->name);
722 : 0 : rte_errno = EINVAL;
723 : 0 : return rte_errno;
724 : : }
725 : :
726 : 0 : attr = simple_calloc(num_actions, sizeof(*attr));
727 [ # # ]: 0 : if (!attr) {
728 : 0 : rte_errno = ENOMEM;
729 : 0 : return rte_errno;
730 : : }
731 : :
732 : : value = simple_calloc(1, MLX5_ST_SZ_BYTES(fte_match_param) +
733 : : offsetof(struct mlx5dv_flow_match_parameters, match_buf));
734 [ # # ]: 0 : if (!value) {
735 : 0 : rte_errno = ENOMEM;
736 : 0 : goto free_attr;
737 : : }
738 : :
739 : 0 : flow_attr.tbl_type = rule->matcher->tbl->type;
740 : :
741 : 0 : ret = flow_dv_translate_items_hws(items, &flow_attr, value->match_buf,
742 : : MLX5_SET_MATCHER_HS_V, NULL,
743 : : &match_criteria,
744 : : &error);
745 [ # # ]: 0 : if (ret) {
746 : 0 : DR_LOG(ERR, "Failed to convert items to PRM [%s]", error.message);
747 : 0 : goto free_value;
748 : : }
749 : :
750 : : /* Convert actions to verb action attr */
751 : 0 : ret = mlx5dr_action_root_build_attr(rule_actions, num_actions, attr);
752 [ # # ]: 0 : if (ret)
753 : 0 : goto free_value;
754 : :
755 : : /* Create verb flow */
756 : 0 : value->match_sz = MLX5_ST_SZ_BYTES(fte_match_param);
757 : 0 : rule->flow = mlx5_glue->dv_create_flow_root(dv_matcher,
758 : : value,
759 : : num_actions,
760 : : attr);
761 : :
762 : : simple_free(value);
763 : : simple_free(attr);
764 : :
765 : 0 : return 0;
766 : :
767 : 0 : free_value:
768 : : simple_free(value);
769 : 0 : free_attr:
770 : : simple_free(attr);
771 : :
772 : 0 : return rte_errno;
773 : : }
774 : :
775 : 0 : static int mlx5dr_rule_create_root(struct mlx5dr_rule *rule,
776 : : struct mlx5dr_rule_attr *rule_attr,
777 : : const struct rte_flow_item items[],
778 : : uint8_t num_actions,
779 : : struct mlx5dr_rule_action rule_actions[])
780 : : {
781 : 0 : struct mlx5dr_context *ctx = rule->matcher->tbl->ctx;
782 : : int ret;
783 : :
784 : 0 : ret = mlx5dr_rule_create_root_no_comp(rule, items,
785 : : num_actions, rule_actions);
786 [ # # ]: 0 : if (ret)
787 : 0 : return rte_errno;
788 : :
789 [ # # ]: 0 : mlx5dr_rule_gen_comp(&ctx->send_queue[rule_attr->queue_id], rule, !rule->flow,
790 : : rule_attr->user_data, MLX5DR_RULE_STATUS_CREATED);
791 : :
792 : 0 : return 0;
793 : : }
794 : :
795 : 0 : int mlx5dr_rule_destroy_root_no_comp(struct mlx5dr_rule *rule)
796 : : {
797 [ # # ]: 0 : if (rule->flow)
798 : 0 : return ibv_destroy_flow(rule->flow);
799 : :
800 : : return 0;
801 : : }
802 : :
803 : 0 : static int mlx5dr_rule_destroy_root(struct mlx5dr_rule *rule,
804 : : struct mlx5dr_rule_attr *attr)
805 : : {
806 : 0 : struct mlx5dr_context *ctx = rule->matcher->tbl->ctx;
807 : : int err;
808 : :
809 : 0 : err = mlx5dr_rule_destroy_root_no_comp(rule);
810 : :
811 [ # # ]: 0 : mlx5dr_rule_gen_comp(&ctx->send_queue[attr->queue_id], rule, err,
812 : : attr->user_data, MLX5DR_RULE_STATUS_DELETED);
813 : :
814 : 0 : return 0;
815 : : }
816 : :
817 : 0 : static int mlx5dr_rule_enqueue_precheck(struct mlx5dr_rule *rule,
818 : : struct mlx5dr_rule_attr *attr)
819 : : {
820 : 0 : struct mlx5dr_context *ctx = rule->matcher->tbl->ctx;
821 : :
822 [ # # ]: 0 : if (unlikely(!attr->user_data)) {
823 : 0 : DR_LOG(DEBUG, "User data must be provided for rule operations");
824 : 0 : rte_errno = EINVAL;
825 : 0 : return rte_errno;
826 : : }
827 : :
828 : : /* Check if there is room in queue */
829 [ # # ]: 0 : if (unlikely(mlx5dr_send_engine_full(&ctx->send_queue[attr->queue_id]))) {
830 : 0 : DR_LOG(NOTICE, "No room in queue[%d]", attr->queue_id);
831 : 0 : rte_errno = EBUSY;
832 : 0 : return rte_errno;
833 : : }
834 : :
835 : : return 0;
836 : : }
837 : :
838 : 0 : static int mlx5dr_rule_enqueue_precheck_move(struct mlx5dr_rule *rule,
839 : : struct mlx5dr_rule_attr *attr)
840 : : {
841 [ # # ]: 0 : if (unlikely(rule->status != MLX5DR_RULE_STATUS_CREATED)) {
842 : 0 : DR_LOG(DEBUG, "Cannot move, rule status is invalid");
843 : 0 : rte_errno = EINVAL;
844 : 0 : return rte_errno;
845 : : }
846 : :
847 : 0 : return mlx5dr_rule_enqueue_precheck(rule, attr);
848 : : }
849 : :
850 : 0 : static int mlx5dr_rule_enqueue_precheck_create(struct mlx5dr_rule *rule,
851 : : struct mlx5dr_rule_attr *attr)
852 : : {
853 [ # # ]: 0 : if (unlikely(mlx5dr_matcher_is_in_resize(rule->matcher))) {
854 : : /* Matcher in resize - new rules are not allowed */
855 : 0 : DR_LOG(NOTICE, "Resizing in progress, cannot create rule");
856 : 0 : rte_errno = EAGAIN;
857 : 0 : return rte_errno;
858 : : }
859 : :
860 : 0 : return mlx5dr_rule_enqueue_precheck(rule, attr);
861 : : }
862 : :
863 : 0 : static int mlx5dr_rule_enqueue_precheck_update(struct mlx5dr_rule *rule,
864 : : struct mlx5dr_rule_attr *attr)
865 : : {
866 : 0 : struct mlx5dr_matcher *matcher = rule->matcher;
867 : :
868 [ # # # # ]: 0 : if (unlikely((mlx5dr_table_is_root(matcher->tbl) ||
869 : : mlx5dr_matcher_req_fw_wqe(matcher)))) {
870 : 0 : DR_LOG(ERR, "Rule update is not supported on current matcher");
871 : 0 : rte_errno = ENOTSUP;
872 : 0 : return rte_errno;
873 : : }
874 : :
875 [ # # # # ]: 0 : if (unlikely(!matcher->attr.optimize_using_rule_idx &&
876 : : !mlx5dr_matcher_is_insert_by_idx(matcher))) {
877 : 0 : DR_LOG(ERR, "Rule update requires optimize by idx matcher");
878 : 0 : rte_errno = ENOTSUP;
879 : 0 : return rte_errno;
880 : : }
881 : :
882 [ # # ]: 0 : if (unlikely(mlx5dr_matcher_is_resizable(rule->matcher))) {
883 : 0 : DR_LOG(ERR, "Rule update is not supported on resizable matcher");
884 : 0 : rte_errno = ENOTSUP;
885 : 0 : return rte_errno;
886 : : }
887 : :
888 [ # # ]: 0 : if (unlikely(rule->status != MLX5DR_RULE_STATUS_CREATED)) {
889 : 0 : DR_LOG(ERR, "Current rule status does not allow update");
890 : 0 : rte_errno = EBUSY;
891 : 0 : return rte_errno;
892 : : }
893 : :
894 : 0 : return mlx5dr_rule_enqueue_precheck_create(rule, attr);
895 : : }
896 : :
897 : 0 : int mlx5dr_rule_move_hws_remove(struct mlx5dr_rule *rule,
898 : : void *queue_ptr,
899 : : void *user_data)
900 : : {
901 : 0 : bool is_jumbo = mlx5dr_matcher_mt_is_jumbo(rule->matcher->mt);
902 : 0 : struct mlx5dr_wqe_gta_ctrl_seg empty_wqe_ctrl = {0};
903 : : struct mlx5dr_matcher *matcher = rule->matcher;
904 : : struct mlx5dr_send_engine *queue = queue_ptr;
905 : 0 : struct mlx5dr_send_ste_attr ste_attr = {0};
906 : :
907 : : /* Send dependent WQEs */
908 : 0 : mlx5dr_send_all_dep_wqe(queue);
909 : :
910 : 0 : rule->resize_info->state = MLX5DR_RULE_RESIZE_STATE_DELETING;
911 : :
912 : 0 : ste_attr.send_attr.fence = 0;
913 : 0 : ste_attr.send_attr.opmod = MLX5DR_WQE_GTA_OPMOD_STE;
914 : 0 : ste_attr.send_attr.opcode = MLX5DR_WQE_OPCODE_TBL_ACCESS;
915 : 0 : ste_attr.send_attr.len = MLX5DR_WQE_SZ_GTA_CTRL + MLX5DR_WQE_SZ_GTA_DATA;
916 : 0 : ste_attr.send_attr.rule = rule;
917 : 0 : ste_attr.send_attr.notify_hw = 1;
918 : 0 : ste_attr.send_attr.user_data = user_data;
919 : 0 : ste_attr.rtc_0 = rule->resize_info->rtc_0;
920 : 0 : ste_attr.rtc_1 = rule->resize_info->rtc_1;
921 : 0 : ste_attr.used_id_rtc_0 = &rule->resize_info->rtc_0;
922 : 0 : ste_attr.used_id_rtc_1 = &rule->resize_info->rtc_1;
923 : 0 : ste_attr.wqe_ctrl = &empty_wqe_ctrl;
924 : 0 : ste_attr.wqe_tag_is_jumbo = is_jumbo;
925 [ # # ]: 0 : ste_attr.gta_opcode = MLX5DR_WQE_GTA_OP_DEACTIVATE;
926 : :
927 [ # # ]: 0 : if (unlikely(mlx5dr_matcher_is_insert_by_idx(matcher)))
928 : 0 : ste_attr.direct_index = rule->resize_info->rule_idx;
929 : :
930 : 0 : mlx5dr_rule_load_delete_info(rule, &ste_attr);
931 : 0 : mlx5dr_send_ste(queue, &ste_attr);
932 : :
933 : 0 : return 0;
934 : : }
935 : :
936 : 0 : int mlx5dr_rule_move_hws_add(struct mlx5dr_rule *rule,
937 : : struct mlx5dr_rule_attr *attr)
938 : : {
939 : 0 : bool is_jumbo = mlx5dr_matcher_mt_is_jumbo(rule->matcher->mt);
940 : 0 : struct mlx5dr_context *ctx = rule->matcher->tbl->ctx;
941 : : struct mlx5dr_matcher *matcher = rule->matcher;
942 : 0 : struct mlx5dr_send_ste_attr ste_attr = {0};
943 : : struct mlx5dr_send_engine *queue;
944 : :
945 [ # # ]: 0 : if (unlikely(mlx5dr_rule_enqueue_precheck_move(rule, attr)))
946 : 0 : return -rte_errno;
947 : :
948 [ # # ]: 0 : queue = &ctx->send_queue[attr->queue_id];
949 : :
950 [ # # ]: 0 : if (unlikely(mlx5dr_send_engine_err(queue))) {
951 : 0 : rte_errno = EIO;
952 : 0 : return rte_errno;
953 : : }
954 : :
955 : : mlx5dr_rule_move_init(rule, attr);
956 : :
957 : 0 : mlx5dr_rule_move_get_rtc(rule, &ste_attr);
958 : :
959 : 0 : ste_attr.send_attr.opmod = MLX5DR_WQE_GTA_OPMOD_STE;
960 : 0 : ste_attr.send_attr.opcode = MLX5DR_WQE_OPCODE_TBL_ACCESS;
961 : 0 : ste_attr.send_attr.len = MLX5DR_WQE_SZ_GTA_CTRL + MLX5DR_WQE_SZ_GTA_DATA;
962 : 0 : ste_attr.gta_opcode = MLX5DR_WQE_GTA_OP_ACTIVATE;
963 : 0 : ste_attr.wqe_tag_is_jumbo = is_jumbo;
964 : :
965 : 0 : ste_attr.send_attr.rule = rule;
966 : 0 : ste_attr.send_attr.fence = 0;
967 : 0 : ste_attr.send_attr.notify_hw = !attr->burst;
968 : 0 : ste_attr.send_attr.user_data = attr->user_data;
969 : :
970 : 0 : ste_attr.used_id_rtc_0 = &rule->rtc_0;
971 : 0 : ste_attr.used_id_rtc_1 = &rule->rtc_1;
972 : 0 : ste_attr.wqe_ctrl = (struct mlx5dr_wqe_gta_ctrl_seg *)rule->resize_info->ctrl_seg;
973 [ # # ]: 0 : ste_attr.wqe_data = (struct mlx5dr_wqe_gta_data_seg_ste *)rule->resize_info->data_seg;
974 : 0 : ste_attr.direct_index = mlx5dr_matcher_is_insert_by_idx(matcher) ?
975 [ # # ]: 0 : attr->rule_idx : 0;
976 : :
977 : 0 : mlx5dr_send_ste(queue, &ste_attr);
978 : : mlx5dr_send_engine_inc_rule(queue);
979 : :
980 : : /* Send dependent WQEs */
981 [ # # ]: 0 : if (!attr->burst)
982 : 0 : mlx5dr_send_all_dep_wqe(queue);
983 : :
984 : : return 0;
985 : : }
986 : :
987 : 0 : int mlx5dr_rule_create(struct mlx5dr_matcher *matcher,
988 : : uint8_t mt_idx,
989 : : const struct rte_flow_item items[],
990 : : uint8_t at_idx,
991 : : struct mlx5dr_rule_action rule_actions[],
992 : : struct mlx5dr_rule_attr *attr,
993 : : struct mlx5dr_rule *rule_handle)
994 : : {
995 : : int ret;
996 : :
997 : 0 : rule_handle->matcher = matcher;
998 : :
999 [ # # ]: 0 : if (unlikely(mlx5dr_rule_enqueue_precheck_create(rule_handle, attr)))
1000 : 0 : return -rte_errno;
1001 : :
1002 [ # # ]: 0 : assert(matcher->num_of_mt >= mt_idx);
1003 [ # # ]: 0 : assert(matcher->num_of_at >= at_idx);
1004 [ # # ]: 0 : assert(items);
1005 : :
1006 [ # # ]: 0 : if (unlikely(mlx5dr_table_is_root(matcher->tbl)))
1007 : 0 : ret = mlx5dr_rule_create_root(rule_handle,
1008 : : attr,
1009 : : items,
1010 : 0 : matcher->at[at_idx].num_actions,
1011 : : rule_actions);
1012 : : else
1013 : 0 : ret = mlx5dr_rule_create_hws(rule_handle,
1014 : : attr,
1015 : : mt_idx,
1016 : : items,
1017 : : at_idx,
1018 : : rule_actions);
1019 : 0 : return -ret;
1020 : : }
1021 : :
1022 : 0 : int mlx5dr_rule_destroy(struct mlx5dr_rule *rule,
1023 : : struct mlx5dr_rule_attr *attr)
1024 : : {
1025 : : int ret;
1026 : :
1027 [ # # ]: 0 : if (unlikely(mlx5dr_rule_enqueue_precheck(rule, attr)))
1028 : 0 : return -rte_errno;
1029 : :
1030 [ # # ]: 0 : if (unlikely(mlx5dr_table_is_root(rule->matcher->tbl)))
1031 : 0 : ret = mlx5dr_rule_destroy_root(rule, attr);
1032 : : else
1033 : 0 : ret = mlx5dr_rule_destroy_hws(rule, attr);
1034 : :
1035 : 0 : return -ret;
1036 : : }
1037 : :
1038 : 0 : int mlx5dr_rule_action_update(struct mlx5dr_rule *rule_handle,
1039 : : uint8_t at_idx,
1040 : : struct mlx5dr_rule_action rule_actions[],
1041 : : struct mlx5dr_rule_attr *attr)
1042 : : {
1043 : : int ret;
1044 : :
1045 [ # # ]: 0 : if (unlikely(mlx5dr_rule_enqueue_precheck_update(rule_handle, attr)))
1046 : 0 : return -rte_errno;
1047 : :
1048 [ # # ]: 0 : if (rule_handle->status != MLX5DR_RULE_STATUS_CREATED) {
1049 : 0 : DR_LOG(ERR, "Current rule status does not allow update");
1050 : 0 : rte_errno = EBUSY;
1051 : 0 : return -rte_errno;
1052 : : }
1053 : :
1054 : 0 : ret = mlx5dr_rule_create_hws(rule_handle,
1055 : : attr,
1056 : : 0,
1057 : : NULL,
1058 : : at_idx,
1059 : : rule_actions);
1060 : :
1061 : 0 : return -ret;
1062 : : }
1063 : :
1064 : 0 : size_t mlx5dr_rule_get_handle_size(void)
1065 : : {
1066 : 0 : return sizeof(struct mlx5dr_rule);
1067 : : }
1068 : :
1069 : 0 : int mlx5dr_rule_hash_calculate(struct mlx5dr_matcher *matcher,
1070 : : const struct rte_flow_item items[],
1071 : : uint8_t mt_idx,
1072 : : enum mlx5dr_rule_hash_calc_mode mode,
1073 : : uint32_t *ret_hash)
1074 : : {
1075 : 0 : uint8_t tag[MLX5DR_WQE_SZ_GTA_DATA] = {0};
1076 : : struct mlx5dr_match_template *mt;
1077 : :
1078 [ # # # # ]: 0 : if (!matcher || !matcher->mt) {
1079 : 0 : rte_errno = EINVAL;
1080 : 0 : return -rte_errno;
1081 : : }
1082 : :
1083 [ # # ]: 0 : mt = &matcher->mt[mt_idx];
1084 : :
1085 [ # # # # ]: 0 : if (mlx5dr_matcher_req_fw_wqe(matcher) ||
1086 [ # # ]: 0 : mlx5dr_table_is_root(matcher->tbl) ||
1087 [ # # ]: 0 : matcher->tbl->ctx->caps->access_index_mode == MLX5DR_MATCHER_INSERT_BY_HASH ||
1088 [ # # ]: 0 : matcher->tbl->ctx->caps->flow_table_hash_type != MLX5_FLOW_TABLE_HASH_TYPE_CRC32) {
1089 : 0 : DR_LOG(DEBUG, "Matcher is not supported");
1090 : 0 : rte_errno = ENOTSUP;
1091 : 0 : return -rte_errno;
1092 : : }
1093 : :
1094 : 0 : mlx5dr_definer_create_tag(items, mt->fc, mt->fc_sz, tag);
1095 [ # # ]: 0 : if (mlx5dr_matcher_mt_is_jumbo(mt))
1096 : 0 : *ret_hash = mlx5dr_crc32_calc(tag, MLX5DR_JUMBO_TAG_SZ);
1097 : : else
1098 : 0 : *ret_hash = mlx5dr_crc32_calc(tag + MLX5DR_ACTIONS_SZ,
1099 : : MLX5DR_MATCH_TAG_SZ);
1100 : :
1101 [ # # ]: 0 : if (mode == MLX5DR_RULE_HASH_CALC_MODE_IDX)
1102 : 0 : *ret_hash = *ret_hash & (BIT(matcher->attr.rule.num_log) - 1);
1103 : :
1104 : : return 0;
1105 : : }
|