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 : 0 : static void mlx5dr_table_init_next_ft_attr(struct mlx5dr_table *tbl,
8 : : struct mlx5dr_cmd_ft_create_attr *ft_attr)
9 : : {
10 : 0 : ft_attr->type = tbl->fw_ft_type;
11 [ # # ]: 0 : if (mlx5dr_table_is_fdb_any(tbl->type))
12 : 0 : ft_attr->level = tbl->ctx->caps->fdb_ft.max_level - 1;
13 : : else
14 : 0 : ft_attr->level = tbl->ctx->caps->nic_ft.max_level - 1;
15 : 0 : ft_attr->rtc_valid = true;
16 : 0 : }
17 : :
18 : : /* Call this under ctx->ctrl_lock */
19 : : static int
20 : 0 : mlx5dr_table_up_default_fdb_miss_tbl(struct mlx5dr_table *tbl)
21 : : {
22 : 0 : struct mlx5dr_cmd_ft_create_attr ft_attr = {0};
23 : 0 : struct mlx5dr_cmd_set_fte_attr fte_attr = {0};
24 : : struct mlx5dr_cmd_forward_tbl *default_miss;
25 : 0 : struct mlx5dr_cmd_set_fte_dest dest = {0};
26 : 0 : struct mlx5dr_context *ctx = tbl->ctx;
27 [ # # ]: 0 : uint8_t tbl_type = tbl->type;
28 : :
29 : : if (!mlx5dr_table_is_fdb_any(tbl_type))
30 : : return 0;
31 : :
32 [ # # ]: 0 : if (ctx->common_res[tbl_type].default_miss) {
33 : 0 : ctx->common_res[tbl_type].default_miss->refcount++;
34 : 0 : return 0;
35 : : }
36 : :
37 : 0 : ft_attr.type = tbl->fw_ft_type;
38 : 0 : ft_attr.level = tbl->ctx->caps->fdb_ft.max_level; /* The last level */
39 : : ft_attr.rtc_valid = false;
40 : :
41 : : dest.destination_type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
42 : 0 : dest.destination_id = ctx->caps->eswitch_manager_vport_number;
43 : 0 : fte_attr.action_flags = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
44 : 0 : fte_attr.dests_num = 1;
45 [ # # ]: 0 : fte_attr.dests = &dest;
46 : :
47 : 0 : default_miss = mlx5dr_cmd_forward_tbl_create(mlx5dr_context_get_local_ibv(ctx),
48 : : &ft_attr, &fte_attr);
49 [ # # ]: 0 : if (!default_miss) {
50 : 0 : DR_LOG(ERR, "Failed to default miss table type: 0x%x", tbl_type);
51 : 0 : return rte_errno;
52 : : }
53 : :
54 : 0 : ctx->common_res[tbl_type].default_miss = default_miss;
55 : 0 : ctx->common_res[tbl_type].default_miss->refcount++;
56 : 0 : return 0;
57 : : }
58 : :
59 : : /* Called under pthread_spin_lock(&ctx->ctrl_lock) */
60 : 0 : static void mlx5dr_table_down_default_fdb_miss_tbl(struct mlx5dr_table *tbl)
61 : : {
62 : : struct mlx5dr_cmd_forward_tbl *default_miss;
63 : 0 : struct mlx5dr_context *ctx = tbl->ctx;
64 [ # # ]: 0 : uint8_t tbl_type = tbl->type;
65 : :
66 : : if (!mlx5dr_table_is_fdb_any(tbl->type))
67 : : return;
68 : :
69 : 0 : default_miss = ctx->common_res[tbl_type].default_miss;
70 [ # # ]: 0 : if (--default_miss->refcount)
71 : : return;
72 : :
73 : 0 : mlx5dr_cmd_forward_tbl_destroy(default_miss);
74 : 0 : ctx->common_res[tbl_type].default_miss = NULL;
75 : : }
76 : :
77 : : static int
78 : 0 : mlx5dr_table_connect_to_default_miss_tbl(struct mlx5dr_table *tbl,
79 : : struct mlx5dr_devx_obj *ft)
80 : : {
81 : 0 : struct mlx5dr_cmd_ft_modify_attr ft_attr = {0};
82 : : int ret;
83 : :
84 [ # # ]: 0 : assert(mlx5dr_table_is_fdb_any(tbl->type));
85 : :
86 : 0 : mlx5dr_cmd_set_attr_connect_miss_tbl(tbl->ctx,
87 : : tbl->fw_ft_type,
88 : : tbl->type,
89 : : &ft_attr);
90 : :
91 : : /* Connect to next */
92 : 0 : ret = mlx5dr_cmd_flow_table_modify(ft, &ft_attr);
93 [ # # ]: 0 : if (ret) {
94 : 0 : DR_LOG(ERR, "Failed to connect FT to default FDB FT");
95 : 0 : return ret;
96 : : }
97 : :
98 : : return 0;
99 : : }
100 : :
101 : : struct mlx5dr_devx_obj *
102 : 0 : mlx5dr_table_create_default_ft(struct ibv_context *ibv,
103 : : struct mlx5dr_table *tbl)
104 : : {
105 : 0 : struct mlx5dr_cmd_ft_create_attr ft_attr = {0};
106 : : struct mlx5dr_devx_obj *ft_obj;
107 : : int ret;
108 : :
109 : 0 : mlx5dr_table_init_next_ft_attr(tbl, &ft_attr);
110 : :
111 : 0 : ft_obj = mlx5dr_cmd_flow_table_create(ibv, &ft_attr);
112 [ # # # # ]: 0 : if (ft_obj && mlx5dr_table_is_fdb_any(tbl->type)) {
113 : : /* Take/create ref over the default miss */
114 : 0 : ret = mlx5dr_table_up_default_fdb_miss_tbl(tbl);
115 [ # # ]: 0 : if (ret) {
116 : 0 : DR_LOG(ERR, "Failed to get default fdb miss for type: %d\n",
117 : : tbl->type);
118 : 0 : goto free_ft_obj;
119 : : }
120 : 0 : ret = mlx5dr_table_connect_to_default_miss_tbl(tbl, ft_obj);
121 [ # # ]: 0 : if (ret) {
122 : 0 : DR_LOG(ERR, "Failed connecting to default miss tbl (type: %d)",
123 : : tbl->type);
124 : 0 : goto down_miss_tbl;
125 : : }
126 : : }
127 : :
128 : : return ft_obj;
129 : :
130 : : down_miss_tbl:
131 : 0 : mlx5dr_table_down_default_fdb_miss_tbl(tbl);
132 : 0 : free_ft_obj:
133 : 0 : mlx5dr_cmd_destroy_obj(ft_obj);
134 : 0 : return NULL;
135 : : }
136 : :
137 : : static int
138 : 0 : mlx5dr_table_init_check_hws_support(struct mlx5dr_context *ctx,
139 : : struct mlx5dr_table *tbl)
140 : : {
141 [ # # ]: 0 : if (!(ctx->flags & MLX5DR_CONTEXT_FLAG_HWS_SUPPORT)) {
142 : 0 : DR_LOG(ERR, "HWS not supported, cannot create mlx5dr_table");
143 : 0 : rte_errno = EOPNOTSUPP;
144 : 0 : return rte_errno;
145 : : }
146 : :
147 [ # # # # ]: 0 : if (mlx5dr_context_shared_gvmi_used(ctx) && mlx5dr_table_is_fdb_any(tbl->type)) {
148 : 0 : DR_LOG(ERR, "FDB with shared port resources is not supported");
149 : 0 : rte_errno = EOPNOTSUPP;
150 : 0 : return rte_errno;
151 : : }
152 : :
153 : : return 0;
154 : : }
155 : :
156 : : static int
157 : 0 : mlx5dr_table_shared_gvmi_resource_create(struct mlx5dr_context *ctx,
158 : : enum mlx5dr_table_type type,
159 : : struct mlx5dr_context_shared_gvmi_res *gvmi_res)
160 : : {
161 [ # # ]: 0 : struct mlx5dr_cmd_ft_create_attr ft_attr = {0};
162 : : uint32_t calculated_ft_id;
163 : : int ret;
164 : :
165 [ # # ]: 0 : if (!mlx5dr_context_shared_gvmi_used(ctx))
166 : : return 0;
167 : :
168 : 0 : ft_attr.type = mlx5dr_table_get_res_fw_ft_type(type, false);
169 : 0 : ft_attr.level = ctx->caps->nic_ft.max_level - 1;
170 : 0 : ft_attr.rtc_valid = true;
171 : :
172 : 0 : gvmi_res->end_ft =
173 : 0 : mlx5dr_cmd_flow_table_create(mlx5dr_context_get_local_ibv(ctx),
174 : : &ft_attr);
175 [ # # ]: 0 : if (!gvmi_res->end_ft) {
176 : 0 : DR_LOG(ERR, "Failed to create end-ft");
177 : 0 : return rte_errno;
178 : : }
179 : :
180 : 0 : calculated_ft_id =
181 : 0 : mlx5dr_table_get_res_fw_ft_type(type, false) << FT_ID_FT_TYPE_OFFSET;
182 : 0 : calculated_ft_id |= gvmi_res->end_ft->id;
183 : :
184 : : /* create alias to that FT */
185 : 0 : ret = mlx5dr_matcher_create_aliased_obj(ctx,
186 : : ctx->local_ibv_ctx,
187 : : ctx->ibv_ctx,
188 : 0 : ctx->caps->vhca_id,
189 : : calculated_ft_id,
190 : : MLX5_GENERAL_OBJ_TYPE_FT_ALIAS,
191 : : &gvmi_res->aliased_end_ft);
192 [ # # ]: 0 : if (ret) {
193 : 0 : DR_LOG(ERR, "Failed to create alias end-ft");
194 : 0 : goto free_end_ft;
195 : : }
196 : :
197 : : return 0;
198 : :
199 : : free_end_ft:
200 : 0 : mlx5dr_cmd_destroy_obj(gvmi_res->end_ft);
201 : :
202 : 0 : return rte_errno;
203 : : }
204 : :
205 : : static void
206 [ # # ]: 0 : mlx5dr_table_shared_gvmi_resourse_destroy(struct mlx5dr_context *ctx,
207 : : struct mlx5dr_context_shared_gvmi_res *gvmi_res)
208 : : {
209 [ # # ]: 0 : if (!mlx5dr_context_shared_gvmi_used(ctx))
210 : : return;
211 : :
212 [ # # ]: 0 : if (gvmi_res->aliased_end_ft) {
213 : 0 : mlx5dr_cmd_destroy_obj(gvmi_res->aliased_end_ft);
214 : 0 : gvmi_res->aliased_end_ft = NULL;
215 : : }
216 [ # # ]: 0 : if (gvmi_res->end_ft) {
217 : 0 : mlx5dr_cmd_destroy_obj(gvmi_res->end_ft);
218 : 0 : gvmi_res->end_ft = NULL;
219 : : }
220 : : }
221 : :
222 : : /* called under spinlock ctx->ctrl_lock */
223 : : static struct mlx5dr_context_shared_gvmi_res *
224 [ # # ]: 0 : mlx5dr_table_get_shared_gvmi_res(struct mlx5dr_context *ctx, enum mlx5dr_table_type type)
225 : : {
226 : : int ret;
227 : :
228 [ # # ]: 0 : if (!mlx5dr_context_shared_gvmi_used(ctx))
229 : : return NULL;
230 : :
231 [ # # ]: 0 : if (ctx->gvmi_res[type].aliased_end_ft) {
232 : 0 : ctx->gvmi_res[type].refcount++;
233 : 0 : return &ctx->gvmi_res[type];
234 : : }
235 : :
236 : 0 : ret = mlx5dr_table_shared_gvmi_resource_create(ctx, type, &ctx->gvmi_res[type]);
237 [ # # ]: 0 : if (ret) {
238 : 0 : DR_LOG(ERR, "Failed to create shared gvmi res for type: %d", type);
239 : 0 : goto out;
240 : : }
241 : :
242 : 0 : ctx->gvmi_res[type].refcount = 1;
243 : :
244 : 0 : return &ctx->gvmi_res[type];
245 : :
246 : : out:
247 : 0 : return NULL;
248 : : }
249 : :
250 : : /* called under spinlock ctx->ctrl_lock */
251 : 0 : static void mlx5dr_table_put_shared_gvmi_res(struct mlx5dr_table *tbl)
252 : : {
253 [ # # ]: 0 : struct mlx5dr_context *ctx = tbl->ctx;
254 : :
255 [ # # ]: 0 : if (!mlx5dr_context_shared_gvmi_used(ctx))
256 : : return;
257 : :
258 [ # # ]: 0 : if (--ctx->gvmi_res[tbl->type].refcount)
259 : : return;
260 : :
261 : 0 : mlx5dr_table_shared_gvmi_resourse_destroy(ctx, &ctx->gvmi_res[tbl->type]);
262 : : }
263 : :
264 : 0 : static void mlx5dr_table_uninit_shared_ctx_res(struct mlx5dr_table *tbl)
265 : : {
266 [ # # ]: 0 : struct mlx5dr_context *ctx = tbl->ctx;
267 : :
268 [ # # ]: 0 : if (!mlx5dr_context_shared_gvmi_used(ctx))
269 : : return;
270 : :
271 : 0 : mlx5dr_cmd_destroy_obj(tbl->local_ft);
272 : :
273 : 0 : mlx5dr_table_put_shared_gvmi_res(tbl);
274 : : }
275 : :
276 : : /* called under spin_lock ctx->ctrl_lock */
277 : 0 : static int mlx5dr_table_init_shared_ctx_res(struct mlx5dr_context *ctx, struct mlx5dr_table *tbl)
278 : : {
279 [ # # ]: 0 : struct mlx5dr_cmd_ft_modify_attr ft_attr = {0};
280 : : int ret;
281 : :
282 [ # # ]: 0 : if (!mlx5dr_context_shared_gvmi_used(ctx))
283 : : return 0;
284 : :
285 : : /* create local-ft for root access */
286 : 0 : tbl->local_ft =
287 : 0 : mlx5dr_table_create_default_ft(mlx5dr_context_get_local_ibv(ctx), tbl);
288 [ # # ]: 0 : if (!tbl->local_ft) {
289 : 0 : DR_LOG(ERR, "Failed to create local-ft");
290 : 0 : return rte_errno;
291 : : }
292 : :
293 [ # # ]: 0 : if (!mlx5dr_table_get_shared_gvmi_res(tbl->ctx, tbl->type)) {
294 : 0 : DR_LOG(ERR, "Failed to shared gvmi resources");
295 : 0 : goto clean_local_ft;
296 : : }
297 : :
298 : : /* On shared gvmi the default behavior is jump to alias end ft */
299 : 0 : mlx5dr_cmd_set_attr_connect_miss_tbl(tbl->ctx,
300 : : tbl->fw_ft_type,
301 : : tbl->type,
302 : : &ft_attr);
303 : :
304 : 0 : ret = mlx5dr_cmd_flow_table_modify(tbl->ft, &ft_attr);
305 [ # # ]: 0 : if (ret) {
306 : 0 : DR_LOG(ERR, "Failed to point table to its default miss");
307 : 0 : goto clean_shared_res;
308 : : }
309 : :
310 : : return 0;
311 : :
312 : : clean_shared_res:
313 : 0 : mlx5dr_table_put_shared_gvmi_res(tbl);
314 : 0 : clean_local_ft:
315 : 0 : mlx5dr_table_destroy_default_ft(tbl, tbl->local_ft);
316 : 0 : return rte_errno;
317 : : }
318 : :
319 : 0 : void mlx5dr_table_destroy_default_ft(struct mlx5dr_table *tbl,
320 : : struct mlx5dr_devx_obj *ft_obj)
321 : : {
322 : 0 : mlx5dr_cmd_destroy_obj(ft_obj);
323 : 0 : mlx5dr_table_down_default_fdb_miss_tbl(tbl);
324 : 0 : }
325 : :
326 : 0 : static int mlx5dr_table_init(struct mlx5dr_table *tbl)
327 : : {
328 [ # # ]: 0 : struct mlx5dr_context *ctx = tbl->ctx;
329 : : int ret;
330 : :
331 [ # # ]: 0 : if (mlx5dr_table_is_root(tbl))
332 : : return 0;
333 : :
334 : 0 : ret = mlx5dr_table_init_check_hws_support(ctx, tbl);
335 [ # # ]: 0 : if (ret)
336 : : return ret;
337 : :
338 : 0 : mlx5dr_table_get_fw_ft_type(tbl->type, (uint8_t *)&tbl->fw_ft_type);
339 : :
340 : 0 : pthread_spin_lock(&ctx->ctrl_lock);
341 : 0 : tbl->ft = mlx5dr_table_create_default_ft(tbl->ctx->ibv_ctx, tbl);
342 [ # # ]: 0 : if (!tbl->ft) {
343 : 0 : DR_LOG(ERR, "Failed to create flow table devx object");
344 : 0 : pthread_spin_unlock(&ctx->ctrl_lock);
345 : 0 : return rte_errno;
346 : : }
347 : :
348 : 0 : ret = mlx5dr_table_init_shared_ctx_res(ctx, tbl);
349 [ # # ]: 0 : if (ret)
350 : 0 : goto tbl_destroy;
351 : :
352 : 0 : ret = mlx5dr_action_get_default_stc(ctx, tbl->type);
353 [ # # ]: 0 : if (ret)
354 : 0 : goto free_shared_ctx;
355 : :
356 : 0 : pthread_spin_unlock(&ctx->ctrl_lock);
357 : :
358 : 0 : return 0;
359 : :
360 : : free_shared_ctx:
361 : 0 : mlx5dr_table_uninit_shared_ctx_res(tbl);
362 : 0 : tbl_destroy:
363 : 0 : mlx5dr_table_destroy_default_ft(tbl, tbl->ft);
364 : 0 : pthread_spin_unlock(&ctx->ctrl_lock);
365 : 0 : return rte_errno;
366 : : }
367 : :
368 [ # # ]: 0 : static void mlx5dr_table_uninit(struct mlx5dr_table *tbl)
369 : : {
370 [ # # ]: 0 : if (mlx5dr_table_is_root(tbl))
371 : : return;
372 : 0 : pthread_spin_lock(&tbl->ctx->ctrl_lock);
373 : 0 : mlx5dr_action_put_default_stc(tbl->ctx, tbl->type);
374 : 0 : mlx5dr_table_uninit_shared_ctx_res(tbl);
375 : 0 : mlx5dr_table_destroy_default_ft(tbl, tbl->ft);
376 : 0 : pthread_spin_unlock(&tbl->ctx->ctrl_lock);
377 : : }
378 : :
379 : 0 : struct mlx5dr_table *mlx5dr_table_create(struct mlx5dr_context *ctx,
380 : : struct mlx5dr_table_attr *attr)
381 : : {
382 : : struct mlx5dr_table *tbl;
383 : : int ret;
384 : :
385 [ # # ]: 0 : if (attr->type >= MLX5DR_TABLE_TYPE_MAX) {
386 : 0 : DR_LOG(ERR, "Invalid table type %d", attr->type);
387 : 0 : return NULL;
388 : : }
389 : :
390 [ # # # # ]: 0 : if (attr->type == MLX5DR_TABLE_TYPE_FDB_UNIFIED && !ctx->caps->fdb_unified_en) {
391 : 0 : DR_LOG(ERR, "Table type %d not supported by current FW", attr->type);
392 : 0 : rte_errno = ENOTSUP;
393 : 0 : return NULL;
394 : : }
395 : :
396 [ # # ]: 0 : if ((mlx5dr_table_is_fdb_any(attr->type) && attr->type != MLX5DR_TABLE_TYPE_FDB) &&
397 [ # # ]: 0 : !attr->level) {
398 : 0 : DR_LOG(ERR, "Table type %d not supported by root table", attr->type);
399 : 0 : rte_errno = ENOTSUP;
400 : 0 : return NULL;
401 : : }
402 : :
403 : : tbl = simple_calloc(1, sizeof(*tbl));
404 [ # # ]: 0 : if (!tbl) {
405 : 0 : rte_errno = ENOMEM;
406 : 0 : return NULL;
407 : : }
408 : :
409 : 0 : tbl->ctx = ctx;
410 : 0 : tbl->type = attr->type;
411 : 0 : tbl->level = attr->level;
412 : :
413 : 0 : ret = mlx5dr_table_init(tbl);
414 [ # # ]: 0 : if (ret) {
415 : 0 : DR_LOG(ERR, "Failed to initialise table");
416 : 0 : goto free_tbl;
417 : : }
418 : :
419 : 0 : pthread_spin_lock(&ctx->ctrl_lock);
420 [ # # ]: 0 : LIST_INSERT_HEAD(&ctx->head, tbl, next);
421 : 0 : pthread_spin_unlock(&ctx->ctrl_lock);
422 : :
423 : 0 : return tbl;
424 : :
425 : : free_tbl:
426 : : simple_free(tbl);
427 : 0 : return NULL;
428 : : }
429 : :
430 : 0 : int mlx5dr_table_destroy(struct mlx5dr_table *tbl)
431 : : {
432 : 0 : struct mlx5dr_context *ctx = tbl->ctx;
433 : 0 : pthread_spin_lock(&ctx->ctrl_lock);
434 [ # # # # ]: 0 : if (!LIST_EMPTY(&tbl->head) || !LIST_EMPTY(&tbl->isolated_matchers)) {
435 : 0 : DR_LOG(ERR, "Cannot destroy table containing matchers");
436 : 0 : rte_errno = EBUSY;
437 : 0 : goto unlock_err;
438 : : }
439 : :
440 [ # # ]: 0 : if (!LIST_EMPTY(&tbl->default_miss.head)) {
441 : 0 : DR_LOG(ERR, "Cannot destroy table pointed by default miss");
442 : 0 : rte_errno = EBUSY;
443 : 0 : goto unlock_err;
444 : : }
445 : :
446 [ # # ]: 0 : LIST_REMOVE(tbl, next);
447 : 0 : pthread_spin_unlock(&ctx->ctrl_lock);
448 : 0 : mlx5dr_table_uninit(tbl);
449 : : simple_free(tbl);
450 : :
451 : 0 : return 0;
452 : :
453 : 0 : unlock_err:
454 : 0 : pthread_spin_unlock(&ctx->ctrl_lock);
455 : 0 : return -rte_errno;
456 : : }
457 : :
458 : : static struct mlx5dr_devx_obj *
459 : : mlx5dr_table_get_last_ft(struct mlx5dr_table *tbl)
460 : : {
461 : 0 : struct mlx5dr_devx_obj *last_ft = tbl->ft;
462 : : struct mlx5dr_matcher *matcher;
463 : :
464 [ # # ]: 0 : LIST_FOREACH(matcher, &tbl->head, next)
465 : 0 : last_ft = matcher->end_ft;
466 : :
467 : : return last_ft;
468 : : }
469 : :
470 : 0 : int mlx5dr_table_ft_set_default_next_ft(struct mlx5dr_table *tbl,
471 : : struct mlx5dr_devx_obj *ft_obj)
472 : : {
473 : 0 : struct mlx5dr_cmd_ft_modify_attr ft_attr = {0};
474 : : int ret;
475 : :
476 : : /* Due to FW limitation, resetting the flow table to default action will
477 : : * disconnect RTC when ignore_flow_level_rtc_valid is not supported.
478 : : */
479 [ # # ]: 0 : if (!tbl->ctx->caps->nic_ft.ignore_flow_level_rtc_valid)
480 : : return 0;
481 : :
482 [ # # ]: 0 : if (mlx5dr_table_is_fdb_any(tbl->type))
483 : 0 : return mlx5dr_table_connect_to_default_miss_tbl(tbl, ft_obj);
484 : :
485 : 0 : ft_attr.type = tbl->fw_ft_type;
486 : 0 : ft_attr.modify_fs = MLX5_IFC_MODIFY_FLOW_TABLE_MISS_ACTION;
487 : : ft_attr.table_miss_action = MLX5_IFC_MODIFY_FLOW_TABLE_MISS_ACTION_DEFAULT;
488 : :
489 : 0 : ret = mlx5dr_cmd_flow_table_modify(ft_obj, &ft_attr);
490 [ # # ]: 0 : if (ret) {
491 : 0 : DR_LOG(ERR, "Failed to set FT default miss action");
492 : 0 : return ret;
493 : : }
494 : :
495 : : return 0;
496 : : }
497 : :
498 : 0 : int mlx5dr_table_ft_set_next_rtc(struct mlx5dr_devx_obj *ft,
499 : : uint32_t fw_ft_type,
500 : : struct mlx5dr_devx_obj *rtc_0,
501 : : struct mlx5dr_devx_obj *rtc_1)
502 : : {
503 : 0 : struct mlx5dr_cmd_ft_modify_attr ft_attr = {0};
504 : :
505 : 0 : ft_attr.modify_fs = MLX5_IFC_MODIFY_FLOW_TABLE_RTC_ID;
506 : 0 : ft_attr.type = fw_ft_type;
507 [ # # ]: 0 : ft_attr.rtc_id_0 = rtc_0 ? rtc_0->id : 0;
508 [ # # ]: 0 : ft_attr.rtc_id_1 = rtc_1 ? rtc_1->id : 0;
509 : :
510 : 0 : return mlx5dr_cmd_flow_table_modify(ft, &ft_attr);
511 : : }
512 : :
513 : : static int mlx5dr_table_ft_set_next_ft(struct mlx5dr_devx_obj *ft,
514 : : uint32_t fw_ft_type,
515 : : uint32_t next_ft_id)
516 : : {
517 : 0 : struct mlx5dr_cmd_ft_modify_attr ft_attr = {0};
518 : :
519 : 0 : ft_attr.modify_fs = MLX5_IFC_MODIFY_FLOW_TABLE_MISS_ACTION;
520 : 0 : ft_attr.table_miss_action = MLX5_IFC_MODIFY_FLOW_TABLE_MISS_ACTION_GOTO_TBL;
521 : 0 : ft_attr.type = fw_ft_type;
522 : 0 : ft_attr.table_miss_id = next_ft_id;
523 : :
524 : 0 : return mlx5dr_cmd_flow_table_modify(ft, &ft_attr);
525 : : }
526 : :
527 : 0 : int mlx5dr_table_update_connected_miss_tables(struct mlx5dr_table *dst_tbl)
528 : : {
529 : : struct mlx5dr_table *src_tbl;
530 : : int ret;
531 : :
532 [ # # ]: 0 : if (LIST_EMPTY(&dst_tbl->default_miss.head))
533 : : return 0;
534 : :
535 [ # # ]: 0 : LIST_FOREACH(src_tbl, &dst_tbl->default_miss.head, default_miss.next) {
536 : 0 : ret = mlx5dr_table_connect_to_miss_table(src_tbl, dst_tbl, false);
537 [ # # ]: 0 : if (ret) {
538 : 0 : DR_LOG(ERR, "Failed to update source miss table, unexpected behavior");
539 : 0 : return ret;
540 : : }
541 : : }
542 : :
543 : : return 0;
544 : : }
545 : :
546 : 0 : int mlx5dr_table_connect_src_ft_to_miss_table(struct mlx5dr_table *src_tbl,
547 : : struct mlx5dr_devx_obj *ft,
548 : : struct mlx5dr_table *dst_tbl)
549 : : {
550 : : struct mlx5dr_matcher *matcher;
551 : : int ret;
552 : :
553 [ # # ]: 0 : if (dst_tbl) {
554 [ # # ]: 0 : if (LIST_EMPTY(&dst_tbl->head)) {
555 : : /* Connect src_tbl ft to dst_tbl start anchor */
556 : 0 : ret = mlx5dr_table_ft_set_next_ft(ft,
557 : : src_tbl->fw_ft_type,
558 : 0 : dst_tbl->ft->id);
559 [ # # ]: 0 : if (ret)
560 : : return ret;
561 : :
562 : : /* Reset ft RTC to default RTC */
563 : 0 : ret = mlx5dr_table_ft_set_next_rtc(ft,
564 : : src_tbl->fw_ft_type,
565 : : NULL, NULL);
566 [ # # ]: 0 : if (ret)
567 : 0 : return ret;
568 : : } else {
569 : : /* Connect src_tbl ft to first matcher RTC */
570 : : matcher = LIST_FIRST(&dst_tbl->head);
571 : 0 : ret = mlx5dr_table_ft_set_next_rtc(ft,
572 : : src_tbl->fw_ft_type,
573 : : matcher->match_ste.rtc_0,
574 : : matcher->match_ste.rtc_1);
575 [ # # ]: 0 : if (ret)
576 : : return ret;
577 : :
578 : : /* Reset next miss FT to default */
579 : 0 : ret = mlx5dr_table_ft_set_default_next_ft(src_tbl, ft);
580 [ # # ]: 0 : if (ret)
581 : 0 : return ret;
582 : : }
583 : : } else {
584 : : /* Reset next miss FT to default */
585 : 0 : ret = mlx5dr_table_ft_set_default_next_ft(src_tbl, ft);
586 [ # # ]: 0 : if (ret)
587 : : return ret;
588 : :
589 : : /* Reset ft RTC to default RTC */
590 : 0 : ret = mlx5dr_table_ft_set_next_rtc(ft,
591 : : src_tbl->fw_ft_type,
592 : : NULL, NULL);
593 [ # # ]: 0 : if (ret)
594 : 0 : return ret;
595 : : }
596 : :
597 : : return 0;
598 : : }
599 : :
600 : 0 : int mlx5dr_table_connect_to_miss_table(struct mlx5dr_table *src_tbl,
601 : : struct mlx5dr_table *dst_tbl,
602 : : bool only_update_last_ft)
603 : : {
604 : : struct mlx5dr_matcher *matcher;
605 : : struct mlx5dr_devx_obj *ft;
606 : : int ret;
607 : :
608 : : /* Connect last FT in the src_tbl matchers chain */
609 : : ft = mlx5dr_table_get_last_ft(src_tbl);
610 : 0 : ret = mlx5dr_table_connect_src_ft_to_miss_table(src_tbl, ft, dst_tbl);
611 [ # # ]: 0 : if (ret)
612 : : return ret;
613 : :
614 [ # # ]: 0 : if (!only_update_last_ft) {
615 : : /* Connect isolated matchers FT */
616 [ # # ]: 0 : LIST_FOREACH(matcher, &src_tbl->isolated_matchers, next) {
617 : 0 : ft = matcher->end_ft;
618 : 0 : ret = mlx5dr_table_connect_src_ft_to_miss_table(src_tbl, ft, dst_tbl);
619 [ # # ]: 0 : if (ret)
620 : 0 : return ret;
621 : : }
622 : : }
623 : :
624 : 0 : src_tbl->default_miss.miss_tbl = dst_tbl;
625 : :
626 : 0 : return 0;
627 : : }
628 : :
629 : : static bool mlx5dr_table_set_default_miss_valid_types(enum mlx5dr_table_type from,
630 : : enum mlx5dr_table_type to)
631 : : {
632 [ # # ]: 0 : if (from == to ||
633 : 0 : ((from == MLX5DR_TABLE_TYPE_FDB_UNIFIED &&
634 [ # # # # ]: 0 : (to == MLX5DR_TABLE_TYPE_FDB_RX || to == MLX5DR_TABLE_TYPE_FDB_TX)) ||
635 : 0 : (to == MLX5DR_TABLE_TYPE_FDB_UNIFIED &&
636 [ # # ]: 0 : (from == MLX5DR_TABLE_TYPE_FDB_RX || from == MLX5DR_TABLE_TYPE_FDB_TX))))
637 : : return true;
638 : :
639 : : return false;
640 : : }
641 : :
642 : 0 : static int mlx5dr_table_set_default_miss_not_valid(struct mlx5dr_table *tbl,
643 : : struct mlx5dr_table *miss_tbl)
644 : : {
645 [ # # # # ]: 0 : if (!tbl->ctx->caps->nic_ft.ignore_flow_level_rtc_valid ||
646 : : mlx5dr_context_shared_gvmi_used(tbl->ctx)) {
647 : 0 : DR_LOG(ERR, "Default miss table is not supported");
648 : 0 : rte_errno = EOPNOTSUPP;
649 : 0 : return -rte_errno;
650 : : }
651 : :
652 [ # # # # ]: 0 : if (mlx5dr_table_is_root(tbl) ||
653 [ # # ]: 0 : (miss_tbl &&
654 : : ((mlx5dr_table_is_root(miss_tbl)) ||
655 [ # # ]: 0 : !mlx5dr_table_set_default_miss_valid_types(tbl->type, miss_tbl->type)))) {
656 : 0 : DR_LOG(ERR, "Invalid arguments");
657 : 0 : rte_errno = EINVAL;
658 : 0 : return -rte_errno;
659 : : }
660 : :
661 : : return 0;
662 : : }
663 : :
664 : 0 : int mlx5dr_table_set_default_miss(struct mlx5dr_table *tbl,
665 : : struct mlx5dr_table *miss_tbl)
666 : : {
667 : 0 : struct mlx5dr_context *ctx = tbl->ctx;
668 : : struct mlx5dr_table *old_miss_tbl;
669 : : int ret;
670 : :
671 : 0 : ret = mlx5dr_table_set_default_miss_not_valid(tbl, miss_tbl);
672 [ # # ]: 0 : if (ret)
673 : : return ret;
674 : :
675 : 0 : pthread_spin_lock(&ctx->ctrl_lock);
676 : 0 : old_miss_tbl = tbl->default_miss.miss_tbl;
677 : 0 : ret = mlx5dr_table_connect_to_miss_table(tbl, miss_tbl, false);
678 [ # # ]: 0 : if (ret)
679 : 0 : goto out;
680 : :
681 [ # # ]: 0 : if (old_miss_tbl)
682 [ # # ]: 0 : LIST_REMOVE(tbl, default_miss.next);
683 : :
684 [ # # ]: 0 : if (miss_tbl)
685 [ # # ]: 0 : LIST_INSERT_HEAD(&miss_tbl->default_miss.head, tbl, default_miss.next);
686 : :
687 : 0 : pthread_spin_unlock(&ctx->ctrl_lock);
688 : 0 : return 0;
689 : : out:
690 : 0 : pthread_spin_unlock(&ctx->ctrl_lock);
691 : 0 : return -ret;
692 : : }
|