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