Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C), 2025, Wuxi Stars Micro System Technologies Co., Ltd.
3 : : */
4 : :
5 : : #include <sys/queue.h>
6 : : #include <unistd.h>
7 : : #include "sxe2_ethdev.h"
8 : : #include "sxe2_flow.h"
9 : : #include "sxe2_flow_parse_pattern.h"
10 : : #include "sxe2_flow_parse_action.h"
11 : : #include "sxe2_flow_parse_engine.h"
12 : : #include "sxe2_cmd_chnl.h"
13 : : #include "sxe2_flow_public.h"
14 : : #include "sxe2_common_log.h"
15 : :
16 : 0 : static int32_t sxe2_check_para(const struct rte_flow_attr *attr,
17 : : const struct rte_flow_item pattern[],
18 : : const struct rte_flow_action actions[],
19 : : struct rte_flow_error *error)
20 : : {
21 : 0 : int32_t ret = 0;
22 [ # # ]: 0 : if (!pattern) {
23 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_NUM,
24 : : NULL, "NULL pattern.");
25 : 0 : ret = -rte_errno;
26 : 0 : goto l_end;
27 : : }
28 : :
29 [ # # ]: 0 : if (!actions) {
30 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION_NUM,
31 : : NULL, "NULL action.");
32 : 0 : ret = -rte_errno;
33 : 0 : goto l_end;
34 : : }
35 : :
36 [ # # ]: 0 : if (!attr) {
37 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ATTR,
38 : : NULL, "NULL attribute.");
39 : 0 : ret = -rte_errno;
40 : 0 : goto l_end;
41 : : }
42 : :
43 : 0 : l_end:
44 : 0 : return ret;
45 : : }
46 : :
47 : 0 : static int32_t sxe2_flow_valid_attr(const struct rte_flow_attr *attr, struct rte_flow_error *error)
48 : : {
49 : 0 : int32_t ret = 0;
50 : :
51 [ # # ]: 0 : if (!attr->ingress) {
52 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
53 : : attr, "Only support ingress.");
54 : 0 : ret = -rte_errno;
55 : 0 : goto l_end;
56 : : }
57 : :
58 [ # # ]: 0 : if (attr->egress) {
59 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
60 : : attr, "Not support egress.");
61 : 0 : ret = -rte_errno;
62 : 0 : goto l_end;
63 : : }
64 : :
65 [ # # ]: 0 : if (attr->group >= 4) {
66 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ATTR_GROUP,
67 : : attr, "Not support group >= 4.");
68 : 0 : ret = -rte_errno;
69 : 0 : goto l_end;
70 : : }
71 : 0 : l_end:
72 : 0 : return ret;
73 : : }
74 : :
75 : 0 : static int32_t sxe2_flow_check_hdr_duplicate(struct sxe2_flow_item *item_new,
76 : : struct sxe2_flow_item *item_exist)
77 : : {
78 : 0 : int32_t ret = 0;
79 : 0 : uint16_t i = 0;
80 : 0 : uint16_t size = sizeof(struct sxe2_flow_item);
81 : 0 : union sxe2_flow_item_raw item_raw_new;
82 : 0 : union sxe2_flow_item_raw item_raw_exist;
83 [ # # ]: 0 : rte_memcpy(&item_raw_new.item, item_new, size);
84 [ # # ]: 0 : rte_memcpy(&item_raw_exist.item, item_exist, size);
85 : :
86 [ # # ]: 0 : for (i = 0; i < size; i++) {
87 [ # # ]: 0 : if (item_raw_new.raw[i] != item_raw_exist.raw[i])
88 : 0 : goto l_end;
89 : : }
90 : : ret = -EEXIST;
91 : 0 : l_end:
92 : 0 : return ret;
93 : : }
94 : :
95 : 0 : static int32_t sxe2_flow_check_flow_duplicate(struct sxe2_flow *flow_new,
96 : : struct sxe2_flow *flow_exist)
97 : : {
98 : 0 : int32_t ret = 0;
99 : 0 : int32_t ret_mask1 = 0;
100 : 0 : int32_t ret_mask2 = 0;
101 : 0 : int32_t ret_spec1 = 0;
102 : 0 : int32_t ret_spec2 = 0;
103 : :
104 [ # # ]: 0 : if (flow_new->engine_type != flow_exist->engine_type)
105 : 0 : goto l_end;
106 [ # # ]: 0 : if (flow_new->meta.flow_type != flow_exist->meta.flow_type)
107 : 0 : goto l_end;
108 [ # # ]: 0 : if (!sxe2_bitmap_equal(flow_new->flow_type, flow_exist->flow_type,
109 : : SXE2_EXPANSION_MAX))
110 : 0 : goto l_end;
111 [ # # ]: 0 : if (flow_new->meta.flow_prio != flow_exist->meta.flow_prio)
112 : 0 : goto l_end;
113 : :
114 : 0 : ret_mask1 = sxe2_flow_check_hdr_duplicate(&flow_new->pattern_outer.item_mask,
115 : : &flow_exist->pattern_outer.item_mask);
116 : 0 : ret_mask2 = sxe2_flow_check_hdr_duplicate(&flow_new->pattern_inner.item_mask,
117 : : &flow_exist->pattern_inner.item_mask);
118 : :
119 : 0 : ret_spec1 = sxe2_flow_check_hdr_duplicate(&flow_new->pattern_outer.item_spec,
120 : : &flow_exist->pattern_outer.item_spec);
121 : 0 : ret_spec2 = sxe2_flow_check_hdr_duplicate(&flow_new->pattern_inner.item_spec,
122 : : &flow_exist->pattern_inner.item_spec);
123 : :
124 [ # # ]: 0 : if (flow_new->engine_type == SXE2_FLOW_ENGINE_FNAV) {
125 [ # # ]: 0 : if (ret_mask1 == 0 || ret_mask2 == 0) {
126 : 0 : ret = -EEXIST;
127 : 0 : goto l_end;
128 : : }
129 : :
130 [ # # ]: 0 : if (ret_spec1 == -EEXIST && ret_spec2 == -EEXIST) {
131 : 0 : ret = -EEXIST;
132 : 0 : goto l_end;
133 : : }
134 : : } else {
135 [ # # ]: 0 : if (ret_mask1 == -EEXIST && ret_mask2 == -EEXIST &&
136 [ # # ]: 0 : ret_spec1 == -EEXIST && ret_spec2 == -EEXIST) {
137 : 0 : ret = -EEXIST;
138 : 0 : goto l_end;
139 : : }
140 : : }
141 : :
142 : 0 : l_end:
143 : 0 : return ret;
144 : : }
145 : :
146 : 0 : static int32_t sxe2_flow_check_flow_list_duplicate(struct rte_eth_dev *dev,
147 : : struct rte_flow *flow_list)
148 : : {
149 : 0 : int32_t ret = 0;
150 : 0 : struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
151 : 0 : struct sxe2_flow *sxe2_flow_new = NULL;
152 : 0 : struct rte_flow *rte_flow_exist = NULL;
153 : 0 : struct sxe2_flow *sxe2_flow_exist = NULL;
154 [ # # ]: 0 : TAILQ_FOREACH(sxe2_flow_new, &flow_list->sxe2_flow_list, next) {
155 [ # # ]: 0 : TAILQ_FOREACH(rte_flow_exist, &adapter->flow_ctxt.rte_flow_list, next) {
156 [ # # ]: 0 : TAILQ_FOREACH(sxe2_flow_exist, &rte_flow_exist->sxe2_flow_list, next) {
157 : 0 : ret = sxe2_flow_check_flow_duplicate(sxe2_flow_new,
158 : : sxe2_flow_exist);
159 [ # # ]: 0 : if (ret != 0)
160 : 0 : goto l_end;
161 : : }
162 : : }
163 : : }
164 : 0 : l_end:
165 : 0 : return ret;
166 : : }
167 : :
168 : 0 : static int32_t sxe2_flow_check_function(struct rte_eth_dev *dev,
169 : : struct rte_flow *flow_list,
170 : : struct rte_flow_error *error)
171 : : {
172 : 0 : struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
173 : 0 : struct sxe2_flow_list_t *sxe2_flow_list = &flow_list->sxe2_flow_list;
174 : 0 : struct sxe2_flow *flow = TAILQ_FIRST(sxe2_flow_list);
175 : 0 : int32_t ret = 0;
176 : :
177 : 0 : uint16_t flow_dst_vsi = UINT16_MAX;
178 : :
179 [ # # ]: 0 : if (adapter->dev_type == SXE2_DEV_T_VF) {
180 [ # # ]: 0 : if (sxe2_test_bit(SXE2_FLOW_ACTION_TO_VSI, flow->action.act_types)) {
181 : 0 : flow_dst_vsi = flow->action.vsi.vsi_index;
182 : :
183 [ # # ]: 0 : if (adapter->vsi_ctxt.dpdk_vsi_id != flow_dst_vsi &&
184 [ # # ]: 0 : adapter->vsi_ctxt.kernel_vsi_id != flow_dst_vsi) {
185 : 0 : PMD_LOG_ERR(DRV, "Failed to redirect other function");
186 : 0 : rte_flow_error_set(error, ENOTSUP,
187 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
188 : : "Failed to redirect other function");
189 : 0 : ret = -ENOTSUP;
190 : 0 : goto l_end;
191 : : }
192 : : }
193 : :
194 [ # # ]: 0 : if (sxe2_test_bit(SXE2_FLOW_ACTION_TO_VSI_LIST, flow->action.act_types)) {
195 : 0 : PMD_LOG_ERR(DRV,
196 : : "Failed to redirect multiple driver or function");
197 : 0 : rte_flow_error_set(error, ENOTSUP,
198 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
199 : : "Failed to redirect multiple driver or function");
200 : 0 : ret = -ENOTSUP;
201 : 0 : goto l_end;
202 : : }
203 : :
204 [ # # ]: 0 : if (!adapter->flow_isolated &&
205 [ # # ]: 0 : flow->engine_type == SXE2_FLOW_ENGINE_SWITCH) {
206 : 0 : PMD_LOG_ERR(DRV,
207 : : "Failed to switch engine rules in a non-flow-isolated state");
208 : 0 : rte_flow_error_set(error, ENOTSUP,
209 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
210 : : "Failed to switch engine rules in a non-flow-isolated state");
211 : 0 : ret = -ENOTSUP;
212 : 0 : goto l_end;
213 : : }
214 : :
215 [ # # ]: 0 : if (adapter->switchdev_info.is_switchdev &&
216 [ # # ]: 0 : flow->engine_type == SXE2_FLOW_ENGINE_SWITCH) {
217 : 0 : PMD_LOG_ERR(DRV,
218 : : "Failed to switch engine rules in a switchdev mode state");
219 : 0 : rte_flow_error_set(error, ENOTSUP,
220 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
221 : : "Failed to switch engine rules in a switchdev mode state");
222 : 0 : ret = -ENOTSUP;
223 : 0 : goto l_end;
224 : : }
225 : : }
226 : :
227 [ # # ]: 0 : if (adapter->is_dev_repr) {
228 [ # # ]: 0 : if (flow->engine_type != SXE2_FLOW_ENGINE_SWITCH) {
229 : 0 : PMD_LOG_ERR(DRV,
230 : : "Failed to config non switch engine rules in representor dev");
231 : 0 : rte_flow_error_set(error, ENOTSUP,
232 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
233 : : "Failed to config non switch engine rules in representor dev");
234 : 0 : ret = -ENOTSUP;
235 : 0 : goto l_end;
236 : : }
237 : :
238 [ # # # # ]: 0 : if (sxe2_test_bit(SXE2_FLOW_ACTION_QUEUE, flow->action.act_types) ||
239 [ # # ]: 0 : sxe2_test_bit(SXE2_FLOW_ACTION_Q_REGION, flow->action.act_types)) {
240 : 0 : PMD_LOG_ERR(DRV,
241 : : "Failed to config queue rules in representor dev");
242 : 0 : rte_flow_error_set(error, ENOTSUP,
243 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
244 : : "Failed to config queue rules in representor dev");
245 : 0 : ret = -ENOTSUP;
246 : 0 : goto l_end;
247 : : }
248 : : }
249 : :
250 [ # # # # ]: 0 : if (adapter->switchdev_info.is_switchdev &&
251 [ # # ]: 0 : adapter->dev_type == SXE2_DEV_T_PF &&
252 : 0 : !adapter->is_dev_repr &&
253 [ # # ]: 0 : !adapter->flow_isolated) {
254 [ # # ]: 0 : if (sxe2_test_bit(SXE2_FLOW_ACTION_TO_VSI, flow->action.act_types)) {
255 [ # # ]: 0 : if (flow->action.vsi.vsi_index == adapter->vsi_ctxt.dpdk_vsi_id) {
256 : 0 : PMD_LOG_ERR(DRV,
257 : : "Failed to config rx fwd rule to current uplink dev");
258 : 0 : rte_flow_error_set(error, ENOTSUP,
259 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
260 : : "Failed to config rx fwd rule to current uplink dev");
261 : 0 : ret = -ENOTSUP;
262 : 0 : goto l_end;
263 : : }
264 : : }
265 : : }
266 : :
267 : 0 : l_end:
268 : 0 : return ret;
269 : : }
270 : :
271 : 0 : static int32_t sxe2_flow_meta_proc(struct rte_eth_dev *dev,
272 : : const struct rte_flow_attr *attr,
273 : : struct rte_flow *flow_list,
274 : : struct rte_flow_error *error)
275 : : {
276 : 0 : struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
277 : 0 : struct sxe2_flow_list_t *sxe2_flow_list = &flow_list->sxe2_flow_list;
278 : 0 : struct sxe2_flow *flow = TAILQ_FIRST(sxe2_flow_list);
279 : 0 : int32_t ret = 0;
280 : :
281 [ # # ]: 0 : if (attr->priority >= 1) {
282 [ # # ]: 0 : if (flow->engine_type != SXE2_FLOW_ENGINE_SWITCH) {
283 : 0 : PMD_LOG_ERR(DRV, "Only support priority 0.");
284 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY,
285 : : attr, "Only support priority 0.");
286 : 0 : ret = -rte_errno;
287 : 0 : goto l_end;
288 [ # # ]: 0 : } else if (!adapter->switchdev_info.is_switchdev) {
289 : 0 : PMD_LOG_ERR(DRV, "Legacy mode only support priority 0.");
290 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY,
291 : : attr, "Legacy mode only priority 0.");
292 : 0 : ret = -rte_errno;
293 : 0 : goto l_end;
294 : : } else {
295 : 0 : flow->meta.flow_prio = attr->priority;
296 : : }
297 : : }
298 : :
299 : 0 : flow->meta.flow_src_vsi = adapter->vsi_ctxt.dpdk_vsi_id;
300 : :
301 [ # # # # ]: 0 : if (adapter->is_dev_repr && adapter->repr_priv_data &&
302 [ # # ]: 0 : adapter->repr_priv_data->parent_adapter) {
303 : 0 : flow->meta.flow_rule_vsi =
304 : 0 : adapter->repr_priv_data->parent_adapter->vsi_ctxt.dpdk_vsi_id;
305 : : } else {
306 : 0 : flow->meta.flow_rule_vsi = adapter->vsi_ctxt.dpdk_vsi_id;
307 : : }
308 : :
309 [ # # ]: 0 : if (flow->engine_type == SXE2_FLOW_ENGINE_SWITCH) {
310 : 0 : flow->meta.switch_pattern_dup_allow =
311 : 0 : adapter->devargs.flow_dup_pattern_mode;
312 : :
313 : 0 : flow->meta.switch_src_direct = SXE2_FLOW_SW_DIRECT_RX;
314 : :
315 [ # # # # ]: 0 : if (adapter->switchdev_info.is_switchdev && adapter->is_dev_repr) {
316 : 0 : flow->meta.switch_src_direct = SXE2_FLOW_SW_DIRECT_TX;
317 : 0 : flow->meta.flow_src_vsi = adapter->repr_priv_data->repr_vf_vsi_id;
318 : : }
319 : : }
320 : :
321 : 0 : l_end:
322 : 0 : return ret;
323 : : }
324 : :
325 : 0 : static int32_t sxe2_flow_src_split_proc(struct rte_eth_dev *dev,
326 : : struct rte_flow *flow_list,
327 : : struct rte_flow_error *error)
328 : : {
329 : 0 : struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
330 : 0 : struct sxe2_flow_list_t *sxe2_flow_list = &flow_list->sxe2_flow_list;
331 : 0 : struct sxe2_flow *flow = TAILQ_FIRST(sxe2_flow_list);
332 : 0 : int32_t ret = 0;
333 : :
334 : 0 : int32_t idx = 0;
335 : 0 : uint8_t flow_cnt = 0;
336 : 0 : uint8_t flow_create_cnt = 0;
337 : 0 : uint8_t flow_bond_num = 1;
338 : 0 : uint16_t flow_src_vsi[SXE2_MAX_DRV_TYPE_CNT][SXE2_MAX_BOND_MEMBER_CNT];
339 : 0 : uint16_t flow_dst_vsi = UINT16_MAX;
340 : 0 : struct sxe2_flow *flow_new = NULL;
341 : :
342 [ # # ]: 0 : if (sxe2_test_bit(SXE2_FLOW_ACTION_TO_VSI, flow->action.act_types))
343 : 0 : flow_dst_vsi = flow->action.vsi.vsi_index;
344 : :
345 : 0 : for (idx = 0; idx < SXE2_MAX_BOND_MEMBER_CNT; idx++) {
346 : : flow_src_vsi[SXE2_MAX_DRV_TYPE_DPDK][idx] = UINT16_MAX;
347 : : flow_src_vsi[SXE2_MAX_DRV_TYPE_KERNEL][idx] = UINT16_MAX;
348 : : }
349 : :
350 : 0 : flow_src_vsi[SXE2_MAX_DRV_TYPE_DPDK][0] = adapter->vsi_ctxt.dpdk_vsi_id;
351 : 0 : flow_src_vsi[SXE2_MAX_DRV_TYPE_KERNEL][0] = adapter->vsi_ctxt.kernel_vsi_id;
352 [ # # ]: 0 : if (flow->engine_type == SXE2_FLOW_ENGINE_FNAV ||
353 : : flow->engine_type == SXE2_FLOW_ENGINE_ACL) {
354 [ # # ]: 0 : if (!adapter->devargs.func_flow_direct_en &&
355 [ # # ]: 0 : adapter->dev_type != SXE2_DEV_T_PF_BOND) {
356 [ # # ]: 0 : if (adapter->flow_isolated) {
357 [ # # ]: 0 : for (idx = 0; idx < flow_bond_num; idx++) {
358 [ # # ]: 0 : if (flow_src_vsi[SXE2_MAX_DRV_TYPE_KERNEL][idx] !=
359 : : UINT16_MAX)
360 : 0 : flow_src_vsi[SXE2_MAX_DRV_TYPE_DPDK][idx] =
361 : : UINT16_MAX;
362 : : }
363 : : } else {
364 [ # # ]: 0 : for (idx = 0; idx < flow_bond_num; idx++)
365 : 0 : flow_src_vsi[SXE2_MAX_DRV_TYPE_KERNEL][idx] = UINT16_MAX;
366 : : }
367 : : }
368 : :
369 [ # # ]: 0 : for (idx = 0; idx < flow_bond_num; idx++) {
370 [ # # ]: 0 : if (flow_dst_vsi == flow_src_vsi[SXE2_MAX_DRV_TYPE_KERNEL][idx])
371 : 0 : flow_src_vsi[SXE2_MAX_DRV_TYPE_KERNEL][idx] = UINT16_MAX;
372 [ # # ]: 0 : if (flow_dst_vsi == flow_src_vsi[SXE2_MAX_DRV_TYPE_DPDK][idx])
373 : 0 : flow_src_vsi[SXE2_MAX_DRV_TYPE_DPDK][idx] = UINT16_MAX;
374 : : }
375 : : } else {
376 [ # # ]: 0 : for (idx = 0; idx < flow_bond_num; idx++)
377 : 0 : flow_src_vsi[SXE2_MAX_DRV_TYPE_KERNEL][idx] = UINT16_MAX;
378 : : }
379 : :
380 [ # # # # ]: 0 : if (adapter->switchdev_info.is_switchdev && adapter->is_dev_repr) {
381 : 0 : flow_bond_num = 1;
382 : 0 : flow_src_vsi[SXE2_MAX_DRV_TYPE_DPDK][0] =
383 : 0 : adapter->repr_priv_data->repr_vf_backup_vsi_id;
384 : 0 : flow_src_vsi[SXE2_MAX_DRV_TYPE_KERNEL][0] =
385 : 0 : adapter->repr_priv_data->repr_vf_primary_vsi_id;
386 : : }
387 : :
388 [ # # ]: 0 : for (idx = 0; idx < flow_bond_num; idx++) {
389 [ # # ]: 0 : if (flow_src_vsi[SXE2_MAX_DRV_TYPE_KERNEL][idx] != UINT16_MAX)
390 : 0 : flow_cnt++;
391 [ # # ]: 0 : if (flow_src_vsi[SXE2_MAX_DRV_TYPE_DPDK][idx] != UINT16_MAX)
392 : 0 : flow_cnt++;
393 : : }
394 : :
395 [ # # ]: 0 : if (flow_cnt == 0) {
396 : 0 : PMD_LOG_ERR(DRV, "Failed to redirect same device.");
397 : 0 : rte_flow_error_set(error, ENOTSUP,
398 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
399 : : "Failed to redirect same device");
400 : 0 : ret = -EINVAL;
401 : 0 : goto l_end;
402 : : }
403 : :
404 [ # # ]: 0 : for (idx = 0; idx < flow_bond_num; idx++) {
405 [ # # ]: 0 : if (flow_src_vsi[SXE2_MAX_DRV_TYPE_DPDK][idx] != UINT16_MAX) {
406 [ # # ]: 0 : if (flow_create_cnt == 0) {
407 : 0 : flow->meta.flow_src_vsi =
408 : : flow_src_vsi[SXE2_MAX_DRV_TYPE_DPDK][idx];
409 : 0 : flow_create_cnt++;
410 : : } else {
411 : 0 : flow_new = rte_zmalloc("sxe2_flow", sizeof(*flow), 0);
412 [ # # ]: 0 : if (!flow_new) {
413 : 0 : rte_flow_error_set(error, ENOMEM,
414 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
415 : : "Failed to alloc memory for flow rule");
416 : 0 : ret = -ENOMEM;
417 : 0 : goto l_end;
418 : : }
419 : 0 : *flow_new = *flow;
420 : 0 : TAILQ_INSERT_TAIL(sxe2_flow_list, flow_new, next);
421 : 0 : flow_new->meta.flow_src_vsi =
422 : : flow_src_vsi[SXE2_MAX_DRV_TYPE_DPDK][idx];
423 : 0 : flow_create_cnt++;
424 : : }
425 : : }
426 [ # # ]: 0 : if (flow_src_vsi[SXE2_MAX_DRV_TYPE_KERNEL][idx] != UINT16_MAX) {
427 [ # # ]: 0 : if (flow_create_cnt == 0) {
428 : 0 : flow->meta.flow_src_vsi =
429 : : flow_src_vsi[SXE2_MAX_DRV_TYPE_KERNEL][idx];
430 : 0 : flow_create_cnt++;
431 : : } else {
432 : 0 : flow_new = rte_zmalloc("sxe2_flow", sizeof(*flow), 0);
433 [ # # ]: 0 : if (!flow_new) {
434 : 0 : rte_flow_error_set(error, ENOMEM,
435 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
436 : : "Failed to alloc memory for flow rule");
437 : 0 : ret = -ENOMEM;
438 : 0 : goto l_end;
439 : : }
440 : 0 : *flow_new = *flow;
441 : 0 : TAILQ_INSERT_TAIL(sxe2_flow_list, flow_new, next);
442 : 0 : flow_new->meta.flow_src_vsi =
443 : : flow_src_vsi[SXE2_MAX_DRV_TYPE_KERNEL][idx];
444 : 0 : flow_create_cnt++;
445 : : }
446 : : }
447 : : }
448 : :
449 : 0 : l_end:
450 : 0 : return ret;
451 : : }
452 : :
453 : 0 : static int32_t sxe2_flow_adjust_action(struct rte_eth_dev *dev __rte_unused,
454 : : struct rte_flow *flow_list,
455 : : struct rte_flow_error *error __rte_unused)
456 : : {
457 : 0 : struct sxe2_flow_list_t *sxe2_flow_list = &flow_list->sxe2_flow_list;
458 : 0 : struct sxe2_flow *flow = NULL;
459 : 0 : int32_t ret = 0;
460 : 0 : int32_t dest_num = 0;
461 : 0 : int32_t pass_num = 0;
462 : 0 : int32_t mark_num = 0;
463 : 0 : int32_t count_num = 0;
464 : 0 : int32_t drop_num = 0;
465 : :
466 [ # # ]: 0 : TAILQ_FOREACH(flow, sxe2_flow_list, next) {
467 [ # # ]: 0 : if (flow->engine_type == SXE2_FLOW_ENGINE_FNAV) {
468 : 0 : dest_num = sxe2_test_bit(SXE2_FLOW_ACTION_Q_REGION,
469 [ # # ]: 0 : flow->action.act_types) +
470 : 0 : sxe2_test_bit(SXE2_FLOW_ACTION_QUEUE,
471 : 0 : flow->action.act_types);
472 : 0 : pass_num = sxe2_test_bit(SXE2_FLOW_ACTION_PASSTHRU,
473 : 0 : flow->action.act_types);
474 : 0 : mark_num = sxe2_test_bit(SXE2_FLOW_ACTION_MARK,
475 : 0 : flow->action.act_types);
476 : 0 : count_num = sxe2_test_bit(SXE2_FLOW_ACTION_COUNT,
477 : 0 : flow->action.act_types);
478 : 0 : drop_num = sxe2_test_bit(SXE2_FLOW_ACTION_DROP,
479 : 0 : flow->action.act_types);
480 : :
481 [ # # ]: 0 : if (dest_num) {
482 : 0 : sxe2_clear_bit(SXE2_FLOW_ACTION_PASSTHRU,
483 : 0 : flow->action.act_types);
484 : 0 : pass_num = 0;
485 : 0 : sxe2_clear_bit(SXE2_FLOW_ACTION_TO_VSI,
486 : 0 : flow->action.act_types);
487 : : }
488 : :
489 [ # # ]: 0 : if (pass_num)
490 : 0 : flow->action.passthru.vsi_index = flow->meta.flow_src_vsi;
491 : :
492 [ # # ]: 0 : if (mark_num) {
493 [ # # ]: 0 : if (dest_num == 0) {
494 : 0 : flow->action.q_region.q_index = 0;
495 : 0 : flow->action.q_region.region = 7;
496 : 0 : flow->action.q_region.vsi_index = flow->meta.flow_src_vsi;
497 : 0 : sxe2_set_bit(SXE2_FLOW_ACTION_Q_REGION,
498 : 0 : flow->action.act_types);
499 : 0 : dest_num++;
500 : : }
501 : 0 : sxe2_clear_bit(SXE2_FLOW_ACTION_PASSTHRU,
502 : 0 : flow->action.act_types);
503 : 0 : pass_num = 0;
504 : : }
505 [ # # ]: 0 : if (count_num) {
506 [ # # ]: 0 : if (dest_num == 0 && drop_num == 0) {
507 [ # # ]: 0 : if (pass_num == 0) {
508 : 0 : sxe2_set_bit(SXE2_FLOW_ACTION_PASSTHRU,
509 : 0 : flow->action.act_types);
510 : 0 : flow->action.passthru.vsi_index =
511 : 0 : flow->meta.flow_src_vsi;
512 : 0 : pass_num++;
513 : : }
514 : : }
515 : : }
516 : 0 : PMD_LOG_DEBUG(DRV, "dest_num: %d, pass_num: %d, mark_num: %d, count_num: "
517 : : "%d, drop_num: %d", dest_num, pass_num, mark_num, count_num,
518 : : drop_num);
519 : 0 : PMD_LOG_DEBUG(DRV, "src_vsi: %d", flow->meta.flow_src_vsi);
520 : : }
521 : : }
522 : :
523 : 0 : return ret;
524 : : }
525 : :
526 : 0 : int32_t sxe2_flow_init_udp_tunnel_port(struct rte_eth_dev *dev)
527 : : {
528 : 0 : struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
529 : 0 : int32_t ret = 0;
530 : 0 : uint16_t i = 0;
531 : 0 : uint16_t *flow_udp_tunnel_port = NULL;
532 : :
533 : 0 : memset(adapter->flow_ctxt.tunnel_port_list, 0,
534 : : sizeof(adapter->flow_ctxt.tunnel_port_list));
535 : :
536 : 0 : flow_udp_tunnel_port = adapter->flow_ctxt.tunnel_port_list;
537 [ # # ]: 0 : for (i = 0; i < SXE2_FLOW_UDP_TUNNEL_MAX; i++) {
538 [ # # ]: 0 : if (flow_udp_tunnel_port[i] == 0) {
539 : 0 : ret = sxe2_drv_get_udp_tunnel_port(adapter, i,
540 : : &flow_udp_tunnel_port[i]);
541 [ # # ]: 0 : if (ret != 0) {
542 : 0 : PMD_LOG_ERR(DRV, "Failed to get udp tunnel port, proto: %d,"
543 : : "ret: %d", i, ret);
544 : 0 : goto l_end;
545 : : }
546 : : }
547 : : }
548 : :
549 : 0 : l_end:
550 : 0 : return ret;
551 : : }
552 : :
553 : 0 : static int32_t sxe2_flow_add_udp_tunnel_port(struct sxe2_adapter *adapter,
554 : : enum sxe2_flow_udp_tunnel_protocol proto,
555 : : struct sxe2_flow *flow,
556 : : BITMAP_TYPE *flow_type)
557 : : {
558 : 0 : int32_t ret = 0;
559 : 0 : uint16_t tun_port;
560 : :
561 : 0 : tun_port = adapter->flow_ctxt.tunnel_port_list[proto];
562 [ # # ]: 0 : if (tun_port == 0xffff || tun_port == 0) {
563 : 0 : ret = -EINVAL;
564 : 0 : PMD_LOG_ERR(DRV, "UDP tunnel port not initialized, proto: %d", proto);
565 : 0 : goto l_end;
566 : : }
567 [ # # ]: 0 : if (!sxe2_test_bit(SXE2_EXPANSION_OUTER_UDP, flow_type)) {
568 : 0 : ret = -EINVAL;
569 : 0 : PMD_LOG_ERR(DRV, "UDP must be over tunnel");
570 : 0 : goto l_end;
571 : : }
572 [ # # ]: 0 : sxe2_set_bit(SXE2_FLOW_FLD_ID_UDP_DST_PORT, flow->pattern_outer.map_spec);
573 [ # # ]: 0 : flow->pattern_outer.item_spec.udp.dest = rte_cpu_to_be_16(tun_port);
574 : 0 : l_end:
575 : 0 : return ret;
576 : : }
577 : :
578 : 0 : static int32_t sxe2_flow_parse_pattern_ipip(struct sxe2_flow *flow, BITMAP_TYPE *flow_type)
579 : : {
580 [ # # ]: 0 : sxe2_set_bit(SXE2_EXPANSION_IPIP, flow_type);
581 [ # # ]: 0 : if (sxe2_test_bit(SXE2_EXPANSION_OUTER_IPV4, flow_type)) {
582 [ # # ]: 0 : sxe2_set_bit(SXE2_FLOW_FLD_ID_IPV4_PROT, flow->pattern_outer.map_spec);
583 [ # # ]: 0 : if (sxe2_test_bit(SXE2_EXPANSION_IPV4, flow_type))
584 : 0 : flow->pattern_outer.item_spec.ipv4.protocol = SXE2_FLOW_IP_PROTOCOL_IPV4;
585 [ # # ]: 0 : if (sxe2_test_bit(SXE2_EXPANSION_IPV6, flow_type))
586 : 0 : flow->pattern_outer.item_spec.ipv4.protocol = SXE2_FLOW_IP_PROTOCOL_IPV6;
587 : : }
588 [ # # ]: 0 : if (sxe2_test_bit(SXE2_EXPANSION_OUTER_IPV6, flow_type)) {
589 [ # # ]: 0 : sxe2_set_bit(SXE2_FLOW_FLD_ID_IPV6_PROT, flow->pattern_outer.map_spec);
590 [ # # ]: 0 : if (sxe2_test_bit(SXE2_EXPANSION_ETH, flow_type)) {
591 : 0 : flow->pattern_outer.item_spec.ipv6.nexthdr = SXE2_FLOW_IP_PROTOCOL_ETH;
592 : : } else {
593 [ # # ]: 0 : if (sxe2_test_bit(SXE2_EXPANSION_IPV4, flow_type))
594 : 0 : flow->pattern_outer.item_spec.ipv6.nexthdr =
595 : : SXE2_FLOW_IP_PROTOCOL_IPV4;
596 [ # # ]: 0 : if (sxe2_test_bit(SXE2_EXPANSION_IPV6, flow_type))
597 : 0 : flow->pattern_outer.item_spec.ipv6.nexthdr =
598 : : SXE2_FLOW_IP_PROTOCOL_IPV6;
599 : : }
600 : : }
601 : 0 : return 0;
602 : : }
603 : :
604 : 0 : static int32_t sxe2_flow_add_tunnel_port(struct rte_eth_dev *dev,
605 : : struct rte_flow_error *error,
606 : : struct sxe2_flow *flow, BITMAP_TYPE *flow_type,
607 : : enum sxe2_flow_tunnel_type tunnel_type)
608 : : {
609 : 0 : int32_t ret = 0;
610 : 0 : enum sxe2_flow_udp_tunnel_protocol proto = SXE2_FLOW_UDP_TUNNEL_MAX;
611 : 0 : struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
612 : 0 : struct sxe2_flow_pattern *pattern = &flow->pattern_outer;
613 [ # # # # : 0 : switch (tunnel_type) {
# # ]
614 : : case SXE2_FLOW_TUNNEL_TYPE_VXLAN:
615 [ # # ]: 0 : if (sxe2_test_bit(SXE2_EXPANSION_ETH, flow_type)) {
616 : : proto = SXE2_FLOW_UDP_TUNNEL_PROTOCOL_VXLAN;
617 [ # # ]: 0 : } else if (sxe2_test_bit(SXE2_EXPANSION_IPV4, flow_type) ||
618 [ # # ]: 0 : sxe2_test_bit(SXE2_EXPANSION_IPV6, flow_type)) {
619 : : proto = SXE2_FLOW_UDP_TUNNEL_PROTOCOL_VXLAN_GPE;
620 : : }
621 : : break;
622 : : case SXE2_FLOW_TUNNEL_TYPE_GTPU:
623 : : proto = SXE2_FLOW_UDP_TUNNEL_PROTOCOL_GTP_U;
624 : : break;
625 : : case SXE2_FLOW_TUNNEL_TYPE_GENEVE:
626 : : proto = SXE2_FLOW_UDP_TUNNEL_PROTOCOL_GENEVE;
627 : : break;
628 : : case SXE2_FLOW_TUNNEL_TYPE_GRE:
629 [ # # ]: 0 : if (sxe2_test_bit(SXE2_EXPANSION_OUTER_UDP, flow_type)) {
630 : : proto = SXE2_FLOW_UDP_TUNNEL_PROTOCOL_NVGRE;
631 : : } else {
632 [ # # ]: 0 : if (sxe2_test_bit(SXE2_EXPANSION_OUTER_IPV4, flow_type)) {
633 : 0 : pattern->item_spec.ipv4.protocol = SXE2_FLOW_IP_PROTOCOL_GRE;
634 : 0 : sxe2_set_bit(SXE2_FLOW_FLD_ID_IPV4_PROT, pattern->map_spec);
635 : : }
636 [ # # ]: 0 : if (sxe2_test_bit(SXE2_EXPANSION_OUTER_IPV6, flow_type)) {
637 : 0 : pattern->item_spec.ipv6.nexthdr = SXE2_FLOW_IP_PROTOCOL_GRE;
638 : 0 : sxe2_set_bit(SXE2_FLOW_FLD_ID_IPV6_PROT, pattern->map_spec);
639 : : }
640 : : }
641 : : break;
642 : 0 : case SXE2_FLOW_TUNNEL_TYPE_IPIP:
643 : 0 : ret = sxe2_flow_parse_pattern_ipip(flow, flow_type);
644 : 0 : break;
645 : : default:
646 : : break;
647 : : }
648 : 0 : if (proto != SXE2_FLOW_UDP_TUNNEL_MAX) {
649 : 0 : ret = sxe2_flow_add_udp_tunnel_port(adapter, proto, flow, flow_type);
650 [ # # ]: 0 : if (ret != 0) {
651 : 0 : rte_flow_error_set(error, EINVAL,
652 : : RTE_FLOW_ERROR_TYPE_ITEM,
653 : : NULL, "Failed to add udp port for tunnel.");
654 : 0 : PMD_LOG_ERR(DRV, "Failed to add udp port for tunnel, ret %d.", ret);
655 : 0 : goto l_end;
656 : : }
657 : : }
658 [ # # ]: 0 : if (tunnel_type != SXE2_FLOW_TUNNEL_TYPE_NONE) {
659 [ # # ]: 0 : if (!sxe2_test_bit(SXE2_EXPANSION_OUTER_UDP, flow_type))
660 : 0 : sxe2_set_bit(SXE2_FLOW_HDR_IPV_OTHER, pattern->hdrs);
661 : : }
662 : 0 : l_end:
663 : 0 : return ret;
664 : : }
665 : :
666 : 0 : static int32_t sxe2_flowlist_add_tunnel_port(struct rte_eth_dev *dev,
667 : : struct rte_flow *flow_list,
668 : : struct rte_flow_error *error)
669 : : {
670 : 0 : struct sxe2_flow_list_t *sxe2_flow_list = &flow_list->sxe2_flow_list;
671 : 0 : struct sxe2_flow *flow = TAILQ_FIRST(sxe2_flow_list);
672 : 0 : enum sxe2_flow_tunnel_type tunnel_type = flow->meta.tunnel_type;
673 : 0 : DECLARE_BITMAP(flow_type, SXE2_EXPANSION_MAX);
674 [ # # ]: 0 : sxe2_bitmap_zero(flow_type, SXE2_EXPANSION_MAX);
675 [ # # ]: 0 : sxe2_bitmap_copy(flow_type, flow->flow_type, SXE2_EXPANSION_MAX);
676 : 0 : int32_t ret = 0;
677 : :
678 [ # # ]: 0 : if (flow->engine_type == SXE2_FLOW_ENGINE_FNAV)
679 : 0 : return sxe2_flow_add_tunnel_port(dev, error, flow, flow_type, tunnel_type);
680 : :
681 : : return ret;
682 : : }
683 : :
684 : 0 : static int32_t sxe2_flow_check_item_empty(uint8_t *item, uint16_t size)
685 : : {
686 : 0 : uint16_t i = 0;
687 : :
688 [ # # # # : 0 : for (i = 0; i < size; i++) {
# # # # ]
689 [ # # # # : 0 : if (item[i] != 0)
# # # # ]
690 : : return -1;
691 : : }
692 : : return 0;
693 : : }
694 : :
695 : 0 : static int32_t sxe2_flowlist_add_proto_type(struct rte_eth_dev *dev __rte_unused,
696 : : struct rte_flow *flow_list,
697 : : struct rte_flow_error *error)
698 : : {
699 : 0 : struct sxe2_flow_list_t *sxe2_flow_list = &flow_list->sxe2_flow_list;
700 : 0 : struct sxe2_flow *flow = TAILQ_FIRST(sxe2_flow_list);
701 : 0 : struct sxe2_flow_pattern *pattern = &flow->pattern_outer;
702 : 0 : int32_t ret = 0;
703 : :
704 [ # # ]: 0 : if (flow->engine_type == SXE2_FLOW_ENGINE_SWITCH) {
705 [ # # ]: 0 : if (sxe2_test_bit(SXE2_EXPANSION_OUTER_IPV4, flow->flow_type) &&
706 [ # # ]: 0 : sxe2_flow_check_item_empty((uint8_t *)&pattern->item_mask.ipv4,
707 : : sizeof(pattern->item_mask.ipv4)) == 0) {
708 : 0 : sxe2_set_bit(SXE2_FLOW_FLD_ID_ETH_TYPE, pattern->map_spec);
709 : 0 : pattern->item_spec.eth.ether_type =
710 : 0 : rte_cpu_to_be_16(SXE2_FLOW_ETH_TYPE_IPV4);
711 : 0 : pattern->item_mask.eth.ether_type = 0xffff;
712 : : }
713 [ # # ]: 0 : if (sxe2_test_bit(SXE2_EXPANSION_OUTER_IPV6, flow->flow_type) &&
714 [ # # ]: 0 : sxe2_flow_check_item_empty((uint8_t *)&pattern->item_mask.ipv6,
715 : : sizeof(pattern->item_mask.ipv6)) == 0) {
716 : 0 : sxe2_set_bit(SXE2_FLOW_FLD_ID_ETH_TYPE, pattern->map_spec);
717 : 0 : pattern->item_spec.eth.ether_type =
718 : 0 : rte_cpu_to_be_16(SXE2_FLOW_ETH_TYPE_IPV6);
719 : 0 : pattern->item_mask.eth.ether_type = 0xffff;
720 : : }
721 : :
722 [ # # ]: 0 : if (flow->meta.tunnel_type == SXE2_FLOW_TUNNEL_TYPE_NONE) {
723 [ # # ]: 0 : if (sxe2_test_bit(SXE2_EXPANSION_OUTER_UDP, flow->flow_type) &&
724 [ # # ]: 0 : sxe2_flow_check_item_empty((uint8_t *)&pattern->item_mask.udp,
725 : : sizeof(pattern->item_mask.udp)) == 0) {
726 : 0 : if (sxe2_test_bit(SXE2_EXPANSION_OUTER_IPV4,
727 [ # # ]: 0 : flow->flow_type)) {
728 : 0 : sxe2_set_bit(SXE2_FLOW_FLD_ID_IPV4_PROT, pattern->map_spec);
729 : 0 : pattern->item_spec.ipv4.protocol =
730 : : SXE2_FLOW_IP_PROTOCOL_UDP;
731 : 0 : pattern->item_mask.ipv4.protocol = 0xff;
732 : : }
733 : 0 : if (sxe2_test_bit(SXE2_EXPANSION_OUTER_IPV6,
734 [ # # ]: 0 : flow->flow_type)) {
735 : 0 : ret = -EINVAL;
736 : 0 : rte_flow_error_set(error, ENOENT,
737 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
738 : : "UDP after IPv6 must has pattern item.");
739 : 0 : PMD_LOG_ERR(DRV,
740 : : "UDP after IPv6 must has pattern item.");
741 : 0 : goto l_end;
742 : : }
743 : : }
744 [ # # ]: 0 : if (sxe2_test_bit(SXE2_EXPANSION_OUTER_TCP, flow->flow_type) &&
745 [ # # ]: 0 : sxe2_flow_check_item_empty((uint8_t *)&pattern->item_mask.tcp,
746 : : sizeof(pattern->item_mask.tcp)) == 0) {
747 : 0 : if (sxe2_test_bit(SXE2_EXPANSION_OUTER_IPV4,
748 [ # # ]: 0 : flow->flow_type)) {
749 : 0 : sxe2_set_bit(SXE2_FLOW_FLD_ID_IPV4_PROT,
750 : 0 : pattern->map_spec);
751 : 0 : pattern->item_spec.ipv4.protocol =
752 : : SXE2_FLOW_IP_PROTOCOL_TCP;
753 : 0 : pattern->item_mask.ipv4.protocol = 0xff;
754 : : }
755 : 0 : if (sxe2_test_bit(SXE2_EXPANSION_OUTER_IPV6,
756 [ # # ]: 0 : flow->flow_type)) {
757 : 0 : ret = -EINVAL;
758 : 0 : rte_flow_error_set(error, ENOENT,
759 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
760 : : "TCP after IPv6 must has pattern item.");
761 : 0 : PMD_LOG_ERR(DRV,
762 : : "TCP after IPv6 must has pattern item.");
763 : 0 : goto l_end;
764 : : }
765 : : }
766 : 0 : if (sxe2_test_bit(SXE2_EXPANSION_OUTER_SCTP,
767 [ # # ]: 0 : flow->flow_type)) {
768 : 0 : ret = -EINVAL;
769 : 0 : rte_flow_error_set(error, ENOENT,
770 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
771 : : "SWITCH not support SCTP.");
772 : 0 : PMD_LOG_ERR(DRV, "SWITCH not support SCTP.");
773 : 0 : goto l_end;
774 : : }
775 : : }
776 : : }
777 : 0 : l_end:
778 : 0 : return ret;
779 : : }
780 : :
781 : 0 : static int32_t sxe2_flow_tunnel_split_proc(struct rte_eth_dev *dev __rte_unused,
782 : : struct rte_flow *flow_list,
783 : : struct rte_flow_error *error)
784 : : {
785 : 0 : struct sxe2_flow_list_t *sxe2_flow_list = &flow_list->sxe2_flow_list;
786 : 0 : struct sxe2_flow_list_t tunnel_flow_list;
787 : 0 : struct sxe2_flow *sxe2_flow_exist = NULL;
788 : 0 : struct sxe2_flow *sxe2_flow_new = NULL;
789 : 0 : struct sxe2_flow_pattern *pattern = NULL;
790 : 0 : int32_t ret = 0;
791 : :
792 : 0 : TAILQ_INIT(&tunnel_flow_list);
793 : :
794 [ # # ]: 0 : TAILQ_FOREACH(sxe2_flow_exist, sxe2_flow_list, next) {
795 [ # # ]: 0 : if (sxe2_flow_exist->engine_type != SXE2_FLOW_ENGINE_SWITCH)
796 : 0 : continue;
797 : 0 : if (sxe2_test_bit(SXE2_FLOW_FLD_ID_IPV4_PROT,
798 [ # # ]: 0 : sxe2_flow_exist->pattern_outer.map_spec)) {
799 : 0 : pattern = &sxe2_flow_exist->pattern_outer;
800 : 0 : if ((pattern->item_spec.ipv4.protocol &
801 [ # # ]: 0 : pattern->item_mask.ipv4.protocol) ==
802 : : (SXE2_FLOW_IP_PROTOCOL_GRE &
803 : : pattern->item_mask.ipv4.protocol)) {
804 : 0 : sxe2_flow_new = rte_zmalloc("sxe2_flow",
805 : : sizeof(struct sxe2_flow), 0);
806 [ # # ]: 0 : if (!sxe2_flow_new) {
807 : 0 : rte_flow_error_set(error, ENOMEM,
808 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
809 : : "Failed to alloc memory for flow rule");
810 : 0 : ret = -ENOMEM;
811 : 0 : goto l_end;
812 : : }
813 : 0 : *sxe2_flow_new = *sxe2_flow_exist;
814 : 0 : pattern = &sxe2_flow_new->pattern_outer;
815 : 0 : sxe2_flow_new->meta.tunnel_type =
816 : : SXE2_FLOW_TUNNEL_TYPE_GRE;
817 : 0 : sxe2_set_bit(SXE2_FLOW_HDR_GRE, pattern->hdrs);
818 : 0 : pattern->item_spec.ipv4.protocol =
819 : : SXE2_FLOW_IP_PROTOCOL_GRE;
820 : 0 : pattern->item_mask.ipv4.protocol = 0xff;
821 : 0 : TAILQ_INSERT_TAIL(&tunnel_flow_list, sxe2_flow_new, next);
822 : : }
823 : : }
824 : : }
825 [ # # ]: 0 : TAILQ_FOREACH(sxe2_flow_exist, &tunnel_flow_list, next)
826 : 0 : TAILQ_INSERT_TAIL(sxe2_flow_list, sxe2_flow_exist, next);
827 : :
828 : 0 : l_end:
829 : 0 : return ret;
830 : : }
831 : :
832 : 0 : static int32_t sxe2_flow_post_proc(struct rte_eth_dev *dev,
833 : : const struct rte_flow_attr *attr,
834 : : struct rte_flow *flow_list,
835 : : struct rte_flow_error *error)
836 : : {
837 : 0 : int32_t ret = 0;
838 : :
839 : 0 : ret = sxe2_flowlist_add_tunnel_port(dev, flow_list, error);
840 [ # # ]: 0 : if (ret)
841 : 0 : goto l_end;
842 : :
843 : 0 : ret = sxe2_flowlist_add_proto_type(dev, flow_list, error);
844 [ # # ]: 0 : if (ret)
845 : 0 : goto l_end;
846 : :
847 : 0 : ret = sxe2_flow_check_function(dev, flow_list, error);
848 [ # # ]: 0 : if (ret)
849 : 0 : goto l_end;
850 : :
851 : 0 : ret = sxe2_flow_meta_proc(dev, attr, flow_list, error);
852 [ # # ]: 0 : if (ret)
853 : 0 : goto l_end;
854 : :
855 : 0 : ret = sxe2_flow_src_split_proc(dev, flow_list, error);
856 [ # # ]: 0 : if (ret)
857 : 0 : goto l_end;
858 : :
859 : 0 : ret = sxe2_flow_adjust_action(dev, flow_list, error);
860 [ # # ]: 0 : if (ret)
861 : 0 : goto l_end;
862 : :
863 : 0 : ret = sxe2_flow_tunnel_split_proc(dev, flow_list, error);
864 [ # # ]: 0 : if (ret)
865 : 0 : goto l_end;
866 : 0 : l_end:
867 : 0 : return ret;
868 : : }
869 : :
870 : 0 : static int32_t sxe2_flow_validate_with_flow(struct rte_eth_dev *dev,
871 : : struct rte_flow *flow_list,
872 : : const struct rte_flow_attr *attr,
873 : : const struct rte_flow_item pattern[],
874 : : const struct rte_flow_action actions[],
875 : : struct rte_flow_error *error)
876 : : {
877 : 0 : int32_t ret = 0;
878 : 0 : struct sxe2_flow *flow = NULL;
879 : :
880 : 0 : ret = sxe2_check_para(attr, pattern, actions, error);
881 [ # # ]: 0 : if (ret != 0)
882 : 0 : goto l_end;
883 : :
884 : 0 : ret = sxe2_flow_valid_attr(attr, error);
885 [ # # ]: 0 : if (ret != 0)
886 : 0 : goto l_end;
887 : :
888 : 0 : flow = rte_zmalloc("sxe2_flow", sizeof(*flow), 0);
889 [ # # ]: 0 : if (!flow) {
890 : 0 : rte_flow_error_set(error, ENOMEM,
891 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
892 : : "Failed to alloc memory for flow rule");
893 : 0 : PMD_LOG_ERR(DRV, "Failed to alloc memory for flow rule.");
894 : 0 : ret = -ENOMEM;
895 : 0 : goto l_end;
896 : : }
897 : :
898 : 0 : TAILQ_INSERT_TAIL(&flow_list->sxe2_flow_list, flow, next);
899 : 0 : flow->create_err = -1;
900 : :
901 : 0 : ret = sxe2_flow_parse_pattern(dev, pattern, error, flow);
902 [ # # ]: 0 : if (ret != 0)
903 : 0 : goto l_end;
904 : :
905 : 0 : ret = sxe2_flow_parse_engine(dev, attr, actions, error, flow);
906 [ # # ]: 0 : if (ret != 0)
907 : 0 : goto l_end;
908 : :
909 : 0 : ret = sxe2_flow_parse_action(dev, actions, error, flow);
910 [ # # ]: 0 : if (ret != 0)
911 : 0 : goto l_end;
912 : :
913 : 0 : ret = sxe2_flow_post_proc(dev, attr, flow_list, error);
914 [ # # ]: 0 : if (ret != 0)
915 : 0 : goto l_end;
916 : :
917 : 0 : ret = sxe2_flow_check_flow_list_duplicate(dev, flow_list);
918 [ # # ]: 0 : if (ret != 0) {
919 : 0 : rte_flow_error_set(error, EEXIST, RTE_FLOW_ERROR_TYPE_ITEM,
920 : : NULL, "Duplicate flow.");
921 : 0 : PMD_LOG_ERR(DRV, "Duplicate flow.");
922 : 0 : goto l_end;
923 : : }
924 : 0 : l_end:
925 : 0 : return ret;
926 : : }
927 : :
928 : 0 : static const char *sxe2_flow_convert_ret_to_flow_msg(int32_t ret)
929 : : {
930 : 0 : const char *msg = NULL;
931 [ # # ]: 0 : if (ret > 0)
932 : 0 : ret = -ret;
933 [ # # # # : 0 : switch (ret) {
# # # # ]
934 : : case -ENOMEM:
935 : : msg = "no memory";
936 : : break;
937 : 0 : case -ENOTSUP:
938 : 0 : msg = "not support";
939 : 0 : break;
940 : 0 : case -EEXIST:
941 : 0 : msg = "rule already exist";
942 : 0 : break;
943 : 0 : case -ETIMEDOUT:
944 : 0 : msg = "timeout";
945 : 0 : break;
946 : 0 : case -EINVAL:
947 : 0 : msg = "invalid parameter";
948 : 0 : break;
949 : 0 : case -ENOSPC:
950 : 0 : msg = "no space";
951 : 0 : break;
952 : 0 : case -ENOENT:
953 : 0 : msg = "no such rule";
954 : 0 : break;
955 : 0 : default:
956 : 0 : msg = "unknown error";
957 : 0 : break;
958 : : }
959 : 0 : return msg;
960 : : }
961 : :
962 : 0 : static int32_t sxe2_flow_rte_list_free(struct sxe2_adapter *adapter,
963 : : struct rte_flow **flow_ptr,
964 : : struct rte_flow_error *error)
965 : : {
966 : 0 : int32_t ret = 0;
967 : 0 : int32_t ret1 = 0;
968 : 0 : struct rte_flow *flow = *flow_ptr;
969 : 0 : struct rte_flow *flow_temp = NULL;
970 : 0 : struct sxe2_flow *hw_flow = NULL;
971 : 0 : struct sxe2_flow *hw_flow_temp = NULL;
972 : 0 : struct sxe2_flow_cid_mgr *mgr = NULL;
973 : 0 : rte_spinlock_lock(&adapter->flow_ctxt.flow_list_lock);
974 [ # # ]: 0 : TAILQ_FOREACH(flow_temp, &adapter->flow_ctxt.rte_flow_list, next) {
975 [ # # ]: 0 : if (flow_temp == flow)
976 [ # # ]: 0 : TAILQ_REMOVE(&adapter->flow_ctxt.rte_flow_list, flow, next);
977 : : }
978 : :
979 [ # # ]: 0 : TAILQ_FOREACH_SAFE(hw_flow, &flow->sxe2_flow_list, next, hw_flow_temp) {
980 [ # # ]: 0 : if (hw_flow->create_err == 0) {
981 [ # # ]: 0 : if (sxe2_test_bit(SXE2_FLOW_ACTION_COUNT, hw_flow->action.act_types)) {
982 : 0 : ret = sxe2_flow_query_mgr(adapter, hw_flow, &mgr, error);
983 [ # # ]: 0 : if (ret) {
984 : 0 : PMD_LOG_ERR(DRV,
985 : : "Failed to query flow count, flow id: %u, ret: %d.",
986 : : hw_flow->flow_id, ret);
987 : 0 : rte_flow_error_set(error, EIO,
988 : : RTE_FLOW_ERROR_TYPE_ACTION, NULL,
989 : : "Failed to query flow count");
990 : 0 : ret1 = ret;
991 : : }
992 : : }
993 : :
994 : 0 : ret = sxe2_drv_flow_filter_del(adapter, hw_flow);
995 [ # # ]: 0 : if (ret) {
996 : 0 : PMD_LOG_ERR(DRV,
997 : : "Failed to delete flow filter, ret: %d:%s",
998 : : ret, sxe2_flow_convert_ret_to_flow_msg(ret));
999 : 0 : rte_flow_error_set(error, EIO,
1000 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1001 : : "Failed to delete flow filter");
1002 : 0 : ret1 = ret;
1003 : : }
1004 : :
1005 [ # # ]: 0 : if (sxe2_test_bit(SXE2_FLOW_ACTION_COUNT, hw_flow->action.act_types)) {
1006 : 0 : ret = sxe2_flow_free_mgr(adapter, hw_flow,
1007 : : &mgr, error);
1008 [ # # ]: 0 : if (ret)
1009 : 0 : ret1 = ret;
1010 : : }
1011 : : }
1012 : :
1013 [ # # ]: 0 : TAILQ_REMOVE(&flow->sxe2_flow_list, hw_flow, next);
1014 : 0 : rte_free(hw_flow);
1015 : : }
1016 : 0 : rte_free(flow);
1017 : 0 : *flow_ptr = NULL;
1018 : 0 : rte_spinlock_unlock(&adapter->flow_ctxt.flow_list_lock);
1019 : :
1020 : 0 : return ret1;
1021 : : }
1022 : :
1023 : 0 : static int32_t sxe2_flow_validate(struct rte_eth_dev *dev,
1024 : : const struct rte_flow_attr *attr,
1025 : : const struct rte_flow_item pattern[],
1026 : : const struct rte_flow_action actions[],
1027 : : struct rte_flow_error *error)
1028 : : {
1029 : 0 : int32_t ret = 0;
1030 : 0 : struct rte_flow *flow_list = NULL;
1031 : 0 : struct sxe2_flow *hw_flow = NULL;
1032 : 0 : struct sxe2_flow *hw_flow_temp = NULL;
1033 : 0 : flow_list = rte_zmalloc("rte_flow_va", sizeof(*flow_list), 0);
1034 [ # # ]: 0 : if (!flow_list) {
1035 : 0 : rte_flow_error_set(error, ENOMEM,
1036 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
1037 : : "Failed to alloc memory for flow rule");
1038 : 0 : PMD_LOG_ERR(DRV, "Failed to alloc memory for flow rule.");
1039 : 0 : ret = -ENOMEM;
1040 : 0 : goto l_end;
1041 : : }
1042 : 0 : TAILQ_INIT(&flow_list->sxe2_flow_list);
1043 : :
1044 : 0 : ret = sxe2_flow_validate_with_flow(dev, flow_list, attr, pattern, actions, error);
1045 : 0 : if (ret != 0)
1046 : : goto l_free;
1047 : 0 : l_free:
1048 : :
1049 [ # # ]: 0 : TAILQ_FOREACH_SAFE(hw_flow, &flow_list->sxe2_flow_list, next, hw_flow_temp) {
1050 [ # # ]: 0 : TAILQ_REMOVE(&flow_list->sxe2_flow_list, hw_flow, next);
1051 : 0 : rte_free(hw_flow);
1052 : : }
1053 : 0 : rte_free(flow_list);
1054 : 0 : l_end:
1055 : 0 : return ret;
1056 : : }
1057 : :
1058 : 0 : static int32_t sxe2_flow_isolate(struct rte_eth_dev *dev,
1059 : : int32_t enable,
1060 : : struct rte_flow_error *error)
1061 : : {
1062 : 0 : int32_t ret = 0;
1063 : 0 : struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
1064 : :
1065 [ # # ]: 0 : if (dev->data->dev_started) {
1066 : 0 : rte_flow_error_set(error, EBUSY,
1067 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1068 : : NULL,
1069 : : "port must be stopped first");
1070 : 0 : ret = -EBUSY;
1071 : 0 : goto l_end;
1072 : : }
1073 : :
1074 [ # # ]: 0 : if (adapter->is_dev_repr) {
1075 : 0 : rte_flow_error_set(error, ENOTSUP,
1076 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1077 : : "representor dev cannot change isolated mode ");
1078 : 0 : ret = -EINVAL;
1079 : 0 : goto l_end;
1080 : : }
1081 : :
1082 [ # # ]: 0 : if (enable == adapter->flow_isolated)
1083 : 0 : goto l_end;
1084 : :
1085 [ # # ]: 0 : if (adapter->dev_type == SXE2_DEV_T_VF &&
1086 [ # # ]: 0 : adapter->switchdev_info.is_switchdev) {
1087 : 0 : rte_flow_error_set(error, ENOTSUP,
1088 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1089 : : "isolated mode cannot be change when port in switch dev mode");
1090 : 0 : ret = -EINVAL;
1091 : 0 : goto l_end;
1092 : : }
1093 : :
1094 : 0 : rte_spinlock_lock(&adapter->flow_ctxt.flow_list_lock);
1095 [ # # ]: 0 : if (!TAILQ_EMPTY(&adapter->flow_ctxt.rte_flow_list))
1096 : 0 : PMD_DEV_LOG_WARN(adapter, DRV,
1097 : : "The configured flow item may not take effect.");
1098 : 0 : rte_spinlock_unlock(&adapter->flow_ctxt.flow_list_lock);
1099 : :
1100 : 0 : adapter->flow_isolated = !!enable;
1101 : :
1102 : 0 : ret = sxe2_l2_rule_update(adapter);
1103 [ # # ]: 0 : if (ret != 0)
1104 : 0 : PMD_DEV_LOG_ERR(adapter, DRV, "Failed to update l2 rule");
1105 : :
1106 : 0 : ret = sxe2_switchdev_rule_update(adapter);
1107 [ # # ]: 0 : if (ret != 0)
1108 : 0 : PMD_DEV_LOG_ERR(adapter, DRV, "Failed to update switchdev rule");
1109 : :
1110 : 0 : l_end:
1111 [ # # ]: 0 : if (ret == 0)
1112 : 0 : adapter->flow_isolate_cfg = !!enable;
1113 : 0 : return ret;
1114 : : }
1115 : :
1116 : 0 : static struct rte_flow *sxe2_flow_create(struct rte_eth_dev *dev,
1117 : : const struct rte_flow_attr *attr,
1118 : : const struct rte_flow_item pattern[],
1119 : : const struct rte_flow_action action[],
1120 : : struct rte_flow_error *error)
1121 : : {
1122 : 0 : int32_t ret = 0;
1123 : 0 : struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
1124 : 0 : struct rte_flow *flow_list = NULL;
1125 : 0 : struct sxe2_flow *flow = NULL;
1126 : :
1127 : 0 : flow_list = rte_zmalloc("sxe2_flow_create", sizeof(*flow_list), 0);
1128 [ # # ]: 0 : if (!flow_list) {
1129 : 0 : rte_flow_error_set(error, ENOMEM,
1130 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
1131 : : "Failed to alloc memory for flow rule");
1132 : 0 : PMD_LOG_ERR(DRV, "Failed to alloc memory for flow rule.");
1133 : 0 : ret = -ENOMEM;
1134 : 0 : goto l_end;
1135 : : }
1136 : 0 : TAILQ_INIT(&flow_list->sxe2_flow_list);
1137 : :
1138 : 0 : ret = sxe2_flow_validate_with_flow(dev, flow_list, attr, pattern, action, error);
1139 [ # # ]: 0 : if (ret != 0)
1140 : 0 : goto l_free_flow;
1141 : :
1142 [ # # ]: 0 : TAILQ_FOREACH(flow, &flow_list->sxe2_flow_list, next) {
1143 : 0 : ret = sxe2_flow_get_filter_cid(adapter, flow);
1144 [ # # ]: 0 : if (ret != 0) {
1145 : 0 : PMD_LOG_ERR(DRV, "fnav get stats id failed, ret:%d", ret);
1146 : 0 : rte_flow_error_set(error, EIO,
1147 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
1148 : : "Failed to add fnav rule:alloc cid failed.");
1149 : 0 : goto l_free_flow;
1150 : : }
1151 : 0 : ret = sxe2_drv_flow_filter_add(adapter, flow);
1152 [ # # ]: 0 : if (ret) {
1153 : 0 : rte_flow_error_set(error, EINVAL,
1154 : : RTE_FLOW_ERROR_TYPE_ITEM, NULL,
1155 : : "Failed to add flow filter to hw.");
1156 : 0 : PMD_LOG_ERR(DRV, "Failed to add flow filter to hw.ret:%d:%s",
1157 : : ret, sxe2_flow_convert_ret_to_flow_msg(ret));
1158 : 0 : goto l_free_flow;
1159 : : }
1160 : : }
1161 : :
1162 : 0 : TAILQ_INSERT_TAIL(&adapter->flow_ctxt.rte_flow_list, flow_list, next);
1163 : 0 : goto l_end;
1164 : 0 : l_free_flow:
1165 : 0 : (void)sxe2_flow_rte_list_free(adapter, &flow_list, error);
1166 : 0 : l_end:
1167 : 0 : return flow_list;
1168 : : }
1169 : :
1170 : 0 : static int32_t sxe2_flow_destroy(struct rte_eth_dev *dev,
1171 : : struct rte_flow *flow,
1172 : : struct rte_flow_error *error)
1173 : : {
1174 : 0 : int32_t ret = 0;
1175 : 0 : struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
1176 : 0 : ret = sxe2_flow_rte_list_free(adapter, &flow, error);
1177 [ # # ]: 0 : if (ret)
1178 : 0 : PMD_LOG_ERR(DRV, "Failed to destroy flow.ret:%d.", ret);
1179 : 0 : return ret;
1180 : : }
1181 : :
1182 : 0 : static int32_t sxe2_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *error)
1183 : : {
1184 : 0 : int32_t ret = 0;
1185 : 0 : struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
1186 : 0 : struct rte_flow *flow = NULL;
1187 : 0 : struct rte_flow *tmp_flow = NULL;
1188 : 0 : struct rte_flow_list_t *flow_list = &adapter->flow_ctxt.rte_flow_list;
1189 [ # # ]: 0 : TAILQ_FOREACH_SAFE(flow, flow_list, next, tmp_flow) {
1190 : 0 : ret = sxe2_flow_destroy(dev, flow, error);
1191 [ # # ]: 0 : if (ret) {
1192 : 0 : PMD_LOG_ERR(DRV, "Failed to flush flows.ret:%d.", ret);
1193 : :
1194 [ # # ]: 0 : if (ret != -EAGAIN)
1195 : 0 : ret = -EINVAL;
1196 : 0 : goto l_end;
1197 : : }
1198 : : }
1199 : 0 : l_end:
1200 : 0 : return ret;
1201 : : }
1202 : :
1203 : 0 : int32_t sxe2_flow_get_filter_cid(struct sxe2_adapter *adapter, struct sxe2_flow *flow)
1204 : : {
1205 : 0 : int32_t ret = 0;
1206 : 0 : struct sxe2_flow_cid_mgr_list_t *cid_mgr_list = NULL;
1207 : 0 : uint32_t stat_index;
1208 : 0 : uint32_t user_id;
1209 : 0 : uint32_t driver_id;
1210 : 0 : struct sxe2_flow_cid_mgr *temp = NULL;
1211 : 0 : struct sxe2_flow_cid_mgr *mgr = NULL;
1212 : 0 : uint32_t count_type;
1213 : :
1214 [ # # ]: 0 : if (flow->engine_type == SXE2_FLOW_ENGINE_FNAV) {
1215 : 0 : cid_mgr_list = &adapter->flow_ctxt.fnav_hw_res.flow_cid_mgr_list;
1216 : 0 : count_type = adapter->flow_ctxt.fnav_hw_res.count_type;
1217 [ # # ]: 0 : } else if (flow->engine_type == SXE2_FLOW_ENGINE_ACL) {
1218 : 0 : cid_mgr_list = &adapter->flow_ctxt.acl_hw_res.flow_cid_mgr_list;
1219 : 0 : count_type = adapter->flow_ctxt.acl_hw_res.count_type;
1220 : : } else {
1221 : 0 : ret = -ENOTSUP;
1222 : 0 : goto l_end;
1223 : : }
1224 : :
1225 [ # # ]: 0 : if (sxe2_test_bit(SXE2_FLOW_ACTION_COUNT, flow->action.act_types)) {
1226 : 0 : user_id = flow->action.count.user_id;
1227 : 0 : driver_id = flow->action.count.driver_id;
1228 : :
1229 [ # # ]: 0 : TAILQ_FOREACH(temp, cid_mgr_list, next) {
1230 [ # # ]: 0 : if (temp->user_id == user_id &&
1231 [ # # ]: 0 : temp->driver_id == driver_id) {
1232 : : mgr = temp;
1233 : : break;
1234 : : }
1235 : : }
1236 [ # # ]: 0 : if (mgr == NULL) {
1237 : 0 : mgr = rte_zmalloc("sxe2_fnav_cid_mgr",
1238 : : sizeof(struct sxe2_flow_cid_mgr), 0);
1239 [ # # ]: 0 : if (!mgr) {
1240 : 0 : PMD_LOG_ERR(DRV,
1241 : : "Failed to alloc sxe2vf_fnav_cid_mgr memory.");
1242 : 0 : ret = -ENOMEM;
1243 : 0 : goto l_end;
1244 : : }
1245 : :
1246 [ # # ]: 0 : if (flow->engine_type == SXE2_FLOW_ENGINE_FNAV)
1247 : 0 : ret = sxe2_drv_flow_fnav_get_stat_id(adapter, &stat_index);
1248 [ # # ]: 0 : else if (flow->engine_type == SXE2_FLOW_ENGINE_ACL)
1249 : 0 : ret = sxe2_drv_flow_acl_get_stat_id(adapter, &stat_index);
1250 [ # # ]: 0 : if (ret) {
1251 : 0 : PMD_LOG_ERR(DRV, "Failed to alloc fw count id.");
1252 : 0 : rte_free(mgr);
1253 : 0 : goto l_end;
1254 : : }
1255 : :
1256 : 0 : TAILQ_INSERT_TAIL(cid_mgr_list, mgr, next);
1257 : 0 : mgr->user_id = user_id;
1258 : 0 : mgr->driver_id = driver_id;
1259 : 0 : mgr->stat_index = stat_index;
1260 : 0 : mgr->count_type = count_type;
1261 : : }
1262 : 0 : flow->action.count.stat_index = mgr->stat_index;
1263 : 0 : flow->action.count.stat_ctrl = mgr->count_type;
1264 : : }
1265 : :
1266 : 0 : l_end:
1267 : 0 : return ret;
1268 : : }
1269 : :
1270 : 0 : int32_t sxe2_flow_free_mgr(struct sxe2_adapter *adapter,
1271 : : struct sxe2_flow *flow,
1272 : : struct sxe2_flow_cid_mgr **mgr_ptr,
1273 : : struct rte_flow_error *error)
1274 : : {
1275 : 0 : int32_t ret = 0;
1276 : 0 : struct sxe2_flow_cid_mgr_list_t *cid_mgr_list = NULL;
1277 : 0 : struct sxe2_flow_cid_mgr *mgr = *mgr_ptr;
1278 : 0 : uint32_t user_id = flow->action.count.user_id;
1279 : :
1280 [ # # ]: 0 : if (user_id == 0 && mgr) {
1281 [ # # ]: 0 : if (flow->engine_type == SXE2_FLOW_ENGINE_ACL) {
1282 : 0 : cid_mgr_list = &adapter->flow_ctxt.acl_hw_res.flow_cid_mgr_list;
1283 [ # # ]: 0 : TAILQ_REMOVE(cid_mgr_list, mgr, next);
1284 : 0 : ret = sxe2_drv_flow_acl_free_stat(adapter, mgr->stat_index);
1285 [ # # ]: 0 : } else if (flow->engine_type == SXE2_FLOW_ENGINE_FNAV) {
1286 : 0 : cid_mgr_list = &adapter->flow_ctxt.fnav_hw_res.flow_cid_mgr_list;
1287 [ # # ]: 0 : TAILQ_REMOVE(cid_mgr_list, mgr, next);
1288 : 0 : ret = sxe2_drv_flow_fnav_free_stat(adapter, mgr->stat_index);
1289 : : } else {
1290 : 0 : PMD_LOG_ERR(DRV,
1291 : : "Failed to free flow count, unknown engine type: %d.",
1292 : : flow->engine_type);
1293 : 0 : ret = -ENOTSUP;
1294 : 0 : return ret;
1295 : : }
1296 [ # # ]: 0 : if (ret) {
1297 : 0 : rte_flow_error_set(error, EIO,
1298 : : RTE_FLOW_ERROR_TYPE_ACTION, NULL,
1299 : : "Failed to free flow count.");
1300 : 0 : PMD_LOG_ERR(DRV,
1301 : : "Failed to free flow count, flow id: %u, ret: %d.",
1302 : : flow->flow_id, ret);
1303 : : }
1304 : 0 : rte_free(mgr);
1305 : 0 : *mgr_ptr = NULL;
1306 : : }
1307 : : return ret;
1308 : : }
1309 : :
1310 : 0 : int32_t sxe2_flow_query_mgr(struct sxe2_adapter *adapter,
1311 : : struct sxe2_flow *flow,
1312 : : struct sxe2_flow_cid_mgr **mgr_ptr,
1313 : : struct rte_flow_error *error)
1314 : : {
1315 : 0 : int32_t ret = 0;
1316 : 0 : struct sxe2_flow_cid_mgr_list_t *cid_mgr_list = NULL;
1317 : 0 : struct sxe2_flow_cid_mgr *temp = NULL;
1318 : 0 : struct sxe2_flow_cid_mgr *mgr = NULL;
1319 : 0 : uint32_t user_id = flow->action.count.user_id;
1320 : 0 : uint32_t driver_id = flow->action.count.driver_id;
1321 : :
1322 [ # # ]: 0 : if (flow->engine_type == SXE2_FLOW_ENGINE_ACL)
1323 : 0 : cid_mgr_list = &adapter->flow_ctxt.acl_hw_res.flow_cid_mgr_list;
1324 [ # # ]: 0 : else if (flow->engine_type == SXE2_FLOW_ENGINE_FNAV)
1325 : 0 : cid_mgr_list = &adapter->flow_ctxt.fnav_hw_res.flow_cid_mgr_list;
1326 : : else
1327 : 0 : goto l_end;
1328 : :
1329 [ # # ]: 0 : TAILQ_FOREACH(temp, cid_mgr_list, next) {
1330 [ # # ]: 0 : if (temp->user_id == user_id &&
1331 [ # # ]: 0 : temp->driver_id == driver_id) {
1332 : : mgr = temp;
1333 : : break;
1334 : : }
1335 : : }
1336 [ # # ]: 0 : if (!mgr) {
1337 : 0 : rte_flow_error_set(error, EINVAL,
1338 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
1339 : : "fnav flow query count invalid user_id or driver_id.");
1340 : 0 : PMD_LOG_ERR(DRV,
1341 : : "fnav flow query count invalid user_id or driver_id.");
1342 : 0 : ret = -EINVAL;
1343 : 0 : goto l_end;
1344 : : }
1345 : :
1346 [ # # ]: 0 : if (flow->engine_type == SXE2_FLOW_ENGINE_ACL) {
1347 : 0 : ret = sxe2_drv_flow_acl_query_stat(adapter, mgr);
1348 : 0 : } else if (flow->engine_type == SXE2_FLOW_ENGINE_FNAV) {
1349 : 0 : ret = sxe2_drv_flow_fnav_query_stat(adapter, mgr);
1350 : : } else {
1351 : : PMD_LOG_ERR(DRV, "query flow engine neither FNAV nor ACL");
1352 : : ret = -ENOTSUP;
1353 : : }
1354 [ # # ]: 0 : if (ret) {
1355 : 0 : rte_flow_error_set(error, EINVAL,
1356 : : RTE_FLOW_ERROR_TYPE_ITEM, NULL,
1357 : : "Failed to query flow count.");
1358 : 0 : PMD_LOG_ERR(DRV,
1359 : : "Failed to query flow count, flow id: %u, ret: %d.",
1360 : : flow->flow_id, ret);
1361 : 0 : goto l_end;
1362 : : }
1363 : 0 : *mgr_ptr = mgr;
1364 : 0 : l_end:
1365 : 0 : return ret;
1366 : : }
1367 : :
1368 : 0 : static int32_t sxe2_flow_query_count(struct sxe2_adapter *adapter,
1369 : : struct sxe2_flow *flow,
1370 : : struct rte_flow_query_count *count,
1371 : : struct rte_flow_error *error)
1372 : : {
1373 : 0 : int32_t ret = 0;
1374 : 0 : struct sxe2_flow_cid_mgr *mgr = NULL;
1375 [ # # # # : 0 : switch (flow->action.count.stat_ctrl) {
# ]
1376 : 0 : case SXE2_FNAV_STAT_ENA_NONE:
1377 : 0 : count->hits_set = 0;
1378 : 0 : count->bytes_set = 0;
1379 : 0 : break;
1380 : 0 : case SXE2_FNAV_STAT_ENA_PKTS:
1381 : 0 : count->hits_set = 1;
1382 : 0 : count->bytes_set = 0;
1383 : 0 : break;
1384 : 0 : case SXE2_FNAV_STAT_ENA_BYTES:
1385 : 0 : count->hits_set = 0;
1386 : 0 : count->bytes_set = 1;
1387 : 0 : break;
1388 : 0 : case SXE2_FNAV_STAT_ENA_ALL:
1389 : 0 : count->hits_set = 1;
1390 : 0 : count->bytes_set = 1;
1391 : 0 : break;
1392 : 0 : default:
1393 : 0 : ret = -EINVAL;
1394 : 0 : goto l_end;
1395 : : }
1396 [ # # ]: 0 : if (!sxe2_test_bit(SXE2_FLOW_ACTION_COUNT, flow->action.act_types)) {
1397 : 0 : rte_flow_error_set(error, EINVAL,
1398 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
1399 : : "this flow don't have count action.");
1400 : 0 : PMD_LOG_ERR(DRV, "this flow don't have count action.");
1401 : 0 : ret = -EINVAL;
1402 : 0 : goto l_end;
1403 : : }
1404 : 0 : ret = sxe2_flow_query_mgr(adapter, flow, &mgr, error);
1405 [ # # ]: 0 : if (ret) {
1406 : 0 : PMD_LOG_ERR(DRV,
1407 : : "Failed to query flow count, flow id: %u, ret: %d.",
1408 : : flow->flow_id, ret);
1409 : 0 : goto l_end;
1410 : : }
1411 : 0 : count->hits = mgr->hits;
1412 : 0 : count->bytes = mgr->bytes;
1413 [ # # ]: 0 : if (count->reset) {
1414 : 0 : mgr->hits = 0;
1415 : 0 : mgr->bytes = 0;
1416 : : }
1417 : 0 : l_end:
1418 : 0 : return ret;
1419 : : }
1420 : :
1421 : 0 : static int32_t sxe2_flow_query(struct rte_eth_dev *dev,
1422 : : struct rte_flow *flow_list,
1423 : : const struct rte_flow_action *actions,
1424 : : void *data,
1425 : : struct rte_flow_error *error)
1426 : : {
1427 : 0 : int32_t ret = 0;
1428 : 0 : struct rte_flow_query_count *count = data;
1429 : 0 : struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
1430 : 0 : struct sxe2_flow *flow = NULL;
1431 : :
1432 [ # # ]: 0 : if (!flow_list) {
1433 : 0 : ret = -EINVAL;
1434 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_HANDLE,
1435 : : NULL, "Invalid flow");
1436 : 0 : PMD_LOG_ERR(DRV, "Invalid flow to query flow.");
1437 : 0 : goto l_end;
1438 : : }
1439 : :
1440 : 0 : rte_spinlock_lock(&adapter->flow_ctxt.flow_list_lock);
1441 [ # # ]: 0 : for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
1442 [ # # # ]: 0 : switch (actions->type) {
1443 : : case RTE_FLOW_ACTION_TYPE_VOID:
1444 : : break;
1445 : 0 : case RTE_FLOW_ACTION_TYPE_COUNT:
1446 : 0 : flow = TAILQ_FIRST(&flow_list->sxe2_flow_list);
1447 : 0 : ret = sxe2_flow_query_count(adapter, flow, count, error);
1448 [ # # ]: 0 : if (ret) {
1449 : 0 : PMD_LOG_ERR(DRV,
1450 : : "Failed to query flow count, flow id: %u, ret: %d.",
1451 : : flow->flow_id, ret);
1452 : 0 : goto l_end_unlock;
1453 : : }
1454 : : break;
1455 : 0 : default:
1456 : 0 : rte_flow_error_set(error, ENOTSUP,
1457 : : RTE_FLOW_ERROR_TYPE_ACTION,
1458 : : actions,
1459 : : "action not supported");
1460 : 0 : PMD_LOG_ERR(DRV,
1461 : : "Failed to query flow action type:%d.",
1462 : : actions->type);
1463 : 0 : ret = -ENOTSUP;
1464 : 0 : goto l_end_unlock;
1465 : : }
1466 : : }
1467 : :
1468 : 0 : l_end_unlock:
1469 : 0 : rte_spinlock_unlock(&adapter->flow_ctxt.flow_list_lock);
1470 : :
1471 : 0 : l_end:
1472 : 0 : return ret;
1473 : : }
1474 : :
1475 : : const struct rte_flow_ops sxe2_flow_ops = {
1476 : : .validate = sxe2_flow_validate,
1477 : : .create = sxe2_flow_create,
1478 : : .destroy = sxe2_flow_destroy,
1479 : : .flush = sxe2_flow_flush,
1480 : : .query = sxe2_flow_query,
1481 : : .isolate = sxe2_flow_isolate,
1482 : : };
1483 : :
1484 : 0 : int32_t sxe2_flow_ops_get(struct rte_eth_dev *dev, const struct rte_flow_ops **ops)
1485 : : {
1486 : 0 : int32_t ret = 0;
1487 : :
1488 [ # # ]: 0 : if (dev == NULL) {
1489 : 0 : ret = -EINVAL;
1490 : 0 : goto l_end;
1491 : : }
1492 : :
1493 : 0 : *ops = &sxe2_flow_ops;
1494 : :
1495 : 0 : l_end:
1496 : 0 : return ret;
1497 : : }
1498 : :
1499 : 0 : int32_t sxe2_flow_init(struct rte_eth_dev *dev)
1500 : : {
1501 : 0 : struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
1502 : 0 : int32_t ret = 0;
1503 : 0 : TAILQ_INIT(&adapter->flow_ctxt.rte_flow_list);
1504 : 0 : TAILQ_INIT(&adapter->flow_ctxt.fnav_hw_res.flow_cid_mgr_list);
1505 : 0 : TAILQ_INIT(&adapter->flow_ctxt.acl_hw_res.flow_cid_mgr_list);
1506 [ # # ]: 0 : if (adapter->devargs.fnav_stat_type)
1507 : 0 : adapter->flow_ctxt.fnav_hw_res.count_type =
1508 : 0 : adapter->devargs.fnav_stat_type;
1509 : : else
1510 : 0 : adapter->flow_ctxt.fnav_hw_res.count_type = SXE2_FNAV_STAT_ENA_ALL;
1511 : :
1512 [ # # ]: 0 : if (adapter->devargs.acl_stat_type)
1513 : 0 : adapter->flow_ctxt.acl_hw_res.count_type = adapter->devargs.acl_stat_type;
1514 : : else
1515 : 0 : adapter->flow_ctxt.acl_hw_res.count_type = SXE2_FNAV_STAT_ENA_ALL;
1516 : :
1517 : 0 : adapter->flow_ctxt.fnav_inited = 1;
1518 : 0 : rte_spinlock_init(&adapter->flow_ctxt.flow_list_lock);
1519 : :
1520 : 0 : ret = sxe2_flow_init_udp_tunnel_port(dev);
1521 [ # # ]: 0 : if (ret)
1522 : 0 : PMD_LOG_ERR(DRV, "Failed to init udp tunnel port, ret: %d.", ret);
1523 : :
1524 : 0 : return ret;
1525 : : }
1526 : :
1527 : 0 : int32_t sxe2_flow_uninit(struct rte_eth_dev *dev)
1528 : : {
1529 : 0 : int32_t ret = 0;
1530 : 0 : struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
1531 : 0 : struct rte_flow_error error;
1532 : 0 : struct sxe2_flow_cid_mgr *mgr = NULL;
1533 : 0 : struct sxe2_flow_cid_mgr *temp = NULL;
1534 : 0 : struct sxe2_flow_cid_mgr_list_t *cid_mgr_list = NULL;
1535 : :
1536 : 0 : ret = sxe2_flow_flush(dev, &error);
1537 [ # # ]: 0 : if (ret)
1538 : 0 : PMD_LOG_ERR(DRV, "Failed to flush flow, ret: %d.", ret);
1539 : :
1540 : 0 : cid_mgr_list = &adapter->flow_ctxt.fnav_hw_res.flow_cid_mgr_list;
1541 [ # # ]: 0 : TAILQ_FOREACH_SAFE(mgr, cid_mgr_list, next, temp) {
1542 [ # # ]: 0 : TAILQ_REMOVE(cid_mgr_list, mgr, next);
1543 : 0 : ret = sxe2_drv_flow_fnav_free_stat(adapter, mgr->stat_index);
1544 [ # # ]: 0 : if (ret)
1545 : 0 : PMD_LOG_ERR(DRV,
1546 : : "Failed to free fnav stat id, ret: %d.", ret);
1547 : 0 : rte_free(mgr);
1548 : : }
1549 : :
1550 : 0 : cid_mgr_list = &adapter->flow_ctxt.acl_hw_res.flow_cid_mgr_list;
1551 [ # # ]: 0 : TAILQ_FOREACH_SAFE(mgr, cid_mgr_list, next, temp) {
1552 [ # # ]: 0 : TAILQ_REMOVE(cid_mgr_list, mgr, next);
1553 : 0 : ret = sxe2_drv_flow_acl_free_stat(adapter, mgr->stat_index);
1554 [ # # ]: 0 : if (ret)
1555 : 0 : PMD_LOG_ERR(DRV, "Failed to free acl stat id, ret: %d.", ret);
1556 : 0 : rte_free(mgr);
1557 : : }
1558 : 0 : return ret;
1559 : : }
|