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 : : enum mlx5dr_matcher_rtc_type {
8 : : DR_MATCHER_RTC_TYPE_MATCH,
9 : : DR_MATCHER_RTC_TYPE_STE_ARRAY,
10 : : DR_MATCHER_RTC_TYPE_MAX,
11 : : };
12 : :
13 : : static const char * const mlx5dr_matcher_rtc_type_str[] = {
14 : : [DR_MATCHER_RTC_TYPE_MATCH] = "MATCH",
15 : : [DR_MATCHER_RTC_TYPE_STE_ARRAY] = "STE_ARRAY",
16 : : [DR_MATCHER_RTC_TYPE_MAX] = "UNKNOWN",
17 : : };
18 : :
19 : : static const char *mlx5dr_matcher_rtc_type_to_str(enum mlx5dr_matcher_rtc_type rtc_type)
20 : : {
21 : : if (rtc_type > DR_MATCHER_RTC_TYPE_MAX)
22 : : rtc_type = DR_MATCHER_RTC_TYPE_MAX;
23 : 0 : return mlx5dr_matcher_rtc_type_str[rtc_type];
24 : : }
25 : :
26 : : static bool mlx5dr_matcher_requires_col_tbl(uint8_t log_num_of_rules)
27 : : {
28 : : /* Collision table concatenation is done only for large rule tables */
29 : : return log_num_of_rules > MLX5DR_MATCHER_ASSURED_RULES_TH;
30 : : }
31 : :
32 : : static uint8_t mlx5dr_matcher_rules_to_tbl_depth(uint8_t log_num_of_rules)
33 : : {
34 : 0 : if (mlx5dr_matcher_requires_col_tbl(log_num_of_rules))
35 : : return MLX5DR_MATCHER_ASSURED_MAIN_TBL_DEPTH;
36 : :
37 : : /* For small rule tables we use a single deep table to assure insertion */
38 : 0 : return RTE_MIN(log_num_of_rules, MLX5DR_MATCHER_ASSURED_COL_TBL_DEPTH);
39 : : }
40 : :
41 : : static void mlx5dr_matcher_destroy_end_ft(struct mlx5dr_matcher *matcher)
42 : : {
43 : 0 : mlx5dr_table_destroy_default_ft(matcher->tbl, matcher->end_ft);
44 : 0 : }
45 : :
46 [ # # ]: 0 : int mlx5dr_matcher_free_rtc_pointing(struct mlx5dr_context *ctx,
47 : : uint32_t fw_ft_type,
48 : : enum mlx5dr_table_type type,
49 : : struct mlx5dr_devx_obj *devx_obj)
50 : : {
51 : : int ret;
52 : :
53 [ # # ]: 0 : if (!mlx5dr_table_is_fdb_any(type) && !mlx5dr_context_shared_gvmi_used(ctx))
54 : : return 0;
55 : :
56 : 0 : ret = mlx5dr_table_ft_set_next_rtc(devx_obj, fw_ft_type, NULL, NULL);
57 [ # # ]: 0 : if (ret)
58 : 0 : DR_LOG(ERR, "Failed to disconnect previous RTC");
59 : :
60 : : return ret;
61 : : }
62 : :
63 : 0 : static int mlx5dr_matcher_shared_point_end_ft(struct mlx5dr_matcher *matcher)
64 : : {
65 : 0 : struct mlx5dr_cmd_ft_modify_attr ft_attr = {0};
66 : : int ret;
67 : :
68 : 0 : mlx5dr_cmd_set_attr_connect_miss_tbl(matcher->tbl->ctx,
69 : : matcher->tbl->fw_ft_type,
70 : 0 : matcher->tbl->type,
71 : : &ft_attr);
72 : :
73 : 0 : ret = mlx5dr_cmd_flow_table_modify(matcher->end_ft, &ft_attr);
74 [ # # ]: 0 : if (ret) {
75 : 0 : DR_LOG(ERR, "Failed to connect new matcher to default miss alias RTC");
76 : 0 : return ret;
77 : : }
78 : :
79 : 0 : ret = mlx5dr_matcher_free_rtc_pointing(matcher->tbl->ctx,
80 : : matcher->tbl->fw_ft_type,
81 : 0 : matcher->tbl->type,
82 : : matcher->end_ft);
83 : :
84 : 0 : return ret;
85 : : }
86 : :
87 : 0 : static int mlx5dr_matcher_shared_create_alias_rtc(struct mlx5dr_matcher *matcher)
88 : : {
89 : 0 : struct mlx5dr_context *ctx = matcher->tbl->ctx;
90 : : int ret;
91 : :
92 : 0 : ret = mlx5dr_matcher_create_aliased_obj(ctx,
93 : : ctx->ibv_ctx,
94 : : ctx->local_ibv_ctx,
95 : 0 : ctx->caps->shared_vhca_id,
96 : 0 : matcher->match_ste.rtc_0->id,
97 : : MLX5_GENERAL_OBJ_TYPE_RTC,
98 : : &matcher->match_ste.aliased_rtc_0);
99 [ # # ]: 0 : if (ret) {
100 : 0 : DR_LOG(ERR, "Failed to allocate alias RTC");
101 : 0 : return ret;
102 : : }
103 : : return 0;
104 : : }
105 : :
106 : 0 : static int mlx5dr_matcher_create_init_shared(struct mlx5dr_matcher *matcher)
107 : : {
108 [ # # ]: 0 : if (!mlx5dr_context_shared_gvmi_used(matcher->tbl->ctx))
109 : : return 0;
110 : :
111 [ # # ]: 0 : if (mlx5dr_matcher_shared_point_end_ft(matcher)) {
112 : 0 : DR_LOG(ERR, "Failed to point shared matcher end flow table");
113 : 0 : return rte_errno;
114 : : }
115 : :
116 [ # # ]: 0 : if (mlx5dr_matcher_shared_create_alias_rtc(matcher)) {
117 : 0 : DR_LOG(ERR, "Failed to create alias RTC");
118 : 0 : return rte_errno;
119 : : }
120 : :
121 : : return 0;
122 : : }
123 : :
124 : 0 : static void mlx5dr_matcher_create_uninit_shared(struct mlx5dr_matcher *matcher)
125 : : {
126 [ # # ]: 0 : if (!mlx5dr_context_shared_gvmi_used(matcher->tbl->ctx))
127 : : return;
128 : :
129 [ # # ]: 0 : if (matcher->match_ste.aliased_rtc_0) {
130 : 0 : mlx5dr_cmd_destroy_obj(matcher->match_ste.aliased_rtc_0);
131 : 0 : matcher->match_ste.aliased_rtc_0 = NULL;
132 : : }
133 : : }
134 : :
135 : 0 : static int mlx5dr_matcher_create_end_ft(struct mlx5dr_matcher *matcher)
136 : : {
137 : 0 : struct mlx5dr_table *tbl = matcher->tbl;
138 : :
139 : 0 : matcher->end_ft = mlx5dr_table_create_default_ft(tbl->ctx->ibv_ctx, tbl);
140 [ # # ]: 0 : if (!matcher->end_ft) {
141 : 0 : DR_LOG(ERR, "Failed to create matcher end flow table");
142 : 0 : return rte_errno;
143 : : }
144 : : return 0;
145 : : }
146 : :
147 : : static uint32_t
148 : : mlx5dr_matcher_connect_get_rtc0(struct mlx5dr_matcher *matcher)
149 : : {
150 : 0 : if (!matcher->match_ste.aliased_rtc_0)
151 : 0 : return matcher->match_ste.rtc_0->id;
152 : : else
153 : 0 : return matcher->match_ste.aliased_rtc_0->id;
154 : : }
155 : :
156 : : /* The function updates tbl->local_ft to the first RTC or 0 if no more matchers */
157 : 0 : static int mlx5dr_matcher_shared_update_local_ft(struct mlx5dr_table *tbl)
158 : : {
159 : 0 : struct mlx5dr_cmd_ft_modify_attr cur_ft_attr = {0};
160 : : struct mlx5dr_matcher *first_matcher;
161 : : int ret;
162 : :
163 [ # # ]: 0 : if (!mlx5dr_context_shared_gvmi_used(tbl->ctx))
164 : : return 0;
165 : :
166 : 0 : first_matcher = LIST_FIRST(&tbl->head);
167 [ # # ]: 0 : if (!first_matcher) {
168 : : /* local ft no longer points to any RTC, drop refcount */
169 : 0 : ret = mlx5dr_matcher_free_rtc_pointing(tbl->ctx,
170 : : tbl->fw_ft_type,
171 : : tbl->type,
172 : : tbl->local_ft);
173 [ # # ]: 0 : if (ret)
174 : 0 : DR_LOG(ERR, "Failed to clear local FT to prev alias RTC");
175 : :
176 : 0 : return ret;
177 : : }
178 : :
179 : : /* point local_ft to the first RTC */
180 : 0 : cur_ft_attr.modify_fs = MLX5_IFC_MODIFY_FLOW_TABLE_RTC_ID;
181 [ # # ]: 0 : cur_ft_attr.type = tbl->fw_ft_type;
182 : 0 : cur_ft_attr.rtc_id_0 = mlx5dr_matcher_connect_get_rtc0(first_matcher);
183 : :
184 : 0 : ret = mlx5dr_cmd_flow_table_modify(tbl->local_ft, &cur_ft_attr);
185 [ # # ]: 0 : if (ret) {
186 : 0 : DR_LOG(ERR, "Failed to point local FT to alias RTC");
187 : 0 : return ret;
188 : : }
189 : :
190 : : return 0;
191 : : }
192 : :
193 : 0 : static int mlx5dr_matcher_connect(struct mlx5dr_matcher *matcher)
194 : : {
195 : 0 : struct mlx5dr_table *tbl = matcher->tbl;
196 : : struct mlx5dr_matcher *prev = NULL;
197 : : struct mlx5dr_matcher *next = NULL;
198 : : struct mlx5dr_matcher *tmp_matcher;
199 : : int ret;
200 : :
201 [ # # ]: 0 : if (matcher->attr.isolated) {
202 [ # # ]: 0 : LIST_INSERT_HEAD(&tbl->isolated_matchers, matcher, next);
203 : 0 : ret = mlx5dr_table_connect_src_ft_to_miss_table(tbl, matcher->end_ft,
204 : : tbl->default_miss.miss_tbl);
205 [ # # ]: 0 : if (ret) {
206 : 0 : DR_LOG(ERR, "Failed to connect the new matcher to the miss_tbl");
207 : 0 : goto remove_from_list;
208 : : }
209 : :
210 : : return 0;
211 : : }
212 : :
213 : : /* Find location in matcher list */
214 [ # # ]: 0 : if (LIST_EMPTY(&tbl->head)) {
215 : 0 : LIST_INSERT_HEAD(&tbl->head, matcher, next);
216 : 0 : goto connect;
217 : : }
218 : :
219 [ # # ]: 0 : LIST_FOREACH(tmp_matcher, &tbl->head, next) {
220 [ # # ]: 0 : if (tmp_matcher->attr.priority > matcher->attr.priority) {
221 : : next = tmp_matcher;
222 : : break;
223 : : }
224 : : prev = tmp_matcher;
225 : : }
226 : :
227 [ # # ]: 0 : if (next)
228 : 0 : LIST_INSERT_BEFORE(next, matcher, next);
229 : : else
230 [ # # ]: 0 : LIST_INSERT_AFTER(prev, matcher, next);
231 : :
232 : 0 : connect:
233 [ # # ]: 0 : if (next) {
234 : : /* Connect to next RTC */
235 : 0 : ret = mlx5dr_table_ft_set_next_rtc(matcher->end_ft,
236 : : tbl->fw_ft_type,
237 : : next->match_ste.rtc_0,
238 : : next->match_ste.rtc_1);
239 [ # # ]: 0 : if (ret) {
240 : 0 : DR_LOG(ERR, "Failed to connect new matcher to next RTC");
241 : 0 : goto remove_from_list;
242 : : }
243 : : } else {
244 : : /* Connect last matcher to next miss_tbl if exists */
245 : 0 : ret = mlx5dr_table_connect_to_miss_table(tbl, tbl->default_miss.miss_tbl, true);
246 [ # # ]: 0 : if (ret) {
247 : 0 : DR_LOG(ERR, "Failed connect new matcher to miss_tbl");
248 : 0 : goto remove_from_list;
249 : : }
250 : : }
251 : :
252 : : /* Connect to previous FT */
253 [ # # ]: 0 : ret = mlx5dr_table_ft_set_next_rtc(prev ? prev->end_ft : tbl->ft,
254 : : tbl->fw_ft_type,
255 : : matcher->match_ste.rtc_0,
256 : : matcher->match_ste.rtc_1);
257 [ # # ]: 0 : if (ret) {
258 : 0 : DR_LOG(ERR, "Failed to connect new matcher to previous FT");
259 : 0 : goto remove_from_list;
260 : : }
261 : :
262 : 0 : ret = mlx5dr_matcher_shared_update_local_ft(tbl);
263 [ # # ]: 0 : if (ret) {
264 : 0 : DR_LOG(ERR, "Failed to update local_ft anchor in shared table");
265 : 0 : goto remove_from_list;
266 : : }
267 : :
268 : : /* Reset next miss FT to default (drop refcount) */
269 [ # # ]: 0 : ret = mlx5dr_table_ft_set_default_next_ft(tbl, prev ? prev->end_ft : tbl->ft);
270 [ # # ]: 0 : if (ret) {
271 : 0 : DR_LOG(ERR, "Failed to reset matcher ft default miss");
272 : 0 : goto remove_from_list;
273 : : }
274 : :
275 [ # # ]: 0 : if (!prev) {
276 : : /* Update tables missing to current matcher in the table */
277 : 0 : ret = mlx5dr_table_update_connected_miss_tables(tbl);
278 [ # # ]: 0 : if (ret) {
279 : 0 : DR_LOG(ERR, "Fatal error, failed to update connected miss table");
280 : 0 : goto remove_from_list;
281 : : }
282 : : }
283 : :
284 : : return 0;
285 : :
286 : 0 : remove_from_list:
287 [ # # ]: 0 : LIST_REMOVE(matcher, next);
288 : 0 : return ret;
289 : : }
290 : :
291 : 0 : static int mlx5dr_matcher_disconnect(struct mlx5dr_matcher *matcher)
292 : : {
293 : 0 : struct mlx5dr_table *tbl = matcher->tbl;
294 : : struct mlx5dr_matcher *tmp_matcher;
295 : : struct mlx5dr_devx_obj *prev_ft;
296 : : struct mlx5dr_matcher *next;
297 : : int ret;
298 : :
299 [ # # ]: 0 : if (matcher->attr.isolated) {
300 [ # # ]: 0 : LIST_REMOVE(matcher, next);
301 : 0 : return 0;
302 : : }
303 : :
304 : 0 : prev_ft = tbl->ft;
305 [ # # ]: 0 : LIST_FOREACH(tmp_matcher, &tbl->head, next) {
306 [ # # ]: 0 : if (tmp_matcher == matcher)
307 : : break;
308 : :
309 : 0 : prev_ft = tmp_matcher->end_ft;
310 : : }
311 : :
312 : 0 : next = matcher->next.le_next;
313 : :
314 [ # # ]: 0 : LIST_REMOVE(matcher, next);
315 : :
316 [ # # ]: 0 : if (next) {
317 : : /* Connect previous end FT to next RTC */
318 : 0 : ret = mlx5dr_table_ft_set_next_rtc(prev_ft,
319 : : tbl->fw_ft_type,
320 : : next->match_ste.rtc_0,
321 : : next->match_ste.rtc_1);
322 [ # # ]: 0 : if (ret) {
323 : 0 : DR_LOG(ERR, "Fatal: failed to disconnect matcher");
324 : 0 : return ret;
325 : : }
326 : : } else {
327 : 0 : ret = mlx5dr_table_connect_to_miss_table(tbl, tbl->default_miss.miss_tbl, true);
328 [ # # ]: 0 : if (ret) {
329 : 0 : DR_LOG(ERR, "Fatal: failed to disconnect last matcher");
330 : 0 : return ret;
331 : : }
332 : : }
333 : :
334 : 0 : ret = mlx5dr_matcher_shared_update_local_ft(tbl);
335 [ # # ]: 0 : if (ret) {
336 : 0 : DR_LOG(ERR, "Fatal: failed to update local_ft in shared table");
337 : 0 : return ret;
338 : : }
339 : :
340 : : /* Removing first matcher, update connected miss tables if exists */
341 [ # # ]: 0 : if (prev_ft == tbl->ft) {
342 : 0 : ret = mlx5dr_table_update_connected_miss_tables(tbl);
343 [ # # ]: 0 : if (ret) {
344 : 0 : DR_LOG(ERR, "Fatal error, failed to update connected miss table");
345 : 0 : return ret;
346 : : }
347 : : }
348 : :
349 : 0 : ret = mlx5dr_table_ft_set_default_next_ft(tbl, prev_ft);
350 [ # # ]: 0 : if (ret) {
351 : 0 : DR_LOG(ERR, "Fatal error, failed to restore matcher ft default miss");
352 : 0 : return ret;
353 : : }
354 : :
355 : : /* Failure to restore/modify FW results in a critical, unrecoverable error.
356 : : * Error handling is not applicable in this fatal scenario.
357 : : */
358 : : return 0;
359 : : }
360 : :
361 : 0 : static bool mlx5dr_matcher_supp_fw_wqe(struct mlx5dr_matcher *matcher)
362 : : {
363 : 0 : struct mlx5dr_cmd_query_caps *caps = matcher->tbl->ctx->caps;
364 : :
365 [ # # ]: 0 : if (matcher->flags & MLX5DR_MATCHER_FLAGS_HASH_DEFINER) {
366 [ # # ]: 0 : if (matcher->hash_definer->type == MLX5DR_DEFINER_TYPE_MATCH &&
367 [ # # ]: 0 : !IS_BIT_SET(caps->supp_ste_format_gen_wqe, MLX5_IFC_RTC_STE_FORMAT_8DW)) {
368 : 0 : DR_LOG(ERR, "Gen WQE MATCH format not supported");
369 : 0 : return false;
370 : : }
371 : :
372 [ # # ]: 0 : if (matcher->hash_definer->type == MLX5DR_DEFINER_TYPE_JUMBO) {
373 : 0 : DR_LOG(ERR, "Gen WQE JUMBO format not supported");
374 : 0 : return false;
375 : : }
376 : : }
377 : :
378 [ # # ]: 0 : if (matcher->attr.insert_mode != MLX5DR_MATCHER_INSERT_BY_HASH ||
379 : : matcher->attr.distribute_mode != MLX5DR_MATCHER_DISTRIBUTE_BY_HASH) {
380 : 0 : DR_LOG(ERR, "Gen WQE must be inserted and distribute by hash");
381 : 0 : return false;
382 : : }
383 : :
384 [ # # ]: 0 : if ((matcher->flags & MLX5DR_MATCHER_FLAGS_RANGE_DEFINER) &&
385 [ # # ]: 0 : !IS_BIT_SET(caps->supp_ste_format_gen_wqe, MLX5_IFC_RTC_STE_FORMAT_RANGE)) {
386 : 0 : DR_LOG(INFO, "Extended match gen wqe RANGE format not supported");
387 : 0 : return false;
388 : : }
389 : :
390 [ # # ]: 0 : if (!(caps->supp_type_gen_wqe & MLX5_GENERATE_WQE_TYPE_FLOW_UPDATE)) {
391 : 0 : DR_LOG(ERR, "Gen WQE command not supporting GTA");
392 : 0 : return false;
393 : : }
394 : :
395 [ # # ]: 0 : if (!caps->rtc_max_hash_def_gen_wqe) {
396 : 0 : DR_LOG(ERR, "Hash definer not supported");
397 : 0 : return false;
398 : : }
399 : :
400 : : return true;
401 : : }
402 : :
403 : : static void mlx5dr_matcher_fixup_rtc_sizes_by_tbl(enum mlx5dr_table_type tbl_type,
404 : : bool is_mirror,
405 : : struct mlx5dr_cmd_rtc_create_attr *rtc_attr)
406 : : {
407 : 0 : if (!is_mirror) {
408 [ # # ]: 0 : if (tbl_type == MLX5DR_TABLE_TYPE_FDB_TX) {
409 : : /* rtc_0 for TX flow is minimal */
410 : 0 : rtc_attr->log_size = 0;
411 : 0 : rtc_attr->log_depth = 0;
412 : : }
413 : : } else {
414 [ # # ]: 0 : if (tbl_type == MLX5DR_TABLE_TYPE_FDB_RX) {
415 : : /* rtc_1 for RX flow is minimal */
416 : 0 : rtc_attr->log_size = 0;
417 : 0 : rtc_attr->log_depth = 0;
418 : : }
419 : : }
420 : : }
421 : :
422 : 0 : static void mlx5dr_matcher_set_rtc_attr_sz(struct mlx5dr_matcher *matcher,
423 : : struct mlx5dr_cmd_rtc_create_attr *rtc_attr,
424 : : enum mlx5dr_matcher_rtc_type rtc_type,
425 : : bool is_mirror)
426 : : {
427 : 0 : enum mlx5dr_matcher_flow_src flow_src = matcher->attr.optimize_flow_src;
428 : : bool is_match_rtc = rtc_type == DR_MATCHER_RTC_TYPE_MATCH;
429 : : struct mlx5dr_pool_chunk *ste = &matcher->action_ste.ste;
430 : :
431 [ # # ]: 0 : if ((flow_src == MLX5DR_MATCHER_FLOW_SRC_VPORT && !is_mirror) ||
432 [ # # ]: 0 : (flow_src == MLX5DR_MATCHER_FLOW_SRC_WIRE && is_mirror)) {
433 : : /* Optimize FDB RTC */
434 : 0 : rtc_attr->log_size = 0;
435 : 0 : rtc_attr->log_depth = 0;
436 : : } else {
437 : : /* Keep original values */
438 [ # # ]: 0 : rtc_attr->log_size = is_match_rtc ? matcher->attr.table.sz_row_log : ste->order;
439 [ # # ]: 0 : rtc_attr->log_depth = is_match_rtc ? matcher->attr.table.sz_col_log : 0;
440 : : }
441 : :
442 : : /* set values according to tbl->type */
443 [ # # ]: 0 : mlx5dr_matcher_fixup_rtc_sizes_by_tbl(matcher->tbl->type,
444 : : is_mirror,
445 : : rtc_attr);
446 : 0 : }
447 : :
448 : 0 : int mlx5dr_matcher_create_aliased_obj(struct mlx5dr_context *ctx,
449 : : struct ibv_context *ibv_owner,
450 : : struct ibv_context *ibv_allowed,
451 : : uint16_t vhca_id_to_be_accessed,
452 : : uint32_t aliased_object_id,
453 : : uint16_t object_type,
454 : : struct mlx5dr_devx_obj **obj)
455 : : {
456 : 0 : struct mlx5dr_cmd_allow_other_vhca_access_attr allow_attr = {0};
457 [ # # ]: 0 : struct mlx5dr_cmd_alias_obj_create_attr alias_attr = {0};
458 : : char key[ACCESS_KEY_LEN];
459 : : int ret;
460 : : int i;
461 : :
462 [ # # ]: 0 : if (!mlx5dr_context_shared_gvmi_used(ctx))
463 : : return 0;
464 : :
465 [ # # ]: 0 : for (i = 0; i < ACCESS_KEY_LEN; i++)
466 : 0 : key[i] = rte_rand() & 0xFF;
467 : :
468 : : memcpy(allow_attr.access_key, key, ACCESS_KEY_LEN);
469 : 0 : allow_attr.obj_type = object_type;
470 : 0 : allow_attr.obj_id = aliased_object_id;
471 : :
472 : 0 : ret = mlx5dr_cmd_allow_other_vhca_access(ibv_owner, &allow_attr);
473 [ # # ]: 0 : if (ret) {
474 : 0 : DR_LOG(ERR, "Failed to allow RTC to be aliased");
475 : 0 : return ret;
476 : : }
477 : :
478 : : memcpy(alias_attr.access_key, key, ACCESS_KEY_LEN);
479 : 0 : alias_attr.obj_id = aliased_object_id;
480 : 0 : alias_attr.obj_type = object_type;
481 : 0 : alias_attr.vhca_id = vhca_id_to_be_accessed;
482 : 0 : *obj = mlx5dr_cmd_alias_obj_create(ibv_allowed, &alias_attr);
483 [ # # ]: 0 : if (!*obj) {
484 : 0 : DR_LOG(ERR, "Failed to create alias object");
485 : 0 : return rte_errno;
486 : : }
487 : :
488 : : return 0;
489 : : }
490 : :
491 : 0 : static int mlx5dr_matcher_create_rtc(struct mlx5dr_matcher *matcher,
492 : : enum mlx5dr_matcher_rtc_type rtc_type)
493 : : {
494 : : struct mlx5dr_matcher_attr *attr = &matcher->attr;
495 : 0 : struct mlx5dr_cmd_rtc_create_attr rtc_attr = {0};
496 : 0 : struct mlx5dr_match_template *mt = matcher->mt;
497 : 0 : struct mlx5dr_context *ctx = matcher->tbl->ctx;
498 : : struct mlx5dr_action_default_stc *default_stc;
499 : : struct mlx5dr_table *tbl = matcher->tbl;
500 : : struct mlx5dr_devx_obj **rtc_0, **rtc_1;
501 : : struct mlx5dr_pool *ste_pool, *stc_pool;
502 : : struct mlx5dr_devx_obj *devx_obj;
503 : : struct mlx5dr_pool_chunk *ste;
504 : : int ret;
505 : :
506 [ # # # ]: 0 : switch (rtc_type) {
507 : 0 : case DR_MATCHER_RTC_TYPE_MATCH:
508 : 0 : rtc_0 = &matcher->match_ste.rtc_0;
509 : 0 : rtc_1 = &matcher->match_ste.rtc_1;
510 : 0 : ste_pool = matcher->match_ste.pool;
511 : 0 : ste = &matcher->match_ste.ste;
512 [ # # ]: 0 : ste->order = attr->table.sz_col_log + attr->table.sz_row_log;
513 : :
514 : : /* Add additional rows due to additional range STE */
515 [ # # ]: 0 : if (mlx5dr_matcher_mt_is_range(mt))
516 : 0 : ste->order++;
517 : :
518 : 0 : rtc_attr.log_size = attr->table.sz_row_log;
519 [ # # ]: 0 : rtc_attr.log_depth = attr->table.sz_col_log;
520 [ # # ]: 0 : rtc_attr.is_frst_jumbo = mlx5dr_matcher_mt_is_jumbo(mt);
521 [ # # ]: 0 : rtc_attr.is_scnd_range = mlx5dr_matcher_mt_is_range(mt);
522 : 0 : rtc_attr.is_compare = mlx5dr_matcher_is_compare(matcher);
523 : 0 : rtc_attr.miss_ft_id = matcher->end_ft->id;
524 : :
525 [ # # ]: 0 : if (attr->insert_mode == MLX5DR_MATCHER_INSERT_BY_HASH) {
526 : : /* The usual Hash Table */
527 : : rtc_attr.update_index_mode = MLX5_IFC_RTC_STE_UPDATE_MODE_BY_HASH;
528 : :
529 [ # # ]: 0 : if (matcher->hash_definer) {
530 : : /* Specify definer_id_0 is used for hashing */
531 : 0 : rtc_attr.fw_gen_wqe = true;
532 : 0 : rtc_attr.num_hash_definer = 1;
533 : 0 : rtc_attr.match_definer_0 =
534 : 0 : mlx5dr_definer_get_id(matcher->hash_definer);
535 [ # # ]: 0 : } else if (mlx5dr_matcher_is_compare(matcher)) {
536 : 0 : rtc_attr.match_definer_0 = ctx->caps->trivial_match_definer;
537 : 0 : rtc_attr.fw_gen_wqe = true;
538 : 0 : rtc_attr.num_hash_definer = 1;
539 : : } else {
540 : : /* The first mt is used since all share the same definer */
541 : 0 : rtc_attr.match_definer_0 = mlx5dr_definer_get_id(mt->definer);
542 : :
543 : : /* This is tricky, instead of passing two definers for
544 : : * match and range, we specify that this RTC uses a hash
545 : : * definer, this will allow us to use any range definer
546 : : * since only first STE is used for hashing anyways.
547 : : */
548 [ # # ]: 0 : if (matcher->flags & MLX5DR_MATCHER_FLAGS_RANGE_DEFINER) {
549 : 0 : rtc_attr.fw_gen_wqe = true;
550 : 0 : rtc_attr.num_hash_definer = 1;
551 : : }
552 : : }
553 [ # # ]: 0 : } else if (attr->insert_mode == MLX5DR_MATCHER_INSERT_BY_INDEX) {
554 : 0 : rtc_attr.update_index_mode = MLX5_IFC_RTC_STE_UPDATE_MODE_BY_OFFSET;
555 : :
556 [ # # ]: 0 : if (attr->distribute_mode == MLX5DR_MATCHER_DISTRIBUTE_BY_HASH) {
557 : : /* Hash Split Table */
558 [ # # ]: 0 : if (mlx5dr_matcher_is_always_hit(matcher))
559 : 0 : rtc_attr.num_hash_definer = 1;
560 : :
561 : : rtc_attr.access_index_mode = MLX5_IFC_RTC_STE_ACCESS_MODE_BY_HASH;
562 : 0 : rtc_attr.match_definer_0 = mlx5dr_definer_get_id(mt->definer);
563 [ # # ]: 0 : } else if (attr->distribute_mode == MLX5DR_MATCHER_DISTRIBUTE_BY_LINEAR) {
564 : : /* Linear Lookup Table */
565 : 0 : rtc_attr.num_hash_definer = 1;
566 : 0 : rtc_attr.access_index_mode = MLX5_IFC_RTC_STE_ACCESS_MODE_LINEAR;
567 : 0 : rtc_attr.match_definer_0 = ctx->caps->linear_match_definer;
568 : : }
569 : : }
570 : :
571 : : /* Match pool requires implicit allocation */
572 : 0 : ret = mlx5dr_pool_chunk_alloc(ste_pool, ste);
573 [ # # ]: 0 : if (ret) {
574 : 0 : DR_LOG(ERR, "Failed to allocate STE for %s RTC",
575 : : mlx5dr_matcher_rtc_type_to_str(rtc_type));
576 : 0 : return ret;
577 : : }
578 : : break;
579 : :
580 : 0 : case DR_MATCHER_RTC_TYPE_STE_ARRAY:
581 : 0 : rtc_0 = &matcher->action_ste.rtc_0;
582 : 0 : rtc_1 = &matcher->action_ste.rtc_1;
583 : 0 : ste_pool = matcher->action_ste.pool;
584 : 0 : ste = &matcher->action_ste.ste;
585 [ # # ]: 0 : ste->order = rte_log2_u32(matcher->action_ste.max_stes) +
586 : 0 : attr->table.sz_row_log;
587 : 0 : rtc_attr.log_size = ste->order;
588 : : rtc_attr.log_depth = 0;
589 : 0 : rtc_attr.update_index_mode = MLX5_IFC_RTC_STE_UPDATE_MODE_BY_OFFSET;
590 : : /* The action STEs use the default always hit definer */
591 : 0 : rtc_attr.match_definer_0 = ctx->caps->trivial_match_definer;
592 : : rtc_attr.is_frst_jumbo = false;
593 : : rtc_attr.miss_ft_id = 0;
594 : 0 : break;
595 : :
596 : 0 : default:
597 : 0 : DR_LOG(ERR, "HWS Invalid RTC type");
598 : 0 : rte_errno = EINVAL;
599 : 0 : return rte_errno;
600 : : }
601 : :
602 : : devx_obj = mlx5dr_pool_chunk_get_base_devx_obj(ste_pool, ste);
603 : :
604 : 0 : rtc_attr.pd = ctx->pd_num;
605 : 0 : rtc_attr.ste_base = devx_obj->id;
606 : 0 : rtc_attr.ste_offset = ste->offset;
607 : 0 : rtc_attr.reparse_mode = mlx5dr_context_get_reparse_mode(ctx);
608 : 0 : rtc_attr.table_type = mlx5dr_table_get_res_fw_ft_type(tbl->type, false);
609 : 0 : mlx5dr_matcher_set_rtc_attr_sz(matcher, &rtc_attr, rtc_type, false);
610 : :
611 : : /* STC is a single resource (devx_obj), use any STC for the ID */
612 : 0 : stc_pool = ctx->stc_pool[tbl->type];
613 : 0 : default_stc = ctx->common_res[tbl->type].default_stc;
614 : : devx_obj = mlx5dr_pool_chunk_get_base_devx_obj(stc_pool, &default_stc->default_hit);
615 : 0 : rtc_attr.stc_base = devx_obj->id;
616 : :
617 : 0 : *rtc_0 = mlx5dr_cmd_rtc_create(ctx->ibv_ctx, &rtc_attr);
618 [ # # ]: 0 : if (!*rtc_0) {
619 : 0 : DR_LOG(ERR, "Failed to create matcher RTC of type %s",
620 : : mlx5dr_matcher_rtc_type_to_str(rtc_type));
621 : 0 : goto free_ste;
622 : : }
623 : :
624 [ # # ]: 0 : if (mlx5dr_table_fdb_no_unified(tbl->type)) {
625 : : devx_obj = mlx5dr_pool_chunk_get_base_devx_obj_mirror(ste_pool, ste);
626 : 0 : rtc_attr.ste_base = devx_obj->id;
627 : 0 : rtc_attr.table_type = mlx5dr_table_get_res_fw_ft_type(tbl->type, true);
628 : :
629 : : devx_obj = mlx5dr_pool_chunk_get_base_devx_obj_mirror(stc_pool, &default_stc->default_hit);
630 : 0 : rtc_attr.stc_base = devx_obj->id;
631 : 0 : mlx5dr_matcher_set_rtc_attr_sz(matcher, &rtc_attr, rtc_type, true);
632 : :
633 : 0 : *rtc_1 = mlx5dr_cmd_rtc_create(ctx->ibv_ctx, &rtc_attr);
634 [ # # ]: 0 : if (!*rtc_1) {
635 : 0 : DR_LOG(ERR, "Failed to create peer matcher RTC of type %s",
636 : : mlx5dr_matcher_rtc_type_to_str(rtc_type));
637 : 0 : goto destroy_rtc_0;
638 : : }
639 [ # # ]: 0 : } else if (tbl->type == MLX5DR_TABLE_TYPE_FDB_UNIFIED) {
640 : : /* Unified domain has 2 identical RTC's, allow connecting from other domains */
641 : 0 : *rtc_1 = *rtc_0;
642 : : }
643 : :
644 : : return 0;
645 : :
646 : : destroy_rtc_0:
647 : 0 : mlx5dr_cmd_destroy_obj(*rtc_0);
648 : 0 : free_ste:
649 [ # # ]: 0 : if (rtc_type == DR_MATCHER_RTC_TYPE_MATCH)
650 : 0 : mlx5dr_pool_chunk_free(ste_pool, ste);
651 : 0 : return rte_errno;
652 : : }
653 : :
654 : 0 : static void mlx5dr_matcher_destroy_rtc(struct mlx5dr_matcher *matcher,
655 : : enum mlx5dr_matcher_rtc_type rtc_type)
656 : : {
657 : 0 : struct mlx5dr_table *tbl = matcher->tbl;
658 : : struct mlx5dr_devx_obj *rtc_0, *rtc_1;
659 : : struct mlx5dr_pool_chunk *ste;
660 : : struct mlx5dr_pool *ste_pool;
661 : :
662 [ # # # ]: 0 : switch (rtc_type) {
663 : 0 : case DR_MATCHER_RTC_TYPE_MATCH:
664 : 0 : rtc_0 = matcher->match_ste.rtc_0;
665 : 0 : rtc_1 = matcher->match_ste.rtc_1;
666 : 0 : ste_pool = matcher->match_ste.pool;
667 : 0 : ste = &matcher->match_ste.ste;
668 : 0 : break;
669 : 0 : case DR_MATCHER_RTC_TYPE_STE_ARRAY:
670 : 0 : rtc_0 = matcher->action_ste.rtc_0;
671 : 0 : rtc_1 = matcher->action_ste.rtc_1;
672 : 0 : ste_pool = matcher->action_ste.pool;
673 : 0 : ste = &matcher->action_ste.ste;
674 : 0 : break;
675 : : default:
676 : : return;
677 : : }
678 : :
679 [ # # ]: 0 : if (mlx5dr_table_fdb_no_unified(tbl->type))
680 : 0 : mlx5dr_cmd_destroy_obj(rtc_1);
681 : :
682 : 0 : mlx5dr_cmd_destroy_obj(rtc_0);
683 [ # # ]: 0 : if (rtc_type == DR_MATCHER_RTC_TYPE_MATCH)
684 : 0 : mlx5dr_pool_chunk_free(ste_pool, ste);
685 : : }
686 : :
687 : : static int
688 : 0 : mlx5dr_matcher_check_attr_sz(struct mlx5dr_cmd_query_caps *caps,
689 : : struct mlx5dr_matcher_attr *attr)
690 : : {
691 [ # # ]: 0 : if (attr->table.sz_col_log > caps->rtc_log_depth_max) {
692 : 0 : DR_LOG(ERR, "Matcher depth exceeds limit %d", caps->rtc_log_depth_max);
693 : 0 : goto not_supported;
694 : : }
695 : :
696 [ # # ]: 0 : if (attr->table.sz_col_log + attr->table.sz_row_log > caps->ste_alloc_log_max) {
697 : 0 : DR_LOG(ERR, "Total matcher size exceeds limit %d", caps->ste_alloc_log_max);
698 : 0 : goto not_supported;
699 : : }
700 : :
701 [ # # ]: 0 : if (attr->table.sz_col_log + attr->table.sz_row_log < caps->ste_alloc_log_gran) {
702 : 0 : DR_LOG(ERR, "Total matcher size below limit %d", caps->ste_alloc_log_gran);
703 : 0 : goto not_supported;
704 : : }
705 : :
706 : : return 0;
707 : :
708 : 0 : not_supported:
709 : 0 : rte_errno = EOPNOTSUPP;
710 : 0 : return rte_errno;
711 : : }
712 : :
713 : 0 : static void mlx5dr_matcher_set_pool_attr(struct mlx5dr_pool_attr *attr,
714 : : struct mlx5dr_matcher *matcher)
715 : : {
716 [ # # # ]: 0 : switch (matcher->attr.optimize_flow_src) {
717 : 0 : case MLX5DR_MATCHER_FLOW_SRC_VPORT:
718 : 0 : attr->opt_type = MLX5DR_POOL_OPTIMIZE_ORIG;
719 : 0 : break;
720 : 0 : case MLX5DR_MATCHER_FLOW_SRC_WIRE:
721 : 0 : attr->opt_type = MLX5DR_POOL_OPTIMIZE_MIRROR;
722 : 0 : break;
723 : : default:
724 : : break;
725 : : }
726 : :
727 : : /* Now set attr according to the table type */
728 [ # # ]: 0 : if (attr->opt_type == MLX5DR_POOL_OPTIMIZE_NONE)
729 : 0 : mlx5dr_context_set_pool_tbl_attr(attr, matcher->tbl->type);
730 : 0 : }
731 : :
732 : 0 : static int mlx5dr_matcher_check_and_process_at(struct mlx5dr_matcher *matcher,
733 : : struct mlx5dr_action_template *at)
734 : : {
735 : : bool valid;
736 : : int ret;
737 : :
738 [ # # ]: 0 : if (!(at->flags & MLX5DR_ACTION_TEMPLATE_FLAG_RELAXED_ORDER)) {
739 : : /* Check if actions combinabtion is valid,
740 : : * in the case of not relaxed actions order.
741 : : */
742 : 0 : valid = mlx5dr_action_check_combo(at->action_type_arr, matcher->tbl->type);
743 [ # # ]: 0 : if (!valid) {
744 : 0 : DR_LOG(ERR, "Invalid combination in action template");
745 : 0 : rte_errno = EINVAL;
746 : 0 : return rte_errno;
747 : : }
748 : : }
749 : :
750 : : /* Process action template to setters */
751 : 0 : ret = mlx5dr_action_template_process(at);
752 [ # # ]: 0 : if (ret) {
753 : 0 : DR_LOG(ERR, "Failed to process action template");
754 : 0 : return ret;
755 : : }
756 : :
757 : : return 0;
758 : : }
759 : :
760 : : static int
761 : 0 : mlx5dr_matcher_resize_init(struct mlx5dr_matcher *src_matcher)
762 : : {
763 : : struct mlx5dr_matcher_resize_data *resize_data;
764 : :
765 : : resize_data = simple_calloc(1, sizeof(*resize_data));
766 [ # # ]: 0 : if (!resize_data) {
767 : 0 : rte_errno = ENOMEM;
768 : 0 : return rte_errno;
769 : : }
770 : :
771 : 0 : resize_data->max_stes = src_matcher->action_ste.max_stes;
772 : 0 : resize_data->ste = src_matcher->action_ste.ste;
773 : 0 : resize_data->stc = src_matcher->action_ste.stc;
774 : 0 : resize_data->action_ste_rtc_0 = src_matcher->action_ste.rtc_0;
775 : 0 : resize_data->action_ste_rtc_1 = src_matcher->action_ste.rtc_1;
776 : 0 : resize_data->action_ste_pool = src_matcher->action_ste.max_stes ?
777 [ # # ]: 0 : src_matcher->action_ste.pool :
778 : : NULL;
779 : :
780 : : /* Place the new resized matcher on the dst matcher's list */
781 [ # # ]: 0 : LIST_INSERT_HEAD(&src_matcher->resize_dst->resize_data,
782 : : resize_data, next);
783 : :
784 : : /* Move all the previous resized matchers to the dst matcher's list */
785 [ # # ]: 0 : while (!LIST_EMPTY(&src_matcher->resize_data)) {
786 : : resize_data = LIST_FIRST(&src_matcher->resize_data);
787 [ # # ]: 0 : LIST_REMOVE(resize_data, next);
788 [ # # ]: 0 : LIST_INSERT_HEAD(&src_matcher->resize_dst->resize_data,
789 : : resize_data, next);
790 : : }
791 : :
792 : : return 0;
793 : : }
794 : :
795 : : static void
796 [ # # ]: 0 : mlx5dr_matcher_resize_uninit(struct mlx5dr_matcher *matcher)
797 : : {
798 : : struct mlx5dr_matcher_resize_data *resize_data;
799 : :
800 [ # # ]: 0 : if (!mlx5dr_matcher_is_resizable(matcher))
801 : : return;
802 : :
803 [ # # ]: 0 : while (!LIST_EMPTY(&matcher->resize_data)) {
804 : : resize_data = LIST_FIRST(&matcher->resize_data);
805 [ # # ]: 0 : LIST_REMOVE(resize_data, next);
806 : :
807 [ # # ]: 0 : if (resize_data->max_stes) {
808 : 0 : mlx5dr_action_free_single_stc(matcher->tbl->ctx,
809 : 0 : matcher->tbl->type,
810 : : &resize_data->stc);
811 : :
812 [ # # ]: 0 : if (matcher->tbl->type == MLX5DR_TABLE_TYPE_FDB)
813 : 0 : mlx5dr_cmd_destroy_obj(resize_data->action_ste_rtc_1);
814 : 0 : mlx5dr_cmd_destroy_obj(resize_data->action_ste_rtc_0);
815 [ # # ]: 0 : if (resize_data->action_ste_pool)
816 : 0 : mlx5dr_pool_destroy(resize_data->action_ste_pool);
817 : : }
818 : :
819 : : simple_free(resize_data);
820 : : }
821 : : }
822 : :
823 : 0 : static int mlx5dr_matcher_bind_at(struct mlx5dr_matcher *matcher)
824 : : {
825 [ # # ]: 0 : bool is_jumbo = mlx5dr_matcher_mt_is_jumbo(matcher->mt);
826 : 0 : struct mlx5dr_cmd_stc_modify_attr stc_attr = {0};
827 : 0 : struct mlx5dr_table *tbl = matcher->tbl;
828 : 0 : struct mlx5dr_pool_attr pool_attr = {0};
829 : 0 : struct mlx5dr_context *ctx = tbl->ctx;
830 : : uint32_t required_stes;
831 : : int i, ret;
832 : :
833 [ # # ]: 0 : if (matcher->flags & MLX5DR_MATCHER_FLAGS_COLLISION)
834 : : return 0;
835 : :
836 [ # # # # ]: 0 : if (matcher->attr.max_num_of_at_attach &&
837 : : mlx5dr_matcher_req_fw_wqe(matcher)) {
838 : 0 : DR_LOG(ERR, "FW extended matcher doesn't support additional at");
839 : 0 : rte_errno = ENOTSUP;
840 : 0 : return rte_errno;
841 : : }
842 : :
843 [ # # ]: 0 : for (i = 0; i < matcher->num_of_at; i++) {
844 : 0 : struct mlx5dr_action_template *at = &matcher->at[i];
845 : :
846 : 0 : ret = mlx5dr_matcher_check_and_process_at(matcher, at);
847 [ # # ]: 0 : if (ret) {
848 : 0 : DR_LOG(ERR, "Invalid at %d", i);
849 : 0 : return rte_errno;
850 : : }
851 : :
852 [ # # # # ]: 0 : required_stes = at->num_of_action_stes - (!is_jumbo || at->only_term);
853 : 0 : matcher->action_ste.max_stes = RTE_MAX(matcher->action_ste.max_stes, required_stes);
854 : :
855 : : /* Future: Optimize reparse */
856 : : }
857 : :
858 : : /* There are no additioanl STEs required for matcher */
859 [ # # ]: 0 : if (!matcher->action_ste.max_stes)
860 : : return 0;
861 : :
862 [ # # ]: 0 : if (mlx5dr_matcher_req_fw_wqe(matcher)) {
863 : 0 : DR_LOG(ERR, "FW extended matcher cannot be binded to complex at");
864 : 0 : rte_errno = ENOTSUP;
865 : 0 : return rte_errno;
866 : : }
867 : :
868 : : /* Allocate action STE mempool */
869 : 0 : pool_attr.table_type = tbl->type;
870 : 0 : pool_attr.pool_type = MLX5DR_POOL_TYPE_STE;
871 : 0 : pool_attr.flags = MLX5DR_POOL_FLAGS_FOR_STE_ACTION_POOL;
872 : 0 : pool_attr.alloc_log_sz = rte_log2_u32(matcher->action_ste.max_stes) +
873 : 0 : matcher->attr.table.sz_row_log;
874 : 0 : mlx5dr_matcher_set_pool_attr(&pool_attr, matcher);
875 : 0 : matcher->action_ste.pool = mlx5dr_pool_create(ctx, &pool_attr);
876 [ # # ]: 0 : if (!matcher->action_ste.pool) {
877 : 0 : DR_LOG(ERR, "Failed to create action ste pool");
878 : 0 : return rte_errno;
879 : : }
880 : :
881 : : /* Allocate action RTC */
882 : 0 : ret = mlx5dr_matcher_create_rtc(matcher, DR_MATCHER_RTC_TYPE_STE_ARRAY);
883 [ # # ]: 0 : if (ret) {
884 : 0 : DR_LOG(ERR, "Failed to create action RTC");
885 : 0 : goto free_ste_pool;
886 : : }
887 : :
888 : : /* Allocate STC for jumps to STE */
889 : 0 : stc_attr.action_offset = MLX5DR_ACTION_OFFSET_HIT;
890 : 0 : stc_attr.action_type = MLX5_IFC_STC_ACTION_TYPE_JUMP_TO_STE_TABLE;
891 : 0 : stc_attr.reparse_mode = MLX5_IFC_STC_REPARSE_IGNORE;
892 : 0 : stc_attr.ste_table.ste = matcher->action_ste.ste;
893 : 0 : stc_attr.ste_table.ste_pool = matcher->action_ste.pool;
894 : 0 : stc_attr.ste_table.match_definer_id = ctx->caps->trivial_match_definer;
895 : :
896 : 0 : ret = mlx5dr_action_alloc_single_stc(ctx, &stc_attr, tbl->type,
897 : : &matcher->action_ste.stc);
898 [ # # ]: 0 : if (ret) {
899 : 0 : DR_LOG(ERR, "Failed to create action jump to table STC");
900 : 0 : goto free_rtc;
901 : : }
902 : :
903 : : return 0;
904 : :
905 : : free_rtc:
906 : 0 : mlx5dr_matcher_destroy_rtc(matcher, DR_MATCHER_RTC_TYPE_STE_ARRAY);
907 : 0 : free_ste_pool:
908 : 0 : mlx5dr_pool_destroy(matcher->action_ste.pool);
909 : 0 : return rte_errno;
910 : : }
911 : :
912 : 0 : static void mlx5dr_matcher_unbind_at(struct mlx5dr_matcher *matcher)
913 : : {
914 : 0 : struct mlx5dr_table *tbl = matcher->tbl;
915 : :
916 [ # # ]: 0 : if (!matcher->action_ste.max_stes ||
917 [ # # # # ]: 0 : matcher->flags & MLX5DR_MATCHER_FLAGS_COLLISION ||
918 : : mlx5dr_matcher_is_in_resize(matcher))
919 : : return;
920 : :
921 : 0 : mlx5dr_action_free_single_stc(tbl->ctx, tbl->type, &matcher->action_ste.stc);
922 : 0 : mlx5dr_matcher_destroy_rtc(matcher, DR_MATCHER_RTC_TYPE_STE_ARRAY);
923 : 0 : mlx5dr_pool_destroy(matcher->action_ste.pool);
924 : : }
925 : :
926 : 0 : static int mlx5dr_matcher_bind_mt(struct mlx5dr_matcher *matcher)
927 : : {
928 : 0 : struct mlx5dr_context *ctx = matcher->tbl->ctx;
929 : 0 : struct mlx5dr_pool_attr pool_attr = {0};
930 : : int ret;
931 : :
932 : : /* Calculate match, range and hash definers */
933 : 0 : ret = mlx5dr_definer_matcher_init(ctx, matcher);
934 [ # # ]: 0 : if (ret) {
935 : 0 : DR_LOG(DEBUG, "Failed to set matcher templates with match definers");
936 : 0 : return ret;
937 : : }
938 : :
939 [ # # # # ]: 0 : if (mlx5dr_matcher_req_fw_wqe(matcher) &&
940 : 0 : !mlx5dr_matcher_supp_fw_wqe(matcher)) {
941 : 0 : DR_LOG(ERR, "Matcher requires FW WQE which is not supported");
942 : 0 : rte_errno = ENOTSUP;
943 : : ret = rte_errno;
944 : 0 : goto uninit_match_definer;
945 : : }
946 : :
947 : : /* Create an STE pool per matcher*/
948 : 0 : pool_attr.table_type = matcher->tbl->type;
949 : 0 : pool_attr.pool_type = MLX5DR_POOL_TYPE_STE;
950 : 0 : pool_attr.flags = MLX5DR_POOL_FLAGS_FOR_MATCHER_STE_POOL;
951 : 0 : pool_attr.alloc_log_sz = matcher->attr.table.sz_col_log +
952 : 0 : matcher->attr.table.sz_row_log;
953 : : /* Add additional rows due to additional range STE */
954 [ # # ]: 0 : if (matcher->flags & MLX5DR_MATCHER_FLAGS_RANGE_DEFINER)
955 : 0 : pool_attr.alloc_log_sz++;
956 : 0 : mlx5dr_matcher_set_pool_attr(&pool_attr, matcher);
957 : :
958 : 0 : matcher->match_ste.pool = mlx5dr_pool_create(ctx, &pool_attr);
959 [ # # ]: 0 : if (!matcher->match_ste.pool) {
960 : 0 : DR_LOG(ERR, "Failed to allocate matcher STE pool");
961 : : ret = ENOTSUP;
962 : 0 : goto uninit_match_definer;
963 : : }
964 : :
965 : : return 0;
966 : :
967 : 0 : uninit_match_definer:
968 : 0 : mlx5dr_definer_matcher_uninit(matcher);
969 : 0 : return ret;
970 : : }
971 : :
972 : : static void mlx5dr_matcher_unbind_mt(struct mlx5dr_matcher *matcher)
973 : : {
974 : 0 : mlx5dr_pool_destroy(matcher->match_ste.pool);
975 : 0 : mlx5dr_definer_matcher_uninit(matcher);
976 : : }
977 : :
978 : : static int
979 : 0 : mlx5dr_matcher_validate_insert_mode(struct mlx5dr_cmd_query_caps *caps,
980 : : struct mlx5dr_matcher *matcher,
981 : : bool is_root)
982 : : {
983 : : struct mlx5dr_matcher_attr *attr = &matcher->attr;
984 : :
985 [ # # ]: 0 : if (is_root) {
986 [ # # ]: 0 : if (attr->mode != MLX5DR_MATCHER_RESOURCE_MODE_RULE) {
987 : 0 : DR_LOG(ERR, "Root matcher supports only rule resource mode");
988 : 0 : goto not_supported;
989 : : }
990 [ # # ]: 0 : if (attr->insert_mode != MLX5DR_MATCHER_INSERT_BY_HASH) {
991 : 0 : DR_LOG(ERR, "Root matcher supports only insert by hash mode");
992 : 0 : goto not_supported;
993 : : }
994 [ # # ]: 0 : if (attr->distribute_mode != MLX5DR_MATCHER_DISTRIBUTE_BY_HASH) {
995 : 0 : DR_LOG(ERR, "Root matcher supports only distribute by hash mode");
996 : 0 : goto not_supported;
997 : : }
998 [ # # ]: 0 : if (attr->optimize_flow_src) {
999 : 0 : DR_LOG(ERR, "Root matcher can't specify FDB direction");
1000 : 0 : goto not_supported;
1001 : : }
1002 : : }
1003 : :
1004 [ # # # ]: 0 : switch (attr->insert_mode) {
1005 : 0 : case MLX5DR_MATCHER_INSERT_BY_HASH:
1006 [ # # ]: 0 : if (matcher->attr.distribute_mode != MLX5DR_MATCHER_DISTRIBUTE_BY_HASH) {
1007 : 0 : DR_LOG(ERR, "Invalid matcher distribute mode");
1008 : 0 : goto not_supported;
1009 : : }
1010 : : break;
1011 : :
1012 : 0 : case MLX5DR_MATCHER_INSERT_BY_INDEX:
1013 [ # # ]: 0 : if (attr->table.sz_col_log) {
1014 : 0 : DR_LOG(ERR, "Matcher with INSERT_BY_INDEX supports only Nx1 table size");
1015 : 0 : goto not_supported;
1016 : : }
1017 : :
1018 [ # # ]: 0 : if (attr->distribute_mode == MLX5DR_MATCHER_DISTRIBUTE_BY_HASH) {
1019 : : /* Hash Split Table */
1020 [ # # ]: 0 : if (attr->match_mode == MLX5DR_MATCHER_MATCH_MODE_ALWAYS_HIT &&
1021 [ # # ]: 0 : !caps->rtc_hash_split_table) {
1022 : 0 : DR_LOG(ERR, "FW doesn't support insert by index and hash distribute");
1023 : 0 : goto not_supported;
1024 : : }
1025 : :
1026 [ # # ]: 0 : if (attr->match_mode == MLX5DR_MATCHER_MATCH_MODE_DEFAULT &&
1027 [ # # ]: 0 : !attr->isolated) {
1028 : 0 : DR_LOG(ERR, "STE array matcher supported only as an isolated matcher");
1029 : 0 : goto not_supported;
1030 : : }
1031 [ # # ]: 0 : } else if (attr->distribute_mode == MLX5DR_MATCHER_DISTRIBUTE_BY_LINEAR) {
1032 : : /* Linear Lookup Table */
1033 [ # # ]: 0 : if (!caps->rtc_linear_lookup_table ||
1034 [ # # ]: 0 : !IS_BIT_SET(caps->access_index_mode,
1035 : : MLX5_IFC_RTC_STE_ACCESS_MODE_LINEAR)) {
1036 : 0 : DR_LOG(ERR, "FW doesn't support insert by index and linear distribute");
1037 : 0 : goto not_supported;
1038 : : }
1039 : :
1040 [ # # ]: 0 : if (attr->table.sz_row_log > MLX5_IFC_RTC_LINEAR_LOOKUP_TBL_LOG_MAX) {
1041 : 0 : DR_LOG(ERR, "Matcher with linear distribute: rows exceed limit %d",
1042 : : MLX5_IFC_RTC_LINEAR_LOOKUP_TBL_LOG_MAX);
1043 : 0 : goto not_supported;
1044 : : }
1045 : :
1046 [ # # ]: 0 : if (attr->match_mode != MLX5DR_MATCHER_MATCH_MODE_ALWAYS_HIT) {
1047 : 0 : DR_LOG(ERR, "Linear lookup tables will always hit, given match mode is not supported %d\n",
1048 : : attr->match_mode);
1049 : 0 : goto not_supported;
1050 : : }
1051 : : } else {
1052 : 0 : DR_LOG(ERR, "Matcher has unsupported distribute mode");
1053 : 0 : goto not_supported;
1054 : : }
1055 : : break;
1056 : :
1057 : 0 : default:
1058 : 0 : DR_LOG(ERR, "Matcher has unsupported insert mode");
1059 : 0 : goto not_supported;
1060 : : }
1061 : :
1062 : : return 0;
1063 : :
1064 : 0 : not_supported:
1065 : 0 : rte_errno = EOPNOTSUPP;
1066 : 0 : return rte_errno;
1067 : : }
1068 : :
1069 : : static int
1070 : 0 : mlx5dr_matcher_process_attr(struct mlx5dr_cmd_query_caps *caps,
1071 : : struct mlx5dr_matcher *matcher,
1072 : : bool is_root)
1073 : : {
1074 : 0 : struct mlx5dr_matcher_attr *attr = &matcher->attr;
1075 : :
1076 [ # # ]: 0 : if (mlx5dr_matcher_validate_insert_mode(caps, matcher, is_root))
1077 : 0 : goto not_supported;
1078 : :
1079 [ # # ]: 0 : if (is_root) {
1080 [ # # ]: 0 : if (attr->optimize_flow_src) {
1081 : 0 : DR_LOG(ERR, "Root matcher can't specify FDB direction");
1082 : 0 : goto not_supported;
1083 : : }
1084 [ # # ]: 0 : if (attr->max_num_of_at_attach) {
1085 : 0 : DR_LOG(ERR, "Root matcher does not support at attaching");
1086 : 0 : goto not_supported;
1087 : : }
1088 [ # # ]: 0 : if (attr->resizable) {
1089 : 0 : DR_LOG(ERR, "Root matcher does not support resizing");
1090 : 0 : goto not_supported;
1091 : : }
1092 [ # # ]: 0 : if (attr->isolated) {
1093 : 0 : DR_LOG(ERR, "Root matcher can not be isolated");
1094 : 0 : goto not_supported;
1095 : : }
1096 : :
1097 : : return 0;
1098 : : }
1099 : :
1100 [ # # # # ]: 0 : if (!mlx5dr_table_is_fdb_any(matcher->tbl->type) && attr->optimize_flow_src) {
1101 : 0 : DR_LOG(ERR, "NIC domain doesn't support flow_src");
1102 : 0 : goto not_supported;
1103 : : }
1104 : :
1105 : : /* Convert number of rules to the required depth */
1106 [ # # ]: 0 : if (attr->mode == MLX5DR_MATCHER_RESOURCE_MODE_RULE &&
1107 [ # # ]: 0 : attr->insert_mode == MLX5DR_MATCHER_INSERT_BY_HASH)
1108 [ # # ]: 0 : attr->table.sz_col_log = mlx5dr_matcher_rules_to_tbl_depth(attr->rule.num_log);
1109 : :
1110 [ # # ]: 0 : if (attr->isolated) {
1111 [ # # ]: 0 : if (attr->insert_mode != MLX5DR_MATCHER_INSERT_BY_INDEX ||
1112 [ # # ]: 0 : attr->distribute_mode != MLX5DR_MATCHER_DISTRIBUTE_BY_HASH ||
1113 [ # # ]: 0 : attr->match_mode != MLX5DR_MATCHER_MATCH_MODE_DEFAULT) {
1114 : 0 : DR_LOG(ERR, "Isolated matcher only supported for STE array matcher");
1115 : 0 : goto not_supported;
1116 : : }
1117 : :
1118 : : /* We reach here only in case of STE array */
1119 : 0 : matcher->flags |= MLX5DR_MATCHER_FLAGS_STE_ARRAY;
1120 : : }
1121 : :
1122 [ # # ]: 0 : matcher->flags |= attr->resizable ? MLX5DR_MATCHER_FLAGS_RESIZABLE : 0;
1123 : :
1124 : 0 : return mlx5dr_matcher_check_attr_sz(caps, attr);
1125 : :
1126 : 0 : not_supported:
1127 : 0 : rte_errno = EOPNOTSUPP;
1128 : 0 : return rte_errno;
1129 : : }
1130 : :
1131 : 0 : static int mlx5dr_matcher_create_and_connect(struct mlx5dr_matcher *matcher)
1132 : : {
1133 : : int ret;
1134 : :
1135 : : /* Select and create the definers for current matcher */
1136 : 0 : ret = mlx5dr_matcher_bind_mt(matcher);
1137 [ # # ]: 0 : if (ret)
1138 : : return ret;
1139 : :
1140 : : /* Calculate and verify action combination */
1141 : 0 : ret = mlx5dr_matcher_bind_at(matcher);
1142 [ # # ]: 0 : if (ret)
1143 : 0 : goto unbind_mt;
1144 : :
1145 : : /* Create matcher end flow table anchor */
1146 : 0 : ret = mlx5dr_matcher_create_end_ft(matcher);
1147 [ # # ]: 0 : if (ret)
1148 : 0 : goto unbind_at;
1149 : :
1150 : : /* Allocate the RTC for the new matcher */
1151 : 0 : ret = mlx5dr_matcher_create_rtc(matcher, DR_MATCHER_RTC_TYPE_MATCH);
1152 [ # # ]: 0 : if (ret)
1153 : 0 : goto destroy_end_ft;
1154 : :
1155 : : /* Allocate and set shared resources */
1156 : 0 : ret = mlx5dr_matcher_create_init_shared(matcher);
1157 [ # # ]: 0 : if (ret)
1158 : 0 : goto destroy_rtc;
1159 : :
1160 : : /* Connect the matcher to the matcher list */
1161 : 0 : ret = mlx5dr_matcher_connect(matcher);
1162 [ # # ]: 0 : if (ret)
1163 : 0 : goto destroy_shared;
1164 : :
1165 : : return 0;
1166 : :
1167 : : destroy_shared:
1168 : 0 : mlx5dr_matcher_create_uninit_shared(matcher);
1169 : 0 : destroy_rtc:
1170 : 0 : mlx5dr_matcher_destroy_rtc(matcher, DR_MATCHER_RTC_TYPE_MATCH);
1171 : 0 : destroy_end_ft:
1172 : : mlx5dr_matcher_destroy_end_ft(matcher);
1173 : 0 : unbind_at:
1174 : 0 : mlx5dr_matcher_unbind_at(matcher);
1175 : 0 : unbind_mt:
1176 : : mlx5dr_matcher_unbind_mt(matcher);
1177 : 0 : return ret;
1178 : : }
1179 : :
1180 : 0 : static void mlx5dr_matcher_destroy_and_disconnect(struct mlx5dr_matcher *matcher)
1181 : : {
1182 : 0 : mlx5dr_matcher_resize_uninit(matcher);
1183 : 0 : mlx5dr_matcher_disconnect(matcher);
1184 : 0 : mlx5dr_matcher_create_uninit_shared(matcher);
1185 : 0 : mlx5dr_matcher_destroy_rtc(matcher, DR_MATCHER_RTC_TYPE_MATCH);
1186 : : mlx5dr_matcher_destroy_end_ft(matcher);
1187 : 0 : mlx5dr_matcher_unbind_at(matcher);
1188 : : mlx5dr_matcher_unbind_mt(matcher);
1189 : 0 : }
1190 : :
1191 : : static int
1192 : 0 : mlx5dr_matcher_create_col_matcher(struct mlx5dr_matcher *matcher)
1193 : : {
1194 : 0 : struct mlx5dr_context *ctx = matcher->tbl->ctx;
1195 : : struct mlx5dr_matcher *col_matcher;
1196 : : int ret;
1197 : :
1198 [ # # ]: 0 : if (matcher->attr.mode != MLX5DR_MATCHER_RESOURCE_MODE_RULE ||
1199 [ # # ]: 0 : matcher->attr.insert_mode == MLX5DR_MATCHER_INSERT_BY_INDEX)
1200 : : return 0;
1201 : :
1202 [ # # ]: 0 : if (!mlx5dr_matcher_requires_col_tbl(matcher->attr.rule.num_log))
1203 : : return 0;
1204 : :
1205 : : col_matcher = simple_calloc(1, sizeof(*matcher));
1206 [ # # ]: 0 : if (!col_matcher) {
1207 : 0 : rte_errno = ENOMEM;
1208 : 0 : return rte_errno;
1209 : : }
1210 : :
1211 : 0 : col_matcher->tbl = matcher->tbl;
1212 : 0 : col_matcher->mt = matcher->mt;
1213 : 0 : col_matcher->at = matcher->at;
1214 : 0 : col_matcher->num_of_at = matcher->num_of_at;
1215 : 0 : col_matcher->num_of_mt = matcher->num_of_mt;
1216 : 0 : col_matcher->hash_definer = matcher->hash_definer;
1217 : 0 : col_matcher->attr.priority = matcher->attr.priority;
1218 : 0 : col_matcher->flags = matcher->flags;
1219 : 0 : col_matcher->flags |= MLX5DR_MATCHER_FLAGS_COLLISION;
1220 : 0 : col_matcher->attr.mode = MLX5DR_MATCHER_RESOURCE_MODE_HTABLE;
1221 : 0 : col_matcher->attr.optimize_flow_src = matcher->attr.optimize_flow_src;
1222 : 0 : col_matcher->attr.table.sz_row_log = matcher->attr.rule.num_log;
1223 : 0 : col_matcher->attr.table.sz_col_log = MLX5DR_MATCHER_ASSURED_COL_TBL_DEPTH;
1224 [ # # ]: 0 : if (col_matcher->attr.table.sz_row_log > MLX5DR_MATCHER_ASSURED_ROW_RATIO)
1225 : 0 : col_matcher->attr.table.sz_row_log -= MLX5DR_MATCHER_ASSURED_ROW_RATIO;
1226 : :
1227 : 0 : col_matcher->attr.max_num_of_at_attach = matcher->attr.max_num_of_at_attach;
1228 : :
1229 : 0 : ret = mlx5dr_matcher_process_attr(ctx->caps, col_matcher, false);
1230 [ # # ]: 0 : if (ret)
1231 : 0 : goto free_col_matcher;
1232 : :
1233 : 0 : ret = mlx5dr_matcher_create_and_connect(col_matcher);
1234 [ # # ]: 0 : if (ret)
1235 : 0 : goto free_col_matcher;
1236 : :
1237 : 0 : matcher->col_matcher = col_matcher;
1238 : :
1239 : 0 : return 0;
1240 : :
1241 : 0 : free_col_matcher:
1242 : : simple_free(col_matcher);
1243 : 0 : DR_LOG(ERR, "Failed to create assured collision matcher");
1244 : 0 : return ret;
1245 : : }
1246 : :
1247 : : static void
1248 : 0 : mlx5dr_matcher_destroy_col_matcher(struct mlx5dr_matcher *matcher)
1249 : : {
1250 [ # # ]: 0 : if (matcher->attr.mode != MLX5DR_MATCHER_RESOURCE_MODE_RULE ||
1251 [ # # ]: 0 : matcher->attr.insert_mode == MLX5DR_MATCHER_INSERT_BY_INDEX)
1252 : : return;
1253 : :
1254 [ # # ]: 0 : if (matcher->col_matcher) {
1255 : 0 : mlx5dr_matcher_destroy_and_disconnect(matcher->col_matcher);
1256 : 0 : simple_free(matcher->col_matcher);
1257 : : }
1258 : : }
1259 : :
1260 : 0 : static int mlx5dr_matcher_init(struct mlx5dr_matcher *matcher)
1261 : : {
1262 : 0 : struct mlx5dr_context *ctx = matcher->tbl->ctx;
1263 : : int ret;
1264 : :
1265 : 0 : pthread_spin_lock(&ctx->ctrl_lock);
1266 : :
1267 : : /* Allocate matcher resource and connect to the packet pipe */
1268 : 0 : ret = mlx5dr_matcher_create_and_connect(matcher);
1269 [ # # ]: 0 : if (ret)
1270 : 0 : goto unlock_err;
1271 : :
1272 : : /* Create additional matcher for collision handling */
1273 : 0 : ret = mlx5dr_matcher_create_col_matcher(matcher);
1274 [ # # ]: 0 : if (ret)
1275 : 0 : goto destory_and_disconnect;
1276 : :
1277 : 0 : pthread_spin_unlock(&ctx->ctrl_lock);
1278 : :
1279 : 0 : return 0;
1280 : :
1281 : : destory_and_disconnect:
1282 : 0 : mlx5dr_matcher_destroy_and_disconnect(matcher);
1283 : 0 : unlock_err:
1284 : 0 : pthread_spin_unlock(&ctx->ctrl_lock);
1285 : 0 : return ret;
1286 : : }
1287 : :
1288 : 0 : static int mlx5dr_matcher_uninit(struct mlx5dr_matcher *matcher)
1289 : : {
1290 : 0 : struct mlx5dr_context *ctx = matcher->tbl->ctx;
1291 : :
1292 : 0 : pthread_spin_lock(&ctx->ctrl_lock);
1293 : 0 : mlx5dr_matcher_destroy_col_matcher(matcher);
1294 : 0 : mlx5dr_matcher_destroy_and_disconnect(matcher);
1295 : 0 : pthread_spin_unlock(&ctx->ctrl_lock);
1296 : :
1297 : 0 : return 0;
1298 : : }
1299 : :
1300 : 0 : static int mlx5dr_matcher_init_root(struct mlx5dr_matcher *matcher)
1301 : : {
1302 : 0 : enum mlx5dr_table_type type = matcher->tbl->type;
1303 : 0 : struct mlx5dr_context *ctx = matcher->tbl->ctx;
1304 : 0 : struct mlx5dv_flow_matcher_attr attr = {0};
1305 : : struct mlx5dv_flow_match_parameters *mask;
1306 : 0 : struct mlx5_flow_attr flow_attr = {0};
1307 : : struct rte_flow_error rte_error;
1308 : : uint8_t match_criteria;
1309 : : int ret;
1310 : :
1311 : : #ifdef HAVE_MLX5DV_FLOW_MATCHER_FT_TYPE
1312 : 0 : attr.comp_mask = MLX5DV_FLOW_MATCHER_MASK_FT_TYPE;
1313 : :
1314 [ # # # # ]: 0 : switch (type) {
1315 : : case MLX5DR_TABLE_TYPE_NIC_RX:
1316 : : attr.ft_type = MLX5DV_FLOW_TABLE_TYPE_NIC_RX;
1317 : : break;
1318 : 0 : case MLX5DR_TABLE_TYPE_NIC_TX:
1319 : 0 : attr.ft_type = MLX5DV_FLOW_TABLE_TYPE_NIC_TX;
1320 : 0 : break;
1321 : 0 : case MLX5DR_TABLE_TYPE_FDB:
1322 : 0 : attr.ft_type = MLX5DV_FLOW_TABLE_TYPE_FDB;
1323 : 0 : break;
1324 : 0 : default:
1325 : 0 : assert(0);
1326 : : break;
1327 : : }
1328 : : #endif
1329 : :
1330 [ # # ]: 0 : if (matcher->attr.priority > UINT16_MAX) {
1331 : 0 : DR_LOG(ERR, "Root matcher priority exceeds allowed limit");
1332 : 0 : rte_errno = EINVAL;
1333 : 0 : return rte_errno;
1334 : : }
1335 : :
1336 : : ret = flow_hw_get_port_id_from_ctx(ctx, &flow_attr.port_id);
1337 : : if (ret) {
1338 : 0 : DR_LOG(ERR, "Failed to get port id for dev %s", ctx->ibv_ctx->device->name);
1339 : 0 : rte_errno = EINVAL;
1340 : 0 : return rte_errno;
1341 : : }
1342 : :
1343 : : mask = simple_calloc(1, MLX5_ST_SZ_BYTES(fte_match_param) +
1344 : : offsetof(struct mlx5dv_flow_match_parameters, match_buf));
1345 [ # # ]: 0 : if (!mask) {
1346 : 0 : rte_errno = ENOMEM;
1347 : 0 : return rte_errno;
1348 : : }
1349 : :
1350 : 0 : flow_attr.tbl_type = type;
1351 : :
1352 : : /* On root table matcher, only a single match template is supported */
1353 : 0 : ret = flow_dv_translate_items_hws(matcher->mt[0].items,
1354 : 0 : &flow_attr, mask->match_buf,
1355 : : MLX5_SET_MATCHER_HS_M, NULL,
1356 : : &match_criteria,
1357 : : &rte_error);
1358 [ # # ]: 0 : if (ret) {
1359 : 0 : DR_LOG(ERR, "Failed to convert items to PRM [%s]", rte_error.message);
1360 : 0 : goto free_mask;
1361 : : }
1362 : :
1363 : 0 : mask->match_sz = MLX5_ST_SZ_BYTES(fte_match_param);
1364 : 0 : attr.match_mask = mask;
1365 : 0 : attr.match_criteria_enable = match_criteria;
1366 : 0 : attr.type = IBV_FLOW_ATTR_NORMAL;
1367 : 0 : attr.priority = matcher->attr.priority;
1368 : :
1369 : 0 : matcher->dv_matcher =
1370 [ # # ]: 0 : mlx5_glue->dv_create_flow_matcher_root(mlx5dr_context_get_local_ibv(ctx),
1371 : : &attr);
1372 [ # # ]: 0 : if (!matcher->dv_matcher) {
1373 : 0 : DR_LOG(ERR, "Failed to create DV flow matcher");
1374 : 0 : rte_errno = errno;
1375 : 0 : goto free_mask;
1376 : : }
1377 : :
1378 : : simple_free(mask);
1379 : :
1380 : 0 : pthread_spin_lock(&ctx->ctrl_lock);
1381 [ # # ]: 0 : LIST_INSERT_HEAD(&matcher->tbl->head, matcher, next);
1382 : 0 : pthread_spin_unlock(&ctx->ctrl_lock);
1383 : :
1384 : 0 : return 0;
1385 : :
1386 : 0 : free_mask:
1387 : : simple_free(mask);
1388 : 0 : return rte_errno;
1389 : : }
1390 : :
1391 : 0 : static int mlx5dr_matcher_uninit_root(struct mlx5dr_matcher *matcher)
1392 : : {
1393 : 0 : struct mlx5dr_context *ctx = matcher->tbl->ctx;
1394 : : int ret;
1395 : :
1396 : 0 : pthread_spin_lock(&ctx->ctrl_lock);
1397 [ # # ]: 0 : LIST_REMOVE(matcher, next);
1398 : 0 : pthread_spin_unlock(&ctx->ctrl_lock);
1399 : :
1400 : 0 : ret = mlx5_glue->dv_destroy_flow_matcher_root(matcher->dv_matcher);
1401 [ # # ]: 0 : if (ret) {
1402 : 0 : DR_LOG(ERR, "Failed to Destroy DV flow matcher");
1403 : 0 : rte_errno = errno;
1404 : : }
1405 : :
1406 : 0 : return ret;
1407 : : }
1408 : :
1409 : 0 : int mlx5dr_matcher_attach_at(struct mlx5dr_matcher *matcher,
1410 : : struct mlx5dr_action_template *at)
1411 : : {
1412 [ # # ]: 0 : bool is_jumbo = mlx5dr_matcher_mt_is_jumbo(matcher->mt);
1413 : : uint32_t required_stes;
1414 : : int ret;
1415 : :
1416 [ # # ]: 0 : if (!matcher->attr.max_num_of_at_attach) {
1417 : 0 : DR_LOG(DEBUG, "Num of current at (%d) exceed allowed value",
1418 : : matcher->num_of_at);
1419 : 0 : rte_errno = ENOTSUP;
1420 : 0 : return -rte_errno;
1421 : : }
1422 : :
1423 : 0 : ret = mlx5dr_matcher_check_and_process_at(matcher, at);
1424 [ # # ]: 0 : if (ret)
1425 : 0 : return -rte_errno;
1426 : :
1427 [ # # # # ]: 0 : required_stes = at->num_of_action_stes - (!is_jumbo || at->only_term);
1428 [ # # ]: 0 : if (matcher->action_ste.max_stes < required_stes) {
1429 : 0 : DR_LOG(DEBUG, "Required STEs [%d] exceeds initial action template STE [%d]",
1430 : : required_stes, matcher->action_ste.max_stes);
1431 : 0 : rte_errno = ENOMEM;
1432 : 0 : return -rte_errno;
1433 : : }
1434 : :
1435 : 0 : matcher->at[matcher->num_of_at] = *at;
1436 : 0 : matcher->num_of_at += 1;
1437 : 0 : matcher->attr.max_num_of_at_attach -= 1;
1438 : :
1439 [ # # ]: 0 : if (matcher->col_matcher)
1440 : 0 : matcher->col_matcher->num_of_at = matcher->num_of_at;
1441 : :
1442 : : return 0;
1443 : : }
1444 : :
1445 : : static int
1446 : 0 : mlx5dr_matcher_set_templates(struct mlx5dr_matcher *matcher,
1447 : : struct mlx5dr_match_template *mt[],
1448 : : uint8_t num_of_mt,
1449 : : struct mlx5dr_action_template *at[],
1450 : : uint8_t num_of_at)
1451 : : {
1452 [ # # ]: 0 : bool is_root = mlx5dr_table_is_root(matcher->tbl);
1453 : : int i;
1454 : :
1455 [ # # ]: 0 : if (!num_of_mt || !num_of_at) {
1456 : 0 : DR_LOG(ERR, "Number of action/match template cannot be zero");
1457 : 0 : rte_errno = ENOTSUP;
1458 : 0 : return rte_errno;
1459 : : }
1460 : :
1461 [ # # ]: 0 : if (is_root && num_of_mt > MLX5DR_MATCHER_MAX_MT_ROOT) {
1462 : 0 : DR_LOG(ERR, "Number of match templates exceeds limit");
1463 : 0 : rte_errno = ENOTSUP;
1464 : 0 : return rte_errno;
1465 : : }
1466 : :
1467 : 0 : matcher->mt = simple_calloc(num_of_mt, sizeof(*matcher->mt));
1468 [ # # ]: 0 : if (!matcher->mt) {
1469 : 0 : DR_LOG(ERR, "Failed to allocate match template array");
1470 : 0 : rte_errno = ENOMEM;
1471 : 0 : return rte_errno;
1472 : : }
1473 : :
1474 : 0 : matcher->at = simple_calloc(num_of_at + matcher->attr.max_num_of_at_attach,
1475 : : sizeof(*matcher->at));
1476 [ # # ]: 0 : if (!matcher->at) {
1477 : 0 : DR_LOG(ERR, "Failed to allocate action template array");
1478 : 0 : rte_errno = ENOMEM;
1479 : 0 : goto free_mt;
1480 : : }
1481 : :
1482 [ # # ]: 0 : for (i = 0; i < num_of_mt; i++)
1483 : 0 : matcher->mt[i] = *mt[i];
1484 : :
1485 [ # # ]: 0 : for (i = 0; i < num_of_at; i++)
1486 : 0 : matcher->at[i] = *at[i];
1487 : :
1488 : 0 : matcher->num_of_mt = num_of_mt;
1489 : 0 : matcher->num_of_at = num_of_at;
1490 : :
1491 : 0 : return 0;
1492 : :
1493 : : free_mt:
1494 : 0 : simple_free(matcher->mt);
1495 : 0 : return rte_errno;
1496 : : }
1497 : :
1498 : : static void
1499 : : mlx5dr_matcher_unset_templates(struct mlx5dr_matcher *matcher)
1500 : : {
1501 : 0 : simple_free(matcher->at);
1502 : 0 : simple_free(matcher->mt);
1503 : 0 : }
1504 : :
1505 : : struct mlx5dr_matcher *
1506 : 0 : mlx5dr_matcher_create(struct mlx5dr_table *tbl,
1507 : : struct mlx5dr_match_template *mt[],
1508 : : uint8_t num_of_mt,
1509 : : struct mlx5dr_action_template *at[],
1510 : : uint8_t num_of_at,
1511 : : struct mlx5dr_matcher_attr *attr)
1512 : : {
1513 : : bool is_root = mlx5dr_table_is_root(tbl);
1514 : : struct mlx5dr_matcher *matcher;
1515 : : int ret;
1516 : :
1517 : : matcher = simple_calloc(1, sizeof(*matcher));
1518 [ # # ]: 0 : if (!matcher) {
1519 : 0 : rte_errno = ENOMEM;
1520 : 0 : return NULL;
1521 : : }
1522 : :
1523 : 0 : matcher->tbl = tbl;
1524 : 0 : matcher->attr = *attr;
1525 : :
1526 : 0 : ret = mlx5dr_matcher_process_attr(tbl->ctx->caps, matcher, is_root);
1527 [ # # ]: 0 : if (ret)
1528 : 0 : goto free_matcher;
1529 : :
1530 : 0 : ret = mlx5dr_matcher_set_templates(matcher, mt, num_of_mt, at, num_of_at);
1531 [ # # ]: 0 : if (ret)
1532 : 0 : goto free_matcher;
1533 : :
1534 [ # # ]: 0 : if (is_root)
1535 : 0 : ret = mlx5dr_matcher_init_root(matcher);
1536 : : else
1537 : 0 : ret = mlx5dr_matcher_init(matcher);
1538 : :
1539 [ # # ]: 0 : if (ret) {
1540 : 0 : DR_LOG(ERR, "Failed to initialise matcher: %d", ret);
1541 : 0 : goto unset_templates;
1542 : : }
1543 : :
1544 : : return matcher;
1545 : :
1546 : : unset_templates:
1547 : : mlx5dr_matcher_unset_templates(matcher);
1548 : 0 : free_matcher:
1549 : : simple_free(matcher);
1550 : 0 : return NULL;
1551 : : }
1552 : :
1553 : 0 : int mlx5dr_matcher_destroy(struct mlx5dr_matcher *matcher)
1554 : : {
1555 [ # # ]: 0 : if (mlx5dr_table_is_root(matcher->tbl))
1556 : 0 : mlx5dr_matcher_uninit_root(matcher);
1557 : : else
1558 : 0 : mlx5dr_matcher_uninit(matcher);
1559 : :
1560 : : mlx5dr_matcher_unset_templates(matcher);
1561 : : simple_free(matcher);
1562 : 0 : return 0;
1563 : : }
1564 : :
1565 : : struct mlx5dr_match_template *
1566 : 0 : mlx5dr_match_template_create(const struct rte_flow_item items[],
1567 : : enum mlx5dr_match_template_flags flags)
1568 : : {
1569 : : struct mlx5dr_match_template *mt;
1570 : : struct rte_flow_error error;
1571 : : int ret, len;
1572 : :
1573 [ # # ]: 0 : if (flags > MLX5DR_MATCH_TEMPLATE_FLAG_RELAXED_MATCH) {
1574 : 0 : DR_LOG(ERR, "Unsupported match template flag provided");
1575 : 0 : rte_errno = EINVAL;
1576 : 0 : return NULL;
1577 : : }
1578 : :
1579 : : mt = simple_calloc(1, sizeof(*mt));
1580 [ # # ]: 0 : if (!mt) {
1581 : 0 : DR_LOG(ERR, "Failed to allocate match template");
1582 : 0 : rte_errno = ENOMEM;
1583 : 0 : return NULL;
1584 : : }
1585 : :
1586 : 0 : mt->flags = flags;
1587 : :
1588 : : /* Duplicate the user given items */
1589 : 0 : ret = rte_flow_conv(RTE_FLOW_CONV_OP_PATTERN, NULL, 0, items, &error);
1590 [ # # ]: 0 : if (ret <= 0) {
1591 [ # # ]: 0 : DR_LOG(ERR, "Unable to process items (%s): %s",
1592 : : error.message ? error.message : "unspecified",
1593 : : strerror(rte_errno));
1594 : 0 : goto free_template;
1595 : : }
1596 : :
1597 : 0 : len = RTE_ALIGN(ret, 16);
1598 : 0 : mt->items = simple_calloc(1, len);
1599 [ # # ]: 0 : if (!mt->items) {
1600 : 0 : DR_LOG(ERR, "Failed to allocate item copy");
1601 : 0 : rte_errno = ENOMEM;
1602 : 0 : goto free_template;
1603 : : }
1604 : :
1605 : 0 : ret = rte_flow_conv(RTE_FLOW_CONV_OP_PATTERN, mt->items, ret, items, &error);
1606 [ # # ]: 0 : if (ret <= 0)
1607 : 0 : goto free_dst;
1608 : :
1609 : : return mt;
1610 : :
1611 : : free_dst:
1612 : 0 : simple_free(mt->items);
1613 : 0 : free_template:
1614 : : simple_free(mt);
1615 : 0 : return NULL;
1616 : : }
1617 : :
1618 : 0 : int mlx5dr_match_template_destroy(struct mlx5dr_match_template *mt)
1619 : : {
1620 : 0 : simple_free(mt->items);
1621 : : simple_free(mt);
1622 : 0 : return 0;
1623 : : }
1624 : :
1625 : 0 : bool mlx5dr_matcher_is_updatable(struct mlx5dr_matcher *matcher)
1626 : : {
1627 [ # # # # ]: 0 : if (mlx5dr_table_is_root(matcher->tbl) ||
1628 [ # # ]: 0 : mlx5dr_matcher_req_fw_wqe(matcher) ||
1629 : 0 : mlx5dr_matcher_is_resizable(matcher) ||
1630 [ # # # # ]: 0 : (!matcher->attr.optimize_using_rule_idx &&
1631 : : !mlx5dr_matcher_is_insert_by_idx(matcher)))
1632 : 0 : return false;
1633 : :
1634 : : return true;
1635 : : }
1636 : :
1637 : 0 : bool mlx5dr_matcher_is_dependent(struct mlx5dr_matcher *matcher)
1638 : : {
1639 : : int i;
1640 : :
1641 [ # # # # ]: 0 : if (matcher->action_ste.max_stes || mlx5dr_matcher_req_fw_wqe(matcher))
1642 : : return true;
1643 : :
1644 [ # # ]: 0 : for (i = 0; i < matcher->num_of_at; i++) {
1645 : 0 : struct mlx5dr_action_template *at = &matcher->at[i];
1646 : :
1647 [ # # ]: 0 : if (at->need_dep_write)
1648 : : return true;
1649 : : }
1650 : :
1651 : : return false;
1652 : : }
1653 : :
1654 : 0 : static int mlx5dr_matcher_resize_precheck(struct mlx5dr_matcher *src_matcher,
1655 : : struct mlx5dr_matcher *dst_matcher)
1656 : : {
1657 : : int i;
1658 : :
1659 [ # # # # ]: 0 : if (mlx5dr_table_is_root(src_matcher->tbl) ||
1660 [ # # ]: 0 : mlx5dr_table_is_root(dst_matcher->tbl)) {
1661 : 0 : DR_LOG(ERR, "Src/dst matcher belongs to root table - resize unsupported");
1662 : 0 : goto out_einval;
1663 : : }
1664 : :
1665 [ # # ]: 0 : if (src_matcher->tbl->type != dst_matcher->tbl->type) {
1666 : 0 : DR_LOG(ERR, "Table type mismatch for src/dst matchers");
1667 : 0 : goto out_einval;
1668 : : }
1669 : :
1670 [ # # # # ]: 0 : if (mlx5dr_matcher_req_fw_wqe(src_matcher) ||
1671 : : mlx5dr_matcher_req_fw_wqe(dst_matcher)) {
1672 : 0 : DR_LOG(ERR, "Matchers require FW WQE - resize unsupported");
1673 : 0 : goto out_einval;
1674 : : }
1675 : :
1676 [ # # # # ]: 0 : if (!mlx5dr_matcher_is_resizable(src_matcher) ||
1677 : : !mlx5dr_matcher_is_resizable(dst_matcher)) {
1678 : 0 : DR_LOG(ERR, "Src/dst matcher is not resizable");
1679 : 0 : goto out_einval;
1680 : : }
1681 : :
1682 [ # # ]: 0 : if (mlx5dr_matcher_is_insert_by_idx(src_matcher) !=
1683 : : mlx5dr_matcher_is_insert_by_idx(dst_matcher)) {
1684 : 0 : DR_LOG(ERR, "Src/dst matchers insert mode mismatch");
1685 : 0 : goto out_einval;
1686 : : }
1687 : :
1688 [ # # # # ]: 0 : if (mlx5dr_matcher_is_in_resize(src_matcher) ||
1689 : : mlx5dr_matcher_is_in_resize(dst_matcher)) {
1690 : 0 : DR_LOG(ERR, "Src/dst matcher is already in resize");
1691 : 0 : goto out_einval;
1692 : : }
1693 : :
1694 : : /* Compare match templates - make sure the definers are equivalent */
1695 [ # # ]: 0 : if (src_matcher->num_of_mt != dst_matcher->num_of_mt) {
1696 : 0 : DR_LOG(ERR, "Src/dst matcher match templates mismatch");
1697 : 0 : goto out_einval;
1698 : : }
1699 : :
1700 [ # # ]: 0 : if (src_matcher->action_ste.max_stes > dst_matcher->action_ste.max_stes) {
1701 : 0 : DR_LOG(ERR, "Src/dst matcher max STEs mismatch");
1702 : 0 : goto out_einval;
1703 : : }
1704 : :
1705 [ # # ]: 0 : for (i = 0; i < src_matcher->num_of_mt; i++) {
1706 [ # # ]: 0 : if (mlx5dr_definer_compare(src_matcher->mt[i].definer,
1707 : 0 : dst_matcher->mt[i].definer)) {
1708 : 0 : DR_LOG(ERR, "Src/dst matcher definers mismatch");
1709 : 0 : goto out_einval;
1710 : : }
1711 : : }
1712 : :
1713 : : return 0;
1714 : :
1715 : 0 : out_einval:
1716 : 0 : rte_errno = EINVAL;
1717 : 0 : return rte_errno;
1718 : : }
1719 : :
1720 : 0 : int mlx5dr_matcher_resize_set_target(struct mlx5dr_matcher *src_matcher,
1721 : : struct mlx5dr_matcher *dst_matcher)
1722 : : {
1723 : : int ret = 0;
1724 : :
1725 : 0 : pthread_spin_lock(&src_matcher->tbl->ctx->ctrl_lock);
1726 : :
1727 [ # # ]: 0 : if (mlx5dr_matcher_resize_precheck(src_matcher, dst_matcher)) {
1728 : 0 : ret = -rte_errno;
1729 : 0 : goto out;
1730 : : }
1731 : :
1732 : 0 : src_matcher->resize_dst = dst_matcher;
1733 : :
1734 [ # # ]: 0 : if (mlx5dr_matcher_resize_init(src_matcher)) {
1735 : 0 : src_matcher->resize_dst = NULL;
1736 : 0 : ret = -rte_errno;
1737 : : }
1738 : :
1739 : 0 : out:
1740 : 0 : pthread_spin_unlock(&src_matcher->tbl->ctx->ctrl_lock);
1741 : 0 : return ret;
1742 : : }
1743 : :
1744 [ # # ]: 0 : int mlx5dr_matcher_resize_rule_move(struct mlx5dr_matcher *src_matcher,
1745 : : struct mlx5dr_rule *rule,
1746 : : struct mlx5dr_rule_attr *attr)
1747 : : {
1748 [ # # ]: 0 : if (unlikely(!mlx5dr_matcher_is_in_resize(src_matcher))) {
1749 : 0 : DR_LOG(ERR, "Matcher is not resizable or not in resize");
1750 : 0 : goto out_einval;
1751 : : }
1752 : :
1753 [ # # ]: 0 : if (unlikely(src_matcher != rule->matcher)) {
1754 : 0 : DR_LOG(ERR, "Rule doesn't belong to src matcher");
1755 : 0 : goto out_einval;
1756 : : }
1757 : :
1758 : 0 : return mlx5dr_rule_move_hws_add(rule, attr);
1759 : :
1760 : 0 : out_einval:
1761 : 0 : rte_errno = EINVAL;
1762 : 0 : return -rte_errno;
1763 : : }
1764 : :
1765 : 0 : int mlx5dr_matcher_validate_compare_attr(struct mlx5dr_matcher *matcher)
1766 : : {
1767 [ # # ]: 0 : struct mlx5dr_cmd_query_caps *caps = matcher->tbl->ctx->caps;
1768 : : struct mlx5dr_matcher_attr *attr = &matcher->attr;
1769 : :
1770 [ # # ]: 0 : if (mlx5dr_table_is_root(matcher->tbl)) {
1771 : 0 : DR_LOG(ERR, "Compare matcher is not supported for root tables");
1772 : 0 : goto err;
1773 : : }
1774 : :
1775 [ # # ]: 0 : if (attr->mode != MLX5DR_MATCHER_RESOURCE_MODE_HTABLE) {
1776 : 0 : DR_LOG(ERR, "Compare matcher is only supported with pre-defined table size");
1777 : 0 : goto err;
1778 : : }
1779 : :
1780 [ # # ]: 0 : if (attr->insert_mode != MLX5DR_MATCHER_INSERT_BY_HASH ||
1781 [ # # ]: 0 : attr->distribute_mode != MLX5DR_MATCHER_DISTRIBUTE_BY_HASH) {
1782 : 0 : DR_LOG(ERR, "Gen WQE for compare matcher must be inserted and distribute by hash");
1783 : 0 : goto err;
1784 : : }
1785 : :
1786 [ # # # # ]: 0 : if (matcher->num_of_mt != 1 || matcher->num_of_at != 1) {
1787 : 0 : DR_LOG(ERR, "Compare matcher match templates and action templates must be 1 for each");
1788 : 0 : goto err;
1789 : : }
1790 : :
1791 [ # # ]: 0 : if (attr->table.sz_col_log || attr->table.sz_row_log) {
1792 : 0 : DR_LOG(ERR, "Compare matcher supports only 1x1 table size");
1793 : 0 : goto err;
1794 : : }
1795 : :
1796 [ # # ]: 0 : if (attr->resizable) {
1797 : 0 : DR_LOG(ERR, "Compare matcher does not support resizeing");
1798 : 0 : goto err;
1799 : : }
1800 : :
1801 [ # # ]: 0 : if (!IS_BIT_SET(caps->supp_ste_format_gen_wqe, MLX5_IFC_RTC_STE_FORMAT_4DW_RANGE)) {
1802 : 0 : DR_LOG(ERR, "Gen WQE Compare match format not supported");
1803 : 0 : goto err;
1804 : : }
1805 : :
1806 : : return 0;
1807 : :
1808 : 0 : err:
1809 : 0 : rte_errno = ENOTSUP;
1810 : 0 : return rte_errno;
1811 : : }
|