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