1
2
3
4#include <stdint.h>
5#include <stdlib.h>
6#include <stdio.h>
7#include <string.h>
8#include <errno.h>
9
10#include "rte_swx_pipeline.h"
11#include "rte_swx_ctl.h"
12
13#define MAX_LINE_LENGTH RTE_SWX_INSTRUCTION_SIZE
14#define MAX_TOKENS RTE_SWX_INSTRUCTION_TOKENS_MAX
15
16#define STRUCT_BLOCK 0
17#define ACTION_BLOCK 1
18#define TABLE_BLOCK 2
19#define TABLE_KEY_BLOCK 3
20#define TABLE_ACTIONS_BLOCK 4
21#define APPLY_BLOCK 5
22
23
24
25
26
27
28struct extobj_spec {
29 char *name;
30 char *extern_type_name;
31 char *pragma;
32};
33
34static void
35extobj_spec_free(struct extobj_spec *s)
36{
37 if (!s)
38 return;
39
40 free(s->name);
41 s->name = NULL;
42
43 free(s->extern_type_name);
44 s->extern_type_name = NULL;
45
46 free(s->pragma);
47 s->pragma = NULL;
48}
49
50static int
51extobj_statement_parse(struct extobj_spec *s,
52 char **tokens,
53 uint32_t n_tokens,
54 uint32_t n_lines,
55 uint32_t *err_line,
56 const char **err_msg)
57{
58
59 if (((n_tokens != 4) && (n_tokens != 6)) ||
60 ((n_tokens == 4) && strcmp(tokens[2], "instanceof")) ||
61 ((n_tokens == 6) && (strcmp(tokens[2], "instanceof") ||
62 strcmp(tokens[4], "pragma")))) {
63 if (err_line)
64 *err_line = n_lines;
65 if (err_msg)
66 *err_msg = "Invalid extobj statement.";
67 return -EINVAL;
68 }
69
70
71 s->name = strdup(tokens[1]);
72 s->extern_type_name = strdup(tokens[3]);
73 s->pragma = (n_tokens == 6) ? strdup(tokens[5]) : NULL;
74
75 if (!s->name ||
76 !s->extern_type_name ||
77 ((n_tokens == 6) && !s->pragma)) {
78 free(s->name);
79 free(s->extern_type_name);
80 free(s->pragma);
81
82 if (err_line)
83 *err_line = n_lines;
84 if (err_msg)
85 *err_msg = "Memory allocation failed.";
86 return -ENOMEM;
87 }
88
89 return 0;
90}
91
92
93
94
95
96
97
98
99
100struct struct_spec {
101 char *name;
102 struct rte_swx_field_params *fields;
103 uint32_t n_fields;
104};
105
106static void
107struct_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
129static int
130struct_statement_parse(struct struct_spec *s,
131 uint32_t *block_mask,
132 char **tokens,
133 uint32_t n_tokens,
134 uint32_t n_lines,
135 uint32_t *err_line,
136 const char **err_msg)
137{
138
139 if ((n_tokens != 3) || strcmp(tokens[2], "{")) {
140 if (err_line)
141 *err_line = n_lines;
142 if (err_msg)
143 *err_msg = "Invalid struct statement.";
144 return -EINVAL;
145 }
146
147
148 s->name = strdup(tokens[1]);
149 if (!s->name) {
150 if (err_line)
151 *err_line = n_lines;
152 if (err_msg)
153 *err_msg = "Memory allocation failed.";
154 return -ENOMEM;
155 }
156
157
158 *block_mask |= 1 << STRUCT_BLOCK;
159
160 return 0;
161}
162
163static int
164struct_block_parse(struct struct_spec *s,
165 uint32_t *block_mask,
166 char **tokens,
167 uint32_t n_tokens,
168 uint32_t n_lines,
169 uint32_t *err_line,
170 const char **err_msg)
171{
172 struct rte_swx_field_params *new_fields;
173 char *p = tokens[0], *name;
174 uint32_t n_bits;
175
176
177 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
178 *block_mask &= ~(1 << STRUCT_BLOCK);
179 return 0;
180 }
181
182
183 if ((n_tokens != 2) ||
184 (strlen(p) < 6) ||
185 (p[0] != 'b') ||
186 (p[1] != 'i') ||
187 (p[2] != 't') ||
188 (p[3] != '<') ||
189 (p[strlen(p) - 1] != '>')) {
190 if (err_line)
191 *err_line = n_lines;
192 if (err_msg)
193 *err_msg = "Invalid struct field statement.";
194 return -EINVAL;
195 }
196
197
198 p[strlen(p) - 1] = 0;
199 p += 4;
200
201 n_bits = strtoul(p, &p, 0);
202 if ((p[0]) ||
203 !n_bits ||
204 (n_bits % 8) ||
205 (n_bits > 64)) {
206 if (err_line)
207 *err_line = n_lines;
208 if (err_msg)
209 *err_msg = "Invalid struct field size.";
210 return -EINVAL;
211 }
212
213
214 name = strdup(tokens[1]);
215 if (!name) {
216 if (err_line)
217 *err_line = n_lines;
218 if (err_msg)
219 *err_msg = "Memory allocation failed.";
220 return -ENOMEM;
221 }
222
223 new_fields = realloc(s->fields,
224 (s->n_fields + 1) * sizeof(struct rte_swx_field_params));
225 if (!new_fields) {
226 free(name);
227
228 if (err_line)
229 *err_line = n_lines;
230 if (err_msg)
231 *err_msg = "Memory allocation failed.";
232 return -ENOMEM;
233 }
234
235 s->fields = new_fields;
236 s->fields[s->n_fields].name = name;
237 s->fields[s->n_fields].n_bits = n_bits;
238 s->n_fields++;
239
240 return 0;
241}
242
243
244
245
246
247
248struct header_spec {
249 char *name;
250 char *struct_type_name;
251};
252
253static void
254header_spec_free(struct header_spec *s)
255{
256 if (!s)
257 return;
258
259 free(s->name);
260 s->name = NULL;
261
262 free(s->struct_type_name);
263 s->struct_type_name = NULL;
264}
265
266static int
267header_statement_parse(struct header_spec *s,
268 char **tokens,
269 uint32_t n_tokens,
270 uint32_t n_lines,
271 uint32_t *err_line,
272 const char **err_msg)
273{
274
275 if ((n_tokens != 4) || strcmp(tokens[2], "instanceof")) {
276 if (err_line)
277 *err_line = n_lines;
278 if (err_msg)
279 *err_msg = "Invalid header statement.";
280 return -EINVAL;
281 }
282
283
284 s->name = strdup(tokens[1]);
285 s->struct_type_name = strdup(tokens[3]);
286
287 if (!s->name || !s->struct_type_name) {
288 free(s->name);
289 free(s->struct_type_name);
290
291 if (err_line)
292 *err_line = n_lines;
293 if (err_msg)
294 *err_msg = "Memory allocation failed.";
295 return -ENOMEM;
296 }
297
298 return 0;
299}
300
301
302
303
304
305
306struct metadata_spec {
307 char *struct_type_name;
308};
309
310static void
311metadata_spec_free(struct metadata_spec *s)
312{
313 if (!s)
314 return;
315
316 free(s->struct_type_name);
317 s->struct_type_name = NULL;
318}
319
320static int
321metadata_statement_parse(struct metadata_spec *s,
322 char **tokens,
323 uint32_t n_tokens,
324 uint32_t n_lines,
325 uint32_t *err_line,
326 const char **err_msg)
327{
328
329 if ((n_tokens != 3) || strcmp(tokens[1], "instanceof")) {
330 if (err_line)
331 *err_line = n_lines;
332 if (err_msg)
333 *err_msg = "Invalid metadata statement.";
334 return -EINVAL;
335 }
336
337
338 s->struct_type_name = strdup(tokens[2]);
339 if (!s->struct_type_name) {
340 if (err_line)
341 *err_line = n_lines;
342 if (err_msg)
343 *err_msg = "Memory allocation failed.";
344 return -ENOMEM;
345 }
346
347 return 0;
348}
349
350
351
352
353
354
355
356
357
358struct action_spec {
359 char *name;
360 char *args_struct_type_name;
361 const char **instructions;
362 uint32_t n_instructions;
363};
364
365static void
366action_spec_free(struct action_spec *s)
367{
368 uint32_t i;
369
370 if (!s)
371 return;
372
373 free(s->name);
374 s->name = NULL;
375
376 free(s->args_struct_type_name);
377 s->args_struct_type_name = NULL;
378
379 for (i = 0; i < s->n_instructions; i++) {
380 uintptr_t instr = (uintptr_t)s->instructions[i];
381
382 free((void *)instr);
383 }
384
385 free(s->instructions);
386 s->instructions = NULL;
387
388 s->n_instructions = 0;
389}
390
391static int
392action_statement_parse(struct action_spec *s,
393 uint32_t *block_mask,
394 char **tokens,
395 uint32_t n_tokens,
396 uint32_t n_lines,
397 uint32_t *err_line,
398 const char **err_msg)
399{
400
401 if (((n_tokens != 5) && (n_tokens != 6)) ||
402 ((n_tokens == 5) &&
403 (strcmp(tokens[2], "args") ||
404 strcmp(tokens[3], "none") ||
405 strcmp(tokens[4], "{"))) ||
406 ((n_tokens == 6) &&
407 (strcmp(tokens[2], "args") ||
408 strcmp(tokens[3], "instanceof") ||
409 strcmp(tokens[5], "{")))) {
410 if (err_line)
411 *err_line = n_lines;
412 if (err_msg)
413 *err_msg = "Invalid action statement.";
414 return -EINVAL;
415 }
416
417
418 s->name = strdup(tokens[1]);
419 s->args_struct_type_name = (n_tokens == 6) ? strdup(tokens[4]) : NULL;
420
421 if ((!s->name) || ((n_tokens == 6) && !s->args_struct_type_name)) {
422 if (err_line)
423 *err_line = n_lines;
424 if (err_msg)
425 *err_msg = "Memory allocation failed.";
426 return -ENOMEM;
427 }
428
429
430 *block_mask |= 1 << ACTION_BLOCK;
431
432 return 0;
433}
434
435static int
436action_block_parse(struct action_spec *s,
437 uint32_t *block_mask,
438 char **tokens,
439 uint32_t n_tokens,
440 uint32_t n_lines,
441 uint32_t *err_line,
442 const char **err_msg)
443{
444 char buffer[RTE_SWX_INSTRUCTION_SIZE], *instr;
445 const char **new_instructions;
446 uint32_t i;
447
448
449 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
450 *block_mask &= ~(1 << ACTION_BLOCK);
451 return 0;
452 }
453
454
455 buffer[0] = 0;
456 for (i = 0; i < n_tokens; i++) {
457 if (i)
458 strcat(buffer, " ");
459 strcat(buffer, tokens[i]);
460 }
461
462 instr = strdup(buffer);
463 if (!instr) {
464 if (err_line)
465 *err_line = n_lines;
466 if (err_msg)
467 *err_msg = "Memory allocation failed.";
468 return -ENOMEM;
469 }
470
471 new_instructions = realloc(s->instructions,
472 (s->n_instructions + 1) * sizeof(char *));
473 if (!new_instructions) {
474 free(instr);
475
476 if (err_line)
477 *err_line = n_lines;
478 if (err_msg)
479 *err_msg = "Memory allocation failed.";
480 return -ENOMEM;
481 }
482
483 s->instructions = new_instructions;
484 s->instructions[s->n_instructions] = instr;
485 s->n_instructions++;
486
487 return 0;
488}
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508struct table_spec {
509 char *name;
510 struct rte_swx_pipeline_table_params params;
511 char *recommended_table_type_name;
512 char *args;
513 uint32_t size;
514};
515
516static void
517table_spec_free(struct table_spec *s)
518{
519 uintptr_t default_action_name;
520 uint32_t i;
521
522 if (!s)
523 return;
524
525 free(s->name);
526 s->name = NULL;
527
528 for (i = 0; i < s->params.n_fields; i++) {
529 uintptr_t name = (uintptr_t)s->params.fields[i].name;
530
531 free((void *)name);
532 }
533
534 free(s->params.fields);
535 s->params.fields = NULL;
536
537 s->params.n_fields = 0;
538
539 for (i = 0; i < s->params.n_actions; i++) {
540 uintptr_t name = (uintptr_t)s->params.action_names[i];
541
542 free((void *)name);
543 }
544
545 free(s->params.action_names);
546 s->params.action_names = NULL;
547
548 s->params.n_actions = 0;
549
550 default_action_name = (uintptr_t)s->params.default_action_name;
551 free((void *)default_action_name);
552 s->params.default_action_name = NULL;
553
554 free(s->params.default_action_data);
555 s->params.default_action_data = NULL;
556
557 s->params.default_action_is_const = 0;
558
559 free(s->recommended_table_type_name);
560 s->recommended_table_type_name = NULL;
561
562 free(s->args);
563 s->args = NULL;
564
565 s->size = 0;
566}
567
568static int
569table_key_statement_parse(uint32_t *block_mask,
570 char **tokens,
571 uint32_t n_tokens,
572 uint32_t n_lines,
573 uint32_t *err_line,
574 const char **err_msg)
575{
576
577 if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
578 if (err_line)
579 *err_line = n_lines;
580 if (err_msg)
581 *err_msg = "Invalid key statement.";
582 return -EINVAL;
583 }
584
585
586 *block_mask |= 1 << TABLE_KEY_BLOCK;
587
588 return 0;
589}
590
591static int
592table_key_block_parse(struct table_spec *s,
593 uint32_t *block_mask,
594 char **tokens,
595 uint32_t n_tokens,
596 uint32_t n_lines,
597 uint32_t *err_line,
598 const char **err_msg)
599{
600 struct rte_swx_match_field_params *new_fields;
601 enum rte_swx_table_match_type match_type = RTE_SWX_TABLE_MATCH_WILDCARD;
602 char *name;
603
604
605 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
606 *block_mask &= ~(1 << TABLE_KEY_BLOCK);
607 return 0;
608 }
609
610
611 if ((n_tokens != 2) ||
612 (strcmp(tokens[1], "exact") &&
613 strcmp(tokens[1], "wildcard") &&
614 strcmp(tokens[1], "lpm"))) {
615 if (err_line)
616 *err_line = n_lines;
617 if (err_msg)
618 *err_msg = "Invalid match field statement.";
619 return -EINVAL;
620 }
621
622 if (!strcmp(tokens[1], "wildcard"))
623 match_type = RTE_SWX_TABLE_MATCH_WILDCARD;
624 if (!strcmp(tokens[1], "lpm"))
625 match_type = RTE_SWX_TABLE_MATCH_LPM;
626 if (!strcmp(tokens[1], "exact"))
627 match_type = RTE_SWX_TABLE_MATCH_EXACT;
628
629 name = strdup(tokens[0]);
630 if (!name) {
631 if (err_line)
632 *err_line = n_lines;
633 if (err_msg)
634 *err_msg = "Memory allocation failed.";
635 return -ENOMEM;
636 }
637
638 new_fields = realloc(s->params.fields,
639 (s->params.n_fields + 1) * sizeof(struct rte_swx_match_field_params));
640 if (!new_fields) {
641 free(name);
642
643 if (err_line)
644 *err_line = n_lines;
645 if (err_msg)
646 *err_msg = "Memory allocation failed.";
647 return -ENOMEM;
648 }
649
650 s->params.fields = new_fields;
651 s->params.fields[s->params.n_fields].name = name;
652 s->params.fields[s->params.n_fields].match_type = match_type;
653 s->params.n_fields++;
654
655 return 0;
656}
657
658static int
659table_actions_statement_parse(uint32_t *block_mask,
660 char **tokens,
661 uint32_t n_tokens,
662 uint32_t n_lines,
663 uint32_t *err_line,
664 const char **err_msg)
665{
666
667 if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
668 if (err_line)
669 *err_line = n_lines;
670 if (err_msg)
671 *err_msg = "Invalid actions statement.";
672 return -EINVAL;
673 }
674
675
676 *block_mask |= 1 << TABLE_ACTIONS_BLOCK;
677
678 return 0;
679}
680
681static int
682table_actions_block_parse(struct table_spec *s,
683 uint32_t *block_mask,
684 char **tokens,
685 uint32_t n_tokens,
686 uint32_t n_lines,
687 uint32_t *err_line,
688 const char **err_msg)
689{
690 const char **new_action_names;
691 char *name;
692
693
694 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
695 *block_mask &= ~(1 << TABLE_ACTIONS_BLOCK);
696 return 0;
697 }
698
699
700 if (n_tokens != 1) {
701 if (err_line)
702 *err_line = n_lines;
703 if (err_msg)
704 *err_msg = "Invalid action name statement.";
705 return -EINVAL;
706 }
707
708 name = strdup(tokens[0]);
709 if (!name) {
710 if (err_line)
711 *err_line = n_lines;
712 if (err_msg)
713 *err_msg = "Memory allocation failed.";
714 return -ENOMEM;
715 }
716
717 new_action_names = realloc(s->params.action_names,
718 (s->params.n_actions + 1) * sizeof(char *));
719 if (!new_action_names) {
720 free(name);
721
722 if (err_line)
723 *err_line = n_lines;
724 if (err_msg)
725 *err_msg = "Memory allocation failed.";
726 return -ENOMEM;
727 }
728
729 s->params.action_names = new_action_names;
730 s->params.action_names[s->params.n_actions] = name;
731 s->params.n_actions++;
732
733 return 0;
734}
735
736static int
737table_statement_parse(struct table_spec *s,
738 uint32_t *block_mask,
739 char **tokens,
740 uint32_t n_tokens,
741 uint32_t n_lines,
742 uint32_t *err_line,
743 const char **err_msg)
744{
745
746 if ((n_tokens != 3) || strcmp(tokens[2], "{")) {
747 if (err_line)
748 *err_line = n_lines;
749 if (err_msg)
750 *err_msg = "Invalid table statement.";
751 return -EINVAL;
752 }
753
754
755 s->name = strdup(tokens[1]);
756 if (!s->name) {
757 if (err_line)
758 *err_line = n_lines;
759 if (err_msg)
760 *err_msg = "Memory allocation failed.";
761 return -ENOMEM;
762 }
763
764
765 *block_mask |= 1 << TABLE_BLOCK;
766
767 return 0;
768}
769
770static int
771table_block_parse(struct table_spec *s,
772 uint32_t *block_mask,
773 char **tokens,
774 uint32_t n_tokens,
775 uint32_t n_lines,
776 uint32_t *err_line,
777 const char **err_msg)
778{
779 if (*block_mask & (1 << TABLE_KEY_BLOCK))
780 return table_key_block_parse(s,
781 block_mask,
782 tokens,
783 n_tokens,
784 n_lines,
785 err_line,
786 err_msg);
787
788 if (*block_mask & (1 << TABLE_ACTIONS_BLOCK))
789 return table_actions_block_parse(s,
790 block_mask,
791 tokens,
792 n_tokens,
793 n_lines,
794 err_line,
795 err_msg);
796
797
798 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
799 *block_mask &= ~(1 << TABLE_BLOCK);
800 return 0;
801 }
802
803 if (!strcmp(tokens[0], "key"))
804 return table_key_statement_parse(block_mask,
805 tokens,
806 n_tokens,
807 n_lines,
808 err_line,
809 err_msg);
810
811 if (!strcmp(tokens[0], "actions"))
812 return table_actions_statement_parse(block_mask,
813 tokens,
814 n_tokens,
815 n_lines,
816 err_line,
817 err_msg);
818
819 if (!strcmp(tokens[0], "default_action")) {
820 if (((n_tokens != 4) && (n_tokens != 5)) ||
821 strcmp(tokens[2], "args") ||
822 strcmp(tokens[3], "none") ||
823 ((n_tokens == 5) && strcmp(tokens[4], "const"))) {
824 if (err_line)
825 *err_line = n_lines;
826 if (err_msg)
827 *err_msg = "Invalid default_action statement.";
828 return -EINVAL;
829 }
830
831 if (s->params.default_action_name) {
832 if (err_line)
833 *err_line = n_lines;
834 if (err_msg)
835 *err_msg = "Duplicate default_action stmt.";
836 return -EINVAL;
837 }
838
839 s->params.default_action_name = strdup(tokens[1]);
840 if (!s->params.default_action_name) {
841 if (err_line)
842 *err_line = n_lines;
843 if (err_msg)
844 *err_msg = "Memory allocation failed.";
845 return -ENOMEM;
846 }
847
848 if (n_tokens == 5)
849 s->params.default_action_is_const = 1;
850
851 return 0;
852 }
853
854 if (!strcmp(tokens[0], "instanceof")) {
855 if (n_tokens != 2) {
856 if (err_line)
857 *err_line = n_lines;
858 if (err_msg)
859 *err_msg = "Invalid instanceof statement.";
860 return -EINVAL;
861 }
862
863 if (s->recommended_table_type_name) {
864 if (err_line)
865 *err_line = n_lines;
866 if (err_msg)
867 *err_msg = "Duplicate instanceof statement.";
868 return -EINVAL;
869 }
870
871 s->recommended_table_type_name = strdup(tokens[1]);
872 if (!s->recommended_table_type_name) {
873 if (err_line)
874 *err_line = n_lines;
875 if (err_msg)
876 *err_msg = "Memory allocation failed.";
877 return -ENOMEM;
878 }
879
880 return 0;
881 }
882
883 if (!strcmp(tokens[0], "pragma")) {
884 if (n_tokens != 2) {
885 if (err_line)
886 *err_line = n_lines;
887 if (err_msg)
888 *err_msg = "Invalid pragma statement.";
889 return -EINVAL;
890 }
891
892 if (s->args) {
893 if (err_line)
894 *err_line = n_lines;
895 if (err_msg)
896 *err_msg = "Duplicate pragma statement.";
897 return -EINVAL;
898 }
899
900 s->args = strdup(tokens[1]);
901 if (!s->args) {
902 if (err_line)
903 *err_line = n_lines;
904 if (err_msg)
905 *err_msg = "Memory allocation failed.";
906 return -ENOMEM;
907 }
908
909 return 0;
910 }
911
912 if (!strcmp(tokens[0], "size")) {
913 char *p = tokens[1];
914
915 if (n_tokens != 2) {
916 if (err_line)
917 *err_line = n_lines;
918 if (err_msg)
919 *err_msg = "Invalid pragma statement.";
920 return -EINVAL;
921 }
922
923 s->size = strtoul(p, &p, 0);
924 if (p[0]) {
925 if (err_line)
926 *err_line = n_lines;
927 if (err_msg)
928 *err_msg = "Invalid size argument.";
929 return -EINVAL;
930 }
931
932 return 0;
933 }
934
935
936 if (err_line)
937 *err_line = n_lines;
938 if (err_msg)
939 *err_msg = "Invalid statement.";
940 return -EINVAL;
941}
942
943
944
945
946
947
948
949
950
951struct apply_spec {
952 const char **instructions;
953 uint32_t n_instructions;
954};
955
956static void
957apply_spec_free(struct apply_spec *s)
958{
959 uint32_t i;
960
961 if (!s)
962 return;
963
964 for (i = 0; i < s->n_instructions; i++) {
965 uintptr_t instr = (uintptr_t)s->instructions[i];
966
967 free((void *)instr);
968 }
969
970 free(s->instructions);
971 s->instructions = NULL;
972
973 s->n_instructions = 0;
974}
975
976static int
977apply_statement_parse(uint32_t *block_mask,
978 char **tokens,
979 uint32_t n_tokens,
980 uint32_t n_lines,
981 uint32_t *err_line,
982 const char **err_msg)
983{
984
985 if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
986 if (err_line)
987 *err_line = n_lines;
988 if (err_msg)
989 *err_msg = "Invalid apply statement.";
990 return -EINVAL;
991 }
992
993
994 *block_mask |= 1 << APPLY_BLOCK;
995
996 return 0;
997}
998
999static int
1000apply_block_parse(struct apply_spec *s,
1001 uint32_t *block_mask,
1002 char **tokens,
1003 uint32_t n_tokens,
1004 uint32_t n_lines,
1005 uint32_t *err_line,
1006 const char **err_msg)
1007{
1008 char buffer[RTE_SWX_INSTRUCTION_SIZE], *instr;
1009 const char **new_instructions;
1010 uint32_t i;
1011
1012
1013 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1014 *block_mask &= ~(1 << APPLY_BLOCK);
1015 return 0;
1016 }
1017
1018
1019 buffer[0] = 0;
1020 for (i = 0; i < n_tokens; i++) {
1021 if (i)
1022 strcat(buffer, " ");
1023 strcat(buffer, tokens[i]);
1024 }
1025
1026 instr = strdup(buffer);
1027 if (!instr) {
1028 if (err_line)
1029 *err_line = n_lines;
1030 if (err_msg)
1031 *err_msg = "Memory allocation failed.";
1032 return -ENOMEM;
1033 }
1034
1035 new_instructions = realloc(s->instructions,
1036 (s->n_instructions + 1) * sizeof(char *));
1037 if (!new_instructions) {
1038 free(instr);
1039
1040 if (err_line)
1041 *err_line = n_lines;
1042 if (err_msg)
1043 *err_msg = "Memory allocation failed.";
1044 return -ENOMEM;
1045 }
1046
1047 s->instructions = new_instructions;
1048 s->instructions[s->n_instructions] = instr;
1049 s->n_instructions++;
1050
1051 return 0;
1052}
1053
1054
1055
1056
1057int
1058rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
1059 FILE *spec,
1060 uint32_t *err_line,
1061 const char **err_msg)
1062{
1063 struct extobj_spec extobj_spec = {0};
1064 struct struct_spec struct_spec = {0};
1065 struct header_spec header_spec = {0};
1066 struct metadata_spec metadata_spec = {0};
1067 struct action_spec action_spec = {0};
1068 struct table_spec table_spec = {0};
1069 struct apply_spec apply_spec = {0};
1070 uint32_t n_lines;
1071 uint32_t block_mask = 0;
1072 int status;
1073
1074
1075 if (!p) {
1076 if (err_line)
1077 *err_line = 0;
1078 if (err_msg)
1079 *err_msg = "Null pipeline arument.";
1080 status = -EINVAL;
1081 goto error;
1082 }
1083
1084 if (!spec) {
1085 if (err_line)
1086 *err_line = 0;
1087 if (err_msg)
1088 *err_msg = "Null specification file argument.";
1089 status = -EINVAL;
1090 goto error;
1091 }
1092
1093 for (n_lines = 1; ; n_lines++) {
1094 char line[MAX_LINE_LENGTH];
1095 char *tokens[MAX_TOKENS], *ptr = line;
1096 uint32_t n_tokens = 0;
1097
1098
1099 if (!fgets(line, sizeof(line), spec))
1100 break;
1101
1102
1103 for ( ; ; ) {
1104 char *token;
1105
1106
1107 token = strtok_r(ptr, " \f\n\r\t\v", &ptr);
1108 if (!token)
1109 break;
1110
1111
1112 if ((token[0] == '#') ||
1113 (token[0] == ';') ||
1114 ((token[0] == '/') && (token[1] == '/'))) {
1115 break;
1116 }
1117
1118
1119 if (n_tokens >= MAX_TOKENS) {
1120 if (err_line)
1121 *err_line = n_lines;
1122 if (err_msg)
1123 *err_msg = "Too many tokens.";
1124 status = -EINVAL;
1125 goto error;
1126 }
1127
1128
1129 if (strnlen(token, RTE_SWX_NAME_SIZE) >=
1130 RTE_SWX_NAME_SIZE) {
1131 if (err_line)
1132 *err_line = n_lines;
1133 if (err_msg)
1134 *err_msg = "Token too big.";
1135 status = -EINVAL;
1136 goto error;
1137 }
1138
1139
1140 tokens[n_tokens] = token;
1141 n_tokens++;
1142 }
1143
1144
1145 if (!n_tokens)
1146 continue;
1147
1148
1149 if (block_mask & (1 << STRUCT_BLOCK)) {
1150 status = struct_block_parse(&struct_spec,
1151 &block_mask,
1152 tokens,
1153 n_tokens,
1154 n_lines,
1155 err_line,
1156 err_msg);
1157 if (status)
1158 goto error;
1159
1160 if (block_mask & (1 << STRUCT_BLOCK))
1161 continue;
1162
1163
1164 status = rte_swx_pipeline_struct_type_register(p,
1165 struct_spec.name,
1166 struct_spec.fields,
1167 struct_spec.n_fields);
1168 if (status) {
1169 if (err_line)
1170 *err_line = n_lines;
1171 if (err_msg)
1172 *err_msg = "Struct registration error.";
1173 goto error;
1174 }
1175
1176 struct_spec_free(&struct_spec);
1177
1178 continue;
1179 }
1180
1181
1182 if (block_mask & (1 << ACTION_BLOCK)) {
1183 status = action_block_parse(&action_spec,
1184 &block_mask,
1185 tokens,
1186 n_tokens,
1187 n_lines,
1188 err_line,
1189 err_msg);
1190 if (status)
1191 goto error;
1192
1193 if (block_mask & (1 << ACTION_BLOCK))
1194 continue;
1195
1196
1197 status = rte_swx_pipeline_action_config(p,
1198 action_spec.name,
1199 action_spec.args_struct_type_name,
1200 action_spec.instructions,
1201 action_spec.n_instructions);
1202 if (status) {
1203 if (err_line)
1204 *err_line = n_lines;
1205 if (err_msg)
1206 *err_msg = "Action config error.";
1207 goto error;
1208 }
1209
1210 action_spec_free(&action_spec);
1211
1212 continue;
1213 }
1214
1215
1216 if (block_mask & (1 << TABLE_BLOCK)) {
1217 status = table_block_parse(&table_spec,
1218 &block_mask,
1219 tokens,
1220 n_tokens,
1221 n_lines,
1222 err_line,
1223 err_msg);
1224 if (status)
1225 goto error;
1226
1227 if (block_mask & (1 << TABLE_BLOCK))
1228 continue;
1229
1230
1231 status = rte_swx_pipeline_table_config(p,
1232 table_spec.name,
1233 &table_spec.params,
1234 table_spec.recommended_table_type_name,
1235 table_spec.args,
1236 table_spec.size);
1237 if (status) {
1238 if (err_line)
1239 *err_line = n_lines;
1240 if (err_msg)
1241 *err_msg = "Table configuration error.";
1242 goto error;
1243 }
1244
1245 table_spec_free(&table_spec);
1246
1247 continue;
1248 }
1249
1250
1251 if (block_mask & (1 << APPLY_BLOCK)) {
1252 status = apply_block_parse(&apply_spec,
1253 &block_mask,
1254 tokens,
1255 n_tokens,
1256 n_lines,
1257 err_line,
1258 err_msg);
1259 if (status)
1260 goto error;
1261
1262 if (block_mask & (1 << APPLY_BLOCK))
1263 continue;
1264
1265
1266 status = rte_swx_pipeline_instructions_config(p,
1267 apply_spec.instructions,
1268 apply_spec.n_instructions);
1269 if (status) {
1270 if (err_line)
1271 *err_line = n_lines;
1272 if (err_msg)
1273 *err_msg = "Pipeline instructions err.";
1274 goto error;
1275 }
1276
1277 apply_spec_free(&apply_spec);
1278
1279 continue;
1280 }
1281
1282
1283 if (!strcmp(tokens[0], "extobj")) {
1284 status = extobj_statement_parse(&extobj_spec,
1285 tokens,
1286 n_tokens,
1287 n_lines,
1288 err_line,
1289 err_msg);
1290 if (status)
1291 goto error;
1292
1293 status = rte_swx_pipeline_extern_object_config(p,
1294 extobj_spec.name,
1295 extobj_spec.extern_type_name,
1296 extobj_spec.pragma);
1297 if (status) {
1298 if (err_line)
1299 *err_line = n_lines;
1300 if (err_msg)
1301 *err_msg = "Extern object config err.";
1302 goto error;
1303 }
1304
1305 extobj_spec_free(&extobj_spec);
1306
1307 continue;
1308 }
1309
1310
1311 if (!strcmp(tokens[0], "struct")) {
1312 status = struct_statement_parse(&struct_spec,
1313 &block_mask,
1314 tokens,
1315 n_tokens,
1316 n_lines,
1317 err_line,
1318 err_msg);
1319 if (status)
1320 goto error;
1321
1322 continue;
1323 }
1324
1325
1326 if (!strcmp(tokens[0], "header")) {
1327 status = header_statement_parse(&header_spec,
1328 tokens,
1329 n_tokens,
1330 n_lines,
1331 err_line,
1332 err_msg);
1333 if (status)
1334 goto error;
1335
1336 status = rte_swx_pipeline_packet_header_register(p,
1337 header_spec.name,
1338 header_spec.struct_type_name);
1339 if (status) {
1340 if (err_line)
1341 *err_line = n_lines;
1342 if (err_msg)
1343 *err_msg = "Header registration error.";
1344 goto error;
1345 }
1346
1347 header_spec_free(&header_spec);
1348
1349 continue;
1350 }
1351
1352
1353 if (!strcmp(tokens[0], "metadata")) {
1354 status = metadata_statement_parse(&metadata_spec,
1355 tokens,
1356 n_tokens,
1357 n_lines,
1358 err_line,
1359 err_msg);
1360 if (status)
1361 goto error;
1362
1363 status = rte_swx_pipeline_packet_metadata_register(p,
1364 metadata_spec.struct_type_name);
1365 if (status) {
1366 if (err_line)
1367 *err_line = n_lines;
1368 if (err_msg)
1369 *err_msg = "Meta-data reg err.";
1370 goto error;
1371 }
1372
1373 metadata_spec_free(&metadata_spec);
1374
1375 continue;
1376 }
1377
1378
1379 if (!strcmp(tokens[0], "action")) {
1380 status = action_statement_parse(&action_spec,
1381 &block_mask,
1382 tokens,
1383 n_tokens,
1384 n_lines,
1385 err_line,
1386 err_msg);
1387 if (status)
1388 goto error;
1389
1390 continue;
1391 }
1392
1393
1394 if (!strcmp(tokens[0], "table")) {
1395 status = table_statement_parse(&table_spec,
1396 &block_mask,
1397 tokens,
1398 n_tokens,
1399 n_lines,
1400 err_line,
1401 err_msg);
1402 if (status)
1403 goto error;
1404
1405 continue;
1406 }
1407
1408
1409 if (!strcmp(tokens[0], "apply")) {
1410 status = apply_statement_parse(&block_mask,
1411 tokens,
1412 n_tokens,
1413 n_lines,
1414 err_line,
1415 err_msg);
1416 if (status)
1417 goto error;
1418
1419 continue;
1420 }
1421
1422
1423 if (err_line)
1424 *err_line = n_lines;
1425 if (err_msg)
1426 *err_msg = "Unknown statement.";
1427 status = -EINVAL;
1428 goto error;
1429 }
1430
1431
1432 if (block_mask) {
1433 if (err_line)
1434 *err_line = n_lines;
1435 if (err_msg)
1436 *err_msg = "Missing }.";
1437 status = -EINVAL;
1438 goto error;
1439 }
1440
1441
1442 status = rte_swx_pipeline_build(p);
1443 if (status) {
1444 if (err_line)
1445 *err_line = n_lines;
1446 if (err_msg)
1447 *err_msg = "Pipeline build error.";
1448 goto error;
1449 }
1450
1451 return 0;
1452
1453error:
1454 extobj_spec_free(&extobj_spec);
1455 struct_spec_free(&struct_spec);
1456 header_spec_free(&header_spec);
1457 metadata_spec_free(&metadata_spec);
1458 action_spec_free(&action_spec);
1459 table_spec_free(&table_spec);
1460 apply_spec_free(&apply_spec);
1461 return status;
1462}
1463