xref: /linux/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/action.h (revision 0b6e452caf03da63aeb2e84475771d6fb6d6cd99)
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_range_action_table {
122 	struct mlx5hws_pool *pool;
123 	u32 rtc_0_id;
124 	u32 rtc_1_id;
125 };
126 
127 struct mlx5hws_action {
128 	u8 type;
129 	u8 flags;
130 	struct mlx5hws_context *ctx;
131 	union {
132 		struct {
133 			struct mlx5hws_pool_chunk stc;
134 			union {
135 				struct {
136 					u32 pat_id;
137 					u32 arg_id;
138 					__be64 single_action;
139 					u32 nop_locations;
140 					u8 num_of_patterns;
141 					u8 single_action_type;
142 					u8 num_of_actions;
143 					u8 max_num_of_actions;
144 					u8 require_reparse;
145 				} modify_header;
146 				struct {
147 					u32 arg_id;
148 					u32 header_size;
149 					u16 max_hdr_sz;
150 					u8 num_of_hdrs;
151 					u8 anchor;
152 					u8 e_anchor;
153 					u8 offset;
154 					bool encap;
155 					u8 require_reparse;
156 				} reformat;
157 				struct {
158 					u32 obj_id;
159 					u8 return_reg_id;
160 				} aso;
161 				struct {
162 					u16 vport_num;
163 					u16 esw_owner_vhca_id;
164 					bool esw_owner_vhca_id_valid;
165 				} vport;
166 				struct {
167 					u32 obj_id;
168 				} dest_obj;
169 				struct {
170 					struct mlx5hws_cmd_forward_tbl *fw_island;
171 					size_t num_dest;
172 					struct mlx5hws_cmd_set_fte_dest *dest_list;
173 				} dest_array;
174 				struct {
175 					struct mlx5hws_cmd_forward_tbl *fw_island;
176 				} flow_sampler;
177 				struct {
178 					u8 type;
179 					u8 start_anchor;
180 					u8 end_anchor;
181 					u8 num_of_words;
182 					bool decap;
183 				} insert_hdr;
184 				struct {
185 					/* PRM start anchor from which header will be removed */
186 					u8 anchor;
187 					/* Header remove offset in bytes, from the start
188 					 * anchor to the location where remove header starts.
189 					 */
190 					u8 offset;
191 					/* Indicates the removed header size in bytes */
192 					size_t size;
193 				} remove_header;
194 				struct {
195 					struct mlx5hws_range_action_table *table_ste;
196 					struct mlx5hws_action *hit_ft_action;
197 					struct mlx5hws_definer *definer;
198 				} range;
199 			};
200 		};
201 
202 		struct ibv_flow_action *flow_action;
203 		u32 obj_id;
204 		struct ibv_qp *qp;
205 	};
206 };
207 
208 const char *mlx5hws_action_type_to_str(enum mlx5hws_action_type action_type);
209 
210 int mlx5hws_action_get_default_stc(struct mlx5hws_context *ctx,
211 				   u8 tbl_type);
212 
213 void mlx5hws_action_put_default_stc(struct mlx5hws_context *ctx,
214 				    u8 tbl_type);
215 
216 void mlx5hws_action_prepare_decap_l3_data(u8 *src, u8 *dst,
217 					  u16 num_of_actions);
218 
219 int mlx5hws_action_template_process(struct mlx5hws_action_template *at);
220 
221 bool mlx5hws_action_check_combo(struct mlx5hws_context *ctx,
222 				enum mlx5hws_action_type *user_actions,
223 				enum mlx5hws_table_type table_type);
224 
225 int mlx5hws_action_alloc_single_stc(struct mlx5hws_context *ctx,
226 				    struct mlx5hws_cmd_stc_modify_attr *stc_attr,
227 				    u32 table_type,
228 				    struct mlx5hws_pool_chunk *stc);
229 
230 void mlx5hws_action_free_single_stc(struct mlx5hws_context *ctx,
231 				    u32 table_type,
232 				    struct mlx5hws_pool_chunk *stc);
233 
234 static inline void
mlx5hws_action_setter_default_single(struct mlx5hws_actions_apply_data * apply,struct mlx5hws_actions_wqe_setter * setter)235 mlx5hws_action_setter_default_single(struct mlx5hws_actions_apply_data *apply,
236 				     struct mlx5hws_actions_wqe_setter *setter)
237 {
238 	apply->wqe_data[MLX5HWS_ACTION_OFFSET_DW5] = 0;
239 	apply->wqe_ctrl->stc_ix[MLX5HWS_ACTION_STC_IDX_DW5] =
240 		htonl(apply->common_res->default_stc->nop_dw5.offset);
241 }
242 
243 static inline void
mlx5hws_action_setter_default_double(struct mlx5hws_actions_apply_data * apply,struct mlx5hws_actions_wqe_setter * setter)244 mlx5hws_action_setter_default_double(struct mlx5hws_actions_apply_data *apply,
245 				     struct mlx5hws_actions_wqe_setter *setter)
246 {
247 	apply->wqe_data[MLX5HWS_ACTION_OFFSET_DW6] = 0;
248 	apply->wqe_data[MLX5HWS_ACTION_OFFSET_DW7] = 0;
249 	apply->wqe_ctrl->stc_ix[MLX5HWS_ACTION_STC_IDX_DW6] =
250 		htonl(apply->common_res->default_stc->nop_dw6.offset);
251 	apply->wqe_ctrl->stc_ix[MLX5HWS_ACTION_STC_IDX_DW7] =
252 		htonl(apply->common_res->default_stc->nop_dw7.offset);
253 }
254 
255 static inline void
mlx5hws_action_setter_default_ctr(struct mlx5hws_actions_apply_data * apply,struct mlx5hws_actions_wqe_setter * setter)256 mlx5hws_action_setter_default_ctr(struct mlx5hws_actions_apply_data *apply,
257 				  struct mlx5hws_actions_wqe_setter *setter)
258 {
259 	apply->wqe_data[MLX5HWS_ACTION_OFFSET_DW0] = 0;
260 	apply->wqe_ctrl->stc_ix[MLX5HWS_ACTION_STC_IDX_CTRL] =
261 		htonl(apply->common_res->default_stc->nop_ctr.offset);
262 }
263 
264 static inline void
mlx5hws_action_apply_setter(struct mlx5hws_actions_apply_data * apply,struct mlx5hws_actions_wqe_setter * setter,bool is_jumbo)265 mlx5hws_action_apply_setter(struct mlx5hws_actions_apply_data *apply,
266 			    struct mlx5hws_actions_wqe_setter *setter,
267 			    bool is_jumbo)
268 {
269 	u8 num_of_actions;
270 
271 	/* Set control counter */
272 	if (setter->set_ctr)
273 		setter->set_ctr(apply, setter);
274 	else
275 		mlx5hws_action_setter_default_ctr(apply, setter);
276 
277 	if (!is_jumbo) {
278 		if (unlikely(setter->set_triple)) {
279 			/* Set triple on match */
280 			setter->set_triple(apply, setter);
281 			num_of_actions = MLX5HWS_ACTION_STC_IDX_LAST_COMBO3;
282 		} else {
283 			/* Set single and double on match */
284 			if (setter->set_single)
285 				setter->set_single(apply, setter);
286 			else
287 				mlx5hws_action_setter_default_single(apply, setter);
288 
289 			if (setter->set_double)
290 				setter->set_double(apply, setter);
291 			else
292 				mlx5hws_action_setter_default_double(apply, setter);
293 
294 			num_of_actions = setter->set_double ?
295 				MLX5HWS_ACTION_STC_IDX_LAST_COMBO1 :
296 				MLX5HWS_ACTION_STC_IDX_LAST_COMBO2;
297 		}
298 	} else {
299 		apply->wqe_data[MLX5HWS_ACTION_OFFSET_DW5] = 0;
300 		apply->wqe_data[MLX5HWS_ACTION_OFFSET_DW6] = 0;
301 		apply->wqe_data[MLX5HWS_ACTION_OFFSET_DW7] = 0;
302 		apply->wqe_ctrl->stc_ix[MLX5HWS_ACTION_STC_IDX_DW5] = 0;
303 		apply->wqe_ctrl->stc_ix[MLX5HWS_ACTION_STC_IDX_DW6] = 0;
304 		apply->wqe_ctrl->stc_ix[MLX5HWS_ACTION_STC_IDX_DW7] = 0;
305 		num_of_actions = MLX5HWS_ACTION_STC_IDX_LAST_JUMBO_STE;
306 	}
307 
308 	/* Set next/final hit action */
309 	setter->set_hit(apply, setter);
310 
311 	/* Set number of actions */
312 	apply->wqe_ctrl->stc_ix[MLX5HWS_ACTION_STC_IDX_CTRL] |=
313 		htonl(num_of_actions << 29);
314 }
315 
316 #endif /* HWS_ACTION_H_ */
317