Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2023 Intel Corporation
3 : : */
4 : : #include <rte_flow_driver.h>
5 : : #include <rte_tailq.h>
6 : :
7 : : #include "cpfl_flow.h"
8 : : #include "cpfl_flow_parser.h"
9 : :
10 : : TAILQ_HEAD(cpfl_flow_engine_list, cpfl_flow_engine);
11 : :
12 : : static struct cpfl_flow_engine_list engine_list = TAILQ_HEAD_INITIALIZER(engine_list);
13 : :
14 : : void
15 : 251 : cpfl_flow_engine_register(struct cpfl_flow_engine *engine)
16 : : {
17 : 251 : TAILQ_INSERT_TAIL(&engine_list, engine, node);
18 : 251 : }
19 : :
20 : : struct cpfl_flow_engine *
21 : 0 : cpfl_flow_engine_match(struct rte_eth_dev *dev,
22 : : const struct rte_flow_attr *attr,
23 : : const struct rte_flow_item pattern[],
24 : : const struct rte_flow_action actions[],
25 : : void **meta)
26 : : {
27 : : struct cpfl_flow_engine *engine = NULL;
28 : : void *temp;
29 : :
30 [ # # ]: 0 : RTE_TAILQ_FOREACH_SAFE(engine, &engine_list, node, temp) {
31 [ # # ]: 0 : if (!engine->parse_pattern_action)
32 : 0 : continue;
33 : :
34 [ # # ]: 0 : if (engine->parse_pattern_action(dev, attr, pattern, actions, meta) < 0)
35 : 0 : continue;
36 : : return engine;
37 : : }
38 : :
39 : : return NULL;
40 : : }
41 : :
42 : : int
43 : 0 : cpfl_flow_engine_init(struct cpfl_adapter_ext *adapter)
44 : : {
45 : : struct cpfl_flow_engine *engine = NULL;
46 : : void *temp;
47 : : int ret;
48 : :
49 [ # # ]: 0 : RTE_TAILQ_FOREACH_SAFE(engine, &engine_list, node, temp) {
50 [ # # ]: 0 : if (!engine->init) {
51 : 0 : PMD_INIT_LOG(ERR, "Invalid engine type (%d)",
52 : : engine->type);
53 : 0 : return -ENOTSUP;
54 : : }
55 : :
56 : 0 : ret = engine->init(adapter);
57 [ # # ]: 0 : if (ret) {
58 : 0 : PMD_INIT_LOG(ERR, "Failed to initialize engine %d",
59 : : engine->type);
60 : 0 : return ret;
61 : : }
62 : : }
63 : :
64 : : return 0;
65 : : }
66 : :
67 : : void
68 : 0 : cpfl_flow_engine_uninit(struct cpfl_adapter_ext *adapter)
69 : : {
70 : : struct cpfl_flow_engine *engine = NULL;
71 : : void *temp;
72 : :
73 [ # # ]: 0 : RTE_TAILQ_FOREACH_SAFE(engine, &engine_list, node, temp) {
74 [ # # ]: 0 : if (engine->uninit)
75 : 0 : engine->uninit(adapter);
76 : : }
77 : 0 : }
78 : :
79 : : static int
80 : : cpfl_flow_attr_valid(const struct rte_flow_attr *attr,
81 : : struct rte_flow_error *error)
82 : : {
83 [ # # ]: 0 : if (attr->priority > CPFL_PREC_MAX) {
84 : 0 : rte_flow_error_set(error, EINVAL,
85 : : RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY,
86 : : attr, "Only support priority 0-7.");
87 : 0 : return -rte_errno;
88 : : }
89 : :
90 : : return 0;
91 : : }
92 : :
93 : : static int
94 : 0 : cpfl_flow_param_valid(const struct rte_flow_attr *attr,
95 : : const struct rte_flow_item pattern[],
96 : : const struct rte_flow_action actions[],
97 : : struct rte_flow_error *error)
98 : : {
99 : : int ret;
100 : :
101 [ # # ]: 0 : if (!pattern) {
102 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_NUM,
103 : : NULL, "NULL pattern.");
104 : 0 : return -rte_errno;
105 : : }
106 : :
107 [ # # ]: 0 : if (!attr) {
108 : 0 : rte_flow_error_set(error, EINVAL,
109 : : RTE_FLOW_ERROR_TYPE_ATTR,
110 : : NULL, "NULL attribute.");
111 : 0 : return -rte_errno;
112 : : }
113 : :
114 : : ret = cpfl_flow_attr_valid(attr, error);
115 [ # # ]: 0 : if (ret)
116 : : return ret;
117 : :
118 [ # # # # ]: 0 : if (!actions || actions->type == RTE_FLOW_ACTION_TYPE_END) {
119 : 0 : rte_flow_error_set(error, EINVAL,
120 : : RTE_FLOW_ERROR_TYPE_ACTION_NUM,
121 : : NULL, "NULL action.");
122 : 0 : return -rte_errno;
123 : : }
124 : :
125 : : return 0;
126 : : }
127 : :
128 : : static int
129 : 0 : __cpfl_flow_validate(struct rte_eth_dev *dev,
130 : : const struct rte_flow_attr *attr,
131 : : const struct rte_flow_item pattern[],
132 : : const struct rte_flow_action actions[],
133 : : void **meta,
134 : : struct cpfl_flow_engine **engine,
135 : : struct rte_flow_error *error)
136 : : {
137 : : int ret;
138 : :
139 : 0 : ret = cpfl_flow_param_valid(attr, pattern, actions, error);
140 [ # # ]: 0 : if (ret)
141 : : return ret;
142 : :
143 : 0 : *engine = cpfl_flow_engine_match(dev, attr, pattern, actions, meta);
144 [ # # ]: 0 : if (!*engine) {
145 : 0 : rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
146 : : NULL, "No matched engine.");
147 : 0 : return -rte_errno;
148 : : }
149 : :
150 : : return 0;
151 : : }
152 : :
153 : : int
154 : 0 : cpfl_flow_validate(struct rte_eth_dev *dev,
155 : : const struct rte_flow_attr *attr,
156 : : const struct rte_flow_item pattern[],
157 : : const struct rte_flow_action actions[],
158 : : struct rte_flow_error *error)
159 : : {
160 : 0 : struct cpfl_flow_engine *engine = NULL;
161 : : int ret;
162 : :
163 : 0 : ret = __cpfl_flow_validate(dev, attr, pattern, actions, NULL, &engine, error);
164 : :
165 : 0 : return ret;
166 : : }
167 : :
168 : : struct rte_flow *
169 : 0 : cpfl_flow_create(struct rte_eth_dev *dev,
170 : : const struct rte_flow_attr *attr,
171 : : const struct rte_flow_item pattern[],
172 : : const struct rte_flow_action actions[],
173 : : struct rte_flow_error *error)
174 : : {
175 : 0 : struct cpfl_itf *itf = CPFL_DEV_TO_ITF(dev);
176 : 0 : struct cpfl_flow_engine *engine = NULL;
177 : : struct rte_flow *flow;
178 : : void *meta;
179 : : int ret;
180 : :
181 : 0 : flow = rte_malloc(NULL, sizeof(struct rte_flow), 0);
182 [ # # ]: 0 : if (!flow) {
183 : 0 : rte_flow_error_set(error, ENOMEM,
184 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
185 : : "Failed to allocate memory");
186 : 0 : return NULL;
187 : : }
188 : :
189 : 0 : ret = __cpfl_flow_validate(dev, attr, pattern, actions, &meta, &engine, error);
190 [ # # ]: 0 : if (ret) {
191 : 0 : rte_free(flow);
192 : 0 : return NULL;
193 : : }
194 : :
195 [ # # ]: 0 : if (!engine->create) {
196 : 0 : rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
197 : : NULL, "No matched flow creation function");
198 : 0 : rte_free(flow);
199 : 0 : return NULL;
200 : : }
201 : :
202 : 0 : ret = engine->create(dev, flow, meta, error);
203 [ # # ]: 0 : if (ret) {
204 : 0 : rte_free(flow);
205 : 0 : return NULL;
206 : : }
207 : :
208 : 0 : flow->engine = engine;
209 : 0 : TAILQ_INSERT_TAIL(&itf->flow_list, flow, next);
210 : :
211 : 0 : return flow;
212 : : }
213 : :
214 : : int
215 : 0 : cpfl_flow_destroy(struct rte_eth_dev *dev,
216 : : struct rte_flow *flow,
217 : : struct rte_flow_error *error)
218 : : {
219 : 0 : struct cpfl_itf *itf = CPFL_DEV_TO_ITF(dev);
220 : : int ret = 0;
221 : :
222 [ # # # # : 0 : if (!flow || !flow->engine || !flow->engine->destroy) {
# # ]
223 : 0 : rte_flow_error_set(error, EINVAL,
224 : : RTE_FLOW_ERROR_TYPE_HANDLE,
225 : : NULL, "Invalid flow");
226 : 0 : return -rte_errno;
227 : : }
228 : :
229 : 0 : ret = flow->engine->destroy(dev, flow, error);
230 [ # # ]: 0 : if (!ret)
231 [ # # ]: 0 : TAILQ_REMOVE(&itf->flow_list, flow, next);
232 : : else
233 : 0 : PMD_DRV_LOG(ERR, "Failed to destroy flow");
234 : :
235 : : return ret;
236 : : }
237 : :
238 : : int
239 : 0 : cpfl_flow_flush(struct rte_eth_dev *dev,
240 : : struct rte_flow_error *error)
241 : : {
242 : 0 : struct cpfl_itf *itf = CPFL_DEV_TO_ITF(dev);
243 : : struct rte_flow *p_flow;
244 : : void *temp;
245 : : int ret = 0;
246 : :
247 [ # # ]: 0 : RTE_TAILQ_FOREACH_SAFE(p_flow, &itf->flow_list, next, temp) {
248 : 0 : ret = cpfl_flow_destroy(dev, p_flow, error);
249 [ # # ]: 0 : if (ret) {
250 : 0 : PMD_DRV_LOG(ERR, "Failed to flush flows");
251 : 0 : return -EINVAL;
252 : : }
253 : : }
254 : :
255 : : return ret;
256 : : }
257 : :
258 : : int
259 : 0 : cpfl_flow_query(struct rte_eth_dev *dev,
260 : : struct rte_flow *flow,
261 : : const struct rte_flow_action *actions,
262 : : void *data,
263 : : struct rte_flow_error *error)
264 : : {
265 : : struct rte_flow_query_count *count = data;
266 : : int ret = -EINVAL;
267 : :
268 [ # # # # : 0 : if (!flow || !flow->engine || !flow->engine->query_count) {
# # ]
269 : 0 : rte_flow_error_set(error, EINVAL,
270 : : RTE_FLOW_ERROR_TYPE_HANDLE,
271 : : NULL, "Invalid flow");
272 : 0 : return -rte_errno;
273 : : }
274 : :
275 [ # # ]: 0 : for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
276 [ # # # ]: 0 : switch (actions->type) {
277 : : case RTE_FLOW_ACTION_TYPE_VOID:
278 : : break;
279 : 0 : case RTE_FLOW_ACTION_TYPE_COUNT:
280 : 0 : ret = flow->engine->query_count(dev, flow, count, error);
281 : 0 : break;
282 : 0 : default:
283 : 0 : ret = rte_flow_error_set(error, ENOTSUP,
284 : : RTE_FLOW_ERROR_TYPE_ACTION,
285 : : actions,
286 : : "action not supported");
287 : 0 : break;
288 : : }
289 : : }
290 : :
291 : : return ret;
292 : : }
293 : :
294 : : const struct rte_flow_ops cpfl_flow_ops = {
295 : : .validate = cpfl_flow_validate,
296 : : .create = cpfl_flow_create,
297 : : .destroy = cpfl_flow_destroy,
298 : : .flush = cpfl_flow_flush,
299 : : .query = cpfl_flow_query,
300 : : };
301 : :
302 : : int
303 : 0 : cpfl_flow_init(struct cpfl_adapter_ext *ad, struct cpfl_devargs *devargs)
304 : : {
305 : : int ret;
306 : :
307 [ # # ]: 0 : if (devargs->flow_parser[0] == '\0') {
308 : 0 : PMD_INIT_LOG(WARNING, "flow module is not initialized");
309 : 0 : return 0;
310 : : }
311 : :
312 : 0 : ret = cpfl_flow_engine_init(ad);
313 [ # # ]: 0 : if (ret) {
314 : 0 : PMD_DRV_LOG(ERR, "Failed to init flow engines");
315 : 0 : goto err;
316 : : }
317 : :
318 : 0 : ret = cpfl_parser_create(&ad->flow_parser, devargs->flow_parser);
319 [ # # ]: 0 : if (ret) {
320 : 0 : PMD_DRV_LOG(ERR, "Failed to create flow parser");
321 : 0 : goto err;
322 : : }
323 : :
324 : : return ret;
325 : :
326 : 0 : err:
327 : 0 : cpfl_flow_engine_uninit(ad);
328 : 0 : return ret;
329 : : }
330 : :
331 : : void
332 : 0 : cpfl_flow_uninit(struct cpfl_adapter_ext *ad)
333 : : {
334 [ # # ]: 0 : if (ad->flow_parser == NULL)
335 : : return;
336 : :
337 : 0 : cpfl_parser_destroy(ad->flow_parser);
338 : 0 : cpfl_flow_engine_uninit(ad);
339 : : }
|