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