1 /* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
2 /* Copyright (c) 2024 NVIDIA Corporation & Affiliates */
3
4 #ifndef HWS_ACTION_H_
5 #define HWS_ACTION_H_
6
7 /* Max number of STEs needed for a rule (including match) */
8 #define MLX5HWS_ACTION_MAX_STE 20
9
10 /* Max number of internal subactions of ipv6_ext */
11 #define MLX5HWS_ACTION_IPV6_EXT_MAX_SA 4
12
13 enum mlx5hws_action_stc_idx {
14 MLX5HWS_ACTION_STC_IDX_CTRL = 0,
15 MLX5HWS_ACTION_STC_IDX_HIT = 1,
16 MLX5HWS_ACTION_STC_IDX_DW5 = 2,
17 MLX5HWS_ACTION_STC_IDX_DW6 = 3,
18 MLX5HWS_ACTION_STC_IDX_DW7 = 4,
19 MLX5HWS_ACTION_STC_IDX_MAX = 5,
20 /* STC Jumvo STE combo: CTR, Hit */
21 MLX5HWS_ACTION_STC_IDX_LAST_JUMBO_STE = 1,
22 /* STC combo1: CTR, SINGLE, DOUBLE, Hit */
23 MLX5HWS_ACTION_STC_IDX_LAST_COMBO1 = 3,
24 /* STC combo2: CTR, 3 x SINGLE, Hit */
25 MLX5HWS_ACTION_STC_IDX_LAST_COMBO2 = 4,
26 /* STC combo2: CTR, TRIPLE, Hit */
27 MLX5HWS_ACTION_STC_IDX_LAST_COMBO3 = 2,
28 };
29
30 enum mlx5hws_action_offset {
31 MLX5HWS_ACTION_OFFSET_DW0 = 0,
32 MLX5HWS_ACTION_OFFSET_DW5 = 5,
33 MLX5HWS_ACTION_OFFSET_DW6 = 6,
34 MLX5HWS_ACTION_OFFSET_DW7 = 7,
35 MLX5HWS_ACTION_OFFSET_HIT = 3,
36 MLX5HWS_ACTION_OFFSET_HIT_LSB = 4,
37 };
38
39 enum {
40 MLX5HWS_ACTION_DOUBLE_SIZE = 8,
41 MLX5HWS_ACTION_INLINE_DATA_SIZE = 4,
42 MLX5HWS_ACTION_HDR_LEN_L2_MACS = 12,
43 MLX5HWS_ACTION_HDR_LEN_L2_VLAN = 4,
44 MLX5HWS_ACTION_HDR_LEN_L2_ETHER = 2,
45 MLX5HWS_ACTION_HDR_LEN_L2 = (MLX5HWS_ACTION_HDR_LEN_L2_MACS +
46 MLX5HWS_ACTION_HDR_LEN_L2_ETHER),
47 MLX5HWS_ACTION_HDR_LEN_L2_W_VLAN = (MLX5HWS_ACTION_HDR_LEN_L2 +
48 MLX5HWS_ACTION_HDR_LEN_L2_VLAN),
49 MLX5HWS_ACTION_REFORMAT_DATA_SIZE = 64,
50 DECAP_L3_NUM_ACTIONS_W_NO_VLAN = 6,
51 DECAP_L3_NUM_ACTIONS_W_VLAN = 7,
52 };
53
54 enum mlx5hws_action_setter_flag {
55 ASF_SINGLE1 = 1 << 0,
56 ASF_SINGLE2 = 1 << 1,
57 ASF_SINGLE3 = 1 << 2,
58 ASF_DOUBLE = ASF_SINGLE2 | ASF_SINGLE3,
59 ASF_TRIPLE = ASF_SINGLE1 | ASF_DOUBLE,
60 ASF_INSERT = 1 << 3,
61 ASF_REMOVE = 1 << 4,
62 ASF_MODIFY = 1 << 5,
63 ASF_CTR = 1 << 6,
64 ASF_HIT = 1 << 7,
65 };
66
67 struct mlx5hws_action_default_stc {
68 struct mlx5hws_pool_chunk nop_ctr;
69 struct mlx5hws_pool_chunk nop_dw5;
70 struct mlx5hws_pool_chunk nop_dw6;
71 struct mlx5hws_pool_chunk nop_dw7;
72 struct mlx5hws_pool_chunk default_hit;
73 u32 refcount; /* protected by context ctrl lock */
74 };
75
76 struct mlx5hws_action_shared_stc {
77 struct mlx5hws_pool_chunk stc_chunk;
78 u32 refcount; /* protected by context ctrl lock */
79 };
80
81 struct mlx5hws_actions_apply_data {
82 struct mlx5hws_send_engine *queue;
83 struct mlx5hws_rule_action *rule_action;
84 __be32 *wqe_data;
85 struct mlx5hws_wqe_gta_ctrl_seg *wqe_ctrl;
86 u32 jump_to_action_stc;
87 struct mlx5hws_context_common_res *common_res;
88 enum mlx5hws_table_type tbl_type;
89 u32 next_direct_idx;
90 u8 require_dep;
91 };
92
93 struct mlx5hws_actions_wqe_setter;
94
95 typedef void (*mlx5hws_action_setter_fp)(struct mlx5hws_actions_apply_data *apply,
96 struct mlx5hws_actions_wqe_setter *setter);
97
98 struct mlx5hws_actions_wqe_setter {
99 mlx5hws_action_setter_fp set_single;
100 mlx5hws_action_setter_fp set_double;
101 mlx5hws_action_setter_fp set_triple;
102 mlx5hws_action_setter_fp set_hit;
103 mlx5hws_action_setter_fp set_ctr;
104 u8 idx_single;
105 u8 idx_double;
106 u8 idx_triple;
107 u8 idx_ctr;
108 u8 idx_hit;
109 u8 stage_idx;
110 u8 flags;
111 };
112
113 struct mlx5hws_action_template {
114 struct mlx5hws_actions_wqe_setter setters[MLX5HWS_ACTION_MAX_STE];
115 enum mlx5hws_action_type *action_type_arr;
116 u8 num_of_action_stes;
117 u8 num_actions;
118 u8 only_term;
119 };
120
121 struct mlx5hws_action {
122 u8 type;
123 u8 flags;
124 struct mlx5hws_context *ctx;
125 union {
126 struct {
127 struct mlx5hws_pool_chunk stc;
128 union {
129 struct {
130 u32 pat_id;
131 u32 arg_id;
132 __be64 single_action;
133 u32 nope_locations;
134 u8 num_of_patterns;
135 u8 single_action_type;
136 u8 num_of_actions;
137 u8 max_num_of_actions;
138 u8 require_reparse;
139 } modify_header;
140 struct {
141 u32 arg_id;
142 u32 header_size;
143 u16 max_hdr_sz;
144 u8 num_of_hdrs;
145 u8 anchor;
146 u8 e_anchor;
147 u8 offset;
148 bool encap;
149 u8 require_reparse;
150 } reformat;
151 struct {
152 u32 obj_id;
153 u8 return_reg_id;
154 } aso;
155 struct {
156 u16 vport_num;
157 u16 esw_owner_vhca_id;
158 bool esw_owner_vhca_id_valid;
159 } vport;
160 struct {
161 u32 obj_id;
162 } dest_obj;
163 struct {
164 struct mlx5hws_cmd_forward_tbl *fw_island;
165 size_t num_dest;
166 struct mlx5hws_cmd_set_fte_dest *dest_list;
167 } dest_array;
168 struct {
169 struct mlx5hws_cmd_forward_tbl *fw_island;
170 } flow_sampler;
171 struct {
172 u8 type;
173 u8 start_anchor;
174 u8 end_anchor;
175 u8 num_of_words;
176 bool decap;
177 } insert_hdr;
178 struct {
179 /* PRM start anchor from which header will be removed */
180 u8 anchor;
181 /* Header remove offset in bytes, from the start
182 * anchor to the location where remove header starts.
183 */
184 u8 offset;
185 /* Indicates the removed header size in bytes */
186 size_t size;
187 } remove_header;
188 struct {
189 struct mlx5hws_matcher_action_ste *table_ste;
190 struct mlx5hws_action *hit_ft_action;
191 struct mlx5hws_definer *definer;
192 } range;
193 };
194 };
195
196 struct ibv_flow_action *flow_action;
197 u32 obj_id;
198 struct ibv_qp *qp;
199 };
200 };
201
202 const char *mlx5hws_action_type_to_str(enum mlx5hws_action_type action_type);
203
204 int mlx5hws_action_get_default_stc(struct mlx5hws_context *ctx,
205 u8 tbl_type);
206
207 void mlx5hws_action_put_default_stc(struct mlx5hws_context *ctx,
208 u8 tbl_type);
209
210 void mlx5hws_action_prepare_decap_l3_data(u8 *src, u8 *dst,
211 u16 num_of_actions);
212
213 int mlx5hws_action_template_process(struct mlx5hws_action_template *at);
214
215 bool mlx5hws_action_check_combo(struct mlx5hws_context *ctx,
216 enum mlx5hws_action_type *user_actions,
217 enum mlx5hws_table_type table_type);
218
219 int mlx5hws_action_alloc_single_stc(struct mlx5hws_context *ctx,
220 struct mlx5hws_cmd_stc_modify_attr *stc_attr,
221 u32 table_type,
222 struct mlx5hws_pool_chunk *stc);
223
224 void mlx5hws_action_free_single_stc(struct mlx5hws_context *ctx,
225 u32 table_type,
226 struct mlx5hws_pool_chunk *stc);
227
228 static inline void
mlx5hws_action_setter_default_single(struct mlx5hws_actions_apply_data * apply,struct mlx5hws_actions_wqe_setter * setter)229 mlx5hws_action_setter_default_single(struct mlx5hws_actions_apply_data *apply,
230 struct mlx5hws_actions_wqe_setter *setter)
231 {
232 apply->wqe_data[MLX5HWS_ACTION_OFFSET_DW5] = 0;
233 apply->wqe_ctrl->stc_ix[MLX5HWS_ACTION_STC_IDX_DW5] =
234 htonl(apply->common_res->default_stc->nop_dw5.offset);
235 }
236
237 static inline void
mlx5hws_action_setter_default_double(struct mlx5hws_actions_apply_data * apply,struct mlx5hws_actions_wqe_setter * setter)238 mlx5hws_action_setter_default_double(struct mlx5hws_actions_apply_data *apply,
239 struct mlx5hws_actions_wqe_setter *setter)
240 {
241 apply->wqe_data[MLX5HWS_ACTION_OFFSET_DW6] = 0;
242 apply->wqe_data[MLX5HWS_ACTION_OFFSET_DW7] = 0;
243 apply->wqe_ctrl->stc_ix[MLX5HWS_ACTION_STC_IDX_DW6] =
244 htonl(apply->common_res->default_stc->nop_dw6.offset);
245 apply->wqe_ctrl->stc_ix[MLX5HWS_ACTION_STC_IDX_DW7] =
246 htonl(apply->common_res->default_stc->nop_dw7.offset);
247 }
248
249 static inline void
mlx5hws_action_setter_default_ctr(struct mlx5hws_actions_apply_data * apply,struct mlx5hws_actions_wqe_setter * setter)250 mlx5hws_action_setter_default_ctr(struct mlx5hws_actions_apply_data *apply,
251 struct mlx5hws_actions_wqe_setter *setter)
252 {
253 apply->wqe_data[MLX5HWS_ACTION_OFFSET_DW0] = 0;
254 apply->wqe_ctrl->stc_ix[MLX5HWS_ACTION_STC_IDX_CTRL] =
255 htonl(apply->common_res->default_stc->nop_ctr.offset);
256 }
257
258 static inline void
mlx5hws_action_apply_setter(struct mlx5hws_actions_apply_data * apply,struct mlx5hws_actions_wqe_setter * setter,bool is_jumbo)259 mlx5hws_action_apply_setter(struct mlx5hws_actions_apply_data *apply,
260 struct mlx5hws_actions_wqe_setter *setter,
261 bool is_jumbo)
262 {
263 u8 num_of_actions;
264
265 /* Set control counter */
266 if (setter->set_ctr)
267 setter->set_ctr(apply, setter);
268 else
269 mlx5hws_action_setter_default_ctr(apply, setter);
270
271 if (!is_jumbo) {
272 if (unlikely(setter->set_triple)) {
273 /* Set triple on match */
274 setter->set_triple(apply, setter);
275 num_of_actions = MLX5HWS_ACTION_STC_IDX_LAST_COMBO3;
276 } else {
277 /* Set single and double on match */
278 if (setter->set_single)
279 setter->set_single(apply, setter);
280 else
281 mlx5hws_action_setter_default_single(apply, setter);
282
283 if (setter->set_double)
284 setter->set_double(apply, setter);
285 else
286 mlx5hws_action_setter_default_double(apply, setter);
287
288 num_of_actions = setter->set_double ?
289 MLX5HWS_ACTION_STC_IDX_LAST_COMBO1 :
290 MLX5HWS_ACTION_STC_IDX_LAST_COMBO2;
291 }
292 } else {
293 apply->wqe_data[MLX5HWS_ACTION_OFFSET_DW5] = 0;
294 apply->wqe_data[MLX5HWS_ACTION_OFFSET_DW6] = 0;
295 apply->wqe_data[MLX5HWS_ACTION_OFFSET_DW7] = 0;
296 apply->wqe_ctrl->stc_ix[MLX5HWS_ACTION_STC_IDX_DW5] = 0;
297 apply->wqe_ctrl->stc_ix[MLX5HWS_ACTION_STC_IDX_DW6] = 0;
298 apply->wqe_ctrl->stc_ix[MLX5HWS_ACTION_STC_IDX_DW7] = 0;
299 num_of_actions = MLX5HWS_ACTION_STC_IDX_LAST_JUMBO_STE;
300 }
301
302 /* Set next/final hit action */
303 setter->set_hit(apply, setter);
304
305 /* Set number of actions */
306 apply->wqe_ctrl->stc_ix[MLX5HWS_ACTION_STC_IDX_CTRL] |=
307 htonl(num_of_actions << 29);
308 }
309
310 #endif /* HWS_ACTION_H_ */
311