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