1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 /* Copyright (c) 2019 Mellanox Technologies. */
7 enum dr_action_domain {
8 DR_ACTION_DOMAIN_NIC_INGRESS,
9 DR_ACTION_DOMAIN_NIC_EGRESS,
10 DR_ACTION_DOMAIN_FDB_INGRESS,
11 DR_ACTION_DOMAIN_FDB_EGRESS,
15 enum dr_action_valid_state {
17 DR_ACTION_STATE_NO_ACTION,
18 DR_ACTION_STATE_ENCAP,
19 DR_ACTION_STATE_DECAP,
20 DR_ACTION_STATE_MODIFY_HDR,
21 DR_ACTION_STATE_POP_VLAN,
22 DR_ACTION_STATE_PUSH_VLAN,
23 DR_ACTION_STATE_NON_TERM,
29 static const char * const action_type_to_str[] = {
30 [DR_ACTION_TYP_TNL_L2_TO_L2] = "DR_ACTION_TYP_TNL_L2_TO_L2",
31 [DR_ACTION_TYP_L2_TO_TNL_L2] = "DR_ACTION_TYP_L2_TO_TNL_L2",
32 [DR_ACTION_TYP_TNL_L3_TO_L2] = "DR_ACTION_TYP_TNL_L3_TO_L2",
33 [DR_ACTION_TYP_L2_TO_TNL_L3] = "DR_ACTION_TYP_L2_TO_TNL_L3",
34 [DR_ACTION_TYP_DROP] = "DR_ACTION_TYP_DROP",
35 [DR_ACTION_TYP_QP] = "DR_ACTION_TYP_QP",
36 [DR_ACTION_TYP_FT] = "DR_ACTION_TYP_FT",
37 [DR_ACTION_TYP_CTR] = "DR_ACTION_TYP_CTR",
38 [DR_ACTION_TYP_TAG] = "DR_ACTION_TYP_TAG",
39 [DR_ACTION_TYP_MODIFY_HDR] = "DR_ACTION_TYP_MODIFY_HDR",
40 [DR_ACTION_TYP_VPORT] = "DR_ACTION_TYP_VPORT",
41 [DR_ACTION_TYP_POP_VLAN] = "DR_ACTION_TYP_POP_VLAN",
42 [DR_ACTION_TYP_PUSH_VLAN] = "DR_ACTION_TYP_PUSH_VLAN",
43 [DR_ACTION_TYP_SAMPLER] = "DR_ACTION_TYP_SAMPLER",
44 [DR_ACTION_TYP_INSERT_HDR] = "DR_ACTION_TYP_INSERT_HDR",
45 [DR_ACTION_TYP_REMOVE_HDR] = "DR_ACTION_TYP_REMOVE_HDR",
46 [DR_ACTION_TYP_ASO_FLOW_METER] = "DR_ACTION_TYP_ASO_FLOW_METER",
47 [DR_ACTION_TYP_RANGE] = "DR_ACTION_TYP_RANGE",
48 [DR_ACTION_TYP_MAX] = "DR_ACTION_UNKNOWN",
51 static const char *dr_action_id_to_str(enum mlx5dr_action_type action_id)
53 if (action_id > DR_ACTION_TYP_MAX)
54 action_id = DR_ACTION_TYP_MAX;
55 return action_type_to_str[action_id];
58 static const enum dr_action_valid_state
59 next_action_state[DR_ACTION_DOMAIN_MAX][DR_ACTION_STATE_MAX][DR_ACTION_TYP_MAX] = {
60 [DR_ACTION_DOMAIN_NIC_INGRESS] = {
61 [DR_ACTION_STATE_NO_ACTION] = {
62 [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM,
63 [DR_ACTION_TYP_QP] = DR_ACTION_STATE_TERM,
64 [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM,
65 [DR_ACTION_TYP_RANGE] = DR_ACTION_STATE_TERM,
66 [DR_ACTION_TYP_SAMPLER] = DR_ACTION_STATE_TERM,
67 [DR_ACTION_TYP_TAG] = DR_ACTION_STATE_NON_TERM,
68 [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_NON_TERM,
69 [DR_ACTION_TYP_TNL_L2_TO_L2] = DR_ACTION_STATE_DECAP,
70 [DR_ACTION_TYP_TNL_L3_TO_L2] = DR_ACTION_STATE_DECAP,
71 [DR_ACTION_TYP_L2_TO_TNL_L2] = DR_ACTION_STATE_ENCAP,
72 [DR_ACTION_TYP_L2_TO_TNL_L3] = DR_ACTION_STATE_ENCAP,
73 [DR_ACTION_TYP_INSERT_HDR] = DR_ACTION_STATE_ENCAP,
74 [DR_ACTION_TYP_REMOVE_HDR] = DR_ACTION_STATE_DECAP,
75 [DR_ACTION_TYP_MODIFY_HDR] = DR_ACTION_STATE_MODIFY_HDR,
76 [DR_ACTION_TYP_POP_VLAN] = DR_ACTION_STATE_POP_VLAN,
77 [DR_ACTION_TYP_PUSH_VLAN] = DR_ACTION_STATE_PUSH_VLAN,
78 [DR_ACTION_TYP_ASO_FLOW_METER] = DR_ACTION_STATE_ASO,
80 [DR_ACTION_STATE_DECAP] = {
81 [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM,
82 [DR_ACTION_TYP_QP] = DR_ACTION_STATE_TERM,
83 [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM,
84 [DR_ACTION_TYP_RANGE] = DR_ACTION_STATE_TERM,
85 [DR_ACTION_TYP_SAMPLER] = DR_ACTION_STATE_TERM,
86 [DR_ACTION_TYP_TAG] = DR_ACTION_STATE_DECAP,
87 [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_DECAP,
88 [DR_ACTION_TYP_L2_TO_TNL_L2] = DR_ACTION_STATE_ENCAP,
89 [DR_ACTION_TYP_L2_TO_TNL_L3] = DR_ACTION_STATE_ENCAP,
90 [DR_ACTION_TYP_INSERT_HDR] = DR_ACTION_STATE_ENCAP,
91 [DR_ACTION_TYP_MODIFY_HDR] = DR_ACTION_STATE_MODIFY_HDR,
92 [DR_ACTION_TYP_POP_VLAN] = DR_ACTION_STATE_POP_VLAN,
93 [DR_ACTION_TYP_PUSH_VLAN] = DR_ACTION_STATE_PUSH_VLAN,
94 [DR_ACTION_TYP_ASO_FLOW_METER] = DR_ACTION_STATE_ASO,
96 [DR_ACTION_STATE_ENCAP] = {
97 [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM,
98 [DR_ACTION_TYP_QP] = DR_ACTION_STATE_TERM,
99 [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM,
100 [DR_ACTION_TYP_RANGE] = DR_ACTION_STATE_TERM,
101 [DR_ACTION_TYP_SAMPLER] = DR_ACTION_STATE_TERM,
102 [DR_ACTION_TYP_TAG] = DR_ACTION_STATE_ENCAP,
103 [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_ENCAP,
104 [DR_ACTION_TYP_ASO_FLOW_METER] = DR_ACTION_STATE_ASO,
106 [DR_ACTION_STATE_MODIFY_HDR] = {
107 [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM,
108 [DR_ACTION_TYP_QP] = DR_ACTION_STATE_TERM,
109 [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM,
110 [DR_ACTION_TYP_RANGE] = DR_ACTION_STATE_TERM,
111 [DR_ACTION_TYP_SAMPLER] = DR_ACTION_STATE_TERM,
112 [DR_ACTION_TYP_TAG] = DR_ACTION_STATE_MODIFY_HDR,
113 [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_MODIFY_HDR,
114 [DR_ACTION_TYP_L2_TO_TNL_L2] = DR_ACTION_STATE_ENCAP,
115 [DR_ACTION_TYP_L2_TO_TNL_L3] = DR_ACTION_STATE_ENCAP,
116 [DR_ACTION_TYP_INSERT_HDR] = DR_ACTION_STATE_ENCAP,
117 [DR_ACTION_TYP_PUSH_VLAN] = DR_ACTION_STATE_PUSH_VLAN,
118 [DR_ACTION_TYP_ASO_FLOW_METER] = DR_ACTION_STATE_ASO,
120 [DR_ACTION_STATE_POP_VLAN] = {
121 [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM,
122 [DR_ACTION_TYP_QP] = DR_ACTION_STATE_TERM,
123 [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM,
124 [DR_ACTION_TYP_RANGE] = DR_ACTION_STATE_TERM,
125 [DR_ACTION_TYP_SAMPLER] = DR_ACTION_STATE_TERM,
126 [DR_ACTION_TYP_TAG] = DR_ACTION_STATE_POP_VLAN,
127 [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_POP_VLAN,
128 [DR_ACTION_TYP_POP_VLAN] = DR_ACTION_STATE_POP_VLAN,
129 [DR_ACTION_TYP_MODIFY_HDR] = DR_ACTION_STATE_MODIFY_HDR,
130 [DR_ACTION_TYP_L2_TO_TNL_L2] = DR_ACTION_STATE_ENCAP,
131 [DR_ACTION_TYP_L2_TO_TNL_L3] = DR_ACTION_STATE_ENCAP,
132 [DR_ACTION_TYP_INSERT_HDR] = DR_ACTION_STATE_ENCAP,
133 [DR_ACTION_TYP_ASO_FLOW_METER] = DR_ACTION_STATE_ASO,
135 [DR_ACTION_STATE_PUSH_VLAN] = {
136 [DR_ACTION_TYP_QP] = DR_ACTION_STATE_TERM,
137 [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM,
138 [DR_ACTION_TYP_RANGE] = DR_ACTION_STATE_TERM,
139 [DR_ACTION_TYP_SAMPLER] = DR_ACTION_STATE_TERM,
140 [DR_ACTION_TYP_TAG] = DR_ACTION_STATE_PUSH_VLAN,
141 [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_PUSH_VLAN,
142 [DR_ACTION_TYP_PUSH_VLAN] = DR_ACTION_STATE_PUSH_VLAN,
143 [DR_ACTION_TYP_L2_TO_TNL_L2] = DR_ACTION_STATE_ENCAP,
144 [DR_ACTION_TYP_L2_TO_TNL_L3] = DR_ACTION_STATE_ENCAP,
145 [DR_ACTION_TYP_ASO_FLOW_METER] = DR_ACTION_STATE_ASO,
147 [DR_ACTION_STATE_NON_TERM] = {
148 [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM,
149 [DR_ACTION_TYP_QP] = DR_ACTION_STATE_TERM,
150 [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM,
151 [DR_ACTION_TYP_RANGE] = DR_ACTION_STATE_TERM,
152 [DR_ACTION_TYP_SAMPLER] = DR_ACTION_STATE_TERM,
153 [DR_ACTION_TYP_TAG] = DR_ACTION_STATE_NON_TERM,
154 [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_NON_TERM,
155 [DR_ACTION_TYP_TNL_L2_TO_L2] = DR_ACTION_STATE_DECAP,
156 [DR_ACTION_TYP_TNL_L3_TO_L2] = DR_ACTION_STATE_DECAP,
157 [DR_ACTION_TYP_L2_TO_TNL_L2] = DR_ACTION_STATE_ENCAP,
158 [DR_ACTION_TYP_L2_TO_TNL_L3] = DR_ACTION_STATE_ENCAP,
159 [DR_ACTION_TYP_INSERT_HDR] = DR_ACTION_STATE_ENCAP,
160 [DR_ACTION_TYP_REMOVE_HDR] = DR_ACTION_STATE_DECAP,
161 [DR_ACTION_TYP_MODIFY_HDR] = DR_ACTION_STATE_MODIFY_HDR,
162 [DR_ACTION_TYP_POP_VLAN] = DR_ACTION_STATE_POP_VLAN,
163 [DR_ACTION_TYP_PUSH_VLAN] = DR_ACTION_STATE_PUSH_VLAN,
164 [DR_ACTION_TYP_ASO_FLOW_METER] = DR_ACTION_STATE_ASO,
166 [DR_ACTION_STATE_ASO] = {
167 [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM,
168 [DR_ACTION_TYP_QP] = DR_ACTION_STATE_TERM,
169 [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM,
170 [DR_ACTION_TYP_RANGE] = DR_ACTION_STATE_TERM,
171 [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_ASO,
173 [DR_ACTION_STATE_TERM] = {
174 [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_TERM,
177 [DR_ACTION_DOMAIN_NIC_EGRESS] = {
178 [DR_ACTION_STATE_NO_ACTION] = {
179 [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM,
180 [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM,
181 [DR_ACTION_TYP_RANGE] = DR_ACTION_STATE_TERM,
182 [DR_ACTION_TYP_SAMPLER] = DR_ACTION_STATE_TERM,
183 [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_NON_TERM,
184 [DR_ACTION_TYP_L2_TO_TNL_L2] = DR_ACTION_STATE_ENCAP,
185 [DR_ACTION_TYP_L2_TO_TNL_L3] = DR_ACTION_STATE_ENCAP,
186 [DR_ACTION_TYP_INSERT_HDR] = DR_ACTION_STATE_ENCAP,
187 [DR_ACTION_TYP_REMOVE_HDR] = DR_ACTION_STATE_DECAP,
188 [DR_ACTION_TYP_MODIFY_HDR] = DR_ACTION_STATE_MODIFY_HDR,
189 [DR_ACTION_TYP_PUSH_VLAN] = DR_ACTION_STATE_PUSH_VLAN,
190 [DR_ACTION_TYP_POP_VLAN] = DR_ACTION_STATE_POP_VLAN,
191 [DR_ACTION_TYP_ASO_FLOW_METER] = DR_ACTION_STATE_ASO,
193 [DR_ACTION_STATE_DECAP] = {
194 [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM,
195 [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM,
196 [DR_ACTION_TYP_RANGE] = DR_ACTION_STATE_TERM,
197 [DR_ACTION_TYP_SAMPLER] = DR_ACTION_STATE_TERM,
198 [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_DECAP,
199 [DR_ACTION_TYP_ASO_FLOW_METER] = DR_ACTION_STATE_ASO,
201 [DR_ACTION_STATE_ENCAP] = {
202 [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM,
203 [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM,
204 [DR_ACTION_TYP_RANGE] = DR_ACTION_STATE_TERM,
205 [DR_ACTION_TYP_SAMPLER] = DR_ACTION_STATE_TERM,
206 [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_ENCAP,
207 [DR_ACTION_TYP_ASO_FLOW_METER] = DR_ACTION_STATE_ASO,
209 [DR_ACTION_STATE_MODIFY_HDR] = {
210 [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM,
211 [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM,
212 [DR_ACTION_TYP_RANGE] = DR_ACTION_STATE_TERM,
213 [DR_ACTION_TYP_SAMPLER] = DR_ACTION_STATE_TERM,
214 [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_MODIFY_HDR,
215 [DR_ACTION_TYP_L2_TO_TNL_L2] = DR_ACTION_STATE_ENCAP,
216 [DR_ACTION_TYP_L2_TO_TNL_L3] = DR_ACTION_STATE_ENCAP,
217 [DR_ACTION_TYP_INSERT_HDR] = DR_ACTION_STATE_ENCAP,
218 [DR_ACTION_TYP_PUSH_VLAN] = DR_ACTION_STATE_PUSH_VLAN,
219 [DR_ACTION_TYP_ASO_FLOW_METER] = DR_ACTION_STATE_ASO,
221 [DR_ACTION_STATE_POP_VLAN] = {
222 [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM,
223 [DR_ACTION_TYP_RANGE] = DR_ACTION_STATE_TERM,
224 [DR_ACTION_TYP_SAMPLER] = DR_ACTION_STATE_TERM,
225 [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_POP_VLAN,
226 [DR_ACTION_TYP_POP_VLAN] = DR_ACTION_STATE_POP_VLAN,
227 [DR_ACTION_TYP_PUSH_VLAN] = DR_ACTION_STATE_PUSH_VLAN,
228 [DR_ACTION_TYP_MODIFY_HDR] = DR_ACTION_STATE_MODIFY_HDR,
229 [DR_ACTION_TYP_L2_TO_TNL_L2] = DR_ACTION_STATE_ENCAP,
230 [DR_ACTION_TYP_L2_TO_TNL_L3] = DR_ACTION_STATE_ENCAP,
231 [DR_ACTION_TYP_INSERT_HDR] = DR_ACTION_STATE_ENCAP,
232 [DR_ACTION_TYP_ASO_FLOW_METER] = DR_ACTION_STATE_ASO,
234 [DR_ACTION_STATE_PUSH_VLAN] = {
235 [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM,
236 [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM,
237 [DR_ACTION_TYP_RANGE] = DR_ACTION_STATE_TERM,
238 [DR_ACTION_TYP_SAMPLER] = DR_ACTION_STATE_TERM,
239 [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_PUSH_VLAN,
240 [DR_ACTION_TYP_PUSH_VLAN] = DR_ACTION_STATE_PUSH_VLAN,
241 [DR_ACTION_TYP_L2_TO_TNL_L2] = DR_ACTION_STATE_ENCAP,
242 [DR_ACTION_TYP_L2_TO_TNL_L3] = DR_ACTION_STATE_ENCAP,
243 [DR_ACTION_TYP_INSERT_HDR] = DR_ACTION_STATE_ENCAP,
244 [DR_ACTION_TYP_ASO_FLOW_METER] = DR_ACTION_STATE_ASO,
246 [DR_ACTION_STATE_NON_TERM] = {
247 [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM,
248 [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM,
249 [DR_ACTION_TYP_RANGE] = DR_ACTION_STATE_TERM,
250 [DR_ACTION_TYP_SAMPLER] = DR_ACTION_STATE_TERM,
251 [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_NON_TERM,
252 [DR_ACTION_TYP_L2_TO_TNL_L2] = DR_ACTION_STATE_ENCAP,
253 [DR_ACTION_TYP_L2_TO_TNL_L3] = DR_ACTION_STATE_ENCAP,
254 [DR_ACTION_TYP_INSERT_HDR] = DR_ACTION_STATE_ENCAP,
255 [DR_ACTION_TYP_REMOVE_HDR] = DR_ACTION_STATE_DECAP,
256 [DR_ACTION_TYP_MODIFY_HDR] = DR_ACTION_STATE_MODIFY_HDR,
257 [DR_ACTION_TYP_PUSH_VLAN] = DR_ACTION_STATE_PUSH_VLAN,
258 [DR_ACTION_TYP_POP_VLAN] = DR_ACTION_STATE_POP_VLAN,
259 [DR_ACTION_TYP_ASO_FLOW_METER] = DR_ACTION_STATE_ASO,
261 [DR_ACTION_STATE_ASO] = {
262 [DR_ACTION_TYP_L2_TO_TNL_L2] = DR_ACTION_STATE_ENCAP,
263 [DR_ACTION_TYP_L2_TO_TNL_L3] = DR_ACTION_STATE_ENCAP,
264 [DR_ACTION_TYP_MODIFY_HDR] = DR_ACTION_STATE_MODIFY_HDR,
265 [DR_ACTION_TYP_PUSH_VLAN] = DR_ACTION_STATE_PUSH_VLAN,
266 [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_ASO,
267 [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM,
268 [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM,
269 [DR_ACTION_TYP_RANGE] = DR_ACTION_STATE_TERM,
271 [DR_ACTION_STATE_TERM] = {
272 [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_TERM,
275 [DR_ACTION_DOMAIN_FDB_INGRESS] = {
276 [DR_ACTION_STATE_NO_ACTION] = {
277 [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM,
278 [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM,
279 [DR_ACTION_TYP_RANGE] = DR_ACTION_STATE_TERM,
280 [DR_ACTION_TYP_SAMPLER] = DR_ACTION_STATE_TERM,
281 [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_NON_TERM,
282 [DR_ACTION_TYP_TNL_L2_TO_L2] = DR_ACTION_STATE_DECAP,
283 [DR_ACTION_TYP_TNL_L3_TO_L2] = DR_ACTION_STATE_DECAP,
284 [DR_ACTION_TYP_L2_TO_TNL_L2] = DR_ACTION_STATE_ENCAP,
285 [DR_ACTION_TYP_L2_TO_TNL_L3] = DR_ACTION_STATE_ENCAP,
286 [DR_ACTION_TYP_INSERT_HDR] = DR_ACTION_STATE_ENCAP,
287 [DR_ACTION_TYP_REMOVE_HDR] = DR_ACTION_STATE_DECAP,
288 [DR_ACTION_TYP_MODIFY_HDR] = DR_ACTION_STATE_MODIFY_HDR,
289 [DR_ACTION_TYP_PUSH_VLAN] = DR_ACTION_STATE_PUSH_VLAN,
290 [DR_ACTION_TYP_POP_VLAN] = DR_ACTION_STATE_POP_VLAN,
291 [DR_ACTION_TYP_VPORT] = DR_ACTION_STATE_TERM,
292 [DR_ACTION_TYP_ASO_FLOW_METER] = DR_ACTION_STATE_ASO,
294 [DR_ACTION_STATE_DECAP] = {
295 [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM,
296 [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM,
297 [DR_ACTION_TYP_RANGE] = DR_ACTION_STATE_TERM,
298 [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_DECAP,
299 [DR_ACTION_TYP_SAMPLER] = DR_ACTION_STATE_TERM,
300 [DR_ACTION_TYP_MODIFY_HDR] = DR_ACTION_STATE_MODIFY_HDR,
301 [DR_ACTION_TYP_VPORT] = DR_ACTION_STATE_TERM,
302 [DR_ACTION_TYP_L2_TO_TNL_L2] = DR_ACTION_STATE_ENCAP,
303 [DR_ACTION_TYP_L2_TO_TNL_L3] = DR_ACTION_STATE_ENCAP,
304 [DR_ACTION_TYP_INSERT_HDR] = DR_ACTION_STATE_ENCAP,
305 [DR_ACTION_TYP_POP_VLAN] = DR_ACTION_STATE_POP_VLAN,
306 [DR_ACTION_TYP_PUSH_VLAN] = DR_ACTION_STATE_PUSH_VLAN,
307 [DR_ACTION_TYP_ASO_FLOW_METER] = DR_ACTION_STATE_ASO,
309 [DR_ACTION_STATE_ENCAP] = {
310 [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM,
311 [DR_ACTION_TYP_QP] = DR_ACTION_STATE_TERM,
312 [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM,
313 [DR_ACTION_TYP_RANGE] = DR_ACTION_STATE_TERM,
314 [DR_ACTION_TYP_VPORT] = DR_ACTION_STATE_TERM,
315 [DR_ACTION_TYP_SAMPLER] = DR_ACTION_STATE_TERM,
316 [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_ENCAP,
317 [DR_ACTION_TYP_ASO_FLOW_METER] = DR_ACTION_STATE_ASO,
319 [DR_ACTION_STATE_MODIFY_HDR] = {
320 [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM,
321 [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM,
322 [DR_ACTION_TYP_RANGE] = DR_ACTION_STATE_TERM,
323 [DR_ACTION_TYP_SAMPLER] = DR_ACTION_STATE_TERM,
324 [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_MODIFY_HDR,
325 [DR_ACTION_TYP_VPORT] = DR_ACTION_STATE_TERM,
326 [DR_ACTION_TYP_L2_TO_TNL_L2] = DR_ACTION_STATE_ENCAP,
327 [DR_ACTION_TYP_L2_TO_TNL_L3] = DR_ACTION_STATE_ENCAP,
328 [DR_ACTION_TYP_INSERT_HDR] = DR_ACTION_STATE_ENCAP,
329 [DR_ACTION_TYP_PUSH_VLAN] = DR_ACTION_STATE_PUSH_VLAN,
330 [DR_ACTION_TYP_ASO_FLOW_METER] = DR_ACTION_STATE_ASO,
332 [DR_ACTION_STATE_POP_VLAN] = {
333 [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM,
334 [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM,
335 [DR_ACTION_TYP_RANGE] = DR_ACTION_STATE_TERM,
336 [DR_ACTION_TYP_SAMPLER] = DR_ACTION_STATE_TERM,
337 [DR_ACTION_TYP_POP_VLAN] = DR_ACTION_STATE_POP_VLAN,
338 [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_POP_VLAN,
339 [DR_ACTION_TYP_VPORT] = DR_ACTION_STATE_TERM,
340 [DR_ACTION_TYP_MODIFY_HDR] = DR_ACTION_STATE_MODIFY_HDR,
341 [DR_ACTION_TYP_L2_TO_TNL_L2] = DR_ACTION_STATE_ENCAP,
342 [DR_ACTION_TYP_L2_TO_TNL_L3] = DR_ACTION_STATE_ENCAP,
343 [DR_ACTION_TYP_INSERT_HDR] = DR_ACTION_STATE_ENCAP,
344 [DR_ACTION_TYP_ASO_FLOW_METER] = DR_ACTION_STATE_ASO,
346 [DR_ACTION_STATE_PUSH_VLAN] = {
347 [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM,
348 [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM,
349 [DR_ACTION_TYP_RANGE] = DR_ACTION_STATE_TERM,
350 [DR_ACTION_TYP_SAMPLER] = DR_ACTION_STATE_TERM,
351 [DR_ACTION_TYP_PUSH_VLAN] = DR_ACTION_STATE_PUSH_VLAN,
352 [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_PUSH_VLAN,
353 [DR_ACTION_TYP_VPORT] = DR_ACTION_STATE_TERM,
354 [DR_ACTION_TYP_MODIFY_HDR] = DR_ACTION_STATE_MODIFY_HDR,
355 [DR_ACTION_TYP_L2_TO_TNL_L2] = DR_ACTION_STATE_ENCAP,
356 [DR_ACTION_TYP_L2_TO_TNL_L3] = DR_ACTION_STATE_ENCAP,
357 [DR_ACTION_TYP_INSERT_HDR] = DR_ACTION_STATE_ENCAP,
358 [DR_ACTION_TYP_ASO_FLOW_METER] = DR_ACTION_STATE_ASO,
360 [DR_ACTION_STATE_NON_TERM] = {
361 [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM,
362 [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM,
363 [DR_ACTION_TYP_RANGE] = DR_ACTION_STATE_TERM,
364 [DR_ACTION_TYP_SAMPLER] = DR_ACTION_STATE_TERM,
365 [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_NON_TERM,
366 [DR_ACTION_TYP_TNL_L2_TO_L2] = DR_ACTION_STATE_DECAP,
367 [DR_ACTION_TYP_TNL_L3_TO_L2] = DR_ACTION_STATE_DECAP,
368 [DR_ACTION_TYP_L2_TO_TNL_L2] = DR_ACTION_STATE_ENCAP,
369 [DR_ACTION_TYP_L2_TO_TNL_L3] = DR_ACTION_STATE_ENCAP,
370 [DR_ACTION_TYP_INSERT_HDR] = DR_ACTION_STATE_ENCAP,
371 [DR_ACTION_TYP_REMOVE_HDR] = DR_ACTION_STATE_DECAP,
372 [DR_ACTION_TYP_MODIFY_HDR] = DR_ACTION_STATE_MODIFY_HDR,
373 [DR_ACTION_TYP_POP_VLAN] = DR_ACTION_STATE_POP_VLAN,
374 [DR_ACTION_TYP_PUSH_VLAN] = DR_ACTION_STATE_PUSH_VLAN,
375 [DR_ACTION_TYP_VPORT] = DR_ACTION_STATE_TERM,
376 [DR_ACTION_TYP_ASO_FLOW_METER] = DR_ACTION_STATE_ASO,
378 [DR_ACTION_STATE_ASO] = {
379 [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM,
380 [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM,
381 [DR_ACTION_TYP_RANGE] = DR_ACTION_STATE_TERM,
382 [DR_ACTION_TYP_VPORT] = DR_ACTION_STATE_TERM,
383 [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_ASO,
385 [DR_ACTION_STATE_TERM] = {
386 [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_TERM,
389 [DR_ACTION_DOMAIN_FDB_EGRESS] = {
390 [DR_ACTION_STATE_NO_ACTION] = {
391 [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM,
392 [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM,
393 [DR_ACTION_TYP_RANGE] = DR_ACTION_STATE_TERM,
394 [DR_ACTION_TYP_SAMPLER] = DR_ACTION_STATE_TERM,
395 [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_NON_TERM,
396 [DR_ACTION_TYP_MODIFY_HDR] = DR_ACTION_STATE_MODIFY_HDR,
397 [DR_ACTION_TYP_L2_TO_TNL_L2] = DR_ACTION_STATE_ENCAP,
398 [DR_ACTION_TYP_L2_TO_TNL_L3] = DR_ACTION_STATE_ENCAP,
399 [DR_ACTION_TYP_INSERT_HDR] = DR_ACTION_STATE_ENCAP,
400 [DR_ACTION_TYP_REMOVE_HDR] = DR_ACTION_STATE_DECAP,
401 [DR_ACTION_TYP_PUSH_VLAN] = DR_ACTION_STATE_PUSH_VLAN,
402 [DR_ACTION_TYP_POP_VLAN] = DR_ACTION_STATE_POP_VLAN,
403 [DR_ACTION_TYP_VPORT] = DR_ACTION_STATE_TERM,
404 [DR_ACTION_TYP_ASO_FLOW_METER] = DR_ACTION_STATE_ASO,
406 [DR_ACTION_STATE_DECAP] = {
407 [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM,
408 [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM,
409 [DR_ACTION_TYP_RANGE] = DR_ACTION_STATE_TERM,
410 [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_DECAP,
411 [DR_ACTION_TYP_VPORT] = DR_ACTION_STATE_TERM,
412 [DR_ACTION_TYP_SAMPLER] = DR_ACTION_STATE_TERM,
413 [DR_ACTION_TYP_ASO_FLOW_METER] = DR_ACTION_STATE_ASO,
415 [DR_ACTION_STATE_ENCAP] = {
416 [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM,
417 [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM,
418 [DR_ACTION_TYP_RANGE] = DR_ACTION_STATE_TERM,
419 [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_ENCAP,
420 [DR_ACTION_TYP_SAMPLER] = DR_ACTION_STATE_TERM,
421 [DR_ACTION_TYP_VPORT] = DR_ACTION_STATE_TERM,
422 [DR_ACTION_TYP_ASO_FLOW_METER] = DR_ACTION_STATE_ASO,
424 [DR_ACTION_STATE_MODIFY_HDR] = {
425 [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM,
426 [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM,
427 [DR_ACTION_TYP_RANGE] = DR_ACTION_STATE_TERM,
428 [DR_ACTION_TYP_SAMPLER] = DR_ACTION_STATE_TERM,
429 [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_MODIFY_HDR,
430 [DR_ACTION_TYP_L2_TO_TNL_L2] = DR_ACTION_STATE_ENCAP,
431 [DR_ACTION_TYP_L2_TO_TNL_L3] = DR_ACTION_STATE_ENCAP,
432 [DR_ACTION_TYP_INSERT_HDR] = DR_ACTION_STATE_ENCAP,
433 [DR_ACTION_TYP_PUSH_VLAN] = DR_ACTION_STATE_PUSH_VLAN,
434 [DR_ACTION_TYP_VPORT] = DR_ACTION_STATE_TERM,
435 [DR_ACTION_TYP_ASO_FLOW_METER] = DR_ACTION_STATE_ASO,
437 [DR_ACTION_STATE_POP_VLAN] = {
438 [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM,
439 [DR_ACTION_TYP_RANGE] = DR_ACTION_STATE_TERM,
440 [DR_ACTION_TYP_SAMPLER] = DR_ACTION_STATE_TERM,
441 [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_POP_VLAN,
442 [DR_ACTION_TYP_POP_VLAN] = DR_ACTION_STATE_POP_VLAN,
443 [DR_ACTION_TYP_PUSH_VLAN] = DR_ACTION_STATE_PUSH_VLAN,
444 [DR_ACTION_TYP_MODIFY_HDR] = DR_ACTION_STATE_MODIFY_HDR,
445 [DR_ACTION_TYP_L2_TO_TNL_L2] = DR_ACTION_STATE_ENCAP,
446 [DR_ACTION_TYP_L2_TO_TNL_L3] = DR_ACTION_STATE_ENCAP,
447 [DR_ACTION_TYP_INSERT_HDR] = DR_ACTION_STATE_ENCAP,
448 [DR_ACTION_TYP_VPORT] = DR_ACTION_STATE_TERM,
449 [DR_ACTION_TYP_ASO_FLOW_METER] = DR_ACTION_STATE_ASO,
451 [DR_ACTION_STATE_PUSH_VLAN] = {
452 [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM,
453 [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM,
454 [DR_ACTION_TYP_RANGE] = DR_ACTION_STATE_TERM,
455 [DR_ACTION_TYP_SAMPLER] = DR_ACTION_STATE_TERM,
456 [DR_ACTION_TYP_PUSH_VLAN] = DR_ACTION_STATE_PUSH_VLAN,
457 [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_PUSH_VLAN,
458 [DR_ACTION_TYP_L2_TO_TNL_L2] = DR_ACTION_STATE_ENCAP,
459 [DR_ACTION_TYP_L2_TO_TNL_L3] = DR_ACTION_STATE_ENCAP,
460 [DR_ACTION_TYP_INSERT_HDR] = DR_ACTION_STATE_ENCAP,
461 [DR_ACTION_TYP_VPORT] = DR_ACTION_STATE_TERM,
462 [DR_ACTION_TYP_ASO_FLOW_METER] = DR_ACTION_STATE_ASO,
464 [DR_ACTION_STATE_NON_TERM] = {
465 [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM,
466 [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM,
467 [DR_ACTION_TYP_RANGE] = DR_ACTION_STATE_TERM,
468 [DR_ACTION_TYP_SAMPLER] = DR_ACTION_STATE_TERM,
469 [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_NON_TERM,
470 [DR_ACTION_TYP_MODIFY_HDR] = DR_ACTION_STATE_MODIFY_HDR,
471 [DR_ACTION_TYP_L2_TO_TNL_L2] = DR_ACTION_STATE_ENCAP,
472 [DR_ACTION_TYP_L2_TO_TNL_L3] = DR_ACTION_STATE_ENCAP,
473 [DR_ACTION_TYP_INSERT_HDR] = DR_ACTION_STATE_ENCAP,
474 [DR_ACTION_TYP_REMOVE_HDR] = DR_ACTION_STATE_DECAP,
475 [DR_ACTION_TYP_PUSH_VLAN] = DR_ACTION_STATE_PUSH_VLAN,
476 [DR_ACTION_TYP_POP_VLAN] = DR_ACTION_STATE_POP_VLAN,
477 [DR_ACTION_TYP_VPORT] = DR_ACTION_STATE_TERM,
478 [DR_ACTION_TYP_ASO_FLOW_METER] = DR_ACTION_STATE_ASO,
480 [DR_ACTION_STATE_ASO] = {
481 [DR_ACTION_TYP_L2_TO_TNL_L2] = DR_ACTION_STATE_ENCAP,
482 [DR_ACTION_TYP_L2_TO_TNL_L3] = DR_ACTION_STATE_ENCAP,
483 [DR_ACTION_TYP_MODIFY_HDR] = DR_ACTION_STATE_MODIFY_HDR,
484 [DR_ACTION_TYP_PUSH_VLAN] = DR_ACTION_STATE_PUSH_VLAN,
485 [DR_ACTION_TYP_DROP] = DR_ACTION_STATE_TERM,
486 [DR_ACTION_TYP_FT] = DR_ACTION_STATE_TERM,
487 [DR_ACTION_TYP_RANGE] = DR_ACTION_STATE_TERM,
488 [DR_ACTION_TYP_VPORT] = DR_ACTION_STATE_TERM,
489 [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_ASO,
491 [DR_ACTION_STATE_TERM] = {
492 [DR_ACTION_TYP_CTR] = DR_ACTION_STATE_TERM,
498 dr_action_reformat_to_action_type(enum mlx5dr_action_reformat_type reformat_type,
499 enum mlx5dr_action_type *action_type)
501 switch (reformat_type) {
502 case DR_ACTION_REFORMAT_TYP_TNL_L2_TO_L2:
503 *action_type = DR_ACTION_TYP_TNL_L2_TO_L2;
505 case DR_ACTION_REFORMAT_TYP_L2_TO_TNL_L2:
506 *action_type = DR_ACTION_TYP_L2_TO_TNL_L2;
508 case DR_ACTION_REFORMAT_TYP_TNL_L3_TO_L2:
509 *action_type = DR_ACTION_TYP_TNL_L3_TO_L2;
511 case DR_ACTION_REFORMAT_TYP_L2_TO_TNL_L3:
512 *action_type = DR_ACTION_TYP_L2_TO_TNL_L3;
514 case DR_ACTION_REFORMAT_TYP_INSERT_HDR:
515 *action_type = DR_ACTION_TYP_INSERT_HDR;
517 case DR_ACTION_REFORMAT_TYP_REMOVE_HDR:
518 *action_type = DR_ACTION_TYP_REMOVE_HDR;
527 /* Apply the actions on the rule STE array starting from the last_ste.
528 * Actions might require more than one STE, new_num_stes will return
529 * the new size of the STEs array, rule with actions.
531 static void dr_actions_apply(struct mlx5dr_domain *dmn,
532 enum mlx5dr_domain_nic_type nic_type,
535 struct mlx5dr_ste_actions_attr *attr,
538 struct mlx5dr_ste_ctx *ste_ctx = dmn->ste_ctx;
541 if (nic_type == DR_DOMAIN_NIC_TYPE_RX)
542 mlx5dr_ste_set_actions_rx(ste_ctx, dmn, action_type_set,
543 last_ste, attr, &added_stes);
545 mlx5dr_ste_set_actions_tx(ste_ctx, dmn, action_type_set,
546 last_ste, attr, &added_stes);
548 *new_num_stes += added_stes;
551 static enum dr_action_domain
552 dr_action_get_action_domain(enum mlx5dr_domain_type domain,
553 enum mlx5dr_domain_nic_type nic_type)
556 case MLX5DR_DOMAIN_TYPE_NIC_RX:
557 return DR_ACTION_DOMAIN_NIC_INGRESS;
558 case MLX5DR_DOMAIN_TYPE_NIC_TX:
559 return DR_ACTION_DOMAIN_NIC_EGRESS;
560 case MLX5DR_DOMAIN_TYPE_FDB:
561 if (nic_type == DR_DOMAIN_NIC_TYPE_RX)
562 return DR_ACTION_DOMAIN_FDB_INGRESS;
563 return DR_ACTION_DOMAIN_FDB_EGRESS;
566 return DR_ACTION_DOMAIN_MAX;
571 int dr_action_validate_and_get_next_state(enum dr_action_domain action_domain,
575 u32 cur_state = *state;
577 /* Check action state machine is valid */
578 *state = next_action_state[action_domain][cur_state][action_type];
580 if (*state == DR_ACTION_STATE_ERR)
586 static int dr_action_handle_cs_recalc(struct mlx5dr_domain *dmn,
587 struct mlx5dr_action *dest_action,
592 switch (dest_action->action_type) {
593 case DR_ACTION_TYP_FT:
594 /* Allow destination flow table only if table is a terminating
595 * table, since there is an *assumption* that in such case FW
596 * will recalculate the CS.
598 if (dest_action->dest_tbl->is_fw_tbl) {
599 *final_icm_addr = dest_action->dest_tbl->fw_tbl.rx_icm_addr;
602 "Destination FT should be terminating when modify TTL is used\n");
607 case DR_ACTION_TYP_VPORT:
608 /* If destination is vport we will get the FW flow table
609 * that recalculates the CS and forwards to the vport.
611 ret = mlx5dr_domain_get_recalc_cs_ft_addr(dest_action->vport->dmn,
612 dest_action->vport->caps->num,
615 mlx5dr_err(dmn, "Failed to get FW cs recalc flow table\n");
627 static void dr_action_modify_ttl_adjust(struct mlx5dr_domain *dmn,
628 struct mlx5dr_ste_actions_attr *attr,
630 bool *recalc_cs_required)
632 *recalc_cs_required = false;
634 /* if device supports csum recalculation - no adjustment needed */
635 if (mlx5dr_ste_supp_ttl_cs_recalc(&dmn->info.caps))
638 /* no adjustment needed on TX rules */
642 if (!MLX5_CAP_ESW_FLOWTABLE(dmn->mdev, fdb_ipv4_ttl_modify)) {
643 /* Ignore the modify TTL action.
644 * It is always kept as last HW action.
646 attr->modify_actions--;
650 if (dmn->type == MLX5DR_DOMAIN_TYPE_FDB)
651 /* Due to a HW bug on some devices, modifying TTL on RX flows
652 * will cause an incorrect checksum calculation. In such cases
653 * we will use a FW table to recalculate the checksum.
655 *recalc_cs_required = true;
658 static void dr_action_print_sequence(struct mlx5dr_domain *dmn,
659 struct mlx5dr_action *actions[],
664 for (i = 0; i <= last_idx; i++)
665 mlx5dr_err(dmn, "< %s (%d) > ",
666 dr_action_id_to_str(actions[i]->action_type),
667 actions[i]->action_type);
670 static int dr_action_get_dest_fw_tbl_addr(struct mlx5dr_matcher *matcher,
671 struct mlx5dr_action_dest_tbl *dest_tbl,
675 struct mlx5dr_cmd_query_flow_table_details output;
676 struct mlx5dr_domain *dmn = matcher->tbl->dmn;
679 if (!dest_tbl->fw_tbl.rx_icm_addr) {
680 ret = mlx5dr_cmd_query_flow_table(dmn->mdev,
681 dest_tbl->fw_tbl.type,
686 "Failed mlx5_cmd_query_flow_table ret: %d\n",
691 dest_tbl->fw_tbl.tx_icm_addr = output.sw_owner_icm_root_1;
692 dest_tbl->fw_tbl.rx_icm_addr = output.sw_owner_icm_root_0;
695 *final_icm_addr = is_rx_rule ? dest_tbl->fw_tbl.rx_icm_addr :
696 dest_tbl->fw_tbl.tx_icm_addr;
700 static int dr_action_get_dest_sw_tbl_addr(struct mlx5dr_matcher *matcher,
701 struct mlx5dr_action_dest_tbl *dest_tbl,
705 struct mlx5dr_domain *dmn = matcher->tbl->dmn;
706 struct mlx5dr_icm_chunk *chunk;
708 if (dest_tbl->tbl->dmn != dmn) {
710 "Destination table belongs to a different domain\n");
714 if (dest_tbl->tbl->level <= matcher->tbl->level) {
715 mlx5_core_dbg_once(dmn->mdev,
716 "Connecting table to a lower/same level destination table\n");
718 "Connecting table at level %d to a destination table at level %d\n",
720 dest_tbl->tbl->level);
723 chunk = is_rx_rule ? dest_tbl->tbl->rx.s_anchor->chunk :
724 dest_tbl->tbl->tx.s_anchor->chunk;
726 *final_icm_addr = mlx5dr_icm_pool_get_chunk_icm_addr(chunk);
730 static int dr_action_get_dest_tbl_addr(struct mlx5dr_matcher *matcher,
731 struct mlx5dr_action_dest_tbl *dest_tbl,
735 if (dest_tbl->is_fw_tbl)
736 return dr_action_get_dest_fw_tbl_addr(matcher,
741 return dr_action_get_dest_sw_tbl_addr(matcher,
747 #define WITH_VLAN_NUM_HW_ACTIONS 6
749 int mlx5dr_actions_build_ste_arr(struct mlx5dr_matcher *matcher,
750 struct mlx5dr_matcher_rx_tx *nic_matcher,
751 struct mlx5dr_action *actions[],
754 u32 *new_hw_ste_arr_sz)
756 struct mlx5dr_domain_rx_tx *nic_dmn = nic_matcher->nic_tbl->nic_dmn;
757 bool rx_rule = nic_dmn->type == DR_DOMAIN_NIC_TYPE_RX;
758 struct mlx5dr_domain *dmn = matcher->tbl->dmn;
759 u8 action_type_set[DR_ACTION_TYP_MAX] = {};
760 struct mlx5dr_ste_actions_attr attr = {};
761 struct mlx5dr_action *dest_action = NULL;
762 u32 state = DR_ACTION_STATE_NO_ACTION;
763 enum dr_action_domain action_domain;
764 bool recalc_cs_required = false;
768 attr.gvmi = dmn->info.caps.gvmi;
769 attr.hit_gvmi = dmn->info.caps.gvmi;
770 attr.final_icm_addr = nic_dmn->default_icm_addr;
771 action_domain = dr_action_get_action_domain(dmn->type, nic_dmn->type);
773 for (i = 0; i < num_actions; i++) {
774 struct mlx5dr_action *action;
775 int max_actions_type = 1;
779 action_type = action->action_type;
781 switch (action_type) {
782 case DR_ACTION_TYP_DROP:
783 attr.final_icm_addr = nic_dmn->drop_icm_addr;
785 case DR_ACTION_TYP_FT:
786 dest_action = action;
787 ret = dr_action_get_dest_tbl_addr(matcher, action->dest_tbl,
788 rx_rule, &attr.final_icm_addr);
792 case DR_ACTION_TYP_RANGE:
793 ret = dr_action_get_dest_tbl_addr(matcher,
794 action->range->hit_tbl_action->dest_tbl,
795 rx_rule, &attr.final_icm_addr);
799 ret = dr_action_get_dest_tbl_addr(matcher,
800 action->range->miss_tbl_action->dest_tbl,
801 rx_rule, &attr.range.miss_icm_addr);
805 attr.range.definer_id = action->range->definer_id;
806 attr.range.min = action->range->min;
807 attr.range.max = action->range->max;
809 case DR_ACTION_TYP_QP:
810 mlx5dr_info(dmn, "Domain doesn't support QP\n");
812 case DR_ACTION_TYP_CTR:
813 attr.ctr_id = action->ctr->ctr_id +
816 case DR_ACTION_TYP_TAG:
817 attr.flow_tag = action->flow_tag->flow_tag;
819 case DR_ACTION_TYP_TNL_L2_TO_L2:
821 case DR_ACTION_TYP_TNL_L3_TO_L2:
822 if (action->rewrite->ptrn && action->rewrite->arg) {
823 attr.decap_index = mlx5dr_arg_get_obj_id(action->rewrite->arg);
824 attr.decap_actions = action->rewrite->ptrn->num_of_actions;
825 attr.decap_pat_idx = action->rewrite->ptrn->index;
827 attr.decap_index = action->rewrite->index;
828 attr.decap_actions = action->rewrite->num_of_actions;
829 attr.decap_with_vlan =
830 attr.decap_actions == WITH_VLAN_NUM_HW_ACTIONS;
831 attr.decap_pat_idx = MLX5DR_INVALID_PATTERN_INDEX;
834 case DR_ACTION_TYP_MODIFY_HDR:
835 if (action->rewrite->single_action_opt) {
836 attr.modify_actions = action->rewrite->num_of_actions;
837 attr.single_modify_action = action->rewrite->data;
839 if (action->rewrite->ptrn && action->rewrite->arg) {
841 mlx5dr_arg_get_obj_id(action->rewrite->arg);
842 attr.modify_actions = action->rewrite->ptrn->num_of_actions;
843 attr.modify_pat_idx = action->rewrite->ptrn->index;
845 attr.modify_index = action->rewrite->index;
846 attr.modify_actions = action->rewrite->num_of_actions;
847 attr.modify_pat_idx = MLX5DR_INVALID_PATTERN_INDEX;
850 if (action->rewrite->modify_ttl)
851 dr_action_modify_ttl_adjust(dmn, &attr, rx_rule,
852 &recalc_cs_required);
854 case DR_ACTION_TYP_L2_TO_TNL_L2:
855 case DR_ACTION_TYP_L2_TO_TNL_L3:
857 !(dmn->ste_ctx->actions_caps & DR_STE_CTX_ACTION_CAP_RX_ENCAP)) {
858 mlx5dr_info(dmn, "Device doesn't support Encap on RX\n");
861 attr.reformat.size = action->reformat->size;
862 attr.reformat.id = action->reformat->id;
864 case DR_ACTION_TYP_SAMPLER:
865 attr.final_icm_addr = rx_rule ? action->sampler->rx_icm_addr :
866 action->sampler->tx_icm_addr;
868 case DR_ACTION_TYP_VPORT:
869 attr.hit_gvmi = action->vport->caps->vhca_gvmi;
870 dest_action = action;
871 attr.final_icm_addr = rx_rule ?
872 action->vport->caps->icm_address_rx :
873 action->vport->caps->icm_address_tx;
875 case DR_ACTION_TYP_POP_VLAN:
876 if (!rx_rule && !(dmn->ste_ctx->actions_caps &
877 DR_STE_CTX_ACTION_CAP_TX_POP)) {
878 mlx5dr_dbg(dmn, "Device doesn't support POP VLAN action on TX\n");
882 max_actions_type = MLX5DR_MAX_VLANS;
885 case DR_ACTION_TYP_PUSH_VLAN:
886 if (rx_rule && !(dmn->ste_ctx->actions_caps &
887 DR_STE_CTX_ACTION_CAP_RX_PUSH)) {
888 mlx5dr_dbg(dmn, "Device doesn't support PUSH VLAN action on RX\n");
892 max_actions_type = MLX5DR_MAX_VLANS;
893 if (attr.vlans.count == MLX5DR_MAX_VLANS) {
894 mlx5dr_dbg(dmn, "Max VLAN push/pop count exceeded\n");
898 attr.vlans.headers[attr.vlans.count++] = action->push_vlan->vlan_hdr;
900 case DR_ACTION_TYP_INSERT_HDR:
901 case DR_ACTION_TYP_REMOVE_HDR:
902 attr.reformat.size = action->reformat->size;
903 attr.reformat.id = action->reformat->id;
904 attr.reformat.param_0 = action->reformat->param_0;
905 attr.reformat.param_1 = action->reformat->param_1;
907 case DR_ACTION_TYP_ASO_FLOW_METER:
908 attr.aso_flow_meter.obj_id = action->aso->obj_id;
909 attr.aso_flow_meter.offset = action->aso->offset;
910 attr.aso_flow_meter.dest_reg_id = action->aso->dest_reg_id;
911 attr.aso_flow_meter.init_color = action->aso->init_color;
914 mlx5dr_err(dmn, "Unsupported action type %d\n", action_type);
918 /* Check action duplication */
919 if (++action_type_set[action_type] > max_actions_type) {
920 mlx5dr_err(dmn, "Action type %d supports only max %d time(s)\n",
921 action_type, max_actions_type);
925 /* Check action state machine is valid */
926 if (dr_action_validate_and_get_next_state(action_domain,
929 mlx5dr_err(dmn, "Invalid action (gvmi: %d, is_rx: %d) sequence provided:",
931 dr_action_print_sequence(dmn, actions, i);
936 *new_hw_ste_arr_sz = nic_matcher->num_of_builders;
937 last_ste = ste_arr + DR_STE_SIZE * (nic_matcher->num_of_builders - 1);
939 if (recalc_cs_required && dest_action) {
940 ret = dr_action_handle_cs_recalc(dmn, dest_action, &attr.final_icm_addr);
943 "Failed to handle checksum recalculation err %d\n",
949 dr_actions_apply(dmn,
959 static unsigned int action_size[DR_ACTION_TYP_MAX] = {
960 [DR_ACTION_TYP_TNL_L2_TO_L2] = sizeof(struct mlx5dr_action_reformat),
961 [DR_ACTION_TYP_L2_TO_TNL_L2] = sizeof(struct mlx5dr_action_reformat),
962 [DR_ACTION_TYP_TNL_L3_TO_L2] = sizeof(struct mlx5dr_action_rewrite),
963 [DR_ACTION_TYP_L2_TO_TNL_L3] = sizeof(struct mlx5dr_action_reformat),
964 [DR_ACTION_TYP_FT] = sizeof(struct mlx5dr_action_dest_tbl),
965 [DR_ACTION_TYP_CTR] = sizeof(struct mlx5dr_action_ctr),
966 [DR_ACTION_TYP_TAG] = sizeof(struct mlx5dr_action_flow_tag),
967 [DR_ACTION_TYP_MODIFY_HDR] = sizeof(struct mlx5dr_action_rewrite),
968 [DR_ACTION_TYP_VPORT] = sizeof(struct mlx5dr_action_vport),
969 [DR_ACTION_TYP_PUSH_VLAN] = sizeof(struct mlx5dr_action_push_vlan),
970 [DR_ACTION_TYP_INSERT_HDR] = sizeof(struct mlx5dr_action_reformat),
971 [DR_ACTION_TYP_REMOVE_HDR] = sizeof(struct mlx5dr_action_reformat),
972 [DR_ACTION_TYP_SAMPLER] = sizeof(struct mlx5dr_action_sampler),
973 [DR_ACTION_TYP_ASO_FLOW_METER] = sizeof(struct mlx5dr_action_aso_flow_meter),
974 [DR_ACTION_TYP_RANGE] = sizeof(struct mlx5dr_action_range),
977 static struct mlx5dr_action *
978 dr_action_create_generic(enum mlx5dr_action_type action_type)
980 struct mlx5dr_action *action;
983 if (action_type < DR_ACTION_TYP_MAX)
984 extra_size = action_size[action_type];
988 action = kzalloc(sizeof(*action) + extra_size, GFP_KERNEL);
992 action->action_type = action_type;
993 refcount_set(&action->refcount, 1);
994 action->data = action + 1;
999 struct mlx5dr_action *mlx5dr_action_create_drop(void)
1001 return dr_action_create_generic(DR_ACTION_TYP_DROP);
1004 struct mlx5dr_action *
1005 mlx5dr_action_create_dest_table_num(struct mlx5dr_domain *dmn, u32 table_num)
1007 struct mlx5dr_action *action;
1009 action = dr_action_create_generic(DR_ACTION_TYP_FT);
1013 action->dest_tbl->is_fw_tbl = true;
1014 action->dest_tbl->fw_tbl.dmn = dmn;
1015 action->dest_tbl->fw_tbl.id = table_num;
1016 action->dest_tbl->fw_tbl.type = FS_FT_FDB;
1017 refcount_inc(&dmn->refcount);
1022 struct mlx5dr_action *
1023 mlx5dr_action_create_dest_table(struct mlx5dr_table *tbl)
1025 struct mlx5dr_action *action;
1027 refcount_inc(&tbl->refcount);
1029 action = dr_action_create_generic(DR_ACTION_TYP_FT);
1033 action->dest_tbl->tbl = tbl;
1038 refcount_dec(&tbl->refcount);
1042 static void dr_action_range_definer_fill(u16 *format_id,
1049 *format_id = MLX5_IFC_DEFINER_FORMAT_ID_SELECT;
1051 dw_selectors[0] = MLX5_IFC_DEFINER_FORMAT_OFFSET_OUTER_ETH_PKT_LEN / 4;
1053 for (i = 1; i < MLX5_IFC_DEFINER_DW_SELECTORS_NUM; i++)
1054 dw_selectors[i] = MLX5_IFC_DEFINER_FORMAT_OFFSET_UNUSED;
1056 for (i = 0; i < MLX5_IFC_DEFINER_BYTE_SELECTORS_NUM; i++)
1057 byte_selectors[i] = MLX5_IFC_DEFINER_FORMAT_OFFSET_UNUSED;
1059 MLX5_SET(match_definer_match_mask, match_mask,
1060 match_dw_0, 0xffffUL << 16);
1063 static int dr_action_create_range_definer(struct mlx5dr_action *action)
1065 u8 match_mask[MLX5_FLD_SZ_BYTES(match_definer, match_mask)] = {};
1066 u8 byte_selectors[MLX5_IFC_DEFINER_BYTE_SELECTORS_NUM] = {};
1067 u8 dw_selectors[MLX5_IFC_DEFINER_DW_SELECTORS_NUM] = {};
1068 struct mlx5dr_domain *dmn = action->range->dmn;
1073 dr_action_range_definer_fill(&format_id,
1078 ret = mlx5dr_definer_get(dmn, format_id,
1079 dw_selectors, byte_selectors,
1080 match_mask, &definer_id);
1084 action->range->definer_id = definer_id;
1088 static void dr_action_destroy_range_definer(struct mlx5dr_action *action)
1090 mlx5dr_definer_put(action->range->dmn, action->range->definer_id);
1093 struct mlx5dr_action *
1094 mlx5dr_action_create_dest_match_range(struct mlx5dr_domain *dmn,
1096 struct mlx5_flow_table *hit_ft,
1097 struct mlx5_flow_table *miss_ft,
1101 struct mlx5dr_action *action;
1104 if (!mlx5dr_supp_match_ranges(dmn->mdev)) {
1105 mlx5dr_dbg(dmn, "SELECT definer support is needed for match range\n");
1109 if (field != MLX5_FLOW_DEST_RANGE_FIELD_PKT_LEN ||
1110 min > 0xffff || max > 0xffff) {
1111 mlx5dr_err(dmn, "Invalid match range parameters\n");
1115 action = dr_action_create_generic(DR_ACTION_TYP_RANGE);
1119 action->range->hit_tbl_action =
1120 mlx5dr_is_fw_table(hit_ft) ?
1121 mlx5dr_action_create_dest_flow_fw_table(dmn, hit_ft) :
1122 mlx5dr_action_create_dest_table(hit_ft->fs_dr_table.dr_table);
1124 if (!action->range->hit_tbl_action)
1127 action->range->miss_tbl_action =
1128 mlx5dr_is_fw_table(miss_ft) ?
1129 mlx5dr_action_create_dest_flow_fw_table(dmn, miss_ft) :
1130 mlx5dr_action_create_dest_table(miss_ft->fs_dr_table.dr_table);
1132 if (!action->range->miss_tbl_action)
1133 goto free_hit_tbl_action;
1135 action->range->min = min;
1136 action->range->max = max;
1137 action->range->dmn = dmn;
1139 ret = dr_action_create_range_definer(action);
1141 goto free_miss_tbl_action;
1143 /* No need to increase refcount on domain for this action,
1144 * the hit/miss table actions will do it internally.
1149 free_miss_tbl_action:
1150 mlx5dr_action_destroy(action->range->miss_tbl_action);
1151 free_hit_tbl_action:
1152 mlx5dr_action_destroy(action->range->hit_tbl_action);
1159 struct mlx5dr_action *
1160 mlx5dr_action_create_mult_dest_tbl(struct mlx5dr_domain *dmn,
1161 struct mlx5dr_action_dest *dests,
1163 bool ignore_flow_level,
1166 struct mlx5dr_cmd_flow_destination_hw_info *hw_dests;
1167 struct mlx5dr_action **ref_actions;
1168 struct mlx5dr_action *action;
1169 bool reformat_req = false;
1175 if (dmn->type != MLX5DR_DOMAIN_TYPE_FDB) {
1176 mlx5dr_err(dmn, "Multiple destination support is for FDB only\n");
1180 hw_dests = kcalloc(num_of_dests, sizeof(*hw_dests), GFP_KERNEL);
1184 if (unlikely(check_mul_overflow(num_of_dests, 2u, &ref_act_cnt)))
1187 ref_actions = kcalloc(ref_act_cnt, sizeof(*ref_actions), GFP_KERNEL);
1191 for (i = 0; i < num_of_dests; i++) {
1192 struct mlx5dr_action *reformat_action = dests[i].reformat;
1193 struct mlx5dr_action *dest_action = dests[i].dest;
1195 ref_actions[num_of_ref++] = dest_action;
1197 switch (dest_action->action_type) {
1198 case DR_ACTION_TYP_VPORT:
1199 hw_dests[i].vport.flags = MLX5_FLOW_DEST_VPORT_VHCA_ID;
1200 hw_dests[i].type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
1201 hw_dests[i].vport.num = dest_action->vport->caps->num;
1202 hw_dests[i].vport.vhca_id = dest_action->vport->caps->vhca_gvmi;
1203 if (reformat_action) {
1204 reformat_req = true;
1205 hw_dests[i].vport.reformat_id =
1206 reformat_action->reformat->id;
1207 ref_actions[num_of_ref++] = reformat_action;
1208 hw_dests[i].vport.flags |= MLX5_FLOW_DEST_VPORT_REFORMAT_ID;
1212 case DR_ACTION_TYP_FT:
1213 hw_dests[i].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
1214 if (dest_action->dest_tbl->is_fw_tbl)
1215 hw_dests[i].ft_id = dest_action->dest_tbl->fw_tbl.id;
1217 hw_dests[i].ft_id = dest_action->dest_tbl->tbl->table_id;
1221 mlx5dr_dbg(dmn, "Invalid multiple destinations action\n");
1222 goto free_ref_actions;
1226 action = dr_action_create_generic(DR_ACTION_TYP_FT);
1228 goto free_ref_actions;
1230 ret = mlx5dr_fw_create_md_tbl(dmn,
1234 &action->dest_tbl->fw_tbl.id,
1235 &action->dest_tbl->fw_tbl.group_id,
1241 refcount_inc(&dmn->refcount);
1243 for (i = 0; i < num_of_ref; i++)
1244 refcount_inc(&ref_actions[i]->refcount);
1246 action->dest_tbl->is_fw_tbl = true;
1247 action->dest_tbl->fw_tbl.dmn = dmn;
1248 action->dest_tbl->fw_tbl.type = FS_FT_FDB;
1249 action->dest_tbl->fw_tbl.ref_actions = ref_actions;
1250 action->dest_tbl->fw_tbl.num_of_ref_actions = num_of_ref;
1265 struct mlx5dr_action *
1266 mlx5dr_action_create_dest_flow_fw_table(struct mlx5dr_domain *dmn,
1267 struct mlx5_flow_table *ft)
1269 struct mlx5dr_action *action;
1271 action = dr_action_create_generic(DR_ACTION_TYP_FT);
1275 action->dest_tbl->is_fw_tbl = 1;
1276 action->dest_tbl->fw_tbl.type = ft->type;
1277 action->dest_tbl->fw_tbl.id = ft->id;
1278 action->dest_tbl->fw_tbl.dmn = dmn;
1280 refcount_inc(&dmn->refcount);
1285 struct mlx5dr_action *
1286 mlx5dr_action_create_flow_counter(u32 counter_id)
1288 struct mlx5dr_action *action;
1290 action = dr_action_create_generic(DR_ACTION_TYP_CTR);
1294 action->ctr->ctr_id = counter_id;
1299 struct mlx5dr_action *mlx5dr_action_create_tag(u32 tag_value)
1301 struct mlx5dr_action *action;
1303 action = dr_action_create_generic(DR_ACTION_TYP_TAG);
1307 action->flow_tag->flow_tag = tag_value & 0xffffff;
1312 struct mlx5dr_action *
1313 mlx5dr_action_create_flow_sampler(struct mlx5dr_domain *dmn, u32 sampler_id)
1315 struct mlx5dr_action *action;
1319 ret = mlx5dr_cmd_query_flow_sampler(dmn->mdev, sampler_id,
1324 action = dr_action_create_generic(DR_ACTION_TYP_SAMPLER);
1328 action->sampler->dmn = dmn;
1329 action->sampler->sampler_id = sampler_id;
1330 action->sampler->rx_icm_addr = icm_rx;
1331 action->sampler->tx_icm_addr = icm_tx;
1333 refcount_inc(&dmn->refcount);
1338 dr_action_verify_reformat_params(enum mlx5dr_action_type reformat_type,
1339 struct mlx5dr_domain *dmn,
1340 u8 reformat_param_0,
1341 u8 reformat_param_1,
1345 if (reformat_type == DR_ACTION_TYP_INSERT_HDR) {
1346 if ((!data && data_sz) || (data && !data_sz) ||
1347 MLX5_CAP_GEN_2(dmn->mdev, max_reformat_insert_size) < data_sz ||
1348 MLX5_CAP_GEN_2(dmn->mdev, max_reformat_insert_offset) < reformat_param_1) {
1349 mlx5dr_dbg(dmn, "Invalid reformat parameters for INSERT_HDR\n");
1352 } else if (reformat_type == DR_ACTION_TYP_REMOVE_HDR) {
1354 MLX5_CAP_GEN_2(dmn->mdev, max_reformat_remove_size) < data_sz ||
1355 MLX5_CAP_GEN_2(dmn->mdev, max_reformat_remove_offset) < reformat_param_1) {
1356 mlx5dr_dbg(dmn, "Invalid reformat parameters for REMOVE_HDR\n");
1359 } else if (reformat_param_0 || reformat_param_1 ||
1360 reformat_type > DR_ACTION_TYP_REMOVE_HDR) {
1361 mlx5dr_dbg(dmn, "Invalid reformat parameters\n");
1365 if (dmn->type == MLX5DR_DOMAIN_TYPE_FDB)
1368 if (dmn->type == MLX5DR_DOMAIN_TYPE_NIC_RX) {
1369 if (reformat_type != DR_ACTION_TYP_TNL_L2_TO_L2 &&
1370 reformat_type != DR_ACTION_TYP_TNL_L3_TO_L2) {
1371 mlx5dr_dbg(dmn, "Action reformat type not support on RX domain\n");
1374 } else if (dmn->type == MLX5DR_DOMAIN_TYPE_NIC_TX) {
1375 if (reformat_type != DR_ACTION_TYP_L2_TO_TNL_L2 &&
1376 reformat_type != DR_ACTION_TYP_L2_TO_TNL_L3) {
1377 mlx5dr_dbg(dmn, "Action reformat type not support on TX domain\n");
1389 dr_action_create_reformat_action(struct mlx5dr_domain *dmn,
1390 u8 reformat_param_0, u8 reformat_param_1,
1391 size_t data_sz, void *data,
1392 struct mlx5dr_action *action)
1397 switch (action->action_type) {
1398 case DR_ACTION_TYP_L2_TO_TNL_L2:
1399 case DR_ACTION_TYP_L2_TO_TNL_L3:
1401 enum mlx5_reformat_ctx_type rt;
1403 if (action->action_type == DR_ACTION_TYP_L2_TO_TNL_L2)
1404 rt = MLX5_REFORMAT_TYPE_L2_TO_L2_TUNNEL;
1406 rt = MLX5_REFORMAT_TYPE_L2_TO_L3_TUNNEL;
1408 ret = mlx5dr_cmd_create_reformat_ctx(dmn->mdev, rt, 0, 0,
1414 action->reformat->id = reformat_id;
1415 action->reformat->size = data_sz;
1418 case DR_ACTION_TYP_TNL_L2_TO_L2:
1422 case DR_ACTION_TYP_TNL_L3_TO_L2:
1427 hw_actions = kzalloc(DR_ACTION_CACHE_LINE_SIZE, GFP_KERNEL);
1431 ret = mlx5dr_ste_set_action_decap_l3_list(dmn->ste_ctx,
1434 DR_ACTION_CACHE_LINE_SIZE,
1435 &action->rewrite->num_of_actions);
1437 mlx5dr_dbg(dmn, "Failed creating decap l3 action list\n");
1442 action->rewrite->data = hw_actions;
1443 action->rewrite->dmn = dmn;
1445 ret = mlx5dr_ste_alloc_modify_hdr(action);
1447 mlx5dr_dbg(dmn, "Failed preparing reformat data\n");
1453 case DR_ACTION_TYP_INSERT_HDR:
1454 ret = mlx5dr_cmd_create_reformat_ctx(dmn->mdev,
1455 MLX5_REFORMAT_TYPE_INSERT_HDR,
1463 action->reformat->id = reformat_id;
1464 action->reformat->size = data_sz;
1465 action->reformat->param_0 = reformat_param_0;
1466 action->reformat->param_1 = reformat_param_1;
1468 case DR_ACTION_TYP_REMOVE_HDR:
1469 action->reformat->id = 0;
1470 action->reformat->size = data_sz;
1471 action->reformat->param_0 = reformat_param_0;
1472 action->reformat->param_1 = reformat_param_1;
1475 mlx5dr_info(dmn, "Reformat type is not supported %d\n", action->action_type);
1480 #define CVLAN_ETHERTYPE 0x8100
1481 #define SVLAN_ETHERTYPE 0x88a8
1483 struct mlx5dr_action *mlx5dr_action_create_pop_vlan(void)
1485 return dr_action_create_generic(DR_ACTION_TYP_POP_VLAN);
1488 struct mlx5dr_action *mlx5dr_action_create_push_vlan(struct mlx5dr_domain *dmn,
1491 u32 vlan_hdr_h = ntohl(vlan_hdr);
1492 u16 ethertype = vlan_hdr_h >> 16;
1493 struct mlx5dr_action *action;
1495 if (ethertype != SVLAN_ETHERTYPE && ethertype != CVLAN_ETHERTYPE) {
1496 mlx5dr_dbg(dmn, "Invalid vlan ethertype\n");
1500 action = dr_action_create_generic(DR_ACTION_TYP_PUSH_VLAN);
1504 action->push_vlan->vlan_hdr = vlan_hdr_h;
1508 struct mlx5dr_action *
1509 mlx5dr_action_create_packet_reformat(struct mlx5dr_domain *dmn,
1510 enum mlx5dr_action_reformat_type reformat_type,
1511 u8 reformat_param_0,
1512 u8 reformat_param_1,
1516 enum mlx5dr_action_type action_type;
1517 struct mlx5dr_action *action;
1520 refcount_inc(&dmn->refcount);
1522 /* General checks */
1523 ret = dr_action_reformat_to_action_type(reformat_type, &action_type);
1525 mlx5dr_dbg(dmn, "Invalid reformat_type provided\n");
1529 ret = dr_action_verify_reformat_params(action_type, dmn,
1530 reformat_param_0, reformat_param_1,
1535 action = dr_action_create_generic(action_type);
1539 action->reformat->dmn = dmn;
1541 ret = dr_action_create_reformat_action(dmn,
1548 mlx5dr_dbg(dmn, "Failed creating reformat action %d\n", ret);
1557 refcount_dec(&dmn->refcount);
1562 dr_action_modify_sw_to_hw_add(struct mlx5dr_domain *dmn,
1565 const struct mlx5dr_ste_action_modify_field **ret_hw_info)
1567 const struct mlx5dr_ste_action_modify_field *hw_action_info;
1572 /* Get SW modify action data */
1573 sw_field = MLX5_GET(set_action_in, sw_action, field);
1574 data = MLX5_GET(set_action_in, sw_action, data);
1576 /* Convert SW data to HW modify action format */
1577 hw_action_info = mlx5dr_ste_conv_modify_hdr_sw_field(dmn->ste_ctx, sw_field);
1578 if (!hw_action_info) {
1579 mlx5dr_dbg(dmn, "Modify add action invalid field given\n");
1583 max_length = hw_action_info->end - hw_action_info->start + 1;
1585 mlx5dr_ste_set_action_add(dmn->ste_ctx,
1587 hw_action_info->hw_field,
1588 hw_action_info->start,
1592 *ret_hw_info = hw_action_info;
1598 dr_action_modify_sw_to_hw_set(struct mlx5dr_domain *dmn,
1601 const struct mlx5dr_ste_action_modify_field **ret_hw_info)
1603 const struct mlx5dr_ste_action_modify_field *hw_action_info;
1604 u8 offset, length, max_length;
1608 /* Get SW modify action data */
1609 length = MLX5_GET(set_action_in, sw_action, length);
1610 offset = MLX5_GET(set_action_in, sw_action, offset);
1611 sw_field = MLX5_GET(set_action_in, sw_action, field);
1612 data = MLX5_GET(set_action_in, sw_action, data);
1614 /* Convert SW data to HW modify action format */
1615 hw_action_info = mlx5dr_ste_conv_modify_hdr_sw_field(dmn->ste_ctx, sw_field);
1616 if (!hw_action_info) {
1617 mlx5dr_dbg(dmn, "Modify set action invalid field given\n");
1621 /* PRM defines that length zero specific length of 32bits */
1622 length = length ? length : 32;
1624 max_length = hw_action_info->end - hw_action_info->start + 1;
1626 if (length + offset > max_length) {
1627 mlx5dr_dbg(dmn, "Modify action length + offset exceeds limit\n");
1631 mlx5dr_ste_set_action_set(dmn->ste_ctx,
1633 hw_action_info->hw_field,
1634 hw_action_info->start + offset,
1638 *ret_hw_info = hw_action_info;
1644 dr_action_modify_sw_to_hw_copy(struct mlx5dr_domain *dmn,
1647 const struct mlx5dr_ste_action_modify_field **ret_dst_hw_info,
1648 const struct mlx5dr_ste_action_modify_field **ret_src_hw_info)
1650 u8 src_offset, dst_offset, src_max_length, dst_max_length, length;
1651 const struct mlx5dr_ste_action_modify_field *hw_dst_action_info;
1652 const struct mlx5dr_ste_action_modify_field *hw_src_action_info;
1653 u16 src_field, dst_field;
1655 /* Get SW modify action data */
1656 src_field = MLX5_GET(copy_action_in, sw_action, src_field);
1657 dst_field = MLX5_GET(copy_action_in, sw_action, dst_field);
1658 src_offset = MLX5_GET(copy_action_in, sw_action, src_offset);
1659 dst_offset = MLX5_GET(copy_action_in, sw_action, dst_offset);
1660 length = MLX5_GET(copy_action_in, sw_action, length);
1662 /* Convert SW data to HW modify action format */
1663 hw_src_action_info = mlx5dr_ste_conv_modify_hdr_sw_field(dmn->ste_ctx, src_field);
1664 hw_dst_action_info = mlx5dr_ste_conv_modify_hdr_sw_field(dmn->ste_ctx, dst_field);
1665 if (!hw_src_action_info || !hw_dst_action_info) {
1666 mlx5dr_dbg(dmn, "Modify copy action invalid field given\n");
1670 /* PRM defines that length zero specific length of 32bits */
1671 length = length ? length : 32;
1673 src_max_length = hw_src_action_info->end -
1674 hw_src_action_info->start + 1;
1675 dst_max_length = hw_dst_action_info->end -
1676 hw_dst_action_info->start + 1;
1678 if (length + src_offset > src_max_length ||
1679 length + dst_offset > dst_max_length) {
1680 mlx5dr_dbg(dmn, "Modify action length + offset exceeds limit\n");
1684 mlx5dr_ste_set_action_copy(dmn->ste_ctx,
1686 hw_dst_action_info->hw_field,
1687 hw_dst_action_info->start + dst_offset,
1689 hw_src_action_info->hw_field,
1690 hw_src_action_info->start + src_offset);
1692 *ret_dst_hw_info = hw_dst_action_info;
1693 *ret_src_hw_info = hw_src_action_info;
1699 dr_action_modify_sw_to_hw(struct mlx5dr_domain *dmn,
1702 const struct mlx5dr_ste_action_modify_field **ret_dst_hw_info,
1703 const struct mlx5dr_ste_action_modify_field **ret_src_hw_info)
1709 *ret_src_hw_info = NULL;
1711 /* Get SW modify action type */
1712 action = MLX5_GET(set_action_in, sw_action, action_type);
1715 case MLX5_ACTION_TYPE_SET:
1716 ret = dr_action_modify_sw_to_hw_set(dmn, sw_action,
1721 case MLX5_ACTION_TYPE_ADD:
1722 ret = dr_action_modify_sw_to_hw_add(dmn, sw_action,
1727 case MLX5_ACTION_TYPE_COPY:
1728 ret = dr_action_modify_sw_to_hw_copy(dmn, sw_action,
1735 mlx5dr_info(dmn, "Unsupported action_type for modify action\n");
1743 dr_action_modify_check_set_field_limitation(struct mlx5dr_action *action,
1744 const __be64 *sw_action)
1746 u16 sw_field = MLX5_GET(set_action_in, sw_action, field);
1747 struct mlx5dr_domain *dmn = action->rewrite->dmn;
1749 if (sw_field == MLX5_ACTION_IN_FIELD_METADATA_REG_A) {
1750 action->rewrite->allow_rx = 0;
1751 if (dmn->type != MLX5DR_DOMAIN_TYPE_NIC_TX) {
1752 mlx5dr_dbg(dmn, "Unsupported field %d for RX/FDB set action\n",
1756 } else if (sw_field == MLX5_ACTION_IN_FIELD_METADATA_REG_B) {
1757 action->rewrite->allow_tx = 0;
1758 if (dmn->type != MLX5DR_DOMAIN_TYPE_NIC_RX) {
1759 mlx5dr_dbg(dmn, "Unsupported field %d for TX/FDB set action\n",
1765 if (!action->rewrite->allow_rx && !action->rewrite->allow_tx) {
1766 mlx5dr_dbg(dmn, "Modify SET actions not supported on both RX and TX\n");
1774 dr_action_modify_check_add_field_limitation(struct mlx5dr_action *action,
1775 const __be64 *sw_action)
1777 u16 sw_field = MLX5_GET(set_action_in, sw_action, field);
1778 struct mlx5dr_domain *dmn = action->rewrite->dmn;
1780 if (sw_field != MLX5_ACTION_IN_FIELD_OUT_IP_TTL &&
1781 sw_field != MLX5_ACTION_IN_FIELD_OUT_IPV6_HOPLIMIT &&
1782 sw_field != MLX5_ACTION_IN_FIELD_OUT_TCP_SEQ_NUM &&
1783 sw_field != MLX5_ACTION_IN_FIELD_OUT_TCP_ACK_NUM) {
1784 mlx5dr_dbg(dmn, "Unsupported field %d for add action\n",
1793 dr_action_modify_check_copy_field_limitation(struct mlx5dr_action *action,
1794 const __be64 *sw_action)
1796 struct mlx5dr_domain *dmn = action->rewrite->dmn;
1800 sw_fields[0] = MLX5_GET(copy_action_in, sw_action, src_field);
1801 sw_fields[1] = MLX5_GET(copy_action_in, sw_action, dst_field);
1803 for (i = 0; i < 2; i++) {
1804 if (sw_fields[i] == MLX5_ACTION_IN_FIELD_METADATA_REG_A) {
1805 action->rewrite->allow_rx = 0;
1806 if (dmn->type != MLX5DR_DOMAIN_TYPE_NIC_TX) {
1807 mlx5dr_dbg(dmn, "Unsupported field %d for RX/FDB set action\n",
1811 } else if (sw_fields[i] == MLX5_ACTION_IN_FIELD_METADATA_REG_B) {
1812 action->rewrite->allow_tx = 0;
1813 if (dmn->type != MLX5DR_DOMAIN_TYPE_NIC_RX) {
1814 mlx5dr_dbg(dmn, "Unsupported field %d for TX/FDB set action\n",
1821 if (!action->rewrite->allow_rx && !action->rewrite->allow_tx) {
1822 mlx5dr_dbg(dmn, "Modify copy actions not supported on both RX and TX\n");
1830 dr_action_modify_check_field_limitation(struct mlx5dr_action *action,
1831 const __be64 *sw_action)
1833 struct mlx5dr_domain *dmn = action->rewrite->dmn;
1837 action_type = MLX5_GET(set_action_in, sw_action, action_type);
1839 switch (action_type) {
1840 case MLX5_ACTION_TYPE_SET:
1841 ret = dr_action_modify_check_set_field_limitation(action,
1845 case MLX5_ACTION_TYPE_ADD:
1846 ret = dr_action_modify_check_add_field_limitation(action,
1850 case MLX5_ACTION_TYPE_COPY:
1851 ret = dr_action_modify_check_copy_field_limitation(action,
1856 mlx5dr_info(dmn, "Unsupported action %d modify action\n",
1865 dr_action_modify_check_is_ttl_modify(const void *sw_action)
1867 u16 sw_field = MLX5_GET(set_action_in, sw_action, field);
1869 return sw_field == MLX5_ACTION_IN_FIELD_OUT_IP_TTL;
1872 static int dr_actions_convert_modify_header(struct mlx5dr_action *action,
1875 __be64 sw_actions[],
1876 __be64 hw_actions[],
1877 u32 *num_hw_actions,
1880 const struct mlx5dr_ste_action_modify_field *hw_dst_action_info;
1881 const struct mlx5dr_ste_action_modify_field *hw_src_action_info;
1882 struct mlx5dr_domain *dmn = action->rewrite->dmn;
1883 __be64 *modify_ttl_sw_action = NULL;
1884 int ret, i, hw_idx = 0;
1891 *modify_ttl = false;
1893 action->rewrite->allow_rx = 1;
1894 action->rewrite->allow_tx = 1;
1896 for (i = 0; i < num_sw_actions || modify_ttl_sw_action; i++) {
1897 /* modify TTL is handled separately, as a last action */
1898 if (i == num_sw_actions) {
1899 sw_action = modify_ttl_sw_action;
1900 modify_ttl_sw_action = NULL;
1902 sw_action = &sw_actions[i];
1905 ret = dr_action_modify_check_field_limitation(action,
1910 if (!(*modify_ttl) &&
1911 dr_action_modify_check_is_ttl_modify(sw_action)) {
1912 modify_ttl_sw_action = sw_action;
1917 /* Convert SW action to HW action */
1918 ret = dr_action_modify_sw_to_hw(dmn,
1921 &hw_dst_action_info,
1922 &hw_src_action_info);
1926 /* Due to a HW limitation we cannot modify 2 different L3 types */
1927 if (l3_type && hw_dst_action_info->l3_type &&
1928 hw_dst_action_info->l3_type != l3_type) {
1929 mlx5dr_dbg(dmn, "Action list can't support two different L3 types\n");
1932 if (hw_dst_action_info->l3_type)
1933 l3_type = hw_dst_action_info->l3_type;
1935 /* Due to a HW limitation we cannot modify two different L4 types */
1936 if (l4_type && hw_dst_action_info->l4_type &&
1937 hw_dst_action_info->l4_type != l4_type) {
1938 mlx5dr_dbg(dmn, "Action list can't support two different L4 types\n");
1941 if (hw_dst_action_info->l4_type)
1942 l4_type = hw_dst_action_info->l4_type;
1944 /* HW reads and executes two actions at once this means we
1945 * need to create a gap if two actions access the same field
1947 if ((hw_idx % 2) && (hw_field == hw_dst_action_info->hw_field ||
1948 (hw_src_action_info &&
1949 hw_field == hw_src_action_info->hw_field))) {
1950 /* Check if after gap insertion the total number of HW
1951 * modify actions doesn't exceeds the limit
1954 if (hw_idx >= max_hw_actions) {
1955 mlx5dr_dbg(dmn, "Modify header action number exceeds HW limit\n");
1959 hw_field = hw_dst_action_info->hw_field;
1961 hw_actions[hw_idx] = hw_action;
1965 /* if the resulting HW actions list is empty, add NOP action */
1969 *num_hw_actions = hw_idx;
1974 static int dr_action_create_modify_action(struct mlx5dr_domain *dmn,
1977 struct mlx5dr_action *action)
1986 num_sw_actions = actions_sz / DR_MODIFY_ACTION_SIZE;
1987 max_hw_actions = mlx5dr_icm_pool_chunk_size_to_entries(DR_CHUNK_SIZE_16);
1989 if (num_sw_actions > max_hw_actions) {
1990 mlx5dr_dbg(dmn, "Max number of actions %d exceeds limit %d\n",
1991 num_sw_actions, max_hw_actions);
1995 hw_actions = kcalloc(1, max_hw_actions * DR_MODIFY_ACTION_SIZE, GFP_KERNEL);
1999 ret = dr_actions_convert_modify_header(action,
2007 goto free_hw_actions;
2009 action->rewrite->modify_ttl = modify_ttl;
2010 action->rewrite->data = (u8 *)hw_actions;
2011 action->rewrite->num_of_actions = num_hw_actions;
2013 if (num_hw_actions == 1 &&
2014 dmn->info.caps.sw_format_ver >= MLX5_STEERING_FORMAT_CONNECTX_6DX) {
2015 action->rewrite->single_action_opt = true;
2017 action->rewrite->single_action_opt = false;
2018 ret = mlx5dr_ste_alloc_modify_hdr(action);
2020 goto free_hw_actions;
2030 struct mlx5dr_action *
2031 mlx5dr_action_create_modify_header(struct mlx5dr_domain *dmn,
2036 struct mlx5dr_action *action;
2039 refcount_inc(&dmn->refcount);
2041 if (actions_sz % DR_MODIFY_ACTION_SIZE) {
2042 mlx5dr_dbg(dmn, "Invalid modify actions size provided\n");
2046 action = dr_action_create_generic(DR_ACTION_TYP_MODIFY_HDR);
2050 action->rewrite->dmn = dmn;
2052 ret = dr_action_create_modify_action(dmn,
2057 mlx5dr_dbg(dmn, "Failed creating modify header action %d\n", ret);
2066 refcount_dec(&dmn->refcount);
2070 struct mlx5dr_action *
2071 mlx5dr_action_create_dest_vport(struct mlx5dr_domain *dmn,
2072 u16 vport, u8 vhca_id_valid,
2075 struct mlx5dr_cmd_vport_cap *vport_cap;
2076 struct mlx5dr_domain *vport_dmn;
2077 struct mlx5dr_action *action;
2080 peer_vport = vhca_id_valid && mlx5_core_is_pf(dmn->mdev) &&
2081 (vhca_id != dmn->info.caps.gvmi);
2082 vport_dmn = peer_vport ? xa_load(&dmn->peer_dmn_xa, vhca_id) : dmn;
2084 mlx5dr_dbg(dmn, "No peer vport domain for given vhca_id\n");
2088 if (vport_dmn->type != MLX5DR_DOMAIN_TYPE_FDB) {
2089 mlx5dr_dbg(dmn, "Domain doesn't support vport actions\n");
2093 vport_cap = mlx5dr_domain_get_vport_cap(vport_dmn, vport);
2096 "Failed to get vport 0x%x caps - vport is disabled or invalid\n",
2101 action = dr_action_create_generic(DR_ACTION_TYP_VPORT);
2105 action->vport->dmn = vport_dmn;
2106 action->vport->caps = vport_cap;
2111 struct mlx5dr_action *
2112 mlx5dr_action_create_aso(struct mlx5dr_domain *dmn, u32 obj_id,
2113 u8 dest_reg_id, u8 aso_type,
2114 u8 init_color, u8 meter_id)
2116 struct mlx5dr_action *action;
2118 if (aso_type != MLX5_EXE_ASO_FLOW_METER)
2121 if (init_color > MLX5_FLOW_METER_COLOR_UNDEFINED)
2124 action = dr_action_create_generic(DR_ACTION_TYP_ASO_FLOW_METER);
2128 action->aso->obj_id = obj_id;
2129 action->aso->offset = meter_id;
2130 action->aso->dest_reg_id = dest_reg_id;
2131 action->aso->init_color = init_color;
2132 action->aso->dmn = dmn;
2134 refcount_inc(&dmn->refcount);
2139 u32 mlx5dr_action_get_pkt_reformat_id(struct mlx5dr_action *action)
2141 return action->reformat->id;
2144 int mlx5dr_action_destroy(struct mlx5dr_action *action)
2146 if (WARN_ON_ONCE(refcount_read(&action->refcount) > 1))
2149 switch (action->action_type) {
2150 case DR_ACTION_TYP_FT:
2151 if (action->dest_tbl->is_fw_tbl)
2152 refcount_dec(&action->dest_tbl->fw_tbl.dmn->refcount);
2154 refcount_dec(&action->dest_tbl->tbl->refcount);
2156 if (action->dest_tbl->is_fw_tbl &&
2157 action->dest_tbl->fw_tbl.num_of_ref_actions) {
2158 struct mlx5dr_action **ref_actions;
2161 ref_actions = action->dest_tbl->fw_tbl.ref_actions;
2162 for (i = 0; i < action->dest_tbl->fw_tbl.num_of_ref_actions; i++)
2163 refcount_dec(&ref_actions[i]->refcount);
2167 mlx5dr_fw_destroy_md_tbl(action->dest_tbl->fw_tbl.dmn,
2168 action->dest_tbl->fw_tbl.id,
2169 action->dest_tbl->fw_tbl.group_id);
2172 case DR_ACTION_TYP_TNL_L2_TO_L2:
2173 case DR_ACTION_TYP_REMOVE_HDR:
2174 refcount_dec(&action->reformat->dmn->refcount);
2176 case DR_ACTION_TYP_TNL_L3_TO_L2:
2177 mlx5dr_ste_free_modify_hdr(action);
2178 kfree(action->rewrite->data);
2179 refcount_dec(&action->rewrite->dmn->refcount);
2181 case DR_ACTION_TYP_L2_TO_TNL_L2:
2182 case DR_ACTION_TYP_L2_TO_TNL_L3:
2183 case DR_ACTION_TYP_INSERT_HDR:
2184 mlx5dr_cmd_destroy_reformat_ctx((action->reformat->dmn)->mdev,
2185 action->reformat->id);
2186 refcount_dec(&action->reformat->dmn->refcount);
2188 case DR_ACTION_TYP_MODIFY_HDR:
2189 if (!action->rewrite->single_action_opt)
2190 mlx5dr_ste_free_modify_hdr(action);
2191 kfree(action->rewrite->data);
2192 refcount_dec(&action->rewrite->dmn->refcount);
2194 case DR_ACTION_TYP_SAMPLER:
2195 refcount_dec(&action->sampler->dmn->refcount);
2197 case DR_ACTION_TYP_ASO_FLOW_METER:
2198 refcount_dec(&action->aso->dmn->refcount);
2200 case DR_ACTION_TYP_RANGE:
2201 dr_action_destroy_range_definer(action);
2202 mlx5dr_action_destroy(action->range->miss_tbl_action);
2203 mlx5dr_action_destroy(action->range->hit_tbl_action);