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