Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2022 Intel Corporation
3 : : */
4 : :
5 : : #include <sys/queue.h>
6 : : #include <stdio.h>
7 : : #include <errno.h>
8 : : #include <stdint.h>
9 : : #include <string.h>
10 : : #include <unistd.h>
11 : : #include <stdarg.h>
12 : : #include <math.h>
13 : : #include <rte_debug.h>
14 : : #include <rte_ether.h>
15 : : #include <rte_log.h>
16 : : #include <rte_malloc.h>
17 : : #include <rte_eth_ctrl.h>
18 : : #include <rte_tailq.h>
19 : : #include <rte_flow_driver.h>
20 : : #include <rte_flow.h>
21 : : #include <rte_bitmap.h>
22 : : #include <ethdev_driver.h>
23 : : #include "cpfl_rules.h"
24 : : #include "cpfl_logs.h"
25 : : #include "cpfl_ethdev.h"
26 : : #include "cpfl_flow.h"
27 : : #include "cpfl_fxp_rule.h"
28 : : #include "cpfl_flow_parser.h"
29 : :
30 : : #define CPFL_COOKIE_DEF 0x1000
31 : : #define CPFL_MOD_COOKIE_DEF 0x1237561
32 : : #define CPFL_PREC_DEF 1
33 : : #define CPFL_PREC_SET 5
34 : : #define CPFL_TYPE_ID 3
35 : : #define CPFL_OFFSET 0x0a
36 : : #define CPFL_HOST_ID_DEF 0
37 : : #define CPFL_PF_NUM_DEF 0
38 : : #define CPFL_PORT_NUM_DEF 0
39 : : #define CPFL_RESP_REQ_DEF 2
40 : : #define CPFL_PIN_TO_CACHE_DEF 0
41 : : #define CPFL_CLEAR_MIRROR_1ST_STATE_DEF 0
42 : : #define CPFL_FIXED_FETCH_DEF 0
43 : : #define CPFL_PTI_DEF 0
44 : : #define CPFL_MOD_OBJ_SIZE_DEF 0
45 : : #define CPFL_PIN_MOD_CONTENT_DEF 0
46 : :
47 : : #define CPFL_MAX_MOD_CONTENT_INDEX 256
48 : : #define CPFL_MAX_MR_ACTION_NUM 8
49 : :
50 : : /* Struct used when parse detailed rule information with json file */
51 : : struct cpfl_rule_info_meta {
52 : : struct cpfl_flow_pr_action pr_action; /* json action field of pattern rule */
53 : : uint32_t pr_num; /* number of pattern rules */
54 : : uint32_t mr_num; /* number of modification rules */
55 : : uint32_t rule_num; /* number of all rules */
56 : : struct cpfl_rule_info rules[];
57 : : };
58 : :
59 : : static uint32_t cpfl_fxp_mod_idx_alloc(struct cpfl_adapter_ext *ad);
60 : : static void cpfl_fxp_mod_idx_free(struct cpfl_adapter_ext *ad, uint32_t idx);
61 : : uint64_t cpfl_rule_cookie = CPFL_COOKIE_DEF;
62 : :
63 : : static int
64 : 0 : cpfl_fxp_create(struct rte_eth_dev *dev,
65 : : struct rte_flow *flow,
66 : : void *meta,
67 : : struct rte_flow_error *error)
68 : : {
69 : : int ret = 0;
70 : : uint32_t cpq_id = 0;
71 : 0 : struct cpfl_itf *itf = CPFL_DEV_TO_ITF(dev);
72 : 0 : struct cpfl_adapter_ext *ad = itf->adapter;
73 : : struct cpfl_rule_info_meta *rim = meta;
74 : : struct cpfl_vport *vport;
75 : : struct cpfl_repr *repr;
76 : :
77 [ # # ]: 0 : if (!rim)
78 : : return ret;
79 : :
80 [ # # ]: 0 : if (itf->type == CPFL_ITF_TYPE_VPORT) {
81 : : vport = (struct cpfl_vport *)itf;
82 : : /* Every vport has one pair control queues configured to handle message.
83 : : * Even index is tx queue and odd index is rx queue.
84 : : */
85 : 0 : cpq_id = vport->base.devarg_id * 2;
86 [ # # ]: 0 : } else if (itf->type == CPFL_ITF_TYPE_REPRESENTOR) {
87 : : repr = (struct cpfl_repr *)itf;
88 : 0 : cpq_id = ((repr->repr_id.pf_id + repr->repr_id.vf_id) &
89 : 0 : (CPFL_TX_CFGQ_NUM - 1)) * 2;
90 : : } else {
91 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
92 : : "fail to find correct control queue");
93 : 0 : return -rte_errno;
94 : : }
95 : :
96 : 0 : ret = cpfl_rule_process(itf, ad->ctlqp[cpq_id], ad->ctlqp[cpq_id + 1],
97 : 0 : rim->rules, rim->rule_num, true);
98 [ # # ]: 0 : if (ret < 0) {
99 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
100 : : "cpfl filter create flow fail");
101 : 0 : rte_free(rim);
102 : 0 : return ret;
103 : : }
104 : :
105 : 0 : flow->rule = rim;
106 : :
107 : 0 : return ret;
108 : : }
109 : :
110 : : static int
111 : 0 : cpfl_fxp_destroy(struct rte_eth_dev *dev,
112 : : struct rte_flow *flow,
113 : : struct rte_flow_error *error)
114 : : {
115 : : int ret = 0;
116 : : uint32_t cpq_id = 0;
117 : 0 : struct cpfl_itf *itf = CPFL_DEV_TO_ITF(dev);
118 : 0 : struct cpfl_adapter_ext *ad = itf->adapter;
119 : : struct cpfl_rule_info_meta *rim;
120 : : uint32_t i;
121 : : struct cpfl_vport *vport;
122 : : struct cpfl_repr *repr;
123 : :
124 : 0 : rim = (struct cpfl_rule_info_meta *)flow->rule;
125 [ # # ]: 0 : if (!rim) {
126 : 0 : rte_flow_error_set(error, EINVAL,
127 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
128 : : "no such flow create by cpfl filter");
129 : :
130 : 0 : return -rte_errno;
131 : : }
132 : :
133 [ # # ]: 0 : if (itf->type == CPFL_ITF_TYPE_VPORT) {
134 : : vport = (struct cpfl_vport *)itf;
135 : 0 : cpq_id = vport->base.devarg_id * 2;
136 [ # # ]: 0 : } else if (itf->type == CPFL_ITF_TYPE_REPRESENTOR) {
137 : : repr = (struct cpfl_repr *)itf;
138 : 0 : cpq_id = ((repr->repr_id.pf_id + repr->repr_id.vf_id) &
139 : 0 : (CPFL_TX_CFGQ_NUM - 1)) * 2;
140 : : } else {
141 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
142 : : "fail to find correct control queue");
143 : 0 : ret = -rte_errno;
144 : 0 : goto err;
145 : : }
146 : :
147 : 0 : ret = cpfl_rule_process(itf, ad->ctlqp[cpq_id], ad->ctlqp[cpq_id + 1], rim->rules,
148 : 0 : rim->rule_num, false);
149 [ # # ]: 0 : if (ret < 0) {
150 : 0 : rte_flow_error_set(error, EINVAL,
151 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
152 : : "fail to destroy cpfl filter rule");
153 : 0 : goto err;
154 : : }
155 : :
156 : : /* free mod index */
157 [ # # ]: 0 : for (i = rim->pr_num; i < rim->rule_num; i++)
158 : 0 : cpfl_fxp_mod_idx_free(ad, rim->rules[i].mod.mod_index);
159 : 0 : err:
160 : 0 : rte_free(rim);
161 : 0 : flow->rule = NULL;
162 : 0 : return ret;
163 : : }
164 : :
165 : : static bool
166 : 0 : cpfl_fxp_parse_pattern(const struct cpfl_flow_pr_action *pr_action,
167 : : struct cpfl_rule_info_meta *rim,
168 : : int i)
169 : : {
170 [ # # ]: 0 : if (pr_action->type == CPFL_JS_PR_ACTION_TYPE_SEM) {
171 : : struct cpfl_rule_info *rinfo = &rim->rules[i];
172 : :
173 : 0 : rinfo->type = CPFL_RULE_TYPE_SEM;
174 : 0 : rinfo->sem.prof_id = pr_action->sem.prof;
175 : 0 : rinfo->sem.sub_prof_id = pr_action->sem.subprof;
176 : 0 : rinfo->sem.key_byte_len = pr_action->sem.keysize;
177 : 0 : memcpy(rinfo->sem.key, pr_action->sem.cpfl_flow_pr_fv, rinfo->sem.key_byte_len);
178 : 0 : rinfo->sem.pin_to_cache = CPFL_PIN_TO_CACHE_DEF;
179 : 0 : rinfo->sem.fixed_fetch = CPFL_FIXED_FETCH_DEF;
180 : : } else {
181 : 0 : PMD_DRV_LOG(ERR, "Invalid pattern item.");
182 : 0 : return false;
183 : : }
184 : :
185 : 0 : return true;
186 : : }
187 : :
188 : : static int
189 : 0 : cpfl_parse_mod_content(struct cpfl_adapter_ext *adapter,
190 : : struct cpfl_rule_info *match_rinfo,
191 : : struct cpfl_rule_info *mod_rinfo,
192 : : const struct cpfl_flow_mr_action *mr_action)
193 : : {
194 : : struct cpfl_mod_rule_info *minfo = &mod_rinfo->mod;
195 : : uint32_t mod_idx;
196 : : int i;
197 : 0 : int next = match_rinfo->act_byte_len / (sizeof(union cpfl_action_set));
198 : 0 : union cpfl_action_set *act_set =
199 : 0 : &((union cpfl_action_set *)match_rinfo->act_bytes)[next];
200 : :
201 [ # # # # ]: 0 : if (!mr_action || mr_action->type != CPFL_JS_MR_ACTION_TYPE_MOD)
202 : : return -EINVAL;
203 : :
204 : 0 : *act_set = cpfl_act_mod_profile(CPFL_PREC_DEF,
205 [ # # ]: 0 : mr_action->mod.prof,
206 : : CPFL_PTI_DEF,
207 : : 0, /* append */
208 : : 0, /* prepend */
209 : : CPFL_ACT_MOD_PROFILE_PREFETCH_256B);
210 : :
211 : : act_set++;
212 : 0 : match_rinfo->act_byte_len += sizeof(union cpfl_action_set);
213 : :
214 : 0 : mod_idx = cpfl_fxp_mod_idx_alloc(adapter);
215 [ # # ]: 0 : if (mod_idx == CPFL_MAX_MOD_CONTENT_INDEX) {
216 : 0 : PMD_DRV_LOG(ERR, "Out of Mod Index.");
217 : 0 : return -ENOMEM;
218 : : }
219 : :
220 : 0 : *act_set = cpfl_act_mod_addr(CPFL_PREC_DEF, mod_idx);
221 : :
222 : : act_set++;
223 : 0 : match_rinfo->act_byte_len += sizeof(union cpfl_action_set);
224 : :
225 : 0 : mod_rinfo->type = CPFL_RULE_TYPE_MOD;
226 : 0 : minfo->mod_obj_size = CPFL_MOD_OBJ_SIZE_DEF;
227 : 0 : minfo->pin_mod_content = CPFL_PIN_MOD_CONTENT_DEF;
228 : 0 : minfo->mod_index = mod_idx;
229 : 0 : mod_rinfo->cookie = CPFL_MOD_COOKIE_DEF;
230 : 0 : mod_rinfo->port_num = CPFL_PORT_NUM_DEF;
231 : 0 : mod_rinfo->resp_req = CPFL_RESP_REQ_DEF;
232 : :
233 : 0 : minfo->mod_content_byte_len = mr_action->mod.byte_len + 2;
234 [ # # ]: 0 : for (i = 0; i < minfo->mod_content_byte_len; i++)
235 : 0 : minfo->mod_content[i] = mr_action->mod.data[i];
236 : :
237 : : return 0;
238 : : }
239 : :
240 : : #define CPFL_FXP_MAX_QREGION_SIZE 128
241 : : #define CPFL_INVALID_QUEUE_ID -2
242 : : static int
243 : 0 : cpfl_fxp_parse_action(struct cpfl_itf *itf,
244 : : const struct rte_flow_action *actions,
245 : : const struct cpfl_flow_mr_action *mr_action,
246 : : struct cpfl_rule_info_meta *rim,
247 : : int priority,
248 : : int index)
249 : : {
250 : : const struct rte_flow_action_ethdev *act_ethdev;
251 : : const struct rte_flow_action *action;
252 : : const struct rte_flow_action_queue *act_q;
253 : : const struct rte_flow_action_rss *rss;
254 : : struct rte_eth_dev_data *data;
255 : : enum rte_flow_action_type action_type;
256 : : struct cpfl_vport *vport;
257 : : /* used when action is PORT_REPRESENTOR type */
258 : : struct cpfl_itf *dst_itf;
259 : : uint16_t dev_id; /* vsi id */
260 : : int queue_id = -1;
261 : : bool fwd_vsi = false;
262 : : bool fwd_q = false;
263 : : bool is_vsi;
264 : : uint32_t i;
265 : 0 : struct cpfl_rule_info *rinfo = &rim->rules[index];
266 : 0 : union cpfl_action_set *act_set = (void *)rinfo->act_bytes;
267 : :
268 : 0 : priority = CPFL_PREC_MAX - priority;
269 [ # # ]: 0 : for (action = actions; action->type !=
270 : 0 : RTE_FLOW_ACTION_TYPE_END; action++) {
271 : : action_type = action->type;
272 [ # # # # : 0 : switch (action_type) {
# # ]
273 : 0 : case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR:
274 : : case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
275 [ # # ]: 0 : if (!fwd_vsi)
276 : : fwd_vsi = true;
277 : : else
278 : 0 : goto err;
279 : :
280 : 0 : act_ethdev = action->conf;
281 : 0 : dst_itf = cpfl_get_itf_by_port_id(act_ethdev->port_id);
282 : :
283 [ # # ]: 0 : if (!dst_itf)
284 : 0 : goto err;
285 : :
286 [ # # ]: 0 : if (dst_itf->type == CPFL_ITF_TYPE_VPORT) {
287 : : vport = (struct cpfl_vport *)dst_itf;
288 : 0 : queue_id = vport->base.chunks_info.rx_start_qid;
289 : : } else {
290 : : queue_id = CPFL_INVALID_QUEUE_ID;
291 : : }
292 : :
293 [ # # # # ]: 0 : is_vsi = (action_type == RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR ||
294 : : dst_itf->type == CPFL_ITF_TYPE_REPRESENTOR);
295 [ # # ]: 0 : if (is_vsi)
296 : 0 : dev_id = cpfl_get_vsi_id(dst_itf);
297 : : else
298 : : dev_id = cpfl_get_port_id(dst_itf);
299 : :
300 [ # # ]: 0 : if (dev_id == CPFL_INVALID_HW_ID)
301 : 0 : goto err;
302 : :
303 [ # # ]: 0 : if (is_vsi)
304 [ # # ]: 0 : *act_set = cpfl_act_fwd_vsi(0, priority, 0, dev_id);
305 : : else
306 [ # # ]: 0 : *act_set = cpfl_act_fwd_port(0, priority, 0, dev_id);
307 : 0 : act_set++;
308 : 0 : rinfo->act_byte_len += sizeof(union cpfl_action_set);
309 : 0 : break;
310 : 0 : case RTE_FLOW_ACTION_TYPE_QUEUE:
311 [ # # ]: 0 : if (!fwd_q)
312 : : fwd_q = true;
313 : : else
314 : 0 : goto err;
315 [ # # ]: 0 : if (queue_id == CPFL_INVALID_QUEUE_ID)
316 : 0 : goto err;
317 : 0 : act_q = action->conf;
318 : 0 : data = itf->data;
319 [ # # ]: 0 : if (act_q->index >= data->nb_rx_queues)
320 : 0 : goto err;
321 : :
322 : : vport = (struct cpfl_vport *)itf;
323 [ # # ]: 0 : if (queue_id < 0)
324 : 0 : queue_id = vport->base.chunks_info.rx_start_qid;
325 : 0 : queue_id += act_q->index;
326 [ # # ]: 0 : *act_set = cpfl_act_set_hash_queue(priority, 0, queue_id, 0);
327 : 0 : act_set++;
328 : 0 : rinfo->act_byte_len += sizeof(union cpfl_action_set);
329 : 0 : break;
330 : 0 : case RTE_FLOW_ACTION_TYPE_RSS:
331 : 0 : rss = action->conf;
332 [ # # ]: 0 : if (rss->queue_num <= 1)
333 : 0 : goto err;
334 [ # # ]: 0 : for (i = 0; i < rss->queue_num - 1; i++) {
335 [ # # ]: 0 : if (rss->queue[i + 1] != rss->queue[i] + 1)
336 : 0 : goto err;
337 : : }
338 : 0 : data = itf->data;
339 [ # # ]: 0 : if (rss->queue[rss->queue_num - 1] >= data->nb_rx_queues)
340 : 0 : goto err;
341 [ # # ]: 0 : if (!(rte_is_power_of_2(rss->queue_num) &&
342 : : rss->queue_num <= CPFL_FXP_MAX_QREGION_SIZE))
343 : 0 : goto err;
344 : :
345 [ # # ]: 0 : if (!fwd_q)
346 : : fwd_q = true;
347 : : else
348 : 0 : goto err;
349 [ # # ]: 0 : if (queue_id == CPFL_INVALID_QUEUE_ID)
350 : 0 : goto err;
351 : : vport = (struct cpfl_vport *)itf;
352 [ # # ]: 0 : if (queue_id < 0)
353 : 0 : queue_id = vport->base.chunks_info.rx_start_qid;
354 : 0 : queue_id += rss->queue[0];
355 : 0 : *act_set = cpfl_act_set_hash_queue_region(priority, 0, queue_id,
356 [ # # ]: 0 : log(rss->queue_num) / log(2), 0);
357 : 0 : act_set++;
358 : 0 : rinfo->act_byte_len += sizeof(union cpfl_action_set);
359 : 0 : break;
360 : 0 : case RTE_FLOW_ACTION_TYPE_DROP:
361 [ # # ]: 0 : (*act_set).data = cpfl_act_drop(priority).data;
362 : : act_set++;
363 [ # # ]: 0 : rinfo->act_byte_len += sizeof(union cpfl_action_set);
364 : 0 : (*act_set).data = cpfl_act_set_commit_mode(priority, 0).data;
365 : 0 : act_set++;
366 : 0 : rinfo->act_byte_len += sizeof(union cpfl_action_set);
367 : 0 : break;
368 : : case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
369 : : case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
370 : : case RTE_FLOW_ACTION_TYPE_PROG:
371 : : break;
372 : : case RTE_FLOW_ACTION_TYPE_VOID:
373 : : break;
374 : 0 : default:
375 : 0 : goto err;
376 : : }
377 : : }
378 : :
379 [ # # ]: 0 : if (mr_action) {
380 : : uint32_t i;
381 : :
382 [ # # ]: 0 : for (i = 0; i < rim->mr_num; i++)
383 [ # # ]: 0 : if (cpfl_parse_mod_content(itf->adapter, rinfo,
384 : 0 : &rim->rules[rim->pr_num + i],
385 : 0 : &mr_action[i]))
386 : 0 : goto err;
387 : : }
388 : :
389 : : return 0;
390 : :
391 : 0 : err:
392 : 0 : PMD_DRV_LOG(ERR, "Invalid action type");
393 : 0 : return -EINVAL;
394 : : }
395 : :
396 : : static void
397 : : cpfl_fill_rinfo_default_value(struct cpfl_rule_info *rinfo)
398 : : {
399 [ # # ]: 0 : if (cpfl_rule_cookie == ~0llu)
400 : 0 : cpfl_rule_cookie = CPFL_COOKIE_DEF;
401 : 0 : rinfo->cookie = cpfl_rule_cookie++;
402 : 0 : rinfo->host_id = CPFL_HOST_ID_DEF;
403 : 0 : rinfo->port_num = CPFL_PORT_NUM_DEF;
404 : 0 : rinfo->resp_req = CPFL_RESP_REQ_DEF;
405 : 0 : rinfo->clear_mirror_1st_state = CPFL_CLEAR_MIRROR_1ST_STATE_DEF;
406 : : }
407 : :
408 : : static bool
409 : : cpfl_is_mod_action(const struct rte_flow_action actions[])
410 : : {
411 : : const struct rte_flow_action *action;
412 : : enum rte_flow_action_type action_type;
413 : :
414 [ # # # # ]: 0 : if (!actions || actions->type == RTE_FLOW_ACTION_TYPE_END)
415 : : return false;
416 : :
417 [ # # ]: 0 : for (action = actions; action->type !=
418 : 0 : RTE_FLOW_ACTION_TYPE_END; action++) {
419 : : action_type = action->type;
420 [ # # ]: 0 : switch (action_type) {
421 : : case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
422 : : case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
423 : : case RTE_FLOW_ACTION_TYPE_PROG:
424 : : return true;
425 : 0 : default:
426 : : continue;
427 : : }
428 : : }
429 : : return false;
430 : : }
431 : :
432 : : static bool
433 : 0 : cpfl_fxp_get_metadata_port(struct cpfl_itf *itf,
434 : : const struct rte_flow_action actions[])
435 : : {
436 : : const struct rte_flow_action *action;
437 : : enum rte_flow_action_type action_type;
438 : : const struct rte_flow_action_ethdev *ethdev;
439 : : struct cpfl_itf *target_itf;
440 : : bool ret;
441 : :
442 [ # # ]: 0 : if (itf->type == CPFL_ITF_TYPE_VPORT) {
443 : 0 : ret = cpfl_metadata_write_port_id(itf);
444 [ # # ]: 0 : if (!ret) {
445 : 0 : PMD_DRV_LOG(ERR, "fail to write port id");
446 : 0 : return false;
447 : : }
448 : : }
449 : :
450 : 0 : ret = cpfl_metadata_write_sourcevsi(itf);
451 [ # # ]: 0 : if (!ret) {
452 : 0 : PMD_DRV_LOG(ERR, "fail to write source vsi id");
453 : 0 : return false;
454 : : }
455 : :
456 : 0 : ret = cpfl_metadata_write_vsi(itf);
457 [ # # ]: 0 : if (!ret) {
458 : 0 : PMD_DRV_LOG(ERR, "fail to write vsi id");
459 : 0 : return false;
460 : : }
461 : :
462 [ # # # # ]: 0 : if (!actions || actions->type == RTE_FLOW_ACTION_TYPE_END)
463 : : return false;
464 : :
465 [ # # ]: 0 : for (action = actions; action->type != RTE_FLOW_ACTION_TYPE_END; action++) {
466 : : action_type = action->type;
467 [ # # ]: 0 : switch (action_type) {
468 : 0 : case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
469 : : case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR:
470 : 0 : ethdev = (const struct rte_flow_action_ethdev *)action->conf;
471 : 0 : target_itf = cpfl_get_itf_by_port_id(ethdev->port_id);
472 [ # # ]: 0 : if (!target_itf) {
473 : 0 : PMD_DRV_LOG(ERR, "fail to get target_itf by port id");
474 : 0 : return false;
475 : : }
476 : 0 : ret = cpfl_metadata_write_targetvsi(target_itf);
477 [ # # ]: 0 : if (!ret) {
478 : 0 : PMD_DRV_LOG(ERR, "fail to write target vsi id");
479 : 0 : return false;
480 : : }
481 : : break;
482 : 0 : default:
483 : 0 : continue;
484 : : }
485 : : }
486 : :
487 : : return true;
488 : : }
489 : :
490 : : static int
491 : 0 : cpfl_fxp_parse_pattern_action(struct rte_eth_dev *dev,
492 : : const struct rte_flow_attr *attr,
493 : : const struct rte_flow_item pattern[],
494 : : const struct rte_flow_action actions[],
495 : : void **meta)
496 : : {
497 : 0 : struct cpfl_itf *itf = CPFL_DEV_TO_ITF(dev);
498 : 0 : struct cpfl_flow_pr_action pr_action = { 0 };
499 : 0 : struct cpfl_adapter_ext *adapter = itf->adapter;
500 : 0 : struct cpfl_flow_mr_action mr_action[CPFL_MAX_MR_ACTION_NUM] = { 0 };
501 : : uint32_t pr_num = 0;
502 : : uint32_t mr_num = 0;
503 : : struct cpfl_rule_info_meta *rim;
504 : : int ret;
505 : :
506 : 0 : ret = cpfl_fxp_get_metadata_port(itf, actions);
507 [ # # ]: 0 : if (!ret) {
508 : 0 : PMD_DRV_LOG(ERR, "Fail to save metadata.");
509 : 0 : return -EINVAL;
510 : : }
511 : :
512 : 0 : ret = cpfl_flow_parse_items(itf, adapter->flow_parser, pattern, attr, &pr_action);
513 [ # # ]: 0 : if (ret) {
514 : 0 : PMD_DRV_LOG(ERR, "No Match pattern support.");
515 : 0 : return -EINVAL;
516 : : }
517 : :
518 [ # # ]: 0 : if (cpfl_is_mod_action(actions)) {
519 : 0 : ret = cpfl_flow_parse_actions(adapter->flow_parser, actions, mr_action);
520 [ # # ]: 0 : if (ret) {
521 : 0 : PMD_DRV_LOG(ERR, "action parse fails.");
522 : 0 : return -EINVAL;
523 : : }
524 : : mr_num++;
525 : : }
526 : :
527 : : pr_num = 1;
528 : 0 : rim = rte_zmalloc(NULL,
529 : : sizeof(struct cpfl_rule_info_meta) +
530 : 0 : (pr_num + mr_num) * sizeof(struct cpfl_rule_info),
531 : : 0);
532 [ # # ]: 0 : if (!rim)
533 : : return -ENOMEM;
534 : :
535 : 0 : rim->pr_action = pr_action;
536 : 0 : rim->pr_num = pr_num;
537 : 0 : rim->mr_num = mr_num;
538 : 0 : rim->rule_num = pr_num + mr_num;
539 : :
540 [ # # ]: 0 : if (!cpfl_fxp_parse_pattern(&pr_action, rim, 0)) {
541 : 0 : PMD_DRV_LOG(ERR, "Invalid pattern");
542 : 0 : rte_free(rim);
543 : 0 : return -rte_errno;
544 : : }
545 : :
546 [ # # ]: 0 : if (cpfl_fxp_parse_action(itf, actions, mr_action, rim, attr->priority, 0)) {
547 : 0 : PMD_DRV_LOG(ERR, "Invalid action");
548 : 0 : rte_free(rim);
549 : 0 : return -rte_errno;
550 : : }
551 : :
552 : : cpfl_fill_rinfo_default_value(&rim->rules[0]);
553 : :
554 [ # # ]: 0 : if (!meta)
555 : 0 : rte_free(rim);
556 : : else
557 : 0 : *meta = rim;
558 : :
559 : : return 0;
560 : : }
561 : :
562 : : static int
563 : 0 : cpfl_fxp_mod_init(struct cpfl_adapter_ext *ad)
564 : : {
565 : : uint32_t size = rte_bitmap_get_memory_footprint(CPFL_MAX_MOD_CONTENT_INDEX);
566 : 0 : void *mem = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
567 : :
568 [ # # ]: 0 : if (!mem)
569 : : return -ENOMEM;
570 : :
571 : : /* a set bit represent a free slot */
572 : 0 : ad->mod_bm = rte_bitmap_init_with_all_set(CPFL_MAX_MOD_CONTENT_INDEX, mem, size);
573 [ # # ]: 0 : if (!ad->mod_bm) {
574 : 0 : rte_free(mem);
575 : 0 : return -EINVAL;
576 : : }
577 : :
578 : 0 : ad->mod_bm_mem = mem;
579 : :
580 : 0 : return 0;
581 : : }
582 : :
583 : : static void
584 : : cpfl_fxp_mod_uninit(struct cpfl_adapter_ext *ad)
585 : : {
586 : 0 : rte_free(ad->mod_bm_mem);
587 : 0 : ad->mod_bm_mem = NULL;
588 : 0 : ad->mod_bm = NULL;
589 : : }
590 : :
591 : : static uint32_t
592 : 0 : cpfl_fxp_mod_idx_alloc(struct cpfl_adapter_ext *ad)
593 : : {
594 : 0 : uint64_t slab = 0;
595 : 0 : uint32_t pos = 0;
596 : :
597 [ # # ]: 0 : if (!rte_bitmap_scan(ad->mod_bm, &pos, &slab))
598 : : return CPFL_MAX_MOD_CONTENT_INDEX;
599 : :
600 : 0 : pos += __builtin_ffsll(slab) - 1;
601 : 0 : rte_bitmap_clear(ad->mod_bm, pos);
602 : :
603 : 0 : return pos;
604 : : }
605 : :
606 : : static void
607 : : cpfl_fxp_mod_idx_free(struct cpfl_adapter_ext *ad, uint32_t idx)
608 : : {
609 : 0 : rte_bitmap_set(ad->mod_bm, idx);
610 : : }
611 : :
612 : : static int
613 : 0 : cpfl_fxp_query(struct rte_eth_dev *dev __rte_unused,
614 : : struct rte_flow *flow __rte_unused,
615 : : struct rte_flow_query_count *count __rte_unused,
616 : : struct rte_flow_error *error)
617 : : {
618 : 0 : rte_flow_error_set(error, EINVAL,
619 : : RTE_FLOW_ERROR_TYPE_HANDLE,
620 : : NULL,
621 : : "count action not supported by this module");
622 : :
623 : 0 : return -rte_errno;
624 : : }
625 : :
626 : : static void
627 : 0 : cpfl_fxp_uninit(struct cpfl_adapter_ext *ad)
628 : : {
629 : : cpfl_fxp_mod_uninit(ad);
630 : 0 : }
631 : :
632 : : static int
633 : 0 : cpfl_fxp_init(struct cpfl_adapter_ext *ad)
634 : : {
635 : : int ret = 0;
636 : :
637 : 0 : ret = cpfl_fxp_mod_init(ad);
638 [ # # ]: 0 : if (ret) {
639 : 0 : PMD_DRV_LOG(ERR, "Failed to init mod content bitmap.");
640 : 0 : return ret;
641 : : }
642 : :
643 : : return ret;
644 : : }
645 : :
646 : : static struct
647 : : cpfl_flow_engine cpfl_fxp_engine = {
648 : : .type = CPFL_FLOW_ENGINE_FXP,
649 : : .init = cpfl_fxp_init,
650 : : .uninit = cpfl_fxp_uninit,
651 : : .create = cpfl_fxp_create,
652 : : .destroy = cpfl_fxp_destroy,
653 : : .query_count = cpfl_fxp_query,
654 : : .parse_pattern_action = cpfl_fxp_parse_pattern_action,
655 : : };
656 : :
657 : 238 : RTE_INIT(cpfl_sw_engine_init)
658 : : {
659 : : struct cpfl_flow_engine *engine = &cpfl_fxp_engine;
660 : :
661 : 238 : cpfl_flow_engine_register(engine);
662 : 238 : }
|