Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2024 Marvell.
3 : : */
4 : :
5 : : #include <fcntl.h>
6 : : #include <unistd.h>
7 : :
8 : : #include <cnxk_flow.h>
9 : : #include <cnxk_rep.h>
10 : : #include <cnxk_rep_msg.h>
11 : :
12 : : #define DEFAULT_DUMP_FILE_NAME "/tmp/fdump"
13 : : #define MAX_BUFFER_SIZE 1500
14 : :
15 : : const struct cnxk_rte_flow_action_info action_info[] = {
16 : : [RTE_FLOW_ACTION_TYPE_MARK] = {sizeof(struct rte_flow_action_mark)},
17 : : [RTE_FLOW_ACTION_TYPE_VF] = {sizeof(struct rte_flow_action_vf)},
18 : : [RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT] = {sizeof(struct rte_flow_action_port_id)},
19 : : [RTE_FLOW_ACTION_TYPE_PORT_ID] = {sizeof(struct rte_flow_action_port_id)},
20 : : [RTE_FLOW_ACTION_TYPE_QUEUE] = {sizeof(struct rte_flow_action_queue)},
21 : : [RTE_FLOW_ACTION_TYPE_RSS] = {sizeof(struct rte_flow_action_rss)},
22 : : [RTE_FLOW_ACTION_TYPE_SECURITY] = {sizeof(struct rte_flow_action_security)},
23 : : [RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID] = {sizeof(struct rte_flow_action_of_set_vlan_vid)},
24 : : [RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN] = {sizeof(struct rte_flow_action_of_push_vlan)},
25 : : [RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP] = {sizeof(struct rte_flow_action_of_set_vlan_pcp)},
26 : : [RTE_FLOW_ACTION_TYPE_METER] = {sizeof(struct rte_flow_action_meter)},
27 : : [RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP] = {sizeof(struct rte_flow_action_vxlan_encap)},
28 : : [RTE_FLOW_ACTION_TYPE_COUNT] = {sizeof(struct rte_flow_action_count)},
29 : : };
30 : :
31 : : static void
32 : 0 : cnxk_flow_params_count(const struct rte_flow_item pattern[], const struct rte_flow_action actions[],
33 : : uint16_t *n_pattern, uint16_t *n_action)
34 : : {
35 : : int i = 0;
36 : :
37 [ # # ]: 0 : for (; pattern->type != RTE_FLOW_ITEM_TYPE_END; pattern++)
38 : 0 : i++;
39 : :
40 : 0 : *n_pattern = ++i;
41 : 0 : plt_rep_dbg("Total patterns is %d", *n_pattern);
42 : :
43 : : i = 0;
44 [ # # ]: 0 : for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++)
45 : 0 : i++;
46 : 0 : *n_action = ++i;
47 : 0 : plt_rep_dbg("Total actions is %d", *n_action);
48 : 0 : }
49 : :
50 : : static void
51 : 0 : populate_attr_data(void *buffer, uint32_t *length, const struct rte_flow_attr *attr)
52 : : {
53 : : uint32_t sz = sizeof(struct rte_flow_attr);
54 : : uint32_t len;
55 : :
56 : 0 : cnxk_rep_msg_populate_type(buffer, length, CNXK_TYPE_ATTR, sz);
57 : :
58 : 0 : len = *length;
59 : : /* Populate the attribute data */
60 [ # # ]: 0 : rte_memcpy(RTE_PTR_ADD(buffer, len), attr, sz);
61 : 0 : len += sz;
62 : :
63 : 0 : *length = len;
64 : 0 : }
65 : :
66 : : static uint16_t
67 : 0 : prepare_pattern_data(const struct rte_flow_item *pattern, uint16_t nb_pattern,
68 : : uint64_t *pattern_data)
69 : : {
70 : : cnxk_pattern_hdr_t hdr;
71 : : uint16_t len = 0;
72 : : int i = 0;
73 : :
74 [ # # ]: 0 : for (i = 0; i < nb_pattern; i++) {
75 : : /* Populate the pattern type hdr */
76 : : memset(&hdr, 0, sizeof(cnxk_pattern_hdr_t));
77 : 0 : hdr.type = pattern->type;
78 [ # # ]: 0 : if (pattern->spec) {
79 : 0 : hdr.spec_sz = term[pattern->type].item_size;
80 : : hdr.last_sz = 0;
81 : 0 : hdr.mask_sz = term[pattern->type].item_size;
82 : : }
83 : :
84 [ # # ]: 0 : rte_memcpy(RTE_PTR_ADD(pattern_data, len), &hdr, sizeof(cnxk_pattern_hdr_t));
85 : 0 : len += sizeof(cnxk_pattern_hdr_t);
86 : :
87 : : /* Copy pattern spec data */
88 [ # # ]: 0 : if (pattern->spec) {
89 : 0 : rte_memcpy(RTE_PTR_ADD(pattern_data, len), pattern->spec,
90 [ # # ]: 0 : term[pattern->type].item_size);
91 : 0 : len += term[pattern->type].item_size;
92 : : }
93 : :
94 : : /* Copy pattern last data */
95 [ # # ]: 0 : if (pattern->last) {
96 : 0 : rte_memcpy(RTE_PTR_ADD(pattern_data, len), pattern->last,
97 [ # # ]: 0 : term[pattern->type].item_size);
98 : 0 : len += term[pattern->type].item_size;
99 : : }
100 : :
101 : : /* Copy pattern mask data */
102 [ # # ]: 0 : if (pattern->mask) {
103 : 0 : rte_memcpy(RTE_PTR_ADD(pattern_data, len), pattern->mask,
104 [ # # ]: 0 : term[pattern->type].item_size);
105 : 0 : len += term[pattern->type].item_size;
106 : : }
107 : 0 : pattern++;
108 : : }
109 : :
110 : 0 : return len;
111 : : }
112 : :
113 : : static void
114 : 0 : populate_pattern_data(void *buffer, uint32_t *length, const struct rte_flow_item *pattern,
115 : : uint16_t nb_pattern)
116 : : {
117 : : uint64_t pattern_data[BUFSIZ];
118 : : uint32_t len;
119 : : uint32_t sz;
120 : :
121 : : memset(pattern_data, 0, BUFSIZ * sizeof(uint64_t));
122 : : /* Prepare pattern_data */
123 : 0 : sz = prepare_pattern_data(pattern, nb_pattern, pattern_data);
124 : :
125 : 0 : cnxk_rep_msg_populate_type(buffer, length, CNXK_TYPE_PATTERN, sz);
126 : :
127 : 0 : len = *length;
128 : : /* Populate the pattern data */
129 [ # # ]: 0 : rte_memcpy(RTE_PTR_ADD(buffer, len), pattern_data, sz);
130 : 0 : len += sz;
131 : :
132 : 0 : *length = len;
133 : 0 : }
134 : :
135 : : static uint16_t
136 : 0 : populate_rss_action_conf(const struct rte_flow_action_rss *conf, void *rss_action_conf)
137 : : {
138 : : int len, sz;
139 : :
140 : : len = sizeof(struct rte_flow_action_rss) - sizeof(conf->key) - sizeof(conf->queue);
141 : :
142 [ # # ]: 0 : if (rss_action_conf)
143 : : rte_memcpy(rss_action_conf, conf, len);
144 : :
145 [ # # ]: 0 : if (conf->key) {
146 : 0 : sz = conf->key_len;
147 [ # # ]: 0 : if (rss_action_conf)
148 [ # # ]: 0 : rte_memcpy(RTE_PTR_ADD(rss_action_conf, len), conf->key, sz);
149 : 0 : len += sz;
150 : : }
151 : :
152 [ # # # # ]: 0 : if (conf->queue) {
153 : 0 : sz = conf->queue_num * sizeof(conf->queue);
154 [ # # ]: 0 : if (rss_action_conf)
155 [ # # ]: 0 : rte_memcpy(RTE_PTR_ADD(rss_action_conf, len), conf->queue, sz);
156 : 0 : len += sz;
157 : : }
158 : :
159 : 0 : return len;
160 : : }
161 : :
162 : : static uint16_t
163 : 0 : populate_vxlan_encap_action_conf(const struct rte_flow_action_vxlan_encap *vxlan_conf,
164 : : void *vxlan_encap_action_data)
165 : : {
166 : : const struct rte_flow_item *pattern;
167 : 0 : uint64_t nb_patterns = 0;
168 : : uint16_t len, sz;
169 : :
170 : 0 : pattern = vxlan_conf->definition;
171 [ # # ]: 0 : for (; pattern->type != RTE_FLOW_ITEM_TYPE_END; pattern++)
172 : 0 : nb_patterns++;
173 : :
174 : : /* +1 for RTE_FLOW_ITEM_TYPE_END */
175 [ # # ]: 0 : nb_patterns++;
176 : :
177 : : len = sizeof(uint64_t);
178 : : rte_memcpy(vxlan_encap_action_data, &nb_patterns, len);
179 : 0 : pattern = vxlan_conf->definition;
180 : : /* Prepare pattern_data */
181 : 0 : sz = prepare_pattern_data(pattern, nb_patterns, RTE_PTR_ADD(vxlan_encap_action_data, len));
182 : :
183 : 0 : len += sz;
184 [ # # ]: 0 : if (len > BUFSIZ) {
185 : 0 : plt_err("Incomplete item definition loaded, len %d", len);
186 : 0 : return 0;
187 : : }
188 : :
189 : : return len;
190 : : }
191 : :
192 : : static uint16_t
193 : 0 : prepare_action_data(const struct rte_flow_action *action, uint16_t nb_action, uint64_t *action_data)
194 : : {
195 : : void *action_conf_data = NULL;
196 : : cnxk_action_hdr_t hdr;
197 : : uint16_t len = 0, sz = 0;
198 : : int i = 0;
199 : :
200 [ # # ]: 0 : for (i = 0; i < nb_action; i++) {
201 [ # # ]: 0 : if (action->conf) {
202 [ # # # ]: 0 : switch (action->type) {
203 [ # # ]: 0 : case RTE_FLOW_ACTION_TYPE_RSS:
204 : : sz = populate_rss_action_conf(action->conf, NULL);
205 : 0 : action_conf_data = plt_zmalloc(sz, 0);
206 [ # # ]: 0 : if (populate_rss_action_conf(action->conf, action_conf_data) !=
207 : : sz) {
208 : 0 : plt_err("Populating RSS action config failed");
209 : 0 : return 0;
210 : : }
211 : : break;
212 : 0 : case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
213 : 0 : action_conf_data = plt_zmalloc(BUFSIZ, 0);
214 : 0 : sz = populate_vxlan_encap_action_conf(action->conf,
215 : : action_conf_data);
216 [ # # ]: 0 : if (!sz) {
217 : 0 : plt_err("Populating vxlan action config failed");
218 : 0 : return 0;
219 : : }
220 : : break;
221 : 0 : default:
222 : 0 : sz = action_info[action->type].conf_size;
223 : 0 : action_conf_data = plt_zmalloc(sz, 0);
224 [ # # ]: 0 : rte_memcpy(action_conf_data, action->conf, sz);
225 : : break;
226 : : };
227 : : }
228 : :
229 : : /* Populate the action type hdr */
230 : : memset(&hdr, 0, sizeof(cnxk_action_hdr_t));
231 : 0 : hdr.type = action->type;
232 : 0 : hdr.conf_sz = sz;
233 : :
234 [ # # ]: 0 : rte_memcpy(RTE_PTR_ADD(action_data, len), &hdr, sizeof(cnxk_action_hdr_t));
235 : 0 : len += sizeof(cnxk_action_hdr_t);
236 : :
237 : : /* Copy action conf data */
238 [ # # ]: 0 : if (action_conf_data) {
239 [ # # ]: 0 : rte_memcpy(RTE_PTR_ADD(action_data, len), action_conf_data, sz);
240 : 0 : len += sz;
241 : 0 : plt_free(action_conf_data);
242 : : action_conf_data = NULL;
243 : : }
244 : :
245 : 0 : action++;
246 : : }
247 : :
248 : : return len;
249 : : }
250 : :
251 : : static void
252 : 0 : populate_action_data(void *buffer, uint32_t *length, const struct rte_flow_action *action,
253 : : uint16_t nb_action)
254 : : {
255 : : uint64_t action_data[BUFSIZ];
256 : : uint32_t len;
257 : : uint32_t sz;
258 : :
259 : : memset(action_data, 0, BUFSIZ * sizeof(uint64_t));
260 : : /* Prepare action_data */
261 : 0 : sz = prepare_action_data(action, nb_action, action_data);
262 : :
263 : 0 : cnxk_rep_msg_populate_type(buffer, length, CNXK_TYPE_ACTION, sz);
264 : :
265 : 0 : len = *length;
266 : : /* Populate the action data */
267 [ # # ]: 0 : rte_memcpy(RTE_PTR_ADD(buffer, len), action_data, sz);
268 : 0 : len += sz;
269 : :
270 : 0 : *length = len;
271 : 0 : }
272 : :
273 : : static int
274 : 0 : process_flow_destroy(struct cnxk_rep_dev *rep_dev, void *flow, cnxk_rep_msg_ack_data_t *adata)
275 : : {
276 : : cnxk_rep_msg_flow_destroy_meta_t msg_fd_meta;
277 : 0 : uint32_t len = 0, rc;
278 : : void *buffer;
279 : : size_t size;
280 : :
281 : : /* If representor not representing any active VF, return 0 */
282 [ # # ]: 0 : if (!rep_dev->is_vf_active)
283 : : return 0;
284 : :
285 : : size = MAX_BUFFER_SIZE;
286 : 0 : buffer = plt_zmalloc(size, 0);
287 [ # # ]: 0 : if (!buffer) {
288 : 0 : plt_err("Failed to allocate mem");
289 : : rc = -ENOMEM;
290 : 0 : goto fail;
291 : : }
292 : :
293 : 0 : cnxk_rep_msg_populate_header(buffer, &len);
294 : :
295 : 0 : msg_fd_meta.portid = rep_dev->rep_id;
296 : 0 : msg_fd_meta.flow = (uint64_t)flow;
297 : 0 : plt_rep_dbg("Flow Destroy: flow 0x%" PRIu64 ", portid %d", msg_fd_meta.flow,
298 : : msg_fd_meta.portid);
299 : 0 : cnxk_rep_msg_populate_command_meta(buffer, &len, &msg_fd_meta,
300 : : sizeof(cnxk_rep_msg_flow_destroy_meta_t),
301 : : CNXK_REP_MSG_FLOW_DESTROY);
302 : 0 : cnxk_rep_msg_populate_msg_end(buffer, &len);
303 : :
304 : 0 : rc = cnxk_rep_msg_send_process(rep_dev, buffer, len, adata);
305 [ # # ]: 0 : if (rc) {
306 : 0 : plt_err("Failed to process the message, err %d", rc);
307 : 0 : goto fail;
308 : : }
309 : :
310 : : return 0;
311 : 0 : fail:
312 : 0 : return rc;
313 : : }
314 : :
315 : : static int
316 : 0 : copy_flow_dump_file(FILE *target)
317 : : {
318 : : FILE *source = NULL;
319 : : int pos;
320 : : char ch;
321 : :
322 : 0 : source = fopen(DEFAULT_DUMP_FILE_NAME, "r");
323 [ # # ]: 0 : if (source == NULL) {
324 : 0 : plt_err("Failed to read default dump file: %s, err %d", DEFAULT_DUMP_FILE_NAME,
325 : : errno);
326 : 0 : return errno;
327 : : }
328 : :
329 : 0 : fseek(source, 0L, SEEK_END);
330 : 0 : pos = ftell(source);
331 : 0 : fseek(source, 0L, SEEK_SET);
332 [ # # ]: 0 : while (pos--) {
333 : 0 : ch = fgetc(source);
334 : 0 : fputc(ch, target);
335 : : }
336 : :
337 : 0 : fclose(source);
338 : :
339 : : /* Remove the default file after reading */
340 : 0 : remove(DEFAULT_DUMP_FILE_NAME);
341 : :
342 : 0 : return 0;
343 : : }
344 : :
345 : : static int
346 : 0 : process_flow_dump(struct cnxk_rep_dev *rep_dev, struct rte_flow *flow, FILE *file,
347 : : cnxk_rep_msg_ack_data_t *adata)
348 : : {
349 : : cnxk_rep_msg_flow_dump_meta_t msg_fp_meta;
350 : 0 : uint32_t len = 0, rc;
351 : : void *buffer;
352 : : size_t size;
353 : :
354 : : size = MAX_BUFFER_SIZE;
355 : 0 : buffer = plt_zmalloc(size, 0);
356 [ # # ]: 0 : if (!buffer) {
357 : 0 : plt_err("Failed to allocate mem");
358 : : rc = -ENOMEM;
359 : 0 : goto fail;
360 : : }
361 : :
362 : 0 : cnxk_rep_msg_populate_header(buffer, &len);
363 : :
364 : 0 : msg_fp_meta.portid = rep_dev->rep_id;
365 : 0 : msg_fp_meta.flow = (uint64_t)flow;
366 : 0 : msg_fp_meta.is_stdout = (file == stdout) ? 1 : 0;
367 : :
368 : 0 : plt_rep_dbg("Flow Dump: flow 0x%" PRIu64 ", portid %d stdout %d", msg_fp_meta.flow,
369 : : msg_fp_meta.portid, msg_fp_meta.is_stdout);
370 : 0 : cnxk_rep_msg_populate_command_meta(buffer, &len, &msg_fp_meta,
371 : : sizeof(cnxk_rep_msg_flow_dump_meta_t),
372 : : CNXK_REP_MSG_FLOW_DUMP);
373 : 0 : cnxk_rep_msg_populate_msg_end(buffer, &len);
374 : :
375 : 0 : rc = cnxk_rep_msg_send_process(rep_dev, buffer, len, adata);
376 [ # # ]: 0 : if (rc) {
377 : 0 : plt_err("Failed to process the message, err %d", rc);
378 : 0 : goto fail;
379 : : }
380 : :
381 : : /* Copy contents from default file to user file */
382 [ # # ]: 0 : if (file != stdout)
383 : 0 : copy_flow_dump_file(file);
384 : :
385 : : return 0;
386 : 0 : fail:
387 : 0 : return rc;
388 : : }
389 : :
390 : : static int
391 : 0 : process_flow_flush(struct cnxk_rep_dev *rep_dev, cnxk_rep_msg_ack_data_t *adata)
392 : : {
393 : : cnxk_rep_msg_flow_flush_meta_t msg_ff_meta;
394 : 0 : uint32_t len = 0, rc;
395 : : void *buffer;
396 : : size_t size;
397 : :
398 : : size = MAX_BUFFER_SIZE;
399 : 0 : buffer = plt_zmalloc(size, 0);
400 [ # # ]: 0 : if (!buffer) {
401 : 0 : plt_err("Failed to allocate mem");
402 : : rc = -ENOMEM;
403 : 0 : goto fail;
404 : : }
405 : :
406 : 0 : cnxk_rep_msg_populate_header(buffer, &len);
407 : :
408 : 0 : msg_ff_meta.portid = rep_dev->rep_id;
409 : 0 : plt_rep_dbg("Flow Flush: portid %d", msg_ff_meta.portid);
410 : 0 : cnxk_rep_msg_populate_command_meta(buffer, &len, &msg_ff_meta,
411 : : sizeof(cnxk_rep_msg_flow_flush_meta_t),
412 : : CNXK_REP_MSG_FLOW_FLUSH);
413 : 0 : cnxk_rep_msg_populate_msg_end(buffer, &len);
414 : :
415 : 0 : rc = cnxk_rep_msg_send_process(rep_dev, buffer, len, adata);
416 [ # # ]: 0 : if (rc) {
417 : 0 : plt_err("Failed to process the message, err %d", rc);
418 : 0 : goto fail;
419 : : }
420 : :
421 : : return 0;
422 : 0 : fail:
423 : 0 : return rc;
424 : : }
425 : :
426 : : static int
427 : 0 : process_flow_query(struct cnxk_rep_dev *rep_dev, struct rte_flow *flow,
428 : : const struct rte_flow_action *action, void *data, cnxk_rep_msg_ack_data_t *adata)
429 : : {
430 : : cnxk_rep_msg_flow_query_meta_t *msg_fq_meta;
431 : : struct rte_flow_query_count *query = data;
432 : 0 : uint32_t len = 0, rc, sz, total_sz;
433 : : uint64_t action_data[BUFSIZ];
434 : : void *buffer;
435 : : size_t size;
436 : :
437 : : size = MAX_BUFFER_SIZE;
438 : 0 : buffer = plt_zmalloc(size, 0);
439 [ # # ]: 0 : if (!buffer) {
440 : 0 : plt_err("Failed to allocate mem");
441 : : rc = -ENOMEM;
442 : 0 : goto fail;
443 : : }
444 : :
445 : 0 : cnxk_rep_msg_populate_header(buffer, &len);
446 : :
447 : : memset(action_data, 0, BUFSIZ * sizeof(uint64_t));
448 : 0 : sz = prepare_action_data(action, 1, action_data);
449 : 0 : total_sz = sz + sizeof(cnxk_rep_msg_flow_query_meta_t);
450 : :
451 : 0 : msg_fq_meta = plt_zmalloc(total_sz, 0);
452 [ # # ]: 0 : if (!msg_fq_meta) {
453 : 0 : plt_err("Failed to allocate memory");
454 : : rc = -ENOMEM;
455 : 0 : goto fail;
456 : : }
457 : :
458 : 0 : msg_fq_meta->portid = rep_dev->rep_id;
459 : 0 : msg_fq_meta->reset = query->reset;
460 : : ;
461 : 0 : msg_fq_meta->flow = (uint64_t)flow;
462 : : /* Populate the action data */
463 [ # # ]: 0 : rte_memcpy(msg_fq_meta->action_data, action_data, sz);
464 : 0 : msg_fq_meta->action_data_sz = sz;
465 : :
466 : 0 : plt_rep_dbg("Flow query: flow 0x%" PRIu64 ", portid %d, action type %d total sz %d "
467 : : "action sz %d", msg_fq_meta->flow, msg_fq_meta->portid, action->type, total_sz,
468 : : sz);
469 : 0 : cnxk_rep_msg_populate_command_meta(buffer, &len, msg_fq_meta, total_sz,
470 : : CNXK_REP_MSG_FLOW_QUERY);
471 : 0 : cnxk_rep_msg_populate_msg_end(buffer, &len);
472 : :
473 : 0 : rc = cnxk_rep_msg_send_process(rep_dev, buffer, len, adata);
474 [ # # ]: 0 : if (rc) {
475 : 0 : plt_err("Failed to process the message, err %d", rc);
476 : 0 : goto free;
477 : : }
478 : :
479 : 0 : rte_free(msg_fq_meta);
480 : :
481 : 0 : return 0;
482 : :
483 : : free:
484 : 0 : rte_free(msg_fq_meta);
485 : 0 : fail:
486 : 0 : return rc;
487 : : }
488 : :
489 : : static int
490 : 0 : process_flow_rule(struct cnxk_rep_dev *rep_dev, const struct rte_flow_attr *attr,
491 : : const struct rte_flow_item pattern[], const struct rte_flow_action actions[],
492 : : cnxk_rep_msg_ack_data_t *adata, cnxk_rep_msg_t msg)
493 : : {
494 : : cnxk_rep_msg_flow_create_meta_t msg_fc_meta;
495 : : uint16_t n_pattern, n_action;
496 : 0 : uint32_t len = 0, rc = 0;
497 : : void *buffer;
498 : : size_t size;
499 : :
500 : : size = MAX_BUFFER_SIZE;
501 : 0 : buffer = plt_zmalloc(size, 0);
502 [ # # ]: 0 : if (!buffer) {
503 : 0 : plt_err("Failed to allocate mem");
504 : : rc = -ENOMEM;
505 : 0 : goto fail;
506 : : }
507 : :
508 : : /* Get no of actions and patterns */
509 : 0 : cnxk_flow_params_count(pattern, actions, &n_pattern, &n_action);
510 : :
511 : : /* Adding the header */
512 : 0 : cnxk_rep_msg_populate_header(buffer, &len);
513 : :
514 : : /* Representor port identified as rep_xport queue */
515 : 0 : msg_fc_meta.portid = rep_dev->rep_id;
516 : 0 : msg_fc_meta.nb_pattern = n_pattern;
517 : 0 : msg_fc_meta.nb_action = n_action;
518 : :
519 : 0 : cnxk_rep_msg_populate_command_meta(buffer, &len, &msg_fc_meta,
520 : : sizeof(cnxk_rep_msg_flow_create_meta_t), msg);
521 : :
522 : : /* Populate flow create parameters data */
523 : 0 : populate_attr_data(buffer, &len, attr);
524 : 0 : populate_pattern_data(buffer, &len, pattern, n_pattern);
525 : 0 : populate_action_data(buffer, &len, actions, n_action);
526 : :
527 : 0 : cnxk_rep_msg_populate_msg_end(buffer, &len);
528 : :
529 : 0 : rc = cnxk_rep_msg_send_process(rep_dev, buffer, len, adata);
530 [ # # ]: 0 : if (rc) {
531 : 0 : plt_err("Failed to process the message, err %d", rc);
532 : 0 : goto fail;
533 : : }
534 : :
535 : : return 0;
536 : 0 : fail:
537 : 0 : return rc;
538 : : }
539 : :
540 : : static struct rte_flow *
541 : 0 : cnxk_rep_flow_create_native(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,
542 : : const struct rte_flow_item pattern[],
543 : : const struct rte_flow_action actions[], struct rte_flow_error *error)
544 : : {
545 : : struct cnxk_rep_dev *rep_dev = cnxk_rep_pmd_priv(eth_dev);
546 : : struct roc_npc_flow *flow;
547 : : uint16_t new_entry;
548 : : int rc;
549 : :
550 : 0 : flow = cnxk_flow_create_common(eth_dev, attr, pattern, actions, error, true);
551 [ # # ]: 0 : if (!flow) {
552 : 0 : plt_err("Fail to create flow");
553 : 0 : goto fail;
554 : : }
555 : :
556 : : /* Shifting the rules with higher priority than exception path rules */
557 : 0 : new_entry = (uint16_t)flow->mcam_id;
558 : 0 : rc = cnxk_eswitch_flow_rule_shift(rep_dev->hw_func, &new_entry);
559 [ # # ]: 0 : if (rc) {
560 : 0 : plt_err("Failed to shift the flow rule entry, err %d", rc);
561 : 0 : goto fail;
562 : : }
563 : :
564 : 0 : flow->mcam_id = new_entry;
565 : :
566 : 0 : return (struct rte_flow *)flow;
567 : : fail:
568 : : return NULL;
569 : : }
570 : :
571 : : static struct rte_flow *
572 [ # # ]: 0 : cnxk_rep_flow_create(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,
573 : : const struct rte_flow_item pattern[], const struct rte_flow_action actions[],
574 : : struct rte_flow_error *error)
575 : : {
576 : : struct cnxk_rep_dev *rep_dev = cnxk_rep_pmd_priv(eth_dev);
577 : : struct rte_flow *flow = NULL;
578 : : cnxk_rep_msg_ack_data_t adata;
579 : : int rc = 0;
580 : :
581 : : /* If representor not representing any active VF, return 0 */
582 [ # # ]: 0 : if (!rep_dev->is_vf_active) {
583 : 0 : rte_flow_error_set(error, -EAGAIN, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
584 : : "Represented VF not active yet");
585 : 0 : return 0;
586 : : }
587 : :
588 [ # # ]: 0 : if (rep_dev->native_repte)
589 : 0 : return cnxk_rep_flow_create_native(eth_dev, attr, pattern, actions, error);
590 : :
591 : 0 : rc = process_flow_rule(rep_dev, attr, pattern, actions, &adata, CNXK_REP_MSG_FLOW_CREATE);
592 [ # # # # ]: 0 : if (!rc || adata.u.sval < 0) {
593 [ # # ]: 0 : if (adata.u.sval < 0) {
594 : 0 : rc = (int)adata.u.sval;
595 : 0 : rte_flow_error_set(error, adata.u.sval, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
596 : : NULL, "Failed to validate flow");
597 : 0 : goto fail;
598 : : }
599 : :
600 : : flow = adata.u.data;
601 [ # # ]: 0 : if (!flow) {
602 : 0 : rte_flow_error_set(error, adata.u.sval, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
603 : : NULL, "Failed to create flow");
604 : 0 : goto fail;
605 : : }
606 : : } else {
607 : 0 : rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
608 : : "Failed to create flow");
609 : 0 : goto fail;
610 : : }
611 : 0 : plt_rep_dbg("Flow %p created successfully", adata.u.data);
612 : :
613 : 0 : return flow;
614 : : fail:
615 : : return NULL;
616 : : }
617 : :
618 : : static int
619 [ # # ]: 0 : cnxk_rep_flow_validate(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,
620 : : const struct rte_flow_item pattern[], const struct rte_flow_action actions[],
621 : : struct rte_flow_error *error)
622 : : {
623 : : struct cnxk_rep_dev *rep_dev = cnxk_rep_pmd_priv(eth_dev);
624 : : cnxk_rep_msg_ack_data_t adata;
625 : : int rc = 0;
626 : :
627 : : /* If representor not representing any active VF, return 0 */
628 [ # # ]: 0 : if (!rep_dev->is_vf_active) {
629 : 0 : rte_flow_error_set(error, -EAGAIN, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
630 : : "Represented VF not active yet");
631 : 0 : return 0;
632 : : }
633 : :
634 [ # # ]: 0 : if (rep_dev->native_repte)
635 : 0 : return cnxk_flow_validate_common(eth_dev, attr, pattern, actions, error, true);
636 : :
637 : 0 : rc = process_flow_rule(rep_dev, attr, pattern, actions, &adata, CNXK_REP_MSG_FLOW_VALIDATE);
638 [ # # # # ]: 0 : if (!rc || adata.u.sval < 0) {
639 [ # # ]: 0 : if (adata.u.sval < 0) {
640 : 0 : rc = (int)adata.u.sval;
641 : 0 : rte_flow_error_set(error, adata.u.sval, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
642 : : NULL, "Failed to validate flow");
643 : 0 : goto fail;
644 : : }
645 : : } else {
646 : 0 : rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
647 : : "Failed to validate flow");
648 : : }
649 : :
650 : 0 : plt_rep_dbg("Flow %p validated successfully", adata.u.data);
651 : :
652 : : fail:
653 : : return rc;
654 : : }
655 : :
656 : : static int
657 [ # # ]: 0 : cnxk_rep_flow_destroy(struct rte_eth_dev *eth_dev, struct rte_flow *flow,
658 : : struct rte_flow_error *error)
659 : : {
660 : : struct cnxk_rep_dev *rep_dev = cnxk_rep_pmd_priv(eth_dev);
661 : : cnxk_rep_msg_ack_data_t adata;
662 : : int rc;
663 : :
664 : : /* If representor not representing any active VF, return 0 */
665 [ # # ]: 0 : if (!rep_dev->is_vf_active) {
666 : 0 : rte_flow_error_set(error, -EAGAIN, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
667 : : "Represented VF not active yet");
668 : 0 : return 0;
669 : : }
670 : :
671 [ # # ]: 0 : if (rep_dev->native_repte)
672 : 0 : return cnxk_flow_destroy_common(eth_dev, (struct roc_npc_flow *)flow, error, true);
673 : :
674 : 0 : rc = process_flow_destroy(rep_dev, flow, &adata);
675 [ # # # # ]: 0 : if (rc || adata.u.sval < 0) {
676 [ # # ]: 0 : if (adata.u.sval < 0)
677 : 0 : rc = adata.u.sval;
678 : :
679 : 0 : rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
680 : : "Failed to destroy flow");
681 : 0 : goto fail;
682 : : }
683 : :
684 : : return 0;
685 : : fail:
686 : 0 : return rc;
687 : : }
688 : :
689 : : static int
690 [ # # ]: 0 : cnxk_rep_flow_query(struct rte_eth_dev *eth_dev, struct rte_flow *flow,
691 : : const struct rte_flow_action *action, void *data, struct rte_flow_error *error)
692 : : {
693 : : struct cnxk_rep_dev *rep_dev = cnxk_rep_pmd_priv(eth_dev);
694 : : cnxk_rep_msg_ack_data_t adata;
695 : : int rc;
696 : :
697 : : /* If representor not representing any active VF, return 0 */
698 [ # # ]: 0 : if (!rep_dev->is_vf_active) {
699 : 0 : rte_flow_error_set(error, -EAGAIN, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
700 : : "Represented VF not active yet");
701 : 0 : return 0;
702 : : }
703 : :
704 [ # # ]: 0 : if (action->type != RTE_FLOW_ACTION_TYPE_COUNT) {
705 : : rc = -ENOTSUP;
706 : 0 : rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
707 : : "Only COUNT is supported in query");
708 : 0 : goto fail;
709 : : }
710 : :
711 [ # # ]: 0 : if (rep_dev->native_repte)
712 : 0 : return cnxk_flow_query_common(eth_dev, flow, action, data, error, true);
713 : :
714 : 0 : rc = process_flow_query(rep_dev, flow, action, data, &adata);
715 [ # # # # ]: 0 : if (rc || adata.u.sval < 0) {
716 [ # # ]: 0 : if (adata.u.sval < 0)
717 : 0 : rc = adata.u.sval;
718 : :
719 : 0 : rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
720 : : "Failed to query the flow");
721 : 0 : goto fail;
722 : : }
723 : :
724 [ # # ]: 0 : rte_memcpy(data, adata.u.data, adata.size);
725 : :
726 : : return 0;
727 : : fail:
728 : : return rc;
729 : : }
730 : :
731 : : static int
732 [ # # ]: 0 : cnxk_rep_flow_flush(struct rte_eth_dev *eth_dev, struct rte_flow_error *error)
733 : : {
734 : : struct cnxk_rep_dev *rep_dev = cnxk_rep_pmd_priv(eth_dev);
735 : : cnxk_rep_msg_ack_data_t adata;
736 : : int rc;
737 : :
738 : : /* If representor not representing any active VF, return 0 */
739 [ # # ]: 0 : if (!rep_dev->is_vf_active) {
740 : 0 : rte_flow_error_set(error, -EAGAIN, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
741 : : "Represented VF not active yet");
742 : 0 : return 0;
743 : : }
744 : :
745 [ # # ]: 0 : if (rep_dev->native_repte)
746 : 0 : return cnxk_flow_flush_common(eth_dev, error, true);
747 : :
748 : 0 : rc = process_flow_flush(rep_dev, &adata);
749 [ # # # # ]: 0 : if (rc || adata.u.sval < 0) {
750 [ # # ]: 0 : if (adata.u.sval < 0)
751 : 0 : rc = adata.u.sval;
752 : :
753 : 0 : rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
754 : : "Failed to destroy flow");
755 : 0 : goto fail;
756 : : }
757 : :
758 : : return 0;
759 : : fail:
760 : 0 : return rc;
761 : : }
762 : :
763 : : static int
764 [ # # ]: 0 : cnxk_rep_flow_dev_dump(struct rte_eth_dev *eth_dev, struct rte_flow *flow, FILE *file,
765 : : struct rte_flow_error *error)
766 : : {
767 : : struct cnxk_rep_dev *rep_dev = cnxk_rep_pmd_priv(eth_dev);
768 : : cnxk_rep_msg_ack_data_t adata;
769 : : int rc;
770 : :
771 : : /* If representor not representing any active VF, return 0 */
772 [ # # ]: 0 : if (!rep_dev->is_vf_active) {
773 : 0 : rte_flow_error_set(error, -EAGAIN, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
774 : : "Represented VF not active yet");
775 : 0 : return 0;
776 : : }
777 : :
778 [ # # ]: 0 : if (rep_dev->native_repte)
779 : 0 : return cnxk_flow_dev_dump_common(eth_dev, flow, file, error, true);
780 : :
781 : 0 : rc = process_flow_dump(rep_dev, flow, file, &adata);
782 [ # # # # ]: 0 : if (rc || adata.u.sval < 0) {
783 [ # # ]: 0 : if (adata.u.sval < 0)
784 : 0 : rc = adata.u.sval;
785 : :
786 : 0 : rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
787 : : "Failed to destroy flow");
788 : 0 : goto fail;
789 : : }
790 : :
791 : : return 0;
792 : : fail:
793 : 0 : return rc;
794 : : }
795 : :
796 : : static int
797 : 0 : cnxk_rep_flow_isolate(struct rte_eth_dev *eth_dev __rte_unused, int enable __rte_unused,
798 : : struct rte_flow_error *error)
799 : : {
800 : : /* If we support, we need to un-install the default mcam
801 : : * entry for this port.
802 : : */
803 : :
804 : 0 : rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
805 : : "Flow isolation not supported");
806 : :
807 : 0 : return -rte_errno;
808 : : }
809 : :
810 : : struct rte_flow_ops cnxk_rep_flow_ops = {
811 : : .validate = cnxk_rep_flow_validate,
812 : : .create = cnxk_rep_flow_create,
813 : : .destroy = cnxk_rep_flow_destroy,
814 : : .query = cnxk_rep_flow_query,
815 : : .flush = cnxk_rep_flow_flush,
816 : : .isolate = cnxk_rep_flow_isolate,
817 : : .dev_dump = cnxk_rep_flow_dev_dump,
818 : : };
|