1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2020 Intel Corporation
3 */
4 #include <stdint.h>
5 #include <inttypes.h>
6 #include <stdlib.h>
7 #include <stdio.h>
8 #include <string.h>
9 #include <errno.h>
10
11 #include <rte_common.h>
12 #include <rte_mempool.h>
13
14 #include <rte_swx_port_ethdev.h>
15 #include <rte_swx_port_ring.h>
16 #include <rte_swx_port_source_sink.h>
17 #include <rte_swx_port_fd.h>
18
19 #include "rte_swx_pipeline_spec.h"
20
21 #ifndef MAX_LINE_LENGTH
22 #define MAX_LINE_LENGTH 2048
23 #endif
24
25 #ifndef MAX_TOKENS
26 #define MAX_TOKENS 256
27 #endif
28
29 #define STRUCT_BLOCK 0
30 #define ACTION_BLOCK 1
31 #define TABLE_BLOCK 2
32 #define TABLE_KEY_BLOCK 3
33 #define TABLE_ACTIONS_BLOCK 4
34 #define SELECTOR_BLOCK 5
35 #define SELECTOR_SELECTOR_BLOCK 6
36 #define LEARNER_BLOCK 7
37 #define LEARNER_KEY_BLOCK 8
38 #define LEARNER_ACTIONS_BLOCK 9
39 #define LEARNER_TIMEOUT_BLOCK 10
40 #define APPLY_BLOCK 11
41
42 /*
43 * extobj.
44 */
45 static void
extobj_spec_free(struct extobj_spec * s)46 extobj_spec_free(struct extobj_spec *s)
47 {
48 if (!s)
49 return;
50
51 free(s->name);
52 s->name = NULL;
53
54 free(s->extern_type_name);
55 s->extern_type_name = NULL;
56
57 free(s->pragma);
58 s->pragma = NULL;
59 }
60
61 static int
extobj_statement_parse(struct extobj_spec * s,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)62 extobj_statement_parse(struct extobj_spec *s,
63 char **tokens,
64 uint32_t n_tokens,
65 uint32_t n_lines,
66 uint32_t *err_line,
67 const char **err_msg)
68 {
69 /* Check format. */
70 if (((n_tokens != 4) && (n_tokens != 6)) ||
71 ((n_tokens == 4) && strcmp(tokens[2], "instanceof")) ||
72 ((n_tokens == 6) && (strcmp(tokens[2], "instanceof") ||
73 strcmp(tokens[4], "pragma")))) {
74 if (err_line)
75 *err_line = n_lines;
76 if (err_msg)
77 *err_msg = "Invalid extobj statement.";
78 return -EINVAL;
79 }
80
81 /* spec. */
82 s->name = strdup(tokens[1]);
83 s->extern_type_name = strdup(tokens[3]);
84 s->pragma = (n_tokens == 6) ? strdup(tokens[5]) : NULL;
85
86 if (!s->name ||
87 !s->extern_type_name ||
88 ((n_tokens == 6) && !s->pragma)) {
89 free(s->name);
90 free(s->extern_type_name);
91 free(s->pragma);
92
93 if (err_line)
94 *err_line = n_lines;
95 if (err_msg)
96 *err_msg = "Memory allocation failed.";
97 return -ENOMEM;
98 }
99
100 return 0;
101 }
102
103 /*
104 * struct.
105 */
106 static void
struct_spec_free(struct struct_spec * s)107 struct_spec_free(struct struct_spec *s)
108 {
109 uint32_t i;
110
111 if (!s)
112 return;
113
114 free(s->name);
115 s->name = NULL;
116
117 for (i = 0; i < s->n_fields; i++) {
118 uintptr_t name = (uintptr_t)s->fields[i].name;
119
120 free((void *)name);
121 }
122
123 free(s->fields);
124 s->fields = NULL;
125
126 s->n_fields = 0;
127
128 s->varbit = 0;
129 }
130
131 static int
struct_statement_parse(struct struct_spec * s,uint32_t * block_mask,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)132 struct_statement_parse(struct struct_spec *s,
133 uint32_t *block_mask,
134 char **tokens,
135 uint32_t n_tokens,
136 uint32_t n_lines,
137 uint32_t *err_line,
138 const char **err_msg)
139 {
140 /* Check format. */
141 if ((n_tokens != 3) || strcmp(tokens[2], "{")) {
142 if (err_line)
143 *err_line = n_lines;
144 if (err_msg)
145 *err_msg = "Invalid struct statement.";
146 return -EINVAL;
147 }
148
149 /* spec. */
150 s->name = strdup(tokens[1]);
151 if (!s->name) {
152 if (err_line)
153 *err_line = n_lines;
154 if (err_msg)
155 *err_msg = "Memory allocation failed.";
156 return -ENOMEM;
157 }
158
159 /* block_mask. */
160 *block_mask |= 1 << STRUCT_BLOCK;
161
162 return 0;
163 }
164
165 static int
struct_block_parse(struct struct_spec * s,uint32_t * block_mask,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)166 struct_block_parse(struct struct_spec *s,
167 uint32_t *block_mask,
168 char **tokens,
169 uint32_t n_tokens,
170 uint32_t n_lines,
171 uint32_t *err_line,
172 const char **err_msg)
173 {
174 struct rte_swx_field_params *new_fields;
175 char *p = tokens[0], *name = NULL;
176 uint32_t n_bits;
177 int varbit = 0, error = 0, error_size_invalid = 0, error_varbit_not_last = 0;
178
179 /* Handle end of block. */
180 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
181 *block_mask &= ~(1 << STRUCT_BLOCK);
182 return 0;
183 }
184
185 /* Check format. */
186 if (n_tokens != 2) {
187 error = -EINVAL;
188 goto error;
189 }
190
191 if (s->varbit) {
192 error = -EINVAL;
193 error_varbit_not_last = 1;
194 goto error;
195 }
196
197 if (!strncmp(p, "bit<", strlen("bit<"))) {
198 size_t len = strlen(p);
199
200 if ((len < strlen("bit< >")) || (p[len - 1] != '>')) {
201 error = -EINVAL;
202 goto error;
203 }
204
205 /* Remove the "bit<" and ">". */
206 p[strlen(p) - 1] = 0;
207 p += strlen("bit<");
208 } else if (!strncmp(p, "varbit<", strlen("varbit<"))) {
209 size_t len = strlen(p);
210
211 if ((len < strlen("varbit< >")) || (p[len - 1] != '>')) {
212 error = -EINVAL;
213 goto error;
214 }
215
216 /* Remove the "varbit<" and ">". */
217 p[strlen(p) - 1] = 0;
218 p += strlen("varbit<");
219
220 /* Set the varbit flag. */
221 varbit = 1;
222 } else {
223 error = -EINVAL;
224 goto error;
225 }
226
227 n_bits = strtoul(p, &p, 0);
228 if ((p[0]) ||
229 !n_bits ||
230 (n_bits % 8)) {
231 error = -EINVAL;
232 error_size_invalid = 1;
233 goto error;
234 }
235
236 /* spec. */
237 name = strdup(tokens[1]);
238 if (!name) {
239 error = -ENOMEM;
240 goto error;
241 }
242
243 new_fields = realloc(s->fields, (s->n_fields + 1) * sizeof(struct rte_swx_field_params));
244 if (!new_fields) {
245 error = -ENOMEM;
246 goto error;
247 }
248
249 s->fields = new_fields;
250 s->fields[s->n_fields].name = name;
251 s->fields[s->n_fields].n_bits = n_bits;
252 s->n_fields++;
253 s->varbit = varbit;
254
255 return 0;
256
257 error:
258 free(name);
259
260 if (err_line)
261 *err_line = n_lines;
262
263 if (err_msg) {
264 *err_msg = "Invalid struct field statement.";
265
266 if ((error == -EINVAL) && error_varbit_not_last)
267 *err_msg = "Varbit field is not the last struct field.";
268
269 if ((error == -EINVAL) && error_size_invalid)
270 *err_msg = "Invalid struct field size.";
271
272 if (error == -ENOMEM)
273 *err_msg = "Memory allocation failed.";
274 }
275
276 return error;
277 }
278
279 /*
280 * header.
281 */
282 static void
header_spec_free(struct header_spec * s)283 header_spec_free(struct header_spec *s)
284 {
285 if (!s)
286 return;
287
288 free(s->name);
289 s->name = NULL;
290
291 free(s->struct_type_name);
292 s->struct_type_name = NULL;
293 }
294
295 static int
header_statement_parse(struct header_spec * s,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)296 header_statement_parse(struct header_spec *s,
297 char **tokens,
298 uint32_t n_tokens,
299 uint32_t n_lines,
300 uint32_t *err_line,
301 const char **err_msg)
302 {
303 /* Check format. */
304 if ((n_tokens != 4) || strcmp(tokens[2], "instanceof")) {
305 if (err_line)
306 *err_line = n_lines;
307 if (err_msg)
308 *err_msg = "Invalid header statement.";
309 return -EINVAL;
310 }
311
312 /* spec. */
313 s->name = strdup(tokens[1]);
314 s->struct_type_name = strdup(tokens[3]);
315
316 if (!s->name || !s->struct_type_name) {
317 free(s->name);
318 free(s->struct_type_name);
319
320 if (err_line)
321 *err_line = n_lines;
322 if (err_msg)
323 *err_msg = "Memory allocation failed.";
324 return -ENOMEM;
325 }
326
327 return 0;
328 }
329
330 /*
331 * metadata.
332 */
333 static void
metadata_spec_free(struct metadata_spec * s)334 metadata_spec_free(struct metadata_spec *s)
335 {
336 if (!s)
337 return;
338
339 free(s->struct_type_name);
340 s->struct_type_name = NULL;
341 }
342
343 static int
metadata_statement_parse(struct metadata_spec * s,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)344 metadata_statement_parse(struct metadata_spec *s,
345 char **tokens,
346 uint32_t n_tokens,
347 uint32_t n_lines,
348 uint32_t *err_line,
349 const char **err_msg)
350 {
351 /* Check format. */
352 if ((n_tokens != 3) || strcmp(tokens[1], "instanceof")) {
353 if (err_line)
354 *err_line = n_lines;
355 if (err_msg)
356 *err_msg = "Invalid metadata statement.";
357 return -EINVAL;
358 }
359
360 /* spec. */
361 s->struct_type_name = strdup(tokens[2]);
362 if (!s->struct_type_name) {
363 if (err_line)
364 *err_line = n_lines;
365 if (err_msg)
366 *err_msg = "Memory allocation failed.";
367 return -ENOMEM;
368 }
369
370 return 0;
371 }
372
373 /*
374 * action.
375 */
376 static void
action_spec_free(struct action_spec * s)377 action_spec_free(struct action_spec *s)
378 {
379 uint32_t i;
380
381 if (!s)
382 return;
383
384 free(s->name);
385 s->name = NULL;
386
387 free(s->args_struct_type_name);
388 s->args_struct_type_name = NULL;
389
390 for (i = 0; i < s->n_instructions; i++) {
391 uintptr_t instr = (uintptr_t)s->instructions[i];
392
393 free((void *)instr);
394 }
395
396 free(s->instructions);
397 s->instructions = NULL;
398
399 s->n_instructions = 0;
400 }
401
402 static int
action_statement_parse(struct action_spec * s,uint32_t * block_mask,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)403 action_statement_parse(struct action_spec *s,
404 uint32_t *block_mask,
405 char **tokens,
406 uint32_t n_tokens,
407 uint32_t n_lines,
408 uint32_t *err_line,
409 const char **err_msg)
410 {
411 /* Check format. */
412 if (((n_tokens != 5) && (n_tokens != 6)) ||
413 ((n_tokens == 5) &&
414 (strcmp(tokens[2], "args") ||
415 strcmp(tokens[3], "none") ||
416 strcmp(tokens[4], "{"))) ||
417 ((n_tokens == 6) &&
418 (strcmp(tokens[2], "args") ||
419 strcmp(tokens[3], "instanceof") ||
420 strcmp(tokens[5], "{")))) {
421 if (err_line)
422 *err_line = n_lines;
423 if (err_msg)
424 *err_msg = "Invalid action statement.";
425 return -EINVAL;
426 }
427
428 /* spec. */
429 s->name = strdup(tokens[1]);
430 s->args_struct_type_name = (n_tokens == 6) ? strdup(tokens[4]) : NULL;
431
432 if ((!s->name) || ((n_tokens == 6) && !s->args_struct_type_name)) {
433 if (err_line)
434 *err_line = n_lines;
435 if (err_msg)
436 *err_msg = "Memory allocation failed.";
437 return -ENOMEM;
438 }
439
440 /* block_mask. */
441 *block_mask |= 1 << ACTION_BLOCK;
442
443 return 0;
444 }
445
446 static int
action_block_parse(struct action_spec * s,uint32_t * block_mask,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)447 action_block_parse(struct action_spec *s,
448 uint32_t *block_mask,
449 char **tokens,
450 uint32_t n_tokens,
451 uint32_t n_lines,
452 uint32_t *err_line,
453 const char **err_msg)
454 {
455 char buffer[RTE_SWX_INSTRUCTION_SIZE], *instr;
456 const char **new_instructions;
457 uint32_t i;
458
459 /* Handle end of block. */
460 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
461 *block_mask &= ~(1 << ACTION_BLOCK);
462 return 0;
463 }
464
465 /* spec. */
466 buffer[0] = 0;
467 for (i = 0; i < n_tokens; i++) {
468 if (i)
469 strcat(buffer, " ");
470 strcat(buffer, tokens[i]);
471 }
472
473 instr = strdup(buffer);
474 if (!instr) {
475 if (err_line)
476 *err_line = n_lines;
477 if (err_msg)
478 *err_msg = "Memory allocation failed.";
479 return -ENOMEM;
480 }
481
482 new_instructions = realloc(s->instructions,
483 (s->n_instructions + 1) * sizeof(char *));
484 if (!new_instructions) {
485 free(instr);
486
487 if (err_line)
488 *err_line = n_lines;
489 if (err_msg)
490 *err_msg = "Memory allocation failed.";
491 return -ENOMEM;
492 }
493
494 s->instructions = new_instructions;
495 s->instructions[s->n_instructions] = instr;
496 s->n_instructions++;
497
498 return 0;
499 }
500
501 /*
502 * table.
503 */
504 static void
table_spec_free(struct table_spec * s)505 table_spec_free(struct table_spec *s)
506 {
507 uintptr_t default_action_name, default_action_args, hash_func_name;
508 uint32_t i;
509
510 if (!s)
511 return;
512
513 free(s->name);
514 s->name = NULL;
515
516 for (i = 0; i < s->params.n_fields; i++) {
517 uintptr_t name = (uintptr_t)s->params.fields[i].name;
518
519 free((void *)name);
520 }
521
522 free(s->params.fields);
523 s->params.fields = NULL;
524
525 s->params.n_fields = 0;
526
527 for (i = 0; i < s->params.n_actions; i++) {
528 uintptr_t name = (uintptr_t)s->params.action_names[i];
529
530 free((void *)name);
531 }
532
533 free(s->params.action_names);
534 s->params.action_names = NULL;
535
536 s->params.n_actions = 0;
537
538 default_action_name = (uintptr_t)s->params.default_action_name;
539 free((void *)default_action_name);
540 s->params.default_action_name = NULL;
541
542 default_action_args = (uintptr_t)s->params.default_action_args;
543 free((void *)default_action_args);
544 s->params.default_action_args = NULL;
545
546 free(s->params.action_is_for_table_entries);
547 s->params.action_is_for_table_entries = NULL;
548
549 free(s->params.action_is_for_default_entry);
550 s->params.action_is_for_default_entry = NULL;
551
552 s->params.default_action_is_const = 0;
553
554 hash_func_name = (uintptr_t)s->params.hash_func_name;
555 free((void *)hash_func_name);
556 s->params.hash_func_name = NULL;
557
558 free(s->recommended_table_type_name);
559 s->recommended_table_type_name = NULL;
560
561 free(s->args);
562 s->args = NULL;
563
564 s->size = 0;
565 }
566
567 static int
table_key_statement_parse(uint32_t * block_mask,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)568 table_key_statement_parse(uint32_t *block_mask,
569 char **tokens,
570 uint32_t n_tokens,
571 uint32_t n_lines,
572 uint32_t *err_line,
573 const char **err_msg)
574 {
575 /* Check format. */
576 if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
577 if (err_line)
578 *err_line = n_lines;
579 if (err_msg)
580 *err_msg = "Invalid key statement.";
581 return -EINVAL;
582 }
583
584 /* block_mask. */
585 *block_mask |= 1 << TABLE_KEY_BLOCK;
586
587 return 0;
588 }
589
590 static int
table_key_block_parse(struct table_spec * s,uint32_t * block_mask,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)591 table_key_block_parse(struct table_spec *s,
592 uint32_t *block_mask,
593 char **tokens,
594 uint32_t n_tokens,
595 uint32_t n_lines,
596 uint32_t *err_line,
597 const char **err_msg)
598 {
599 struct rte_swx_match_field_params *new_fields;
600 enum rte_swx_table_match_type match_type = RTE_SWX_TABLE_MATCH_WILDCARD;
601 char *name;
602
603 /* Handle end of block. */
604 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
605 *block_mask &= ~(1 << TABLE_KEY_BLOCK);
606 return 0;
607 }
608
609 /* Check input arguments. */
610 if ((n_tokens != 2) ||
611 (strcmp(tokens[1], "exact") &&
612 strcmp(tokens[1], "wildcard") &&
613 strcmp(tokens[1], "lpm"))) {
614 if (err_line)
615 *err_line = n_lines;
616 if (err_msg)
617 *err_msg = "Invalid match field statement.";
618 return -EINVAL;
619 }
620
621 if (!strcmp(tokens[1], "wildcard"))
622 match_type = RTE_SWX_TABLE_MATCH_WILDCARD;
623 if (!strcmp(tokens[1], "lpm"))
624 match_type = RTE_SWX_TABLE_MATCH_LPM;
625 if (!strcmp(tokens[1], "exact"))
626 match_type = RTE_SWX_TABLE_MATCH_EXACT;
627
628 name = strdup(tokens[0]);
629 if (!name) {
630 if (err_line)
631 *err_line = n_lines;
632 if (err_msg)
633 *err_msg = "Memory allocation failed.";
634 return -ENOMEM;
635 }
636
637 new_fields = realloc(s->params.fields,
638 (s->params.n_fields + 1) * sizeof(struct rte_swx_match_field_params));
639 if (!new_fields) {
640 free(name);
641
642 if (err_line)
643 *err_line = n_lines;
644 if (err_msg)
645 *err_msg = "Memory allocation failed.";
646 return -ENOMEM;
647 }
648
649 s->params.fields = new_fields;
650 s->params.fields[s->params.n_fields].name = name;
651 s->params.fields[s->params.n_fields].match_type = match_type;
652 s->params.n_fields++;
653
654 return 0;
655 }
656
657 static int
table_actions_statement_parse(uint32_t * block_mask,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)658 table_actions_statement_parse(uint32_t *block_mask,
659 char **tokens,
660 uint32_t n_tokens,
661 uint32_t n_lines,
662 uint32_t *err_line,
663 const char **err_msg)
664 {
665 /* Check format. */
666 if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
667 if (err_line)
668 *err_line = n_lines;
669 if (err_msg)
670 *err_msg = "Invalid actions statement.";
671 return -EINVAL;
672 }
673
674 /* block_mask. */
675 *block_mask |= 1 << TABLE_ACTIONS_BLOCK;
676
677 return 0;
678 }
679
680 static int
table_actions_block_parse(struct table_spec * s,uint32_t * block_mask,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)681 table_actions_block_parse(struct table_spec *s,
682 uint32_t *block_mask,
683 char **tokens,
684 uint32_t n_tokens,
685 uint32_t n_lines,
686 uint32_t *err_line,
687 const char **err_msg)
688 {
689 const char **new_action_names = NULL;
690 int *new_action_is_for_table_entries = NULL, *new_action_is_for_default_entry = NULL;
691 char *name = NULL;
692 int action_is_for_table_entries = 1, action_is_for_default_entry = 1;
693
694 /* Handle end of block. */
695 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
696 *block_mask &= ~(1 << TABLE_ACTIONS_BLOCK);
697 return 0;
698 }
699
700 /* Check input arguments. */
701 if ((n_tokens > 2) ||
702 ((n_tokens == 2) && strcmp(tokens[1], "@tableonly") &&
703 strcmp(tokens[1], "@defaultonly"))) {
704 if (err_line)
705 *err_line = n_lines;
706 if (err_msg)
707 *err_msg = "Invalid action name statement.";
708 return -EINVAL;
709 }
710
711 name = strdup(tokens[0]);
712
713 if (n_tokens == 2) {
714 if (!strcmp(tokens[1], "@tableonly"))
715 action_is_for_default_entry = 0;
716
717 if (!strcmp(tokens[1], "@defaultonly"))
718 action_is_for_table_entries = 0;
719 }
720
721 new_action_names = realloc(s->params.action_names,
722 (s->params.n_actions + 1) * sizeof(char *));
723 new_action_is_for_table_entries = realloc(s->params.action_is_for_table_entries,
724 (s->params.n_actions + 1) * sizeof(int));
725 new_action_is_for_default_entry = realloc(s->params.action_is_for_default_entry,
726 (s->params.n_actions + 1) * sizeof(int));
727
728 if (!name ||
729 !new_action_names ||
730 !new_action_is_for_table_entries ||
731 !new_action_is_for_default_entry) {
732 free(name);
733 free(new_action_names);
734 free(new_action_is_for_table_entries);
735 free(new_action_is_for_default_entry);
736
737 if (err_line)
738 *err_line = n_lines;
739 if (err_msg)
740 *err_msg = "Memory allocation failed.";
741 return -ENOMEM;
742 }
743
744 s->params.action_names = new_action_names;
745 s->params.action_names[s->params.n_actions] = name;
746
747 s->params.action_is_for_table_entries = new_action_is_for_table_entries;
748 s->params.action_is_for_table_entries[s->params.n_actions] = action_is_for_table_entries;
749
750 s->params.action_is_for_default_entry = new_action_is_for_default_entry;
751 s->params.action_is_for_default_entry[s->params.n_actions] = action_is_for_default_entry;
752
753 s->params.n_actions++;
754
755 return 0;
756 }
757
758 static int
table_default_action_statement_parse(struct table_spec * s,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)759 table_default_action_statement_parse(struct table_spec *s,
760 char **tokens,
761 uint32_t n_tokens,
762 uint32_t n_lines,
763 uint32_t *err_line,
764 const char **err_msg)
765 {
766 uint32_t i;
767 int status = 0, duplicate = 0;
768
769 /* Check format. */
770 if ((n_tokens < 4) ||
771 strcmp(tokens[2], "args")) {
772 status = -EINVAL;
773 goto error;
774 }
775
776 if (s->params.default_action_name) {
777 duplicate = 1;
778 status = -EINVAL;
779 goto error;
780 }
781
782 s->params.default_action_name = strdup(tokens[1]);
783 if (!s->params.default_action_name) {
784 status = -ENOMEM;
785 goto error;
786 }
787
788 if (strcmp(tokens[3], "none")) {
789 char buffer[MAX_LINE_LENGTH];
790 uint32_t n_tokens_args = n_tokens - 3;
791
792 if (!strcmp(tokens[n_tokens - 1], "const"))
793 n_tokens_args--;
794
795 if (!n_tokens_args) {
796 status = -EINVAL;
797 goto error;
798 }
799
800 buffer[0] = 0;
801 for (i = 0; i < n_tokens_args; i++) {
802 if (i)
803 strcat(buffer, " ");
804
805 strcat(buffer, tokens[3 + i]);
806 }
807
808 s->params.default_action_args = strdup(buffer);
809 if (!s->params.default_action_args) {
810 status = -ENOMEM;
811 goto error;
812 }
813 } else {
814 if (((n_tokens != 4) && (n_tokens != 5)) ||
815 ((n_tokens == 5) && (strcmp(tokens[4], "const")))) {
816 status = -EINVAL;
817 goto error;
818 }
819 }
820
821 if (!strcmp(tokens[n_tokens - 1], "const"))
822 s->params.default_action_is_const = 1;
823
824 return 0;
825
826 error:
827 if (err_line)
828 *err_line = n_lines;
829
830 if (err_msg)
831 switch (status) {
832 case -ENOMEM:
833 *err_msg = "Memory allocation failed.";
834 break;
835
836 default:
837 if (duplicate)
838 *err_msg = "Duplicate default_action statement.";
839
840 *err_msg = "Invalid default_action statement.";
841 }
842
843 return status;
844 }
845
846 static int
table_statement_parse(struct table_spec * s,uint32_t * block_mask,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)847 table_statement_parse(struct table_spec *s,
848 uint32_t *block_mask,
849 char **tokens,
850 uint32_t n_tokens,
851 uint32_t n_lines,
852 uint32_t *err_line,
853 const char **err_msg)
854 {
855 /* Check format. */
856 if ((n_tokens != 3) || strcmp(tokens[2], "{")) {
857 if (err_line)
858 *err_line = n_lines;
859 if (err_msg)
860 *err_msg = "Invalid table statement.";
861 return -EINVAL;
862 }
863
864 /* spec. */
865 s->name = strdup(tokens[1]);
866 if (!s->name) {
867 if (err_line)
868 *err_line = n_lines;
869 if (err_msg)
870 *err_msg = "Memory allocation failed.";
871 return -ENOMEM;
872 }
873
874 /* block_mask. */
875 *block_mask |= 1 << TABLE_BLOCK;
876
877 return 0;
878 }
879
880 static int
table_block_parse(struct table_spec * s,uint32_t * block_mask,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)881 table_block_parse(struct table_spec *s,
882 uint32_t *block_mask,
883 char **tokens,
884 uint32_t n_tokens,
885 uint32_t n_lines,
886 uint32_t *err_line,
887 const char **err_msg)
888 {
889 if (*block_mask & (1 << TABLE_KEY_BLOCK))
890 return table_key_block_parse(s,
891 block_mask,
892 tokens,
893 n_tokens,
894 n_lines,
895 err_line,
896 err_msg);
897
898 if (*block_mask & (1 << TABLE_ACTIONS_BLOCK))
899 return table_actions_block_parse(s,
900 block_mask,
901 tokens,
902 n_tokens,
903 n_lines,
904 err_line,
905 err_msg);
906
907 /* Handle end of block. */
908 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
909 *block_mask &= ~(1 << TABLE_BLOCK);
910 return 0;
911 }
912
913 if (!strcmp(tokens[0], "key"))
914 return table_key_statement_parse(block_mask,
915 tokens,
916 n_tokens,
917 n_lines,
918 err_line,
919 err_msg);
920
921 if (!strcmp(tokens[0], "actions"))
922 return table_actions_statement_parse(block_mask,
923 tokens,
924 n_tokens,
925 n_lines,
926 err_line,
927 err_msg);
928
929 if (!strcmp(tokens[0], "default_action"))
930 return table_default_action_statement_parse(s,
931 tokens,
932 n_tokens,
933 n_lines,
934 err_line,
935 err_msg);
936
937 if (!strcmp(tokens[0], "hash")) {
938 if (n_tokens != 2) {
939 if (err_line)
940 *err_line = n_lines;
941 if (err_msg)
942 *err_msg = "Invalid hash statement.";
943 return -EINVAL;
944 }
945
946 if (s->params.hash_func_name) {
947 if (err_line)
948 *err_line = n_lines;
949 if (err_msg)
950 *err_msg = "Duplicate hash statement.";
951 return -EINVAL;
952 }
953
954 s->params.hash_func_name = strdup(tokens[1]);
955 if (!s->params.hash_func_name) {
956 if (err_line)
957 *err_line = n_lines;
958 if (err_msg)
959 *err_msg = "Memory allocation failed.";
960 return -ENOMEM;
961 }
962
963 return 0;
964 }
965
966 if (!strcmp(tokens[0], "instanceof")) {
967 if (n_tokens != 2) {
968 if (err_line)
969 *err_line = n_lines;
970 if (err_msg)
971 *err_msg = "Invalid instanceof statement.";
972 return -EINVAL;
973 }
974
975 if (s->recommended_table_type_name) {
976 if (err_line)
977 *err_line = n_lines;
978 if (err_msg)
979 *err_msg = "Duplicate instanceof statement.";
980 return -EINVAL;
981 }
982
983 s->recommended_table_type_name = strdup(tokens[1]);
984 if (!s->recommended_table_type_name) {
985 if (err_line)
986 *err_line = n_lines;
987 if (err_msg)
988 *err_msg = "Memory allocation failed.";
989 return -ENOMEM;
990 }
991
992 return 0;
993 }
994
995 if (!strcmp(tokens[0], "pragma")) {
996 if (n_tokens != 2) {
997 if (err_line)
998 *err_line = n_lines;
999 if (err_msg)
1000 *err_msg = "Invalid pragma statement.";
1001 return -EINVAL;
1002 }
1003
1004 if (s->args) {
1005 if (err_line)
1006 *err_line = n_lines;
1007 if (err_msg)
1008 *err_msg = "Duplicate pragma statement.";
1009 return -EINVAL;
1010 }
1011
1012 s->args = strdup(tokens[1]);
1013 if (!s->args) {
1014 if (err_line)
1015 *err_line = n_lines;
1016 if (err_msg)
1017 *err_msg = "Memory allocation failed.";
1018 return -ENOMEM;
1019 }
1020
1021 return 0;
1022 }
1023
1024 if (!strcmp(tokens[0], "size")) {
1025 char *p = tokens[1];
1026
1027 if (n_tokens != 2) {
1028 if (err_line)
1029 *err_line = n_lines;
1030 if (err_msg)
1031 *err_msg = "Invalid pragma statement.";
1032 return -EINVAL;
1033 }
1034
1035 s->size = strtoul(p, &p, 0);
1036 if (p[0]) {
1037 if (err_line)
1038 *err_line = n_lines;
1039 if (err_msg)
1040 *err_msg = "Invalid size argument.";
1041 return -EINVAL;
1042 }
1043
1044 return 0;
1045 }
1046
1047 /* Anything else. */
1048 if (err_line)
1049 *err_line = n_lines;
1050 if (err_msg)
1051 *err_msg = "Invalid statement.";
1052 return -EINVAL;
1053 }
1054
1055 /*
1056 * selector.
1057 */
1058 static void
selector_spec_free(struct selector_spec * s)1059 selector_spec_free(struct selector_spec *s)
1060 {
1061 uintptr_t field_name;
1062 uint32_t i;
1063
1064 if (!s)
1065 return;
1066
1067 /* name. */
1068 free(s->name);
1069 s->name = NULL;
1070
1071 /* params->group_id_field_name. */
1072 field_name = (uintptr_t)s->params.group_id_field_name;
1073 free((void *)field_name);
1074 s->params.group_id_field_name = NULL;
1075
1076 /* params->selector_field_names. */
1077 for (i = 0; i < s->params.n_selector_fields; i++) {
1078 field_name = (uintptr_t)s->params.selector_field_names[i];
1079
1080 free((void *)field_name);
1081 }
1082
1083 free(s->params.selector_field_names);
1084 s->params.selector_field_names = NULL;
1085
1086 s->params.n_selector_fields = 0;
1087
1088 /* params->member_id_field_name. */
1089 field_name = (uintptr_t)s->params.member_id_field_name;
1090 free((void *)field_name);
1091 s->params.member_id_field_name = NULL;
1092
1093 /* params->n_groups_max. */
1094 s->params.n_groups_max = 0;
1095
1096 /* params->n_members_per_group_max. */
1097 s->params.n_members_per_group_max = 0;
1098 }
1099
1100 static int
selector_statement_parse(struct selector_spec * s,uint32_t * block_mask,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)1101 selector_statement_parse(struct selector_spec *s,
1102 uint32_t *block_mask,
1103 char **tokens,
1104 uint32_t n_tokens,
1105 uint32_t n_lines,
1106 uint32_t *err_line,
1107 const char **err_msg)
1108 {
1109 /* Check format. */
1110 if ((n_tokens != 3) || strcmp(tokens[2], "{")) {
1111 if (err_line)
1112 *err_line = n_lines;
1113 if (err_msg)
1114 *err_msg = "Invalid selector statement.";
1115 return -EINVAL;
1116 }
1117
1118 /* spec. */
1119 s->name = strdup(tokens[1]);
1120 if (!s->name) {
1121 if (err_line)
1122 *err_line = n_lines;
1123 if (err_msg)
1124 *err_msg = "Memory allocation failed.";
1125 return -ENOMEM;
1126 }
1127
1128 /* block_mask. */
1129 *block_mask |= 1 << SELECTOR_BLOCK;
1130
1131 return 0;
1132 }
1133
1134 static int
selector_selector_statement_parse(uint32_t * block_mask,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)1135 selector_selector_statement_parse(uint32_t *block_mask,
1136 char **tokens,
1137 uint32_t n_tokens,
1138 uint32_t n_lines,
1139 uint32_t *err_line,
1140 const char **err_msg)
1141 {
1142 /* Check format. */
1143 if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
1144 if (err_line)
1145 *err_line = n_lines;
1146 if (err_msg)
1147 *err_msg = "Invalid selector statement.";
1148 return -EINVAL;
1149 }
1150
1151 /* block_mask. */
1152 *block_mask |= 1 << SELECTOR_SELECTOR_BLOCK;
1153
1154 return 0;
1155 }
1156
1157 static int
selector_selector_block_parse(struct selector_spec * s,uint32_t * block_mask,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)1158 selector_selector_block_parse(struct selector_spec *s,
1159 uint32_t *block_mask,
1160 char **tokens,
1161 uint32_t n_tokens,
1162 uint32_t n_lines,
1163 uint32_t *err_line,
1164 const char **err_msg)
1165 {
1166 const char **new_fields;
1167 char *name;
1168
1169 /* Handle end of block. */
1170 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1171 *block_mask &= ~(1 << SELECTOR_SELECTOR_BLOCK);
1172 return 0;
1173 }
1174
1175 /* Check input arguments. */
1176 if (n_tokens != 1) {
1177 if (err_line)
1178 *err_line = n_lines;
1179 if (err_msg)
1180 *err_msg = "Invalid selector field statement.";
1181 return -EINVAL;
1182 }
1183
1184 name = strdup(tokens[0]);
1185 if (!name) {
1186 if (err_line)
1187 *err_line = n_lines;
1188 if (err_msg)
1189 *err_msg = "Memory allocation failed.";
1190 return -ENOMEM;
1191 }
1192
1193 new_fields = realloc(s->params.selector_field_names,
1194 (s->params.n_selector_fields + 1) * sizeof(char *));
1195 if (!new_fields) {
1196 free(name);
1197
1198 if (err_line)
1199 *err_line = n_lines;
1200 if (err_msg)
1201 *err_msg = "Memory allocation failed.";
1202 return -ENOMEM;
1203 }
1204
1205 s->params.selector_field_names = new_fields;
1206 s->params.selector_field_names[s->params.n_selector_fields] = name;
1207 s->params.n_selector_fields++;
1208
1209 return 0;
1210 }
1211
1212 static int
selector_block_parse(struct selector_spec * s,uint32_t * block_mask,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)1213 selector_block_parse(struct selector_spec *s,
1214 uint32_t *block_mask,
1215 char **tokens,
1216 uint32_t n_tokens,
1217 uint32_t n_lines,
1218 uint32_t *err_line,
1219 const char **err_msg)
1220 {
1221 if (*block_mask & (1 << SELECTOR_SELECTOR_BLOCK))
1222 return selector_selector_block_parse(s,
1223 block_mask,
1224 tokens,
1225 n_tokens,
1226 n_lines,
1227 err_line,
1228 err_msg);
1229
1230 /* Handle end of block. */
1231 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1232 *block_mask &= ~(1 << SELECTOR_BLOCK);
1233 return 0;
1234 }
1235
1236 if (!strcmp(tokens[0], "group_id")) {
1237 if (n_tokens != 2) {
1238 if (err_line)
1239 *err_line = n_lines;
1240 if (err_msg)
1241 *err_msg = "Invalid group_id statement.";
1242 return -EINVAL;
1243 }
1244
1245 s->params.group_id_field_name = strdup(tokens[1]);
1246 if (!s->params.group_id_field_name) {
1247 if (err_line)
1248 *err_line = n_lines;
1249 if (err_msg)
1250 *err_msg = "Memory allocation failed.";
1251 return -ENOMEM;
1252 }
1253
1254 return 0;
1255 }
1256
1257 if (!strcmp(tokens[0], "selector"))
1258 return selector_selector_statement_parse(block_mask,
1259 tokens,
1260 n_tokens,
1261 n_lines,
1262 err_line,
1263 err_msg);
1264
1265 if (!strcmp(tokens[0], "member_id")) {
1266 if (n_tokens != 2) {
1267 if (err_line)
1268 *err_line = n_lines;
1269 if (err_msg)
1270 *err_msg = "Invalid member_id statement.";
1271 return -EINVAL;
1272 }
1273
1274 s->params.member_id_field_name = strdup(tokens[1]);
1275 if (!s->params.member_id_field_name) {
1276 if (err_line)
1277 *err_line = n_lines;
1278 if (err_msg)
1279 *err_msg = "Memory allocation failed.";
1280 return -ENOMEM;
1281 }
1282
1283 return 0;
1284 }
1285
1286 if (!strcmp(tokens[0], "n_groups_max")) {
1287 char *p = tokens[1];
1288
1289 if (n_tokens != 2) {
1290 if (err_line)
1291 *err_line = n_lines;
1292 if (err_msg)
1293 *err_msg = "Invalid n_groups statement.";
1294 return -EINVAL;
1295 }
1296
1297 s->params.n_groups_max = strtoul(p, &p, 0);
1298 if (p[0]) {
1299 if (err_line)
1300 *err_line = n_lines;
1301 if (err_msg)
1302 *err_msg = "Invalid n_groups argument.";
1303 return -EINVAL;
1304 }
1305
1306 return 0;
1307 }
1308
1309 if (!strcmp(tokens[0], "n_members_per_group_max")) {
1310 char *p = tokens[1];
1311
1312 if (n_tokens != 2) {
1313 if (err_line)
1314 *err_line = n_lines;
1315 if (err_msg)
1316 *err_msg = "Invalid n_members_per_group statement.";
1317 return -EINVAL;
1318 }
1319
1320 s->params.n_members_per_group_max = strtoul(p, &p, 0);
1321 if (p[0]) {
1322 if (err_line)
1323 *err_line = n_lines;
1324 if (err_msg)
1325 *err_msg = "Invalid n_members_per_group argument.";
1326 return -EINVAL;
1327 }
1328
1329 return 0;
1330 }
1331
1332 /* Anything else. */
1333 if (err_line)
1334 *err_line = n_lines;
1335 if (err_msg)
1336 *err_msg = "Invalid statement.";
1337 return -EINVAL;
1338 }
1339
1340 /*
1341 * learner.
1342 */
1343 static void
learner_spec_free(struct learner_spec * s)1344 learner_spec_free(struct learner_spec *s)
1345 {
1346 uintptr_t default_action_name, default_action_args, hash_func_name;
1347 uint32_t i;
1348
1349 if (!s)
1350 return;
1351
1352 free(s->name);
1353 s->name = NULL;
1354
1355 for (i = 0; i < s->params.n_fields; i++) {
1356 uintptr_t name = (uintptr_t)s->params.field_names[i];
1357
1358 free((void *)name);
1359 }
1360
1361 free(s->params.field_names);
1362 s->params.field_names = NULL;
1363
1364 s->params.n_fields = 0;
1365
1366 for (i = 0; i < s->params.n_actions; i++) {
1367 uintptr_t name = (uintptr_t)s->params.action_names[i];
1368
1369 free((void *)name);
1370 }
1371
1372 free(s->params.action_names);
1373 s->params.action_names = NULL;
1374
1375 s->params.n_actions = 0;
1376
1377 default_action_name = (uintptr_t)s->params.default_action_name;
1378 free((void *)default_action_name);
1379 s->params.default_action_name = NULL;
1380
1381 default_action_args = (uintptr_t)s->params.default_action_args;
1382 free((void *)default_action_args);
1383 s->params.default_action_args = NULL;
1384
1385 free(s->params.action_is_for_table_entries);
1386 s->params.action_is_for_table_entries = NULL;
1387
1388 free(s->params.action_is_for_default_entry);
1389 s->params.action_is_for_default_entry = NULL;
1390
1391 s->params.default_action_is_const = 0;
1392
1393 hash_func_name = (uintptr_t)s->params.hash_func_name;
1394 free((void *)hash_func_name);
1395 s->params.hash_func_name = NULL;
1396
1397 s->size = 0;
1398
1399 free(s->timeout);
1400 s->timeout = NULL;
1401
1402 s->n_timeouts = 0;
1403 }
1404
1405 static int
learner_key_statement_parse(uint32_t * block_mask,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)1406 learner_key_statement_parse(uint32_t *block_mask,
1407 char **tokens,
1408 uint32_t n_tokens,
1409 uint32_t n_lines,
1410 uint32_t *err_line,
1411 const char **err_msg)
1412 {
1413 /* Check format. */
1414 if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
1415 if (err_line)
1416 *err_line = n_lines;
1417 if (err_msg)
1418 *err_msg = "Invalid key statement.";
1419 return -EINVAL;
1420 }
1421
1422 /* block_mask. */
1423 *block_mask |= 1 << LEARNER_KEY_BLOCK;
1424
1425 return 0;
1426 }
1427
1428 static int
learner_key_block_parse(struct learner_spec * s,uint32_t * block_mask,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)1429 learner_key_block_parse(struct learner_spec *s,
1430 uint32_t *block_mask,
1431 char **tokens,
1432 uint32_t n_tokens,
1433 uint32_t n_lines,
1434 uint32_t *err_line,
1435 const char **err_msg)
1436 {
1437 const char **new_field_names = NULL;
1438 char *field_name = NULL;
1439
1440 /* Handle end of block. */
1441 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1442 *block_mask &= ~(1 << LEARNER_KEY_BLOCK);
1443 return 0;
1444 }
1445
1446 /* Check input arguments. */
1447 if (n_tokens != 1) {
1448 if (err_line)
1449 *err_line = n_lines;
1450 if (err_msg)
1451 *err_msg = "Invalid match field statement.";
1452 return -EINVAL;
1453 }
1454
1455 field_name = strdup(tokens[0]);
1456 new_field_names = realloc(s->params.field_names, (s->params.n_fields + 1) * sizeof(char *));
1457 if (!field_name || !new_field_names) {
1458 free(field_name);
1459 free(new_field_names);
1460
1461 if (err_line)
1462 *err_line = n_lines;
1463 if (err_msg)
1464 *err_msg = "Memory allocation failed.";
1465 return -ENOMEM;
1466 }
1467
1468 s->params.field_names = new_field_names;
1469 s->params.field_names[s->params.n_fields] = field_name;
1470 s->params.n_fields++;
1471
1472 return 0;
1473 }
1474
1475 static int
learner_actions_statement_parse(uint32_t * block_mask,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)1476 learner_actions_statement_parse(uint32_t *block_mask,
1477 char **tokens,
1478 uint32_t n_tokens,
1479 uint32_t n_lines,
1480 uint32_t *err_line,
1481 const char **err_msg)
1482 {
1483 /* Check format. */
1484 if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
1485 if (err_line)
1486 *err_line = n_lines;
1487 if (err_msg)
1488 *err_msg = "Invalid actions statement.";
1489 return -EINVAL;
1490 }
1491
1492 /* block_mask. */
1493 *block_mask |= 1 << LEARNER_ACTIONS_BLOCK;
1494
1495 return 0;
1496 }
1497
1498 static int
learner_actions_block_parse(struct learner_spec * s,uint32_t * block_mask,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)1499 learner_actions_block_parse(struct learner_spec *s,
1500 uint32_t *block_mask,
1501 char **tokens,
1502 uint32_t n_tokens,
1503 uint32_t n_lines,
1504 uint32_t *err_line,
1505 const char **err_msg)
1506 {
1507 const char **new_action_names = NULL;
1508 int *new_action_is_for_table_entries = NULL, *new_action_is_for_default_entry = NULL;
1509 char *name = NULL;
1510 int action_is_for_table_entries = 1, action_is_for_default_entry = 1;
1511
1512 /* Handle end of block. */
1513 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1514 *block_mask &= ~(1 << LEARNER_ACTIONS_BLOCK);
1515 return 0;
1516 }
1517
1518 /* Check input arguments. */
1519 if ((n_tokens > 2) ||
1520 ((n_tokens == 2) && strcmp(tokens[1], "@tableonly") &&
1521 strcmp(tokens[1], "@defaultonly"))) {
1522 if (err_line)
1523 *err_line = n_lines;
1524 if (err_msg)
1525 *err_msg = "Invalid action name statement.";
1526 return -EINVAL;
1527 }
1528
1529 name = strdup(tokens[0]);
1530
1531 if (n_tokens == 2) {
1532 if (!strcmp(tokens[1], "@tableonly"))
1533 action_is_for_default_entry = 0;
1534
1535 if (!strcmp(tokens[1], "@defaultonly"))
1536 action_is_for_table_entries = 0;
1537 }
1538
1539 new_action_names = realloc(s->params.action_names,
1540 (s->params.n_actions + 1) * sizeof(char *));
1541 new_action_is_for_table_entries = realloc(s->params.action_is_for_table_entries,
1542 (s->params.n_actions + 1) * sizeof(int));
1543 new_action_is_for_default_entry = realloc(s->params.action_is_for_default_entry,
1544 (s->params.n_actions + 1) * sizeof(int));
1545
1546 if (!name ||
1547 !new_action_names ||
1548 !new_action_is_for_table_entries ||
1549 !new_action_is_for_default_entry) {
1550 free(name);
1551 free(new_action_names);
1552 free(new_action_is_for_table_entries);
1553 free(new_action_is_for_default_entry);
1554
1555 if (err_line)
1556 *err_line = n_lines;
1557 if (err_msg)
1558 *err_msg = "Memory allocation failed.";
1559 return -ENOMEM;
1560 }
1561
1562 s->params.action_names = new_action_names;
1563 s->params.action_names[s->params.n_actions] = name;
1564
1565 s->params.action_is_for_table_entries = new_action_is_for_table_entries;
1566 s->params.action_is_for_table_entries[s->params.n_actions] = action_is_for_table_entries;
1567
1568 s->params.action_is_for_default_entry = new_action_is_for_default_entry;
1569 s->params.action_is_for_default_entry[s->params.n_actions] = action_is_for_default_entry;
1570
1571 s->params.n_actions++;
1572
1573 return 0;
1574 }
1575
1576 static int
learner_default_action_statement_parse(struct learner_spec * s,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)1577 learner_default_action_statement_parse(struct learner_spec *s,
1578 char **tokens,
1579 uint32_t n_tokens,
1580 uint32_t n_lines,
1581 uint32_t *err_line,
1582 const char **err_msg)
1583 {
1584 uint32_t i;
1585 int status = 0, duplicate = 0;
1586
1587 /* Check format. */
1588 if ((n_tokens < 4) ||
1589 strcmp(tokens[2], "args")) {
1590 status = -EINVAL;
1591 goto error;
1592 }
1593
1594 if (s->params.default_action_name) {
1595 duplicate = 1;
1596 status = -EINVAL;
1597 goto error;
1598 }
1599
1600 s->params.default_action_name = strdup(tokens[1]);
1601 if (!s->params.default_action_name) {
1602 status = -ENOMEM;
1603 goto error;
1604 }
1605
1606 if (strcmp(tokens[3], "none")) {
1607 char buffer[MAX_LINE_LENGTH];
1608 uint32_t n_tokens_args = n_tokens - 3;
1609
1610 if (!strcmp(tokens[n_tokens - 1], "const"))
1611 n_tokens_args--;
1612
1613 if (!n_tokens_args) {
1614 status = -EINVAL;
1615 goto error;
1616 }
1617
1618 buffer[0] = 0;
1619 for (i = 0; i < n_tokens_args; i++) {
1620 if (i)
1621 strcat(buffer, " ");
1622
1623 strcat(buffer, tokens[3 + i]);
1624 }
1625
1626 s->params.default_action_args = strdup(buffer);
1627 if (!s->params.default_action_args) {
1628 status = -ENOMEM;
1629 goto error;
1630 }
1631 } else {
1632 if (((n_tokens != 4) && (n_tokens != 5)) ||
1633 ((n_tokens == 5) && (strcmp(tokens[4], "const")))) {
1634 status = -EINVAL;
1635 goto error;
1636 }
1637 }
1638
1639 if (!strcmp(tokens[n_tokens - 1], "const"))
1640 s->params.default_action_is_const = 1;
1641
1642 return 0;
1643
1644 error:
1645 if (err_line)
1646 *err_line = n_lines;
1647
1648 if (err_msg)
1649 switch (status) {
1650 case -ENOMEM:
1651 *err_msg = "Memory allocation failed.";
1652 break;
1653
1654 default:
1655 if (duplicate)
1656 *err_msg = "Duplicate default_action statement.";
1657
1658 *err_msg = "Invalid default_action statement.";
1659 }
1660
1661 return status;
1662 }
1663
1664 static int
learner_timeout_statement_parse(uint32_t * block_mask,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)1665 learner_timeout_statement_parse(uint32_t *block_mask,
1666 char **tokens,
1667 uint32_t n_tokens,
1668 uint32_t n_lines,
1669 uint32_t *err_line,
1670 const char **err_msg)
1671 {
1672 /* Check format. */
1673 if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
1674 if (err_line)
1675 *err_line = n_lines;
1676 if (err_msg)
1677 *err_msg = "Invalid timeout statement.";
1678 return -EINVAL;
1679 }
1680
1681 /* block_mask. */
1682 *block_mask |= 1 << LEARNER_TIMEOUT_BLOCK;
1683
1684 return 0;
1685 }
1686
1687 static int
learner_timeout_block_parse(struct learner_spec * s,uint32_t * block_mask,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)1688 learner_timeout_block_parse(struct learner_spec *s,
1689 uint32_t *block_mask,
1690 char **tokens,
1691 uint32_t n_tokens,
1692 uint32_t n_lines,
1693 uint32_t *err_line,
1694 const char **err_msg)
1695 {
1696 uint32_t *new_timeout = NULL;
1697 char *str;
1698 uint32_t val;
1699 int status = 0;
1700
1701 /* Handle end of block. */
1702 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1703 *block_mask &= ~(1 << LEARNER_TIMEOUT_BLOCK);
1704 return 0;
1705 }
1706
1707 /* Check input arguments. */
1708 if (n_tokens != 1) {
1709 status = -EINVAL;
1710 goto error;
1711 }
1712
1713 str = tokens[0];
1714 val = strtoul(str, &str, 0);
1715 if (str[0]) {
1716 status = -EINVAL;
1717 goto error;
1718 }
1719
1720 new_timeout = realloc(s->timeout, (s->n_timeouts + 1) * sizeof(uint32_t));
1721 if (!new_timeout) {
1722 status = -ENOMEM;
1723 goto error;
1724 }
1725
1726 s->timeout = new_timeout;
1727 s->timeout[s->n_timeouts] = val;
1728 s->n_timeouts++;
1729
1730 return 0;
1731
1732 error:
1733 free(new_timeout);
1734
1735 if (err_line)
1736 *err_line = n_lines;
1737
1738 if (err_msg)
1739 switch (status) {
1740 case -ENOMEM:
1741 *err_msg = "Memory allocation failed.";
1742 break;
1743
1744 default:
1745 *err_msg = "Invalid timeout value statement.";
1746 break;
1747 }
1748
1749 return status;
1750 }
1751
1752
1753 static int
learner_statement_parse(struct learner_spec * s,uint32_t * block_mask,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)1754 learner_statement_parse(struct learner_spec *s,
1755 uint32_t *block_mask,
1756 char **tokens,
1757 uint32_t n_tokens,
1758 uint32_t n_lines,
1759 uint32_t *err_line,
1760 const char **err_msg)
1761 {
1762 /* Check format. */
1763 if ((n_tokens != 3) || strcmp(tokens[2], "{")) {
1764 if (err_line)
1765 *err_line = n_lines;
1766 if (err_msg)
1767 *err_msg = "Invalid learner statement.";
1768 return -EINVAL;
1769 }
1770
1771 /* spec. */
1772 s->name = strdup(tokens[1]);
1773 if (!s->name) {
1774 if (err_line)
1775 *err_line = n_lines;
1776 if (err_msg)
1777 *err_msg = "Memory allocation failed.";
1778 return -ENOMEM;
1779 }
1780
1781 /* block_mask. */
1782 *block_mask |= 1 << LEARNER_BLOCK;
1783
1784 return 0;
1785 }
1786
1787 static int
learner_block_parse(struct learner_spec * s,uint32_t * block_mask,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)1788 learner_block_parse(struct learner_spec *s,
1789 uint32_t *block_mask,
1790 char **tokens,
1791 uint32_t n_tokens,
1792 uint32_t n_lines,
1793 uint32_t *err_line,
1794 const char **err_msg)
1795 {
1796 if (*block_mask & (1 << LEARNER_KEY_BLOCK))
1797 return learner_key_block_parse(s,
1798 block_mask,
1799 tokens,
1800 n_tokens,
1801 n_lines,
1802 err_line,
1803 err_msg);
1804
1805 if (*block_mask & (1 << LEARNER_ACTIONS_BLOCK))
1806 return learner_actions_block_parse(s,
1807 block_mask,
1808 tokens,
1809 n_tokens,
1810 n_lines,
1811 err_line,
1812 err_msg);
1813
1814 if (*block_mask & (1 << LEARNER_TIMEOUT_BLOCK))
1815 return learner_timeout_block_parse(s,
1816 block_mask,
1817 tokens,
1818 n_tokens,
1819 n_lines,
1820 err_line,
1821 err_msg);
1822
1823 /* Handle end of block. */
1824 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1825 *block_mask &= ~(1 << LEARNER_BLOCK);
1826 return 0;
1827 }
1828
1829 if (!strcmp(tokens[0], "key"))
1830 return learner_key_statement_parse(block_mask,
1831 tokens,
1832 n_tokens,
1833 n_lines,
1834 err_line,
1835 err_msg);
1836
1837 if (!strcmp(tokens[0], "actions"))
1838 return learner_actions_statement_parse(block_mask,
1839 tokens,
1840 n_tokens,
1841 n_lines,
1842 err_line,
1843 err_msg);
1844
1845 if (!strcmp(tokens[0], "default_action"))
1846 return learner_default_action_statement_parse(s,
1847 tokens,
1848 n_tokens,
1849 n_lines,
1850 err_line,
1851 err_msg);
1852
1853 if (!strcmp(tokens[0], "hash")) {
1854 if (n_tokens != 2) {
1855 if (err_line)
1856 *err_line = n_lines;
1857 if (err_msg)
1858 *err_msg = "Invalid hash statement.";
1859 return -EINVAL;
1860 }
1861
1862 if (s->params.hash_func_name) {
1863 if (err_line)
1864 *err_line = n_lines;
1865 if (err_msg)
1866 *err_msg = "Duplicate hash statement.";
1867 return -EINVAL;
1868 }
1869
1870 s->params.hash_func_name = strdup(tokens[1]);
1871 if (!s->params.hash_func_name) {
1872 if (err_line)
1873 *err_line = n_lines;
1874 if (err_msg)
1875 *err_msg = "Memory allocation failed.";
1876 return -ENOMEM;
1877 }
1878
1879 return 0;
1880 }
1881
1882 if (!strcmp(tokens[0], "size")) {
1883 char *p = tokens[1];
1884
1885 if (n_tokens != 2) {
1886 if (err_line)
1887 *err_line = n_lines;
1888 if (err_msg)
1889 *err_msg = "Invalid size statement.";
1890 return -EINVAL;
1891 }
1892
1893 s->size = strtoul(p, &p, 0);
1894 if (p[0]) {
1895 if (err_line)
1896 *err_line = n_lines;
1897 if (err_msg)
1898 *err_msg = "Invalid size argument.";
1899 return -EINVAL;
1900 }
1901
1902 return 0;
1903 }
1904
1905 if (!strcmp(tokens[0], "timeout"))
1906 return learner_timeout_statement_parse(block_mask,
1907 tokens,
1908 n_tokens,
1909 n_lines,
1910 err_line,
1911 err_msg);
1912
1913 /* Anything else. */
1914 if (err_line)
1915 *err_line = n_lines;
1916 if (err_msg)
1917 *err_msg = "Invalid statement.";
1918 return -EINVAL;
1919 }
1920
1921 /*
1922 * regarray.
1923 */
1924 static void
regarray_spec_free(struct regarray_spec * s)1925 regarray_spec_free(struct regarray_spec *s)
1926 {
1927 if (!s)
1928 return;
1929
1930 free(s->name);
1931 s->name = NULL;
1932 }
1933
1934 static int
regarray_statement_parse(struct regarray_spec * s,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)1935 regarray_statement_parse(struct regarray_spec *s,
1936 char **tokens,
1937 uint32_t n_tokens,
1938 uint32_t n_lines,
1939 uint32_t *err_line,
1940 const char **err_msg)
1941 {
1942 char *p;
1943
1944 /* Check format. */
1945 if ((n_tokens != 6) ||
1946 strcmp(tokens[2], "size") ||
1947 strcmp(tokens[4], "initval")) {
1948 if (err_line)
1949 *err_line = n_lines;
1950 if (err_msg)
1951 *err_msg = "Invalid regarray statement.";
1952 return -EINVAL;
1953 }
1954
1955 /* spec. */
1956 s->name = strdup(tokens[1]);
1957 if (!s->name) {
1958 if (err_line)
1959 *err_line = n_lines;
1960 if (err_msg)
1961 *err_msg = "Memory allocation failed.";
1962 return -ENOMEM;
1963 }
1964
1965 p = tokens[3];
1966 s->size = strtoul(p, &p, 0);
1967 if (p[0] || !s->size) {
1968 if (err_line)
1969 *err_line = n_lines;
1970 if (err_msg)
1971 *err_msg = "Invalid size argument.";
1972 return -EINVAL;
1973 }
1974
1975 p = tokens[5];
1976 s->init_val = strtoull(p, &p, 0);
1977 if (p[0]) {
1978 if (err_line)
1979 *err_line = n_lines;
1980 if (err_msg)
1981 *err_msg = "Invalid initval argument.";
1982 return -EINVAL;
1983 }
1984
1985 return 0;
1986 }
1987
1988 /*
1989 * metarray.
1990 */
1991 static void
metarray_spec_free(struct metarray_spec * s)1992 metarray_spec_free(struct metarray_spec *s)
1993 {
1994 if (!s)
1995 return;
1996
1997 free(s->name);
1998 s->name = NULL;
1999 }
2000
2001 static int
metarray_statement_parse(struct metarray_spec * s,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)2002 metarray_statement_parse(struct metarray_spec *s,
2003 char **tokens,
2004 uint32_t n_tokens,
2005 uint32_t n_lines,
2006 uint32_t *err_line,
2007 const char **err_msg)
2008 {
2009 char *p;
2010
2011 /* Check format. */
2012 if ((n_tokens != 4) || strcmp(tokens[2], "size")) {
2013 if (err_line)
2014 *err_line = n_lines;
2015 if (err_msg)
2016 *err_msg = "Invalid metarray statement.";
2017 return -EINVAL;
2018 }
2019
2020 /* spec. */
2021 s->name = strdup(tokens[1]);
2022 if (!s->name) {
2023 if (err_line)
2024 *err_line = n_lines;
2025 if (err_msg)
2026 *err_msg = "Memory allocation failed.";
2027 return -ENOMEM;
2028 }
2029
2030 p = tokens[3];
2031 s->size = strtoul(p, &p, 0);
2032 if (p[0] || !s->size) {
2033 if (err_line)
2034 *err_line = n_lines;
2035 if (err_msg)
2036 *err_msg = "Invalid size argument.";
2037 return -EINVAL;
2038 }
2039
2040 return 0;
2041 }
2042
2043 /*
2044 *
2045 * rss
2046 */
2047
2048 static void
rss_spec_free(struct rss_spec * s)2049 rss_spec_free(struct rss_spec *s)
2050 {
2051 if (!s)
2052 return;
2053
2054 free(s->name);
2055 s->name = NULL;
2056 }
2057
2058 static int
rss_statement_parse(struct rss_spec * s,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)2059 rss_statement_parse(struct rss_spec *s,
2060 char **tokens,
2061 uint32_t n_tokens,
2062 uint32_t n_lines,
2063 uint32_t *err_line,
2064 const char **err_msg)
2065 {
2066 /* Check format. */
2067 if ((n_tokens != 2)) {
2068 if (err_line)
2069 *err_line = n_lines;
2070 if (err_msg)
2071 *err_msg = "Invalid rss statement.";
2072 return -EINVAL;
2073 }
2074
2075 /* spec. */
2076 s->name = strdup(tokens[1]);
2077 if (!s->name) {
2078 if (err_line)
2079 *err_line = n_lines;
2080 if (err_msg)
2081 *err_msg = "Memory allocation failed.";
2082 return -ENOMEM;
2083 }
2084
2085 return 0;
2086 }
2087
2088 /*
2089 * apply.
2090 */
2091 static void
apply_spec_free(struct apply_spec * s)2092 apply_spec_free(struct apply_spec *s)
2093 {
2094 uint32_t i;
2095
2096 if (!s)
2097 return;
2098
2099 for (i = 0; i < s->n_instructions; i++) {
2100 uintptr_t instr = (uintptr_t)s->instructions[i];
2101
2102 free((void *)instr);
2103 }
2104
2105 free(s->instructions);
2106 s->instructions = NULL;
2107
2108 s->n_instructions = 0;
2109 }
2110
2111 static int
apply_statement_parse(uint32_t * block_mask,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)2112 apply_statement_parse(uint32_t *block_mask,
2113 char **tokens,
2114 uint32_t n_tokens,
2115 uint32_t n_lines,
2116 uint32_t *err_line,
2117 const char **err_msg)
2118 {
2119 /* Check format. */
2120 if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
2121 if (err_line)
2122 *err_line = n_lines;
2123 if (err_msg)
2124 *err_msg = "Invalid apply statement.";
2125 return -EINVAL;
2126 }
2127
2128 /* block_mask. */
2129 *block_mask |= 1 << APPLY_BLOCK;
2130
2131 return 0;
2132 }
2133
2134 static int
apply_block_parse(struct apply_spec * s,uint32_t * block_mask,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)2135 apply_block_parse(struct apply_spec *s,
2136 uint32_t *block_mask,
2137 char **tokens,
2138 uint32_t n_tokens,
2139 uint32_t n_lines,
2140 uint32_t *err_line,
2141 const char **err_msg)
2142 {
2143 char buffer[RTE_SWX_INSTRUCTION_SIZE], *instr;
2144 const char **new_instructions;
2145 uint32_t i;
2146
2147 /* Handle end of block. */
2148 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
2149 *block_mask &= ~(1 << APPLY_BLOCK);
2150 return 0;
2151 }
2152
2153 /* spec. */
2154 buffer[0] = 0;
2155 for (i = 0; i < n_tokens; i++) {
2156 if (i)
2157 strcat(buffer, " ");
2158 strcat(buffer, tokens[i]);
2159 }
2160
2161 instr = strdup(buffer);
2162 if (!instr) {
2163 if (err_line)
2164 *err_line = n_lines;
2165 if (err_msg)
2166 *err_msg = "Memory allocation failed.";
2167 return -ENOMEM;
2168 }
2169
2170 new_instructions = realloc(s->instructions,
2171 (s->n_instructions + 1) * sizeof(char *));
2172 if (!new_instructions) {
2173 free(instr);
2174
2175 if (err_line)
2176 *err_line = n_lines;
2177 if (err_msg)
2178 *err_msg = "Memory allocation failed.";
2179 return -ENOMEM;
2180 }
2181
2182 s->instructions = new_instructions;
2183 s->instructions[s->n_instructions] = instr;
2184 s->n_instructions++;
2185
2186 return 0;
2187 }
2188
2189 /*
2190 * Pipeline.
2191 */
2192 void
pipeline_spec_free(struct pipeline_spec * s)2193 pipeline_spec_free(struct pipeline_spec *s)
2194 {
2195 if (!s)
2196 return;
2197
2198 free(s->extobjs);
2199 free(s->structs);
2200 free(s->headers);
2201 free(s->metadata);
2202 free(s->actions);
2203 free(s->tables);
2204 free(s->selectors);
2205 free(s->learners);
2206 free(s->regarrays);
2207 free(s->metarrays);
2208 free(s->apply);
2209
2210 memset(s, 0, sizeof(struct pipeline_spec));
2211 }
2212
2213 static const char *
match_type_string_get(enum rte_swx_table_match_type match_type)2214 match_type_string_get(enum rte_swx_table_match_type match_type)
2215 {
2216 switch (match_type) {
2217 case RTE_SWX_TABLE_MATCH_WILDCARD: return "RTE_SWX_TABLE_MATCH_WILDCARD";
2218 case RTE_SWX_TABLE_MATCH_LPM: return "RTE_SWX_TABLE_MATCH_LPM";
2219 case RTE_SWX_TABLE_MATCH_EXACT: return "RTE_SWX_TABLE_MATCH_EXACT";
2220 default: return "RTE_SWX_TABLE_MATCH_UNKNOWN";
2221 }
2222 }
2223
2224 void
pipeline_spec_codegen(FILE * f,struct pipeline_spec * s)2225 pipeline_spec_codegen(FILE *f,
2226 struct pipeline_spec *s)
2227 {
2228 uint32_t i;
2229
2230 /* Check the input arguments. */
2231 if (!f || !s)
2232 return;
2233
2234 /* extobj. */
2235 fprintf(f, "static struct extobj_spec extobjs[] = {\n");
2236
2237 for (i = 0; i < s->n_extobjs; i++) {
2238 struct extobj_spec *extobj_spec = &s->extobjs[i];
2239
2240 fprintf(f, "\t[%d] = {\n", i);
2241 fprintf(f, "\t\t.name = \"%s\",\n", extobj_spec->name);
2242 fprintf(f, "\t\t.extern_type_name = \"%s\",\n", extobj_spec->extern_type_name);
2243 if (extobj_spec->pragma)
2244 fprintf(f, "\t\t.pragma = \"%s\",\n", extobj_spec->pragma);
2245 else
2246 fprintf(f, "\t\t.pragma = NULL,\n");
2247 fprintf(f, "\t},\n");
2248 }
2249
2250 fprintf(f, "};\n\n");
2251
2252 /* regarray. */
2253 fprintf(f, "static struct regarray_spec regarrays[] = {\n");
2254
2255 for (i = 0; i < s->n_regarrays; i++) {
2256 struct regarray_spec *regarray_spec = &s->regarrays[i];
2257
2258 fprintf(f, "\t[%d] = {\n", i);
2259 fprintf(f, "\t\t.name = \"%s\",\n", regarray_spec->name);
2260 fprintf(f, "\t\t.init_val = %" PRIu64 ",\n", regarray_spec->init_val);
2261 fprintf(f, "\t\t.size = %u,\n", regarray_spec->size);
2262 fprintf(f, "\t},\n");
2263 }
2264
2265 fprintf(f, "};\n\n");
2266
2267 /* metarray. */
2268 fprintf(f, "static struct metarray_spec metarrays[] = {\n");
2269
2270 for (i = 0; i < s->n_metarrays; i++) {
2271 struct metarray_spec *metarray_spec = &s->metarrays[i];
2272
2273 fprintf(f, "\t[%d] = {\n", i);
2274 fprintf(f, "\t\t.name = \"%s\",\n", metarray_spec->name);
2275 fprintf(f, "\t\t.size = %u,\n", metarray_spec->size);
2276 fprintf(f, "\t},\n");
2277 }
2278
2279 fprintf(f, "};\n\n");
2280
2281 /* rss. */
2282 fprintf(f, "static struct rss_spec rss[] = {\n");
2283
2284 for (i = 0; i < s->n_rss; i++) {
2285 struct rss_spec *rss_spec = &s->rss[i];
2286 fprintf(f, "\t[%d] = {\n", i);
2287 fprintf(f, "\t\t.name = \"%s\",\n", rss_spec->name);
2288 fprintf(f, "\t},\n");
2289 }
2290 fprintf(f, "};\n\n");
2291
2292 /* struct. */
2293 for (i = 0; i < s->n_structs; i++) {
2294 struct struct_spec *struct_spec = &s->structs[i];
2295 uint32_t j;
2296
2297 fprintf(f, "static struct rte_swx_field_params struct_%s_fields[] = {\n",
2298 struct_spec->name);
2299
2300 for (j = 0; j < struct_spec->n_fields; j++) {
2301 struct rte_swx_field_params *field = &struct_spec->fields[j];
2302
2303 fprintf(f, "\t[%d] = {\n", j);
2304 fprintf(f, "\t\t.name = \"%s\",\n", field->name);
2305 fprintf(f, "\t\t.n_bits = %u,\n", field->n_bits);
2306 fprintf(f, "\t},\n");
2307 }
2308
2309 fprintf(f, "};\n\n");
2310 }
2311
2312 fprintf(f, "static struct struct_spec structs[] = {\n");
2313
2314 for (i = 0; i < s->n_structs; i++) {
2315 struct struct_spec *struct_spec = &s->structs[i];
2316
2317 fprintf(f, "\t[%d] = {\n", i);
2318 fprintf(f, "\t\t.name = \"%s\",\n", struct_spec->name);
2319 fprintf(f, "\t\t.fields = struct_%s_fields,\n", struct_spec->name);
2320 fprintf(f, "\t\t.n_fields = "
2321 "sizeof(struct_%s_fields) / sizeof(struct_%s_fields[0]),\n",
2322 struct_spec->name,
2323 struct_spec->name);
2324 fprintf(f, "\t\t.varbit = %d,\n", struct_spec->varbit);
2325 fprintf(f, "\t},\n");
2326 }
2327
2328 fprintf(f, "};\n\n");
2329
2330 /* header. */
2331 fprintf(f, "static struct header_spec headers[] = {\n");
2332
2333 for (i = 0; i < s->n_headers; i++) {
2334 struct header_spec *header_spec = &s->headers[i];
2335
2336 fprintf(f, "\t[%d] = {\n", i);
2337 fprintf(f, "\t\t.name = \"%s\",\n", header_spec->name);
2338 fprintf(f, "\t\t.struct_type_name = \"%s\",\n", header_spec->struct_type_name);
2339 fprintf(f, "\t},\n");
2340 }
2341
2342 fprintf(f, "};\n\n");
2343
2344 /* metadata. */
2345 fprintf(f, "static struct metadata_spec metadata[] = {\n");
2346
2347 for (i = 0; i < s->n_metadata; i++) {
2348 struct metadata_spec *metadata_spec = &s->metadata[i];
2349
2350 fprintf(f, "\t[%d] = {\n", i);
2351 fprintf(f, "\t\t.struct_type_name = \"%s\",\n", metadata_spec->struct_type_name);
2352 fprintf(f, "\t},\n");
2353
2354 }
2355
2356 fprintf(f, "};\n\n");
2357
2358 /* action. */
2359 for (i = 0; i < s->n_actions; i++) {
2360 struct action_spec *action_spec = &s->actions[i];
2361 uint32_t j;
2362
2363 fprintf(f, "static const char *action_%s_initial_instructions[] = {\n",
2364 action_spec->name);
2365
2366 for (j = 0; j < action_spec->n_instructions; j++) {
2367 const char *instr = action_spec->instructions[j];
2368
2369 fprintf(f, "\t[%d] = \"%s\",\n", j, instr);
2370 }
2371
2372 fprintf(f, "};\n\n");
2373 }
2374
2375 fprintf(f, "static struct action_spec actions[] = {\n");
2376
2377 for (i = 0; i < s->n_actions; i++) {
2378 struct action_spec *action_spec = &s->actions[i];
2379
2380 fprintf(f, "\t[%d] = {\n", i);
2381 fprintf(f, "\t\t.name = \"%s\",\n", action_spec->name);
2382
2383 if (action_spec->args_struct_type_name)
2384 fprintf(f, "\t\t.args_struct_type_name = \"%s\",\n",
2385 action_spec->args_struct_type_name);
2386 else
2387 fprintf(f, "\t\t.args_struct_type_name = NULL,\n");
2388
2389 fprintf(f, "\t\t.instructions = action_%s_initial_instructions,\n",
2390 action_spec->name);
2391 fprintf(f, "\t\t.n_instructions = "
2392 "sizeof(action_%s_initial_instructions) / "
2393 "sizeof(action_%s_initial_instructions[0]),\n",
2394 action_spec->name,
2395 action_spec->name);
2396 fprintf(f, "\t},\n");
2397 }
2398
2399 fprintf(f, "};\n\n");
2400
2401 /* table. */
2402 for (i = 0; i < s->n_tables; i++) {
2403 struct table_spec *table_spec = &s->tables[i];
2404 uint32_t j;
2405
2406 /* fields. */
2407 if (table_spec->params.fields && table_spec->params.n_fields) {
2408 fprintf(f, "static struct rte_swx_match_field_params "
2409 "table_%s_fields[] = {\n",
2410 table_spec->name);
2411
2412 for (j = 0; j < table_spec->params.n_fields; j++) {
2413 struct rte_swx_match_field_params *field =
2414 &table_spec->params.fields[j];
2415
2416 fprintf(f, "\t[%d] = {\n", j);
2417 fprintf(f, "\t\t.name = \"%s\",\n", field->name);
2418 fprintf(f, "\t\t.match_type = %s,\n",
2419 match_type_string_get(field->match_type));
2420 fprintf(f, "\t},\n");
2421 }
2422
2423 fprintf(f, "};\n\n");
2424 }
2425
2426 /* action_names. */
2427 if (table_spec->params.action_names && table_spec->params.n_actions) {
2428 fprintf(f, "static const char *table_%s_action_names[] = {\n",
2429 table_spec->name);
2430
2431 for (j = 0; j < table_spec->params.n_actions; j++) {
2432 const char *action_name = table_spec->params.action_names[j];
2433
2434 fprintf(f, "\t[%d] = \"%s\",\n", j, action_name);
2435 }
2436
2437 fprintf(f, "};\n\n");
2438 }
2439
2440 /* action_is_for_table_entries. */
2441 if (table_spec->params.action_is_for_table_entries &&
2442 table_spec->params.n_actions) {
2443 fprintf(f, "static int table_%s_action_is_for_table_entries[] = {\n",
2444 table_spec->name);
2445
2446 for (j = 0; j < table_spec->params.n_actions; j++) {
2447 int value = table_spec->params.action_is_for_table_entries[j];
2448
2449 fprintf(f, "\t[%d] = %d,\n", j, value);
2450 }
2451
2452 fprintf(f, "};\n\n");
2453 }
2454
2455 /* action_is_for_default_entry. */
2456 if (table_spec->params.action_is_for_default_entry &&
2457 table_spec->params.n_actions) {
2458 fprintf(f, "static int table_%s_action_is_for_default_entry[] = {\n",
2459 table_spec->name);
2460
2461 for (j = 0; j < table_spec->params.n_actions; j++) {
2462 int value = table_spec->params.action_is_for_default_entry[j];
2463
2464 fprintf(f, "\t[%d] = %d,\n", j, value);
2465 }
2466
2467 fprintf(f, "};\n\n");
2468 }
2469 }
2470
2471 fprintf(f, "static struct table_spec tables[] = {\n");
2472
2473 for (i = 0; i < s->n_tables; i++) {
2474 struct table_spec *table_spec = &s->tables[i];
2475
2476 fprintf(f, "\t[%d] = {\n", i);
2477 fprintf(f, "\t\t.name = \"%s\",\n", table_spec->name);
2478
2479 fprintf(f, "\t\t.params = {\n");
2480
2481 if (table_spec->params.fields && table_spec->params.n_fields) {
2482 fprintf(f, "\t\t\t.fields = table_%s_fields,\n", table_spec->name);
2483 fprintf(f, "\t\t\t.n_fields = "
2484 "sizeof(table_%s_fields) / sizeof(table_%s_fields[0]),\n",
2485 table_spec->name,
2486 table_spec->name);
2487 } else {
2488 fprintf(f, "\t\t\t.fields = NULL,\n");
2489 fprintf(f, "\t\t\t.n_fields = 0,\n");
2490 }
2491
2492 if (table_spec->params.action_names && table_spec->params.n_actions)
2493 fprintf(f, "\t\t\t.action_names = table_%s_action_names,\n",
2494 table_spec->name);
2495 else
2496 fprintf(f, "\t\t\t.action_names = NULL,\n");
2497
2498 if (table_spec->params.action_is_for_table_entries && table_spec->params.n_actions)
2499 fprintf(f, "\t\t\t.action_is_for_table_entries = "
2500 "table_%s_action_is_for_table_entries,\n",
2501 table_spec->name);
2502 else
2503 fprintf(f, "\t\t\t.action_is_for_table_entries = NULL,\n");
2504
2505 if (table_spec->params.action_is_for_default_entry && table_spec->params.n_actions)
2506 fprintf(f, "\t\t\t.action_is_for_default_entry = "
2507 "table_%s_action_is_for_default_entry,\n",
2508 table_spec->name);
2509 else
2510 fprintf(f, "\t\t\t.action_is_for_default_entry = NULL,\n");
2511
2512 if (table_spec->params.n_actions)
2513 fprintf(f, "\t\t\t.n_actions = sizeof(table_%s_action_names) / "
2514 "sizeof(table_%s_action_names[0]),\n",
2515 table_spec->name,
2516 table_spec->name);
2517 else
2518 fprintf(f, "\t\t\t.n_actions = 0,\n");
2519
2520 if (table_spec->params.default_action_name)
2521 fprintf(f, "\t\t\t.default_action_name = \"%s\",\n",
2522 table_spec->params.default_action_name);
2523 else
2524 fprintf(f, "\t\t\t.default_action_name = NULL,\n");
2525
2526 if (table_spec->params.default_action_args)
2527 fprintf(f, "\t\t\t.default_action_args = \"%s\",\n",
2528 table_spec->params.default_action_args);
2529 else
2530 fprintf(f, "\t\t\t.default_action_args = NULL,\n");
2531
2532 fprintf(f, "\t\t\t.default_action_is_const = %d,\n",
2533 table_spec->params.default_action_is_const);
2534
2535 if (table_spec->params.hash_func_name)
2536 fprintf(f, "\t\t\t.hash_func_name = \"%s\",\n",
2537 table_spec->params.hash_func_name);
2538 else
2539 fprintf(f, "\t\t\t.hash_func_name = NULL,\n");
2540
2541 fprintf(f, "\t\t},\n");
2542
2543 if (table_spec->recommended_table_type_name)
2544 fprintf(f, "\t\t.recommended_table_type_name = \"%s\",\n",
2545 table_spec->recommended_table_type_name);
2546 else
2547 fprintf(f, "\t\t.recommended_table_type_name = NULL,\n");
2548
2549 if (table_spec->args)
2550 fprintf(f, "\t\t.args = \"%s\",\n", table_spec->args);
2551 else
2552 fprintf(f, "\t\t.args = NULL,\n");
2553
2554 fprintf(f, "\t\t.size = %u,\n", table_spec->size);
2555
2556 fprintf(f, "\t},\n");
2557 }
2558
2559 fprintf(f, "};\n\n");
2560
2561 /* selector. */
2562 for (i = 0; i < s->n_selectors; i++) {
2563 struct selector_spec *selector_spec = &s->selectors[i];
2564 uint32_t j;
2565
2566 if (selector_spec->params.selector_field_names &&
2567 selector_spec->params.n_selector_fields) {
2568 fprintf(f, "static const char *selector_%s_field_names[] = {\n",
2569 selector_spec->name);
2570
2571 for (j = 0; j < selector_spec->params.n_selector_fields; j++) {
2572 const char *field_name =
2573 selector_spec->params.selector_field_names[j];
2574
2575 fprintf(f, "\t[%d] = \"%s\",\n", j, field_name);
2576 }
2577
2578 fprintf(f, "};\n\n");
2579 }
2580 }
2581
2582 fprintf(f, "static struct selector_spec selectors[] = {\n");
2583
2584 for (i = 0; i < s->n_selectors; i++) {
2585 struct selector_spec *selector_spec = &s->selectors[i];
2586
2587 fprintf(f, "\t[%d] = {\n", i);
2588
2589 fprintf(f, "\t\t.name = \"%s\",\n", selector_spec->name);
2590 fprintf(f, "\t\t.params = {\n");
2591
2592 if (selector_spec->params.group_id_field_name)
2593 fprintf(f, "\t\t\t.group_id_field_name = \"%s\",\n",
2594 selector_spec->params.group_id_field_name);
2595 else
2596 fprintf(f, "\t\t\t.group_id_field_name = NULL,\n");
2597
2598 if (selector_spec->params.selector_field_names &&
2599 selector_spec->params.n_selector_fields) {
2600 fprintf(f, "\t\t\t.selector_field_names = selector_%s_field_names,\n",
2601 selector_spec->name);
2602 fprintf(f, "\t\t\t.n_selector_fields = "
2603 "sizeof(selector_%s_field_names) / sizeof(selector_%s_field_names[0]),\n",
2604 selector_spec->name,
2605 selector_spec->name);
2606 } else {
2607 fprintf(f, "\t\t\t.selector_field_names = NULL,\n");
2608 fprintf(f, "\t\t\t.n_selector_fields = 0,\n");
2609 }
2610
2611 if (selector_spec->params.member_id_field_name)
2612 fprintf(f, "\t\t\t.member_id_field_name = \"%s\",\n",
2613 selector_spec->params.member_id_field_name);
2614 else
2615 fprintf(f, "\t\t\t.member_id_field_name = NULL,\n");
2616
2617 fprintf(f, "\t\t\t.n_groups_max = %u,\n", selector_spec->params.n_groups_max);
2618
2619 fprintf(f, "\t\t\t.n_members_per_group_max = %u,\n",
2620 selector_spec->params.n_members_per_group_max);
2621
2622 fprintf(f, "\t\t},\n");
2623 fprintf(f, "\t},\n");
2624 }
2625
2626 fprintf(f, "};\n\n");
2627
2628 /* learner. */
2629 for (i = 0; i < s->n_learners; i++) {
2630 struct learner_spec *learner_spec = &s->learners[i];
2631 uint32_t j;
2632
2633 /* field_names. */
2634 if (learner_spec->params.field_names && learner_spec->params.n_fields) {
2635 fprintf(f, "static const char *learner_%s_field_names[] = {\n",
2636 learner_spec->name);
2637
2638 for (j = 0; j < learner_spec->params.n_fields; j++) {
2639 const char *field_name = learner_spec->params.field_names[j];
2640
2641 fprintf(f, "\t[%d] = \"%s\",\n", j, field_name);
2642 }
2643
2644 fprintf(f, "};\n\n");
2645 }
2646
2647 /* action_names. */
2648 if (learner_spec->params.action_names && learner_spec->params.n_actions) {
2649 fprintf(f, "static const char *learner_%s_action_names[] = {\n",
2650 learner_spec->name);
2651
2652 for (j = 0; j < learner_spec->params.n_actions; j++) {
2653 const char *action_name = learner_spec->params.action_names[j];
2654
2655 fprintf(f, "\t[%d] = \"%s\",\n", j, action_name);
2656 }
2657
2658 fprintf(f, "};\n\n");
2659 }
2660
2661 /* action_is_for_table_entries. */
2662 if (learner_spec->params.action_is_for_table_entries &&
2663 learner_spec->params.n_actions) {
2664 fprintf(f, "static int learner_%s_action_is_for_table_entries[] = {\n",
2665 learner_spec->name);
2666
2667 for (j = 0; j < learner_spec->params.n_actions; j++) {
2668 int value = learner_spec->params.action_is_for_table_entries[j];
2669
2670 fprintf(f, "\t[%d] = %d,\n", j, value);
2671 }
2672
2673 fprintf(f, "};\n\n");
2674 }
2675
2676 /* action_is_for_default_entry. */
2677 if (learner_spec->params.action_is_for_default_entry &&
2678 learner_spec->params.n_actions) {
2679 fprintf(f, "static int learner_%s_action_is_for_default_entry[] = {\n",
2680 learner_spec->name);
2681
2682 for (j = 0; j < learner_spec->params.n_actions; j++) {
2683 int value = learner_spec->params.action_is_for_default_entry[j];
2684
2685 fprintf(f, "\t[%d] = %d,\n", j, value);
2686 }
2687
2688 fprintf(f, "};\n\n");
2689 }
2690
2691 /* timeout. */
2692 if (learner_spec->timeout && learner_spec->n_timeouts) {
2693 fprintf(f, "static uint32_t learner_%s_timeout[] = {\n",
2694 learner_spec->name);
2695
2696 for (j = 0; j < learner_spec->n_timeouts; j++) {
2697 uint32_t value = learner_spec->timeout[j];
2698
2699 fprintf(f, "\t[%d] = %u,\n", j, value);
2700 }
2701
2702 fprintf(f, "};\n\n");
2703 }
2704 }
2705
2706 fprintf(f, "static struct learner_spec learners[] = {\n");
2707
2708 for (i = 0; i < s->n_learners; i++) {
2709 struct learner_spec *learner_spec = &s->learners[i];
2710
2711 fprintf(f, "\t[%d] = {\n", i);
2712 fprintf(f, "\t\t.name = \"%s\",\n", learner_spec->name);
2713
2714 fprintf(f, "\t\t.params = {\n");
2715
2716 if (learner_spec->params.field_names && learner_spec->params.n_fields) {
2717 fprintf(f, "\t\t\t.field_names = learner_%s_field_names,\n",
2718 learner_spec->name);
2719 fprintf(f, "\t\t\t.n_fields = "
2720 "sizeof(learner_%s_field_names) / "
2721 "sizeof(learner_%s_field_names[0]),\n",
2722 learner_spec->name,
2723 learner_spec->name);
2724 } else {
2725 fprintf(f, "\t\t\t.field_names = NULL,\n");
2726 fprintf(f, "\t\t\t.n_fields = 0,\n");
2727 }
2728
2729 if (learner_spec->params.action_names && learner_spec->params.n_actions)
2730 fprintf(f, "\t\t\t.action_names = learner_%s_action_names,\n",
2731 learner_spec->name);
2732 else
2733 fprintf(f, "\t\t\t.action_names = NULL,\n");
2734
2735 if (learner_spec->params.action_is_for_table_entries &&
2736 learner_spec->params.n_actions)
2737 fprintf(f, "\t\t\t.action_is_for_table_entries = "
2738 "learner_%s_action_is_for_table_entries,\n",
2739 learner_spec->name);
2740 else
2741 fprintf(f, "\t\t\t.action_is_for_table_entries = NULL,\n");
2742
2743 if (learner_spec->params.action_is_for_default_entry &&
2744 learner_spec->params.n_actions)
2745 fprintf(f, "\t\t\t.action_is_for_default_entry = "
2746 "learner_%s_action_is_for_default_entry,\n",
2747 learner_spec->name);
2748 else
2749 fprintf(f, "\t\t\t.action_is_for_default_entry = NULL,\n");
2750
2751 if (learner_spec->params.action_names && learner_spec->params.n_actions)
2752 fprintf(f, "\t\t\t.n_actions = "
2753 "sizeof(learner_%s_action_names) / sizeof(learner_%s_action_names[0]),\n",
2754 learner_spec->name,
2755 learner_spec->name);
2756 else
2757 fprintf(f, "\t\t\t.n_actions = NULL,\n");
2758
2759 if (learner_spec->params.default_action_name)
2760 fprintf(f, "\t\t\t.default_action_name = \"%s\",\n",
2761 learner_spec->params.default_action_name);
2762 else
2763 fprintf(f, "\t\t\t.default_action_name = NULL,\n");
2764
2765 if (learner_spec->params.default_action_args)
2766 fprintf(f, "\t\t\t.default_action_args = \"%s\",\n",
2767 learner_spec->params.default_action_args);
2768 else
2769 fprintf(f, "\t\t\t.default_action_args = NULL,\n");
2770
2771 fprintf(f, "\t\t\t.default_action_is_const = %d,\n",
2772 learner_spec->params.default_action_is_const);
2773
2774 if (learner_spec->params.hash_func_name)
2775 fprintf(f, "\t\t\t.hash_func_name = \"%s\",\n",
2776 learner_spec->params.hash_func_name);
2777 else
2778 fprintf(f, "\t\t\t.hash_func_name = NULL,\n");
2779
2780 fprintf(f, "\t\t},\n");
2781
2782 fprintf(f, "\t\t.size = %u,\n", learner_spec->size);
2783
2784 if (learner_spec->timeout && learner_spec->n_timeouts) {
2785 fprintf(f, "\t\t.timeout = learner_%s_timeout,\n", learner_spec->name);
2786 fprintf(f, "\t\t\t.n_timeouts = "
2787 "sizeof(learner_%s_timeout) / sizeof(learner_%s_timeout[0]),\n",
2788 learner_spec->name,
2789 learner_spec->name);
2790 } else {
2791 fprintf(f, "\t\t.timeout = NULL,\n");
2792 fprintf(f, "\t\t\t.n_timeouts = 0,\n");
2793 }
2794
2795 fprintf(f, "\t},\n");
2796 }
2797
2798 fprintf(f, "};\n\n");
2799
2800 /* apply. */
2801 for (i = 0; i < s->n_apply; i++) {
2802 struct apply_spec *apply_spec = &s->apply[i];
2803 uint32_t j;
2804
2805 fprintf(f, "static const char *apply%u_initial_instructions[] = {\n", i);
2806
2807 for (j = 0; j < apply_spec->n_instructions; j++) {
2808 const char *instr = apply_spec->instructions[j];
2809
2810 fprintf(f, "\t[%d] = \"%s\",\n", j, instr);
2811 }
2812
2813 fprintf(f, "};\n\n");
2814 }
2815
2816 fprintf(f, "static struct apply_spec apply[] = {\n");
2817
2818 for (i = 0; i < s->n_apply; i++) {
2819 fprintf(f, "\t[%d] = {\n", i);
2820 fprintf(f, "\t.instructions = apply%u_initial_instructions,\n", i);
2821 fprintf(f, "\t.n_instructions = "
2822 "sizeof(apply%u_initial_instructions) / "
2823 "sizeof(apply%u_initial_instructions[0]),\n",
2824 i,
2825 i);
2826 fprintf(f, "\t},\n");
2827 }
2828
2829 fprintf(f, "};\n\n");
2830
2831 /* pipeline. */
2832 fprintf(f, "struct pipeline_spec pipeline_spec = {\n");
2833 fprintf(f, "\t.extobjs = extobjs,\n");
2834 fprintf(f, "\t.structs = structs,\n");
2835 fprintf(f, "\t.headers = headers,\n");
2836 fprintf(f, "\t.metadata = metadata,\n");
2837 fprintf(f, "\t.actions = actions,\n");
2838 fprintf(f, "\t.tables = tables,\n");
2839 fprintf(f, "\t.selectors = selectors,\n");
2840 fprintf(f, "\t.learners = learners,\n");
2841 fprintf(f, "\t.regarrays = regarrays,\n");
2842 fprintf(f, "\t.metarrays = metarrays,\n");
2843 fprintf(f, "\t.rss = rss,\n");
2844 fprintf(f, "\t.apply = apply,\n");
2845 fprintf(f, "\t.n_extobjs = sizeof(extobjs) / sizeof(extobjs[0]),\n");
2846 fprintf(f, "\t.n_structs = sizeof(structs) / sizeof(structs[0]),\n");
2847 fprintf(f, "\t.n_headers = sizeof(headers) / sizeof(headers[0]),\n");
2848 fprintf(f, "\t.n_metadata = sizeof(metadata) / sizeof(metadata[0]),\n");
2849 fprintf(f, "\t.n_actions = sizeof(actions) / sizeof(actions[0]),\n");
2850 fprintf(f, "\t.n_tables = sizeof(tables) / sizeof(tables[0]),\n");
2851 fprintf(f, "\t.n_selectors = sizeof(selectors) / sizeof(selectors[0]),\n");
2852 fprintf(f, "\t.n_learners = sizeof(learners) / sizeof(learners[0]),\n");
2853 fprintf(f, "\t.n_regarrays = sizeof(regarrays) / sizeof(regarrays[0]),\n");
2854 fprintf(f, "\t.n_metarrays = sizeof(metarrays) / sizeof(metarrays[0]),\n");
2855 fprintf(f, "\t.n_rss = sizeof(rss) / sizeof(rss[0]),\n");
2856 fprintf(f, "\t.n_apply = sizeof(apply) / sizeof(apply[0]),\n");
2857 fprintf(f, "};\n");
2858 }
2859
2860 struct pipeline_spec *
pipeline_spec_parse(FILE * spec,uint32_t * err_line,const char ** err_msg)2861 pipeline_spec_parse(FILE *spec,
2862 uint32_t *err_line,
2863 const char **err_msg)
2864 {
2865 struct extobj_spec extobj_spec = {0};
2866 struct struct_spec struct_spec = {0};
2867 struct header_spec header_spec = {0};
2868 struct metadata_spec metadata_spec = {0};
2869 struct action_spec action_spec = {0};
2870 struct table_spec table_spec = {0};
2871 struct selector_spec selector_spec = {0};
2872 struct learner_spec learner_spec = {0};
2873 struct regarray_spec regarray_spec = {0};
2874 struct metarray_spec metarray_spec = {0};
2875 struct rss_spec rss_spec = {0};
2876 struct apply_spec apply_spec = {0};
2877 struct pipeline_spec *s = NULL;
2878 uint32_t n_lines = 0;
2879 uint32_t block_mask = 0;
2880 int status = 0;
2881
2882 /* Check the input arguments. */
2883 if (!spec) {
2884 if (err_line)
2885 *err_line = n_lines;
2886 if (err_msg)
2887 *err_msg = "Invalid input argument.";
2888 status = -EINVAL;
2889 goto error;
2890 }
2891
2892 /* Memory allocation. */
2893 s = calloc(1, sizeof(struct pipeline_spec));
2894 if (!s) {
2895 if (err_line)
2896 *err_line = n_lines;
2897 if (err_msg)
2898 *err_msg = "Memory allocation failed.";
2899 status = -ENOMEM;
2900 goto error;
2901 }
2902
2903 for (n_lines = 1; ; n_lines++) {
2904 char line[MAX_LINE_LENGTH];
2905 char *tokens[MAX_TOKENS], *ptr = line;
2906 uint32_t n_tokens = 0;
2907
2908 /* Read next line. */
2909 if (!fgets(line, sizeof(line), spec))
2910 break;
2911
2912 /* Parse the line into tokens. */
2913 for ( ; ; ) {
2914 char *token;
2915
2916 /* Get token. */
2917 token = strtok_r(ptr, " \f\n\r\t\v", &ptr);
2918 if (!token)
2919 break;
2920
2921 /* Handle comments. */
2922 if ((token[0] == '#') ||
2923 (token[0] == ';') ||
2924 ((token[0] == '/') && (token[1] == '/'))) {
2925 break;
2926 }
2927
2928 /* Handle excessively long lines. */
2929 if (n_tokens >= RTE_DIM(tokens)) {
2930 if (err_line)
2931 *err_line = n_lines;
2932 if (err_msg)
2933 *err_msg = "Too many tokens.";
2934 status = -EINVAL;
2935 goto error;
2936 }
2937
2938 /* Handle excessively long tokens. */
2939 if (strnlen(token, RTE_SWX_NAME_SIZE) >=
2940 RTE_SWX_NAME_SIZE) {
2941 if (err_line)
2942 *err_line = n_lines;
2943 if (err_msg)
2944 *err_msg = "Token too big.";
2945 status = -EINVAL;
2946 goto error;
2947 }
2948
2949 /* Save token. */
2950 tokens[n_tokens] = token;
2951 n_tokens++;
2952 }
2953
2954 /* Handle empty lines. */
2955 if (!n_tokens)
2956 continue;
2957
2958 /* struct block. */
2959 if (block_mask & (1 << STRUCT_BLOCK)) {
2960 struct struct_spec *new_structs;
2961
2962 status = struct_block_parse(&struct_spec,
2963 &block_mask,
2964 tokens,
2965 n_tokens,
2966 n_lines,
2967 err_line,
2968 err_msg);
2969 if (status)
2970 goto error;
2971
2972 if (block_mask & (1 << STRUCT_BLOCK))
2973 continue;
2974
2975 /* End of block. */
2976 new_structs = realloc(s->structs,
2977 (s->n_structs + 1) * sizeof(struct struct_spec));
2978 if (!new_structs) {
2979 if (err_line)
2980 *err_line = n_lines;
2981 if (err_msg)
2982 *err_msg = "Memory allocation failed.";
2983 status = -ENOMEM;
2984 goto error;
2985 }
2986
2987 s->structs = new_structs;
2988 memcpy(&s->structs[s->n_structs], &struct_spec, sizeof(struct struct_spec));
2989 s->n_structs++;
2990 memset(&struct_spec, 0, sizeof(struct struct_spec));
2991
2992 continue;
2993 }
2994
2995 /* action block. */
2996 if (block_mask & (1 << ACTION_BLOCK)) {
2997 struct action_spec *new_actions;
2998
2999 status = action_block_parse(&action_spec,
3000 &block_mask,
3001 tokens,
3002 n_tokens,
3003 n_lines,
3004 err_line,
3005 err_msg);
3006 if (status)
3007 goto error;
3008
3009 if (block_mask & (1 << ACTION_BLOCK))
3010 continue;
3011
3012 /* End of block. */
3013 new_actions = realloc(s->actions,
3014 (s->n_actions + 1) * sizeof(struct action_spec));
3015 if (!new_actions) {
3016 if (err_line)
3017 *err_line = n_lines;
3018 if (err_msg)
3019 *err_msg = "Memory allocation failed.";
3020 status = -ENOMEM;
3021 goto error;
3022 }
3023
3024 s->actions = new_actions;
3025 memcpy(&s->actions[s->n_actions], &action_spec, sizeof(struct action_spec));
3026 s->n_actions++;
3027 memset(&action_spec, 0, sizeof(struct action_spec));
3028
3029 continue;
3030 }
3031
3032 /* table block. */
3033 if (block_mask & (1 << TABLE_BLOCK)) {
3034 struct table_spec *new_tables;
3035
3036 status = table_block_parse(&table_spec,
3037 &block_mask,
3038 tokens,
3039 n_tokens,
3040 n_lines,
3041 err_line,
3042 err_msg);
3043 if (status)
3044 goto error;
3045
3046 if (block_mask & (1 << TABLE_BLOCK))
3047 continue;
3048
3049 /* End of block. */
3050 new_tables = realloc(s->tables,
3051 (s->n_tables + 1) * sizeof(struct table_spec));
3052 if (!new_tables) {
3053 if (err_line)
3054 *err_line = n_lines;
3055 if (err_msg)
3056 *err_msg = "Memory allocation failed.";
3057 status = -ENOMEM;
3058 goto error;
3059 }
3060
3061 s->tables = new_tables;
3062 memcpy(&s->tables[s->n_tables], &table_spec, sizeof(struct table_spec));
3063 s->n_tables++;
3064 memset(&table_spec, 0, sizeof(struct table_spec));
3065
3066 continue;
3067 }
3068
3069 /* selector block. */
3070 if (block_mask & (1 << SELECTOR_BLOCK)) {
3071 struct selector_spec *new_selectors;
3072
3073 status = selector_block_parse(&selector_spec,
3074 &block_mask,
3075 tokens,
3076 n_tokens,
3077 n_lines,
3078 err_line,
3079 err_msg);
3080 if (status)
3081 goto error;
3082
3083 if (block_mask & (1 << SELECTOR_BLOCK))
3084 continue;
3085
3086 /* End of block. */
3087 new_selectors = realloc(s->selectors,
3088 (s->n_selectors + 1) * sizeof(struct selector_spec));
3089 if (!new_selectors) {
3090 if (err_line)
3091 *err_line = n_lines;
3092 if (err_msg)
3093 *err_msg = "Memory allocation failed.";
3094 status = -ENOMEM;
3095 goto error;
3096 }
3097
3098 s->selectors = new_selectors;
3099 memcpy(&s->selectors[s->n_selectors],
3100 &selector_spec,
3101 sizeof(struct selector_spec));
3102 s->n_selectors++;
3103 memset(&selector_spec, 0, sizeof(struct selector_spec));
3104
3105 continue;
3106 }
3107
3108 /* learner block. */
3109 if (block_mask & (1 << LEARNER_BLOCK)) {
3110 struct learner_spec *new_learners;
3111
3112 status = learner_block_parse(&learner_spec,
3113 &block_mask,
3114 tokens,
3115 n_tokens,
3116 n_lines,
3117 err_line,
3118 err_msg);
3119 if (status)
3120 goto error;
3121
3122 if (block_mask & (1 << LEARNER_BLOCK))
3123 continue;
3124
3125 /* End of block. */
3126 new_learners = realloc(s->learners,
3127 (s->n_learners + 1) * sizeof(struct learner_spec));
3128 if (!new_learners) {
3129 if (err_line)
3130 *err_line = n_lines;
3131 if (err_msg)
3132 *err_msg = "Memory allocation failed.";
3133 status = -ENOMEM;
3134 goto error;
3135 }
3136
3137 s->learners = new_learners;
3138 memcpy(&s->learners[s->n_learners],
3139 &learner_spec,
3140 sizeof(struct learner_spec));
3141 s->n_learners++;
3142 memset(&learner_spec, 0, sizeof(struct learner_spec));
3143
3144 continue;
3145 }
3146
3147 /* apply block. */
3148 if (block_mask & (1 << APPLY_BLOCK)) {
3149 struct apply_spec *new_apply;
3150
3151 status = apply_block_parse(&apply_spec,
3152 &block_mask,
3153 tokens,
3154 n_tokens,
3155 n_lines,
3156 err_line,
3157 err_msg);
3158 if (status)
3159 goto error;
3160
3161 if (block_mask & (1 << APPLY_BLOCK))
3162 continue;
3163
3164 /* End of block. */
3165 new_apply = realloc(s->apply, (s->n_apply + 1) * sizeof(struct apply_spec));
3166 if (!new_apply) {
3167 if (err_line)
3168 *err_line = n_lines;
3169 if (err_msg)
3170 *err_msg = "Memory allocation failed.";
3171 status = -ENOMEM;
3172 goto error;
3173 }
3174
3175 s->apply = new_apply;
3176 memcpy(&s->apply[s->n_apply], &apply_spec, sizeof(struct apply_spec));
3177 s->n_apply++;
3178 memset(&apply_spec, 0, sizeof(struct apply_spec));
3179
3180 continue;
3181 }
3182
3183 /* extobj. */
3184 if (!strcmp(tokens[0], "extobj")) {
3185 struct extobj_spec *new_extobjs;
3186
3187 status = extobj_statement_parse(&extobj_spec,
3188 tokens,
3189 n_tokens,
3190 n_lines,
3191 err_line,
3192 err_msg);
3193 if (status)
3194 goto error;
3195
3196 new_extobjs = realloc(s->extobjs,
3197 (s->n_extobjs + 1) * sizeof(struct extobj_spec));
3198 if (!new_extobjs) {
3199 if (err_line)
3200 *err_line = n_lines;
3201 if (err_msg)
3202 *err_msg = "Memory allocation failed.";
3203 status = -ENOMEM;
3204 goto error;
3205 }
3206
3207 s->extobjs = new_extobjs;
3208 memcpy(&s->extobjs[s->n_extobjs], &extobj_spec, sizeof(struct extobj_spec));
3209 s->n_extobjs++;
3210 memset(&extobj_spec, 0, sizeof(struct extobj_spec));
3211
3212 continue;
3213 }
3214
3215 /* struct. */
3216 if (!strcmp(tokens[0], "struct")) {
3217 status = struct_statement_parse(&struct_spec,
3218 &block_mask,
3219 tokens,
3220 n_tokens,
3221 n_lines,
3222 err_line,
3223 err_msg);
3224 if (status)
3225 goto error;
3226
3227 continue;
3228 }
3229
3230 /* header. */
3231 if (!strcmp(tokens[0], "header")) {
3232 struct header_spec *new_headers;
3233
3234 status = header_statement_parse(&header_spec,
3235 tokens,
3236 n_tokens,
3237 n_lines,
3238 err_line,
3239 err_msg);
3240 if (status)
3241 goto error;
3242
3243 new_headers = realloc(s->headers,
3244 (s->n_headers + 1) * sizeof(struct header_spec));
3245 if (!new_headers) {
3246 if (err_line)
3247 *err_line = n_lines;
3248 if (err_msg)
3249 *err_msg = "Memory allocation failed.";
3250 status = -ENOMEM;
3251 goto error;
3252 }
3253
3254 s->headers = new_headers;
3255 memcpy(&s->headers[s->n_headers], &header_spec, sizeof(struct header_spec));
3256 s->n_headers++;
3257 memset(&header_spec, 0, sizeof(struct header_spec));
3258
3259 continue;
3260 }
3261
3262 /* metadata. */
3263 if (!strcmp(tokens[0], "metadata")) {
3264 struct metadata_spec *new_metadata;
3265
3266 status = metadata_statement_parse(&metadata_spec,
3267 tokens,
3268 n_tokens,
3269 n_lines,
3270 err_line,
3271 err_msg);
3272 if (status)
3273 goto error;
3274
3275 new_metadata = realloc(s->metadata,
3276 (s->n_metadata + 1) * sizeof(struct metadata_spec));
3277 if (!new_metadata) {
3278 if (err_line)
3279 *err_line = n_lines;
3280 if (err_msg)
3281 *err_msg = "Memory allocation failed.";
3282 status = -ENOMEM;
3283 goto error;
3284 }
3285
3286 s->metadata = new_metadata;
3287 memcpy(&s->metadata[s->n_metadata],
3288 &metadata_spec,
3289 sizeof(struct metadata_spec));
3290 s->n_metadata++;
3291 memset(&metadata_spec, 0, sizeof(struct metadata_spec));
3292
3293 continue;
3294 }
3295
3296 /* action. */
3297 if (!strcmp(tokens[0], "action")) {
3298 status = action_statement_parse(&action_spec,
3299 &block_mask,
3300 tokens,
3301 n_tokens,
3302 n_lines,
3303 err_line,
3304 err_msg);
3305 if (status)
3306 goto error;
3307
3308 continue;
3309 }
3310
3311 /* table. */
3312 if (!strcmp(tokens[0], "table")) {
3313 status = table_statement_parse(&table_spec,
3314 &block_mask,
3315 tokens,
3316 n_tokens,
3317 n_lines,
3318 err_line,
3319 err_msg);
3320 if (status)
3321 goto error;
3322
3323 continue;
3324 }
3325
3326 /* selector. */
3327 if (!strcmp(tokens[0], "selector")) {
3328 status = selector_statement_parse(&selector_spec,
3329 &block_mask,
3330 tokens,
3331 n_tokens,
3332 n_lines,
3333 err_line,
3334 err_msg);
3335 if (status)
3336 goto error;
3337
3338 continue;
3339 }
3340
3341 /* learner. */
3342 if (!strcmp(tokens[0], "learner")) {
3343 status = learner_statement_parse(&learner_spec,
3344 &block_mask,
3345 tokens,
3346 n_tokens,
3347 n_lines,
3348 err_line,
3349 err_msg);
3350 if (status)
3351 goto error;
3352
3353 continue;
3354 }
3355
3356 /* regarray. */
3357 if (!strcmp(tokens[0], "regarray")) {
3358 struct regarray_spec *new_regarrays;
3359
3360 status = regarray_statement_parse(®array_spec,
3361 tokens,
3362 n_tokens,
3363 n_lines,
3364 err_line,
3365 err_msg);
3366 if (status)
3367 goto error;
3368
3369 new_regarrays = realloc(s->regarrays,
3370 (s->n_regarrays + 1) * sizeof(struct regarray_spec));
3371 if (!new_regarrays) {
3372 if (err_line)
3373 *err_line = n_lines;
3374 if (err_msg)
3375 *err_msg = "Memory allocation failed.";
3376 status = -ENOMEM;
3377 goto error;
3378 }
3379
3380 s->regarrays = new_regarrays;
3381 memcpy(&s->regarrays[s->n_regarrays],
3382 ®array_spec,
3383 sizeof(struct regarray_spec));
3384 s->n_regarrays++;
3385 memset(®array_spec, 0, sizeof(struct regarray_spec));
3386
3387 continue;
3388 }
3389
3390 /* metarray. */
3391 if (!strcmp(tokens[0], "metarray")) {
3392 struct metarray_spec *new_metarrays;
3393
3394 status = metarray_statement_parse(&metarray_spec,
3395 tokens,
3396 n_tokens,
3397 n_lines,
3398 err_line,
3399 err_msg);
3400 if (status)
3401 goto error;
3402
3403 new_metarrays = realloc(s->metarrays,
3404 (s->n_metarrays + 1) * sizeof(struct metarray_spec));
3405 if (!new_metarrays) {
3406 if (err_line)
3407 *err_line = n_lines;
3408 if (err_msg)
3409 *err_msg = "Memory allocation failed.";
3410 status = -ENOMEM;
3411 goto error;
3412 }
3413
3414 s->metarrays = new_metarrays;
3415 memcpy(&s->metarrays[s->n_metarrays],
3416 &metarray_spec,
3417 sizeof(struct metarray_spec));
3418 s->n_metarrays++;
3419 memset(&metarray_spec, 0, sizeof(struct metarray_spec));
3420
3421 continue;
3422 }
3423
3424 /* rss object configuration */
3425 if (!strcmp(tokens[0], "rss")) {
3426 struct rss_spec *new_rss;
3427
3428 status = rss_statement_parse(&rss_spec,
3429 tokens,
3430 n_tokens,
3431 n_lines,
3432 err_line,
3433 err_msg);
3434 if (status)
3435 goto error;
3436
3437 new_rss = realloc(s->rss,
3438 (s->n_rss + 1) * sizeof(struct rss_spec));
3439 if (!new_rss) {
3440 if (err_line)
3441 *err_line = n_lines;
3442 if (err_msg)
3443 *err_msg = "Memory allocation failed.";
3444 status = -ENOMEM;
3445 goto error;
3446 }
3447
3448 s->rss = new_rss;
3449 memcpy(&s->rss[s->n_rss],
3450 &rss_spec,
3451 sizeof(struct rss_spec));
3452 s->n_rss++;
3453 memset(&rss_spec, 0, sizeof(struct rss_spec));
3454
3455 continue;
3456 }
3457
3458 /* apply. */
3459 if (!strcmp(tokens[0], "apply")) {
3460 status = apply_statement_parse(&block_mask,
3461 tokens,
3462 n_tokens,
3463 n_lines,
3464 err_line,
3465 err_msg);
3466 if (status)
3467 goto error;
3468
3469 continue;
3470 }
3471
3472 /* Anything else. */
3473 if (err_line)
3474 *err_line = n_lines;
3475 if (err_msg)
3476 *err_msg = "Unknown statement.";
3477 status = -EINVAL;
3478 goto error;
3479 }
3480
3481 /* Handle unfinished block. */
3482 if (block_mask) {
3483 if (err_line)
3484 *err_line = n_lines;
3485 if (err_msg)
3486 *err_msg = "Missing }.";
3487 status = -EINVAL;
3488 goto error;
3489 }
3490
3491 return s;
3492
3493 error:
3494 extobj_spec_free(&extobj_spec);
3495 struct_spec_free(&struct_spec);
3496 header_spec_free(&header_spec);
3497 metadata_spec_free(&metadata_spec);
3498 action_spec_free(&action_spec);
3499 table_spec_free(&table_spec);
3500 selector_spec_free(&selector_spec);
3501 learner_spec_free(&learner_spec);
3502 regarray_spec_free(®array_spec);
3503 metarray_spec_free(&metarray_spec);
3504 rss_spec_free(&rss_spec);
3505 apply_spec_free(&apply_spec);
3506 pipeline_spec_free(s);
3507
3508 return NULL;
3509 }
3510
3511 int
pipeline_spec_configure(struct rte_swx_pipeline * p,struct pipeline_spec * s,const char ** err_msg)3512 pipeline_spec_configure(struct rte_swx_pipeline *p,
3513 struct pipeline_spec *s,
3514 const char **err_msg)
3515 {
3516 uint32_t i;
3517 int status = 0;
3518
3519 /* extobj. */
3520 for (i = 0; i < s->n_extobjs; i++) {
3521 struct extobj_spec *extobj_spec = &s->extobjs[i];
3522
3523 status = rte_swx_pipeline_extern_object_config(p,
3524 extobj_spec->name,
3525 extobj_spec->extern_type_name,
3526 extobj_spec->pragma);
3527 if (status) {
3528 if (err_msg)
3529 *err_msg = "Extern object configuration error.";
3530 return status;
3531 }
3532 }
3533
3534 /* regarray. */
3535 for (i = 0; i < s->n_regarrays; i++) {
3536 struct regarray_spec *regarray_spec = &s->regarrays[i];
3537
3538 status = rte_swx_pipeline_regarray_config(p,
3539 regarray_spec->name,
3540 regarray_spec->size,
3541 regarray_spec->init_val);
3542 if (status) {
3543 if (err_msg)
3544 *err_msg = "Register array configuration error.";
3545 return status;
3546 }
3547 }
3548
3549 /* rss. */
3550 for (i = 0; i < s->n_rss; i++) {
3551 struct rss_spec *rss_spec = &s->rss[i];
3552
3553 status = rte_swx_pipeline_rss_config(p, rss_spec->name);
3554 if (status) {
3555 if (err_msg)
3556 *err_msg = "rss object configuration error.";
3557 return status;
3558 }
3559 }
3560
3561 /* metarray. */
3562 for (i = 0; i < s->n_metarrays; i++) {
3563 struct metarray_spec *metarray_spec = &s->metarrays[i];
3564
3565 status = rte_swx_pipeline_metarray_config(p,
3566 metarray_spec->name,
3567 metarray_spec->size);
3568 if (status) {
3569 if (err_msg)
3570 *err_msg = "Meter array configuration error.";
3571 return status;
3572 }
3573 }
3574
3575 /* struct. */
3576 for (i = 0; i < s->n_structs; i++) {
3577 struct struct_spec *struct_spec = &s->structs[i];
3578
3579 status = rte_swx_pipeline_struct_type_register(p,
3580 struct_spec->name,
3581 struct_spec->fields,
3582 struct_spec->n_fields,
3583 struct_spec->varbit);
3584 if (status) {
3585 if (err_msg)
3586 *err_msg = "Struct type registration error.";
3587 return status;
3588 }
3589 }
3590
3591 /* header. */
3592 for (i = 0; i < s->n_headers; i++) {
3593 struct header_spec *header_spec = &s->headers[i];
3594
3595 status = rte_swx_pipeline_packet_header_register(p,
3596 header_spec->name,
3597 header_spec->struct_type_name);
3598 if (status) {
3599 if (err_msg)
3600 *err_msg = "Header configuration error.";
3601 return status;
3602 }
3603 }
3604
3605 /* metadata. */
3606 for (i = 0; i < s->n_metadata; i++) {
3607 struct metadata_spec *metadata_spec = &s->metadata[i];
3608
3609 status = rte_swx_pipeline_packet_metadata_register(p,
3610 metadata_spec->struct_type_name);
3611 if (status) {
3612 if (err_msg)
3613 *err_msg = "Meta-data registration error.";
3614 return status;
3615 }
3616 }
3617
3618 /* action. */
3619 for (i = 0; i < s->n_actions; i++) {
3620 struct action_spec *action_spec = &s->actions[i];
3621
3622 status = rte_swx_pipeline_action_config(p,
3623 action_spec->name,
3624 action_spec->args_struct_type_name,
3625 action_spec->instructions,
3626 action_spec->n_instructions);
3627 if (status) {
3628 if (err_msg)
3629 *err_msg = "Action configuration error.";
3630 return status;
3631 }
3632 }
3633
3634 /* table. */
3635 for (i = 0; i < s->n_tables; i++) {
3636 struct table_spec *table_spec = &s->tables[i];
3637
3638 status = rte_swx_pipeline_table_config(p,
3639 table_spec->name,
3640 &table_spec->params,
3641 table_spec->recommended_table_type_name,
3642 table_spec->args,
3643 table_spec->size);
3644 if (status) {
3645 if (err_msg)
3646 *err_msg = "Table configuration error.";
3647 return status;
3648 }
3649 }
3650
3651 /* selector. */
3652 for (i = 0; i < s->n_selectors; i++) {
3653 struct selector_spec *selector_spec = &s->selectors[i];
3654
3655 status = rte_swx_pipeline_selector_config(p,
3656 selector_spec->name,
3657 &selector_spec->params);
3658 if (status) {
3659 if (err_msg)
3660 *err_msg = "Selector table configuration error.";
3661 return status;
3662 }
3663 }
3664
3665 /* learner. */
3666 for (i = 0; i < s->n_learners; i++) {
3667 struct learner_spec *learner_spec = &s->learners[i];
3668
3669 status = rte_swx_pipeline_learner_config(p,
3670 learner_spec->name,
3671 &learner_spec->params,
3672 learner_spec->size,
3673 learner_spec->timeout,
3674 learner_spec->n_timeouts);
3675 if (status) {
3676 if (err_msg)
3677 *err_msg = "Learner table configuration error.";
3678 return status;
3679 }
3680 }
3681
3682 /* apply. */
3683 for (i = 0; i < s->n_apply; i++) {
3684 struct apply_spec *apply_spec = &s->apply[i];
3685
3686 status = rte_swx_pipeline_instructions_config(p,
3687 apply_spec->instructions,
3688 apply_spec->n_instructions);
3689 if (status) {
3690 if (err_msg)
3691 *err_msg = "Pipeline instructions configuration error.";
3692 return status;
3693 }
3694 }
3695
3696 return 0;
3697 }
3698
3699 static void
port_in_params_free(void * params,const char * port_type)3700 port_in_params_free(void *params, const char *port_type)
3701 {
3702 uintptr_t dev_name;
3703
3704 if (!params || !port_type)
3705 return;
3706
3707 if (!strcmp(port_type, "ethdev")) {
3708 struct rte_swx_port_ethdev_reader_params *p = params;
3709
3710 dev_name = (uintptr_t)p->dev_name;
3711 } else if (!strcmp(port_type, "ring")) {
3712 struct rte_swx_port_ring_reader_params *p = params;
3713
3714 dev_name = (uintptr_t)p->name;
3715 } else if (!strcmp(port_type, "source")) {
3716 struct rte_swx_port_source_params *p = params;
3717
3718 dev_name = (uintptr_t)p->file_name;
3719 } else
3720 dev_name = (uintptr_t)NULL;
3721
3722 free((void *)dev_name);
3723 free(params);
3724 }
3725
3726 static void
port_out_params_free(void * params,const char * port_type)3727 port_out_params_free(void *params, const char *port_type)
3728 {
3729 uintptr_t dev_name;
3730
3731 if (!params || !port_type)
3732 return;
3733
3734 if (!strcmp(port_type, "ethdev")) {
3735 struct rte_swx_port_ethdev_writer_params *p = params;
3736
3737 dev_name = (uintptr_t)p->dev_name;
3738 } else if (!strcmp(port_type, "ring")) {
3739 struct rte_swx_port_ring_writer_params *p = params;
3740
3741 dev_name = (uintptr_t)p->name;
3742 } else if (!strcmp(port_type, "sink")) {
3743 struct rte_swx_port_sink_params *p = params;
3744
3745 dev_name = (uintptr_t)p->file_name;
3746 } else
3747 dev_name = (uintptr_t)NULL;
3748
3749 free((void *)dev_name);
3750 free(params);
3751 }
3752
3753 void
pipeline_iospec_free(struct pipeline_iospec * s)3754 pipeline_iospec_free(struct pipeline_iospec *s)
3755 {
3756 uint32_t i;
3757
3758 if (!s)
3759 return;
3760
3761 /* Input ports. */
3762 for (i = 0; i < s->n_ports_in; i++) {
3763 uintptr_t name = (uintptr_t)s->port_in_type[i];
3764
3765 port_in_params_free(s->port_in_params[i], s->port_in_type[i]);
3766 free((void *)name);
3767 }
3768
3769 free(s->port_in_type);
3770 free(s->port_in_params);
3771
3772 /* Output ports. */
3773 for (i = 0; i < s->n_ports_out; i++) {
3774 uintptr_t name = (uintptr_t)s->port_out_type[i];
3775
3776 port_out_params_free(s->port_out_params[i], s->port_out_type[i]);
3777 free((void *)name);
3778 }
3779
3780 free(s->port_out_type);
3781 free(s->port_out_params);
3782
3783 free(s);
3784 }
3785
3786 static int
mirroring_parse(struct rte_swx_pipeline_mirroring_params * p,char ** tokens,uint32_t n_tokens,const char ** err_msg)3787 mirroring_parse(struct rte_swx_pipeline_mirroring_params *p,
3788 char **tokens,
3789 uint32_t n_tokens,
3790 const char **err_msg)
3791 {
3792 char *token;
3793
3794 if ((n_tokens != 4) || strcmp(tokens[0], "slots") || strcmp(tokens[2], "sessions")) {
3795 if (err_msg)
3796 *err_msg = "Invalid statement.";
3797 return -EINVAL;
3798 }
3799
3800 /* <n_slots>. */
3801 token = tokens[1];
3802 p->n_slots = strtoul(token, &token, 0);
3803 if (token[0]) {
3804 if (err_msg)
3805 *err_msg = "Invalid <n_slots> parameter.";
3806 return -EINVAL;
3807 }
3808
3809 /* <n_sessions>. */
3810 token = tokens[3];
3811 p->n_sessions = strtoul(token, &token, 0);
3812 if (token[0]) {
3813 if (err_msg)
3814 *err_msg = "Invalid <n_sessions> parameter.";
3815 return -EINVAL;
3816 }
3817
3818 return 0;
3819 }
3820
3821 static void *
port_in_ethdev_parse(char ** tokens,uint32_t n_tokens,const char ** err_msg)3822 port_in_ethdev_parse(char **tokens, uint32_t n_tokens, const char **err_msg)
3823 {
3824 struct rte_swx_port_ethdev_reader_params *p = NULL;
3825 char *token, *dev_name = NULL;
3826 uint32_t queue_id, burst_size;
3827
3828 if ((n_tokens != 5) || strcmp(tokens[1], "rxq") || strcmp(tokens[3], "bsz")) {
3829 if (err_msg)
3830 *err_msg = "Invalid statement.";
3831 return NULL;
3832 }
3833
3834 /* <queue_id>. */
3835 token = tokens[2];
3836 queue_id = strtoul(token, &token, 0);
3837 if (token[0]) {
3838 if (err_msg)
3839 *err_msg = "Invalid <queue_id> parameter.";
3840 return NULL;
3841 }
3842
3843 /* <burst_size>. */
3844 token = tokens[4];
3845 burst_size = strtoul(token, &token, 0);
3846 if (token[0]) {
3847 if (err_msg)
3848 *err_msg = "Invalid <burst_size> parameter.";
3849 return NULL;
3850 }
3851
3852 /* Memory allocation. */
3853 dev_name = strdup(tokens[0]);
3854 p = malloc(sizeof(struct rte_swx_port_ethdev_reader_params));
3855 if (!dev_name || !p) {
3856 free(dev_name);
3857 free(p);
3858
3859 if (err_msg)
3860 *err_msg = "Memory allocation failed.";
3861 return NULL;
3862 }
3863
3864 /* Initialization. */
3865 p->dev_name = dev_name;
3866 p->queue_id = queue_id;
3867 p->burst_size = burst_size;
3868
3869 return p;
3870 }
3871
3872 static void *
port_in_ring_parse(char ** tokens,uint32_t n_tokens,const char ** err_msg)3873 port_in_ring_parse(char **tokens, uint32_t n_tokens, const char **err_msg)
3874 {
3875 struct rte_swx_port_ring_reader_params *p = NULL;
3876 char *token, *name = NULL;
3877 uint32_t burst_size;
3878
3879 if ((n_tokens != 3) || strcmp(tokens[1], "bsz")) {
3880 if (err_msg)
3881 *err_msg = "Invalid statement.";
3882 return NULL;
3883 }
3884
3885 /* <burst_size>. */
3886 token = tokens[2];
3887 burst_size = strtoul(token, &token, 0);
3888 if (token[0]) {
3889 if (err_msg)
3890 *err_msg = "Invalid <burst_size> parameter.";
3891 return NULL;
3892 }
3893
3894 /* Memory allocation. */
3895 name = strdup(tokens[0]);
3896 p = malloc(sizeof(struct rte_swx_port_ring_reader_params));
3897 if (!name || !p) {
3898 free(name);
3899 free(p);
3900
3901 if (err_msg)
3902 *err_msg = "Memory allocation failed.";
3903 return NULL;
3904 }
3905
3906 /* Initialization. */
3907 p->name = name;
3908 p->burst_size = burst_size;
3909
3910 return p;
3911 }
3912
3913 static void *
port_in_source_parse(char ** tokens,uint32_t n_tokens,const char ** err_msg)3914 port_in_source_parse(char **tokens, uint32_t n_tokens, const char **err_msg)
3915 {
3916 struct rte_swx_port_source_params *p = NULL;
3917 struct rte_mempool *pool = NULL;
3918 char *token, *file_name = NULL;
3919 uint32_t n_loops, n_pkts_max;
3920
3921 if ((n_tokens != 8) ||
3922 strcmp(tokens[0], "mempool") ||
3923 strcmp(tokens[2], "file") ||
3924 strcmp(tokens[4], "loop") ||
3925 strcmp(tokens[6], "packets")) {
3926 if (err_msg)
3927 *err_msg = "Invalid statement.";
3928 return NULL;
3929 }
3930
3931 /* <mempool_name>. */
3932 pool = rte_mempool_lookup(tokens[1]);
3933 if (!pool) {
3934 if (err_msg)
3935 *err_msg = "Invalid <mempool_name> parameter.";
3936 return NULL;
3937 }
3938
3939 /* <n_loops>. */
3940 token = tokens[5];
3941 n_loops = strtoul(token, &token, 0);
3942 if (token[0]) {
3943 if (err_msg)
3944 *err_msg = "Invalid <n_loops> parameter.";
3945 return NULL;
3946 }
3947
3948 /* <n_pkts_max>. */
3949 token = tokens[7];
3950 n_pkts_max = strtoul(token, &token, 0);
3951 if (token[0]) {
3952 if (err_msg)
3953 *err_msg = "Invalid <n_pkts_max> parameter.";
3954 return NULL;
3955 }
3956
3957 /* Memory allocation. */
3958 file_name = strdup(tokens[3]);
3959 p = malloc(sizeof(struct rte_swx_port_source_params));
3960 if (!file_name || !p) {
3961 free(file_name);
3962 free(p);
3963
3964 if (err_msg)
3965 *err_msg = "Memory allocation failed.";
3966 return NULL;
3967 }
3968
3969 /* Initialization. */
3970 p->pool = pool;
3971 p->file_name = file_name;
3972 p->n_loops = n_loops;
3973 p->n_pkts_max = n_pkts_max;
3974
3975 return p;
3976 }
3977
3978 static void *
port_in_fd_parse(char ** tokens,uint32_t n_tokens,const char ** err_msg)3979 port_in_fd_parse(char **tokens,
3980 uint32_t n_tokens,
3981 const char **err_msg)
3982 {
3983 struct rte_swx_port_fd_reader_params *p = NULL;
3984 struct rte_mempool *mempool = NULL;
3985 char *token;
3986 uint32_t mtu, burst_size;
3987 int fd;
3988
3989 if ((n_tokens != 7) ||
3990 strcmp(tokens[1], "mtu") ||
3991 strcmp(tokens[3], "mempool") ||
3992 strcmp(tokens[5], "bsz")) {
3993 if (err_msg)
3994 *err_msg = "Invalid statement.";
3995 return NULL;
3996 }
3997
3998 /* <file_descriptor>. */
3999 token = tokens[0];
4000 fd = strtol(token, &token, 0);
4001 if (token[0]) {
4002 if (err_msg)
4003 *err_msg = "Invalid <file_descriptor> parameter.";
4004 return NULL;
4005 }
4006
4007 /* <mtu>. */
4008 token = tokens[2];
4009 mtu = strtoul(token, &token, 0);
4010 if (token[0]) {
4011 if (err_msg)
4012 *err_msg = "Invalid <mtu> parameter.";
4013 return NULL;
4014 }
4015
4016 /* <mempool_name>. */
4017 mempool = rte_mempool_lookup(tokens[4]);
4018 if (!mempool) {
4019 if (err_msg)
4020 *err_msg = "Invalid <mempool_name> parameter.";
4021 return NULL;
4022 }
4023
4024 /* <burst_size>. */
4025 token = tokens[6];
4026 burst_size = strtoul(token, &token, 0);
4027 if (token[0]) {
4028 if (err_msg)
4029 *err_msg = "Invalid <burst_size> parameter.";
4030 return NULL;
4031 }
4032
4033 /* Memory allocation. */
4034 p = malloc(sizeof(struct rte_swx_port_fd_reader_params));
4035 if (!p) {
4036 if (err_msg)
4037 *err_msg = "Memory allocation failed.";
4038 return NULL;
4039 }
4040
4041 /* Initialization. */
4042 p->fd = fd;
4043 p->mtu = mtu;
4044 p->mempool = mempool;
4045 p->burst_size = burst_size;
4046
4047 return p;
4048 }
4049
4050 static void *
port_out_ethdev_parse(char ** tokens,uint32_t n_tokens,const char ** err_msg)4051 port_out_ethdev_parse(char **tokens, uint32_t n_tokens, const char **err_msg)
4052 {
4053 struct rte_swx_port_ethdev_writer_params *p = NULL;
4054 char *token, *dev_name = NULL;
4055 uint32_t queue_id, burst_size;
4056
4057 if ((n_tokens != 5) || strcmp(tokens[1], "txq") || strcmp(tokens[3], "bsz")) {
4058 if (err_msg)
4059 *err_msg = "Invalid statement.";
4060 return NULL;
4061 }
4062
4063 /* <queue_id>. */
4064 token = tokens[2];
4065 queue_id = strtoul(token, &token, 0);
4066 if (token[0]) {
4067 if (err_msg)
4068 *err_msg = "Invalid <queue_id> parameter.";
4069 return NULL;
4070 }
4071
4072 /* <burst_size>. */
4073 token = tokens[4];
4074 burst_size = strtoul(token, &token, 0);
4075 if (token[0]) {
4076 if (err_msg)
4077 *err_msg = "Invalid <burst_size> parameter.";
4078 return NULL;
4079 }
4080
4081 /* Memory allocation. */
4082 dev_name = strdup(tokens[0]);
4083 p = malloc(sizeof(struct rte_swx_port_ethdev_writer_params));
4084 if (!dev_name || !p) {
4085 free(dev_name);
4086 free(p);
4087
4088 if (err_msg)
4089 *err_msg = "Memory allocation failed.";
4090 return NULL;
4091 }
4092
4093 /* Initialization. */
4094 p->dev_name = dev_name;
4095 p->queue_id = queue_id;
4096 p->burst_size = burst_size;
4097
4098 return p;
4099 }
4100
4101 static void *
port_out_ring_parse(char ** tokens,uint32_t n_tokens,const char ** err_msg)4102 port_out_ring_parse(char **tokens, uint32_t n_tokens, const char **err_msg)
4103 {
4104 struct rte_swx_port_ring_writer_params *p = NULL;
4105 char *token, *name = NULL;
4106 uint32_t burst_size;
4107
4108 if ((n_tokens != 3) || strcmp(tokens[1], "bsz")) {
4109 if (err_msg)
4110 *err_msg = "Invalid statement.";
4111 return NULL;
4112 }
4113
4114 /* <burst_size>. */
4115 token = tokens[2];
4116 burst_size = strtoul(token, &token, 0);
4117 if (token[0]) {
4118 if (err_msg)
4119 *err_msg = "Invalid <burst_size> parameter.";
4120 return NULL;
4121 }
4122
4123 /* Memory allocation. */
4124 name = strdup(tokens[0]);
4125 p = malloc(sizeof(struct rte_swx_port_ring_writer_params));
4126 if (!name || !p) {
4127 free(name);
4128 free(p);
4129
4130 if (err_msg)
4131 *err_msg = "Memory allocation failed.";
4132 return NULL;
4133 }
4134
4135 /* Initialization. */
4136 p->name = name;
4137 p->burst_size = burst_size;
4138
4139 return p;
4140 }
4141
4142 static void *
port_out_sink_parse(char ** tokens,uint32_t n_tokens,const char ** err_msg)4143 port_out_sink_parse(char **tokens, uint32_t n_tokens, const char **err_msg)
4144 {
4145 struct rte_swx_port_sink_params *p = NULL;
4146 char *file_name = NULL;
4147 int file_name_valid = 0;
4148
4149 if ((n_tokens != 2) || strcmp(tokens[0], "file")) {
4150 if (err_msg)
4151 *err_msg = "Invalid statement.";
4152 return NULL;
4153 }
4154
4155 /* Memory allocation. */
4156 if (strcmp(tokens[1], "none")) {
4157 file_name_valid = 1;
4158 file_name = strdup(tokens[1]);
4159 }
4160
4161 p = malloc(sizeof(struct rte_swx_port_ring_writer_params));
4162 if ((file_name_valid && !file_name) || !p) {
4163 free(file_name);
4164 free(p);
4165
4166 if (err_msg)
4167 *err_msg = "Memory allocation failed.";
4168 return NULL;
4169 }
4170
4171 /* Initialization. */
4172 p->file_name = file_name;
4173
4174 return p;
4175 }
4176
4177 static void *
port_out_fd_parse(char ** tokens,uint32_t n_tokens,const char ** err_msg)4178 port_out_fd_parse(char **tokens,
4179 uint32_t n_tokens,
4180 const char **err_msg)
4181 {
4182 struct rte_swx_port_fd_writer_params *p = NULL;
4183 char *token;
4184 uint32_t burst_size;
4185 int fd;
4186
4187 if ((n_tokens != 3) || strcmp(tokens[1], "bsz")) {
4188 if (err_msg)
4189 *err_msg = "Invalid statement.";
4190 return NULL;
4191 }
4192
4193 /* <file_descriptor>. */
4194 token = tokens[0];
4195 fd = strtol(token, &token, 0);
4196 if (token[0]) {
4197 if (err_msg)
4198 *err_msg = "Invalid <file_descriptor> parameter.";
4199 return NULL;
4200 }
4201
4202 /* <burst_size>. */
4203 token = tokens[2];
4204 burst_size = strtoul(token, &token, 0);
4205 if (token[0]) {
4206 if (err_msg)
4207 *err_msg = "Invalid <burst_size> parameter.";
4208 return NULL;
4209 }
4210
4211 /* Memory allocation. */
4212 p = malloc(sizeof(struct rte_swx_port_fd_writer_params));
4213 if (!p) {
4214 if (err_msg)
4215 *err_msg = "Memory allocation failed.";
4216 return NULL;
4217 }
4218
4219 /* Initialization. */
4220 p->fd = fd;
4221 p->burst_size = burst_size;
4222
4223 return p;
4224 }
4225
4226 struct pipeline_iospec *
pipeline_iospec_parse(FILE * spec,uint32_t * err_line,const char ** err_msg)4227 pipeline_iospec_parse(FILE *spec,
4228 uint32_t *err_line,
4229 const char **err_msg)
4230 {
4231 struct pipeline_iospec *s = NULL;
4232 uint32_t n_lines = 0;
4233
4234 /* Check the input arguments. */
4235 if (!spec) {
4236 if (err_line)
4237 *err_line = n_lines;
4238 if (err_msg)
4239 *err_msg = "Invalid input argument.";
4240 goto error;
4241 }
4242
4243 /* Memory allocation. */
4244 s = calloc(1, sizeof(struct pipeline_iospec));
4245 if (!s) {
4246 if (err_line)
4247 *err_line = n_lines;
4248 if (err_msg)
4249 *err_msg = "Memory allocation failed.";
4250 goto error;
4251 }
4252
4253 /* Initialize with the default values. */
4254 s->mirroring_params.n_slots = RTE_SWX_PACKET_MIRRORING_SLOTS_DEFAULT;
4255 s->mirroring_params.n_sessions = RTE_SWX_PACKET_MIRRORING_SESSIONS_DEFAULT;
4256
4257 for (n_lines = 1; ; n_lines++) {
4258 char line[MAX_LINE_LENGTH];
4259 char *tokens[MAX_TOKENS], *ptr = line;
4260 uint32_t n_tokens = 0;
4261
4262 /* Read next line. */
4263 if (!fgets(line, sizeof(line), spec))
4264 break;
4265
4266 /* Parse the line into tokens. */
4267 for ( ; ; ) {
4268 char *token;
4269
4270 /* Get token. */
4271 token = strtok_r(ptr, " \f\n\r\t\v", &ptr);
4272 if (!token)
4273 break;
4274
4275 /* Handle comments. */
4276 if ((token[0] == '#') ||
4277 (token[0] == ';') ||
4278 ((token[0] == '/') && (token[1] == '/'))) {
4279 break;
4280 }
4281
4282 /* Handle excessively long lines. */
4283 if (n_tokens >= RTE_DIM(tokens)) {
4284 if (err_line)
4285 *err_line = n_lines;
4286 if (err_msg)
4287 *err_msg = "Too many tokens.";
4288 goto error;
4289 }
4290
4291 /* Handle excessively long tokens. */
4292 if (strnlen(token, RTE_SWX_NAME_SIZE) >=
4293 RTE_SWX_NAME_SIZE) {
4294 if (err_line)
4295 *err_line = n_lines;
4296 if (err_msg)
4297 *err_msg = "Token too big.";
4298 goto error;
4299 }
4300
4301 /* Save token. */
4302 tokens[n_tokens] = token;
4303 n_tokens++;
4304 }
4305
4306 /* Handle empty lines. */
4307 if (!n_tokens)
4308 continue;
4309
4310 /* mirroring. */
4311 if ((n_tokens >= 1) && !strcmp(tokens[0], "mirroring")) {
4312 int status = 0;
4313
4314 status = mirroring_parse(&s->mirroring_params,
4315 &tokens[1],
4316 n_tokens - 1,
4317 err_msg);
4318 if (status) {
4319 if (err_line)
4320 *err_line = n_lines;
4321 goto error;
4322 }
4323
4324 continue;
4325 }
4326
4327 /* port in. */
4328 if ((n_tokens >= 4) && !strcmp(tokens[0], "port") && !strcmp(tokens[1], "in")) {
4329 char *token = tokens[2];
4330 uint32_t *new_id = NULL;
4331 const char **new_type = NULL, *port_type = NULL;
4332 void **new_params = NULL, *p = NULL;
4333 uint32_t port_id;
4334
4335 /* <port_id>. */
4336 port_id = strtoul(token, &token, 0);
4337 if (token[0]) {
4338 if (err_line)
4339 *err_line = n_lines;
4340 if (err_msg)
4341 *err_msg = "Invalid port ID.";
4342 goto error;
4343 }
4344
4345 /* <port_type>. */
4346 if (!strcmp(tokens[3], "ethdev"))
4347 p = port_in_ethdev_parse(&tokens[4], n_tokens - 4, err_msg);
4348 else if (!strcmp(tokens[3], "ring"))
4349 p = port_in_ring_parse(&tokens[4], n_tokens - 4, err_msg);
4350 else if (!strcmp(tokens[3], "source"))
4351 p = port_in_source_parse(&tokens[4], n_tokens - 4, err_msg);
4352 else if (!strcmp(tokens[3], "fd"))
4353 p = port_in_fd_parse(&tokens[4], n_tokens - 4, err_msg);
4354 else {
4355 p = NULL;
4356 if (err_msg)
4357 *err_msg = "Invalid port type.";
4358 }
4359
4360 if (!p) {
4361 if (err_line)
4362 *err_line = n_lines;
4363 goto error;
4364 }
4365
4366 /* New port. */
4367 port_type = strdup(tokens[3]);
4368 new_id = realloc(s->port_in_id,
4369 (s->n_ports_in + 1) * sizeof(uint32_t));
4370 new_type = realloc(s->port_in_type,
4371 (s->n_ports_in + 1) * sizeof(char *));
4372 new_params = realloc(s->port_in_params,
4373 (s->n_ports_in + 1) * sizeof(void *));
4374 if (!port_type || !new_id || !new_type || !new_params) {
4375 uintptr_t pt = (uintptr_t)port_type;
4376
4377 port_in_params_free(p, tokens[3]);
4378 free((void *)pt);
4379 free(new_id);
4380 free(new_type);
4381 free(new_params);
4382
4383 if (err_line)
4384 *err_line = n_lines;
4385 if (err_msg)
4386 *err_msg = "Memory allocation failed.";
4387 goto error;
4388 }
4389
4390 s->port_in_id = new_id;
4391 s->port_in_type = new_type;
4392 s->port_in_params = new_params;
4393
4394 s->port_in_id[s->n_ports_in] = port_id;
4395 s->port_in_type[s->n_ports_in] = port_type;
4396 s->port_in_params[s->n_ports_in] = p;
4397 s->n_ports_in++;
4398
4399 continue;
4400 }
4401
4402 /* port out. */
4403 if ((n_tokens >= 4) && !strcmp(tokens[0], "port") && !strcmp(tokens[1], "out")) {
4404 char *token = tokens[2];
4405 uint32_t *new_id = NULL;
4406 const char **new_type = NULL, *port_type = NULL;
4407 void **new_params = NULL, *p = NULL;
4408 uint32_t port_id;
4409
4410 /* <port_id>. */
4411 port_id = strtoul(token, &token, 0);
4412 if (token[0]) {
4413 if (err_line)
4414 *err_line = n_lines;
4415 if (err_msg)
4416 *err_msg = "Invalid port ID.";
4417 goto error;
4418 }
4419
4420 /* <port_type>. */
4421 if (!strcmp(tokens[3], "ethdev"))
4422 p = port_out_ethdev_parse(&tokens[4], n_tokens - 4, err_msg);
4423 else if (!strcmp(tokens[3], "ring"))
4424 p = port_out_ring_parse(&tokens[4], n_tokens - 4, err_msg);
4425 else if (!strcmp(tokens[3], "sink"))
4426 p = port_out_sink_parse(&tokens[4], n_tokens - 4, err_msg);
4427 else if (!strcmp(tokens[3], "fd"))
4428 p = port_out_fd_parse(&tokens[4], n_tokens - 4, err_msg);
4429 else {
4430 p = NULL;
4431 if (err_msg)
4432 *err_msg = "Invalid port type.";
4433 }
4434
4435 if (!p) {
4436 if (err_line)
4437 *err_line = n_lines;
4438 goto error;
4439 }
4440
4441 /* New port. */
4442 port_type = strdup(tokens[3]);
4443 new_id = realloc(s->port_out_id,
4444 (s->n_ports_out + 1) * sizeof(uint32_t));
4445 new_type = realloc(s->port_out_type,
4446 (s->n_ports_out + 1) * sizeof(char *));
4447 new_params = realloc(s->port_out_params,
4448 (s->n_ports_out + 1) * sizeof(void *));
4449 if (!port_type || !new_id || !new_type || !new_params) {
4450 uintptr_t pt = (uintptr_t)port_type;
4451
4452 port_out_params_free(p, tokens[3]);
4453 free((void *)pt);
4454 free(new_id);
4455 free(new_type);
4456 free(new_params);
4457
4458 if (err_line)
4459 *err_line = n_lines;
4460 if (err_msg)
4461 *err_msg = "Memory allocation failed.";
4462 goto error;
4463 }
4464
4465 s->port_out_id = new_id;
4466 s->port_out_type = new_type;
4467 s->port_out_params = new_params;
4468
4469 s->port_out_id[s->n_ports_out] = port_id;
4470 s->port_out_type[s->n_ports_out] = port_type;
4471 s->port_out_params[s->n_ports_out] = p;
4472 s->n_ports_out++;
4473
4474 continue;
4475 }
4476
4477 /* Anything else. */
4478 if (err_line)
4479 *err_line = n_lines;
4480 if (err_msg)
4481 *err_msg = "Unknown I/O statement.";
4482 goto error;
4483 }
4484
4485 return s;
4486
4487 error:
4488 pipeline_iospec_free(s);
4489
4490 return NULL;
4491 }
4492
4493 int
pipeline_iospec_configure(struct rte_swx_pipeline * p,struct pipeline_iospec * s,const char ** err_msg)4494 pipeline_iospec_configure(struct rte_swx_pipeline *p,
4495 struct pipeline_iospec *s,
4496 const char **err_msg)
4497 {
4498 uint32_t i;
4499 int status = 0;
4500
4501 /* Check input arguments. */
4502 if (!p || !s) {
4503 if (err_msg)
4504 *err_msg = "Invalid input argument";
4505 return -EINVAL;
4506 }
4507
4508 /* Mirroring. */
4509 status = rte_swx_pipeline_mirroring_config(p, &s->mirroring_params);
4510 if (status) {
4511 if (err_msg)
4512 *err_msg = "Pipeline mirroring configuration error.";
4513 return status;
4514 }
4515
4516 /* Input ports. */
4517 for (i = 0; i < s->n_ports_in; i++) {
4518 status = rte_swx_pipeline_port_in_config(p,
4519 i,
4520 s->port_in_type[i],
4521 s->port_in_params[i]);
4522 if (status) {
4523 if (err_msg)
4524 *err_msg = "Pipeline input port configuration error.";
4525 return status;
4526 }
4527 }
4528
4529 /* Output ports. */
4530 for (i = 0; i < s->n_ports_out; i++) {
4531 status = rte_swx_pipeline_port_out_config(p,
4532 i,
4533 s->port_out_type[i],
4534 s->port_out_params[i]);
4535 if (status) {
4536 if (err_msg)
4537 *err_msg = "Pipeline output port configuration error.";
4538 return status;
4539 }
4540 }
4541
4542 return 0;
4543 }
4544