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