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 : 0 : flow_attr.hws_root_match_flags = rule->matcher->hws_root_match_flags;
745 : :
746 : 0 : ret = mlx5_flow_dv_translate_items_hws(items, &flow_attr, value->match_buf,
747 : : MLX5_SET_MATCHER_HS_V, NULL,
748 : : &match_criteria,
749 : : &error);
750 [ # # ]: 0 : if (ret) {
751 : 0 : DR_LOG(ERR, "Failed to convert items to PRM [%s]", error.message);
752 : 0 : goto free_value;
753 : : }
754 : :
755 : : /* Convert actions to verb action attr */
756 : 0 : ret = mlx5dr_action_root_build_attr(rule_actions, num_actions, attr);
757 [ # # ]: 0 : if (ret)
758 : 0 : goto free_value;
759 : :
760 : : /* Create verb flow */
761 : 0 : value->match_sz = MLX5_ST_SZ_BYTES(fte_match_param);
762 : 0 : rule->flow = mlx5_glue->dv_create_flow_root(dv_matcher,
763 : : value,
764 : : num_actions,
765 : : attr);
766 : :
767 : : simple_free(value);
768 : : simple_free(attr);
769 : :
770 : 0 : return 0;
771 : :
772 : 0 : free_value:
773 : : simple_free(value);
774 : 0 : free_attr:
775 : : simple_free(attr);
776 : :
777 : 0 : return rte_errno;
778 : : }
779 : :
780 : 0 : static int mlx5dr_rule_create_root(struct mlx5dr_rule *rule,
781 : : struct mlx5dr_rule_attr *rule_attr,
782 : : const struct rte_flow_item items[],
783 : : uint8_t num_actions,
784 : : struct mlx5dr_rule_action rule_actions[])
785 : : {
786 : 0 : struct mlx5dr_context *ctx = rule->matcher->tbl->ctx;
787 : : int ret;
788 : :
789 : 0 : ret = mlx5dr_rule_create_root_no_comp(rule, items,
790 : : num_actions, rule_actions);
791 [ # # ]: 0 : if (ret)
792 : 0 : return rte_errno;
793 : :
794 [ # # ]: 0 : mlx5dr_rule_gen_comp(&ctx->send_queue[rule_attr->queue_id], rule, !rule->flow,
795 : : rule_attr->user_data, MLX5DR_RULE_STATUS_CREATED);
796 : :
797 : 0 : return 0;
798 : : }
799 : :
800 : 0 : int mlx5dr_rule_destroy_root_no_comp(struct mlx5dr_rule *rule)
801 : : {
802 [ # # ]: 0 : if (rule->flow)
803 : 0 : return ibv_destroy_flow(rule->flow);
804 : :
805 : : return 0;
806 : : }
807 : :
808 : 0 : static int mlx5dr_rule_destroy_root(struct mlx5dr_rule *rule,
809 : : struct mlx5dr_rule_attr *attr)
810 : : {
811 : 0 : struct mlx5dr_context *ctx = rule->matcher->tbl->ctx;
812 : : int err;
813 : :
814 : 0 : err = mlx5dr_rule_destroy_root_no_comp(rule);
815 : :
816 [ # # ]: 0 : mlx5dr_rule_gen_comp(&ctx->send_queue[attr->queue_id], rule, err,
817 : : attr->user_data, MLX5DR_RULE_STATUS_DELETED);
818 : :
819 : 0 : return 0;
820 : : }
821 : :
822 : 0 : static int mlx5dr_rule_enqueue_precheck(struct mlx5dr_rule *rule,
823 : : struct mlx5dr_rule_attr *attr)
824 : : {
825 : 0 : struct mlx5dr_context *ctx = rule->matcher->tbl->ctx;
826 : :
827 [ # # ]: 0 : if (unlikely(!attr->user_data)) {
828 : 0 : DR_LOG(DEBUG, "User data must be provided for rule operations");
829 : 0 : rte_errno = EINVAL;
830 : 0 : return rte_errno;
831 : : }
832 : :
833 : : /* Check if there is room in queue */
834 [ # # ]: 0 : if (unlikely(mlx5dr_send_engine_full(&ctx->send_queue[attr->queue_id]))) {
835 : 0 : DR_LOG(NOTICE, "No room in queue[%d]", attr->queue_id);
836 : 0 : rte_errno = EBUSY;
837 : 0 : return rte_errno;
838 : : }
839 : :
840 : : return 0;
841 : : }
842 : :
843 : 0 : static int mlx5dr_rule_enqueue_precheck_move(struct mlx5dr_rule *rule,
844 : : struct mlx5dr_rule_attr *attr)
845 : : {
846 [ # # ]: 0 : if (unlikely(rule->status != MLX5DR_RULE_STATUS_CREATED)) {
847 : 0 : DR_LOG(DEBUG, "Cannot move, rule status is invalid");
848 : 0 : rte_errno = EINVAL;
849 : 0 : return rte_errno;
850 : : }
851 : :
852 : 0 : return mlx5dr_rule_enqueue_precheck(rule, attr);
853 : : }
854 : :
855 : 0 : static int mlx5dr_rule_enqueue_precheck_create(struct mlx5dr_rule *rule,
856 : : struct mlx5dr_rule_attr *attr)
857 : : {
858 [ # # ]: 0 : if (unlikely(mlx5dr_matcher_is_in_resize(rule->matcher))) {
859 : : /* Matcher in resize - new rules are not allowed */
860 : 0 : DR_LOG(NOTICE, "Resizing in progress, cannot create rule");
861 : 0 : rte_errno = EAGAIN;
862 : 0 : return rte_errno;
863 : : }
864 : :
865 : 0 : return mlx5dr_rule_enqueue_precheck(rule, attr);
866 : : }
867 : :
868 : 0 : static int mlx5dr_rule_enqueue_precheck_update(struct mlx5dr_rule *rule,
869 : : struct mlx5dr_rule_attr *attr)
870 : : {
871 : 0 : struct mlx5dr_matcher *matcher = rule->matcher;
872 : :
873 [ # # # # ]: 0 : if (unlikely((mlx5dr_table_is_root(matcher->tbl) ||
874 : : mlx5dr_matcher_req_fw_wqe(matcher)))) {
875 : 0 : DR_LOG(ERR, "Rule update is not supported on current matcher");
876 : 0 : rte_errno = ENOTSUP;
877 : 0 : return rte_errno;
878 : : }
879 : :
880 [ # # # # ]: 0 : if (unlikely(!matcher->attr.optimize_using_rule_idx &&
881 : : !mlx5dr_matcher_is_insert_by_idx(matcher))) {
882 : 0 : DR_LOG(ERR, "Rule update requires optimize by idx matcher");
883 : 0 : rte_errno = ENOTSUP;
884 : 0 : return rte_errno;
885 : : }
886 : :
887 [ # # ]: 0 : if (unlikely(mlx5dr_matcher_is_resizable(rule->matcher))) {
888 : 0 : DR_LOG(ERR, "Rule update is not supported on resizable matcher");
889 : 0 : rte_errno = ENOTSUP;
890 : 0 : return rte_errno;
891 : : }
892 : :
893 [ # # ]: 0 : if (unlikely(rule->status != MLX5DR_RULE_STATUS_CREATED)) {
894 : 0 : DR_LOG(ERR, "Current rule status does not allow update");
895 : 0 : rte_errno = EBUSY;
896 : 0 : return rte_errno;
897 : : }
898 : :
899 : 0 : return mlx5dr_rule_enqueue_precheck_create(rule, attr);
900 : : }
901 : :
902 : 0 : int mlx5dr_rule_move_hws_remove(struct mlx5dr_rule *rule,
903 : : void *queue_ptr,
904 : : void *user_data)
905 : : {
906 : 0 : bool is_jumbo = mlx5dr_matcher_mt_is_jumbo(rule->matcher->mt);
907 : 0 : struct mlx5dr_wqe_gta_ctrl_seg empty_wqe_ctrl = {0};
908 : : struct mlx5dr_matcher *matcher = rule->matcher;
909 : : struct mlx5dr_send_engine *queue = queue_ptr;
910 : 0 : struct mlx5dr_send_ste_attr ste_attr = {0};
911 : :
912 : : /* Send dependent WQEs */
913 : 0 : mlx5dr_send_all_dep_wqe(queue);
914 : :
915 : 0 : rule->resize_info->state = MLX5DR_RULE_RESIZE_STATE_DELETING;
916 : :
917 : 0 : ste_attr.send_attr.fence = 0;
918 : 0 : ste_attr.send_attr.opmod = MLX5DR_WQE_GTA_OPMOD_STE;
919 : 0 : ste_attr.send_attr.opcode = MLX5DR_WQE_OPCODE_TBL_ACCESS;
920 : 0 : ste_attr.send_attr.len = MLX5DR_WQE_SZ_GTA_CTRL + MLX5DR_WQE_SZ_GTA_DATA;
921 : 0 : ste_attr.send_attr.rule = rule;
922 : 0 : ste_attr.send_attr.notify_hw = 1;
923 : 0 : ste_attr.send_attr.user_data = user_data;
924 : 0 : ste_attr.rtc_0 = rule->resize_info->rtc_0;
925 : 0 : ste_attr.rtc_1 = rule->resize_info->rtc_1;
926 : 0 : ste_attr.used_id_rtc_0 = &rule->resize_info->rtc_0;
927 : 0 : ste_attr.used_id_rtc_1 = &rule->resize_info->rtc_1;
928 : 0 : ste_attr.wqe_ctrl = &empty_wqe_ctrl;
929 : 0 : ste_attr.wqe_tag_is_jumbo = is_jumbo;
930 [ # # ]: 0 : ste_attr.gta_opcode = MLX5DR_WQE_GTA_OP_DEACTIVATE;
931 : :
932 [ # # ]: 0 : if (unlikely(mlx5dr_matcher_is_insert_by_idx(matcher)))
933 : 0 : ste_attr.direct_index = rule->resize_info->rule_idx;
934 : :
935 : 0 : mlx5dr_rule_load_delete_info(rule, &ste_attr);
936 : 0 : mlx5dr_send_ste(queue, &ste_attr);
937 : :
938 : 0 : return 0;
939 : : }
940 : :
941 : 0 : int mlx5dr_rule_move_hws_add(struct mlx5dr_rule *rule,
942 : : struct mlx5dr_rule_attr *attr)
943 : : {
944 : 0 : bool is_jumbo = mlx5dr_matcher_mt_is_jumbo(rule->matcher->mt);
945 : 0 : struct mlx5dr_context *ctx = rule->matcher->tbl->ctx;
946 : : struct mlx5dr_matcher *matcher = rule->matcher;
947 : 0 : struct mlx5dr_send_ste_attr ste_attr = {0};
948 : : struct mlx5dr_send_engine *queue;
949 : :
950 [ # # ]: 0 : if (unlikely(mlx5dr_rule_enqueue_precheck_move(rule, attr)))
951 : 0 : return -rte_errno;
952 : :
953 [ # # ]: 0 : queue = &ctx->send_queue[attr->queue_id];
954 : :
955 [ # # ]: 0 : if (unlikely(mlx5dr_send_engine_err(queue))) {
956 : 0 : rte_errno = EIO;
957 : 0 : return rte_errno;
958 : : }
959 : :
960 : : mlx5dr_rule_move_init(rule, attr);
961 : :
962 : 0 : mlx5dr_rule_move_get_rtc(rule, &ste_attr);
963 : :
964 : 0 : ste_attr.send_attr.opmod = MLX5DR_WQE_GTA_OPMOD_STE;
965 : 0 : ste_attr.send_attr.opcode = MLX5DR_WQE_OPCODE_TBL_ACCESS;
966 : 0 : ste_attr.send_attr.len = MLX5DR_WQE_SZ_GTA_CTRL + MLX5DR_WQE_SZ_GTA_DATA;
967 : 0 : ste_attr.gta_opcode = MLX5DR_WQE_GTA_OP_ACTIVATE;
968 : 0 : ste_attr.wqe_tag_is_jumbo = is_jumbo;
969 : :
970 : 0 : ste_attr.send_attr.rule = rule;
971 : 0 : ste_attr.send_attr.fence = 0;
972 : 0 : ste_attr.send_attr.notify_hw = !attr->burst;
973 : 0 : ste_attr.send_attr.user_data = attr->user_data;
974 : :
975 : 0 : ste_attr.used_id_rtc_0 = &rule->rtc_0;
976 : 0 : ste_attr.used_id_rtc_1 = &rule->rtc_1;
977 : 0 : ste_attr.wqe_ctrl = (struct mlx5dr_wqe_gta_ctrl_seg *)rule->resize_info->ctrl_seg;
978 [ # # ]: 0 : ste_attr.wqe_data = (struct mlx5dr_wqe_gta_data_seg_ste *)rule->resize_info->data_seg;
979 : 0 : ste_attr.direct_index = mlx5dr_matcher_is_insert_by_idx(matcher) ?
980 [ # # ]: 0 : attr->rule_idx : 0;
981 : :
982 : 0 : mlx5dr_send_ste(queue, &ste_attr);
983 : : mlx5dr_send_engine_inc_rule(queue);
984 : :
985 : : /* Send dependent WQEs */
986 [ # # ]: 0 : if (!attr->burst)
987 : 0 : mlx5dr_send_all_dep_wqe(queue);
988 : :
989 : : return 0;
990 : : }
991 : :
992 : 0 : int mlx5dr_rule_create(struct mlx5dr_matcher *matcher,
993 : : uint8_t mt_idx,
994 : : const struct rte_flow_item items[],
995 : : uint8_t at_idx,
996 : : struct mlx5dr_rule_action rule_actions[],
997 : : struct mlx5dr_rule_attr *attr,
998 : : struct mlx5dr_rule *rule_handle)
999 : : {
1000 : : int ret;
1001 : :
1002 : 0 : rule_handle->matcher = matcher;
1003 : :
1004 [ # # ]: 0 : if (unlikely(mlx5dr_rule_enqueue_precheck_create(rule_handle, attr)))
1005 : 0 : return -rte_errno;
1006 : :
1007 [ # # ]: 0 : assert(matcher->num_of_mt >= mt_idx);
1008 [ # # ]: 0 : assert(matcher->num_of_at >= at_idx);
1009 [ # # ]: 0 : assert(items);
1010 : :
1011 [ # # ]: 0 : if (unlikely(mlx5dr_table_is_root(matcher->tbl)))
1012 : 0 : ret = mlx5dr_rule_create_root(rule_handle,
1013 : : attr,
1014 : : items,
1015 : 0 : matcher->at[at_idx].num_actions,
1016 : : rule_actions);
1017 : : else
1018 : 0 : ret = mlx5dr_rule_create_hws(rule_handle,
1019 : : attr,
1020 : : mt_idx,
1021 : : items,
1022 : : at_idx,
1023 : : rule_actions);
1024 : 0 : return -ret;
1025 : : }
1026 : :
1027 : 0 : int mlx5dr_rule_destroy(struct mlx5dr_rule *rule,
1028 : : struct mlx5dr_rule_attr *attr)
1029 : : {
1030 : : int ret;
1031 : :
1032 [ # # ]: 0 : if (unlikely(mlx5dr_rule_enqueue_precheck(rule, attr)))
1033 : 0 : return -rte_errno;
1034 : :
1035 [ # # ]: 0 : if (unlikely(mlx5dr_table_is_root(rule->matcher->tbl)))
1036 : 0 : ret = mlx5dr_rule_destroy_root(rule, attr);
1037 : : else
1038 : 0 : ret = mlx5dr_rule_destroy_hws(rule, attr);
1039 : :
1040 : 0 : return -ret;
1041 : : }
1042 : :
1043 : 0 : int mlx5dr_rule_action_update(struct mlx5dr_rule *rule_handle,
1044 : : uint8_t at_idx,
1045 : : struct mlx5dr_rule_action rule_actions[],
1046 : : struct mlx5dr_rule_attr *attr)
1047 : : {
1048 : : int ret;
1049 : :
1050 [ # # ]: 0 : if (unlikely(mlx5dr_rule_enqueue_precheck_update(rule_handle, attr)))
1051 : 0 : return -rte_errno;
1052 : :
1053 [ # # ]: 0 : if (rule_handle->status != MLX5DR_RULE_STATUS_CREATED) {
1054 : 0 : DR_LOG(ERR, "Current rule status does not allow update");
1055 : 0 : rte_errno = EBUSY;
1056 : 0 : return -rte_errno;
1057 : : }
1058 : :
1059 : 0 : ret = mlx5dr_rule_create_hws(rule_handle,
1060 : : attr,
1061 : : 0,
1062 : : NULL,
1063 : : at_idx,
1064 : : rule_actions);
1065 : :
1066 : 0 : return -ret;
1067 : : }
1068 : :
1069 : 0 : size_t mlx5dr_rule_get_handle_size(void)
1070 : : {
1071 : 0 : return sizeof(struct mlx5dr_rule);
1072 : : }
1073 : :
1074 : 0 : int mlx5dr_rule_hash_calculate(struct mlx5dr_matcher *matcher,
1075 : : const struct rte_flow_item items[],
1076 : : uint8_t mt_idx,
1077 : : enum mlx5dr_rule_hash_calc_mode mode,
1078 : : uint32_t *ret_hash)
1079 : : {
1080 : 0 : uint8_t tag[MLX5DR_WQE_SZ_GTA_DATA] = {0};
1081 : : struct mlx5dr_match_template *mt;
1082 : :
1083 [ # # # # ]: 0 : if (!matcher || !matcher->mt) {
1084 : 0 : rte_errno = EINVAL;
1085 : 0 : return -rte_errno;
1086 : : }
1087 : :
1088 [ # # ]: 0 : mt = &matcher->mt[mt_idx];
1089 : :
1090 [ # # # # ]: 0 : if (mlx5dr_matcher_req_fw_wqe(matcher) ||
1091 [ # # ]: 0 : mlx5dr_table_is_root(matcher->tbl) ||
1092 [ # # ]: 0 : matcher->attr.distribute_mode != MLX5DR_MATCHER_DISTRIBUTE_BY_HASH ||
1093 [ # # ]: 0 : matcher->tbl->ctx->caps->flow_table_hash_type != MLX5_FLOW_TABLE_HASH_TYPE_CRC32) {
1094 : 0 : DR_LOG(DEBUG, "Matcher is not supported");
1095 : 0 : rte_errno = ENOTSUP;
1096 : 0 : return -rte_errno;
1097 : : }
1098 : :
1099 : 0 : mlx5dr_definer_create_tag(items, mt->fc, mt->fc_sz, tag);
1100 [ # # ]: 0 : if (mlx5dr_matcher_mt_is_jumbo(mt))
1101 : 0 : *ret_hash = mlx5dr_crc32_calc(tag, MLX5DR_JUMBO_TAG_SZ);
1102 : : else
1103 : 0 : *ret_hash = mlx5dr_crc32_calc(tag + MLX5DR_ACTIONS_SZ,
1104 : : MLX5DR_MATCH_TAG_SZ);
1105 : :
1106 [ # # ]: 0 : if (mode == MLX5DR_RULE_HASH_CALC_MODE_IDX)
1107 : 0 : *ret_hash = *ret_hash & (BIT(matcher->attr.rule.num_log) - 1);
1108 : :
1109 : : return 0;
1110 : : }
|