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