1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 // Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
4 #include "en/tc_priv.h"
10 struct mlx5e_post_act
{
11 enum mlx5_flow_namespace_type ns_type
;
12 struct mlx5_fs_chains
*chains
;
13 struct mlx5_flow_table
*ft
;
14 struct mlx5e_priv
*priv
;
18 struct mlx5e_post_act_handle
{
19 enum mlx5_flow_namespace_type ns_type
;
20 struct mlx5_flow_attr
*attr
;
21 struct mlx5_flow_handle
*rule
;
25 #define MLX5_POST_ACTION_BITS MLX5_REG_MAPPING_MBITS(FTEID_TO_REG)
26 #define MLX5_POST_ACTION_MASK MLX5_REG_MAPPING_MASK(FTEID_TO_REG)
27 #define MLX5_POST_ACTION_MAX MLX5_POST_ACTION_MASK
29 struct mlx5e_post_act
*
30 mlx5e_tc_post_act_init(struct mlx5e_priv
*priv
, struct mlx5_fs_chains
*chains
,
31 enum mlx5_flow_namespace_type ns_type
)
33 enum fs_flow_table_type table_type
= ns_type
== MLX5_FLOW_NAMESPACE_FDB
?
34 FS_FT_FDB
: FS_FT_NIC_RX
;
35 struct mlx5e_post_act
*post_act
;
38 if (!MLX5_CAP_FLOWTABLE_TYPE(priv
->mdev
, ignore_flow_level
, table_type
)) {
39 if (priv
->mdev
->coredev_type
== MLX5_COREDEV_PF
)
40 mlx5_core_warn(priv
->mdev
, "firmware level support is missing\n");
45 post_act
= kzalloc(sizeof(*post_act
), GFP_KERNEL
);
50 post_act
->ft
= mlx5_chains_create_global_table(chains
);
51 if (IS_ERR(post_act
->ft
)) {
52 err
= PTR_ERR(post_act
->ft
);
53 mlx5_core_warn(priv
->mdev
, "failed to create post action table, err: %d\n", err
);
56 post_act
->chains
= chains
;
57 post_act
->ns_type
= ns_type
;
58 post_act
->priv
= priv
;
59 xa_init_flags(&post_act
->ids
, XA_FLAGS_ALLOC1
);
69 mlx5e_tc_post_act_destroy(struct mlx5e_post_act
*post_act
)
71 if (IS_ERR_OR_NULL(post_act
))
74 xa_destroy(&post_act
->ids
);
75 mlx5_chains_destroy_global_table(post_act
->chains
, post_act
->ft
);
80 mlx5e_tc_post_act_offload(struct mlx5e_post_act
*post_act
,
81 struct mlx5e_post_act_handle
*handle
)
83 struct mlx5_flow_spec
*spec
;
87 return PTR_ERR(post_act
);
89 spec
= kvzalloc(sizeof(*spec
), GFP_KERNEL
);
93 /* Post action rule matches on fte_id and executes original rule's tc rule action */
94 mlx5e_tc_match_to_reg_match(spec
, FTEID_TO_REG
, handle
->id
, MLX5_POST_ACTION_MASK
);
96 handle
->rule
= mlx5e_tc_rule_offload(post_act
->priv
, spec
, handle
->attr
);
97 if (IS_ERR(handle
->rule
)) {
98 err
= PTR_ERR(handle
->rule
);
99 netdev_warn(post_act
->priv
->netdev
, "Failed to add post action rule");
111 struct mlx5e_post_act_handle
*
112 mlx5e_tc_post_act_add(struct mlx5e_post_act
*post_act
, struct mlx5_flow_attr
*post_attr
)
114 struct mlx5e_post_act_handle
*handle
;
117 if (IS_ERR(post_act
))
118 return ERR_CAST(post_act
);
120 handle
= kzalloc(sizeof(*handle
), GFP_KERNEL
);
122 return ERR_PTR(-ENOMEM
);
124 post_attr
->chain
= 0;
126 post_attr
->ft
= post_act
->ft
;
127 post_attr
->inner_match_level
= MLX5_MATCH_NONE
;
128 post_attr
->outer_match_level
= MLX5_MATCH_NONE
;
129 post_attr
->action
&= ~MLX5_FLOW_CONTEXT_ACTION_DECAP
;
130 post_attr
->flags
|= MLX5_ATTR_FLAG_NO_IN_PORT
;
132 handle
->ns_type
= post_act
->ns_type
;
133 /* Splits were handled before post action */
134 if (handle
->ns_type
== MLX5_FLOW_NAMESPACE_FDB
)
135 post_attr
->esw_attr
->split_count
= 0;
137 err
= xa_alloc(&post_act
->ids
, &handle
->id
, post_attr
,
138 XA_LIMIT(1, MLX5_POST_ACTION_MAX
), GFP_KERNEL
);
142 handle
->attr
= post_attr
;
152 mlx5e_tc_post_act_unoffload(struct mlx5e_post_act
*post_act
,
153 struct mlx5e_post_act_handle
*handle
)
155 mlx5e_tc_rule_unoffload(post_act
->priv
, handle
->rule
, handle
->attr
);
160 mlx5e_tc_post_act_del(struct mlx5e_post_act
*post_act
, struct mlx5e_post_act_handle
*handle
)
162 if (!IS_ERR_OR_NULL(handle
->rule
))
163 mlx5e_tc_post_act_unoffload(post_act
, handle
);
164 xa_erase(&post_act
->ids
, handle
->id
);
168 struct mlx5_flow_table
*
169 mlx5e_tc_post_act_get_ft(struct mlx5e_post_act
*post_act
)
174 /* Allocate a header modify action to write the post action handle fte id to a register. */
176 mlx5e_tc_post_act_set_handle(struct mlx5_core_dev
*dev
,
177 struct mlx5e_post_act_handle
*handle
,
178 struct mlx5e_tc_mod_hdr_acts
*acts
)
180 return mlx5e_tc_match_to_reg_set(dev
, acts
, handle
->ns_type
, FTEID_TO_REG
, handle
->id
);