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