c57893f18c45ab7bbf24b8612a85176bf7d7d220
[dpdk.git] / lib / pipeline / rte_swx_pipeline_spec.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2020 Intel Corporation
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 SELECTOR_BLOCK 5
22 #define SELECTOR_SELECTOR_BLOCK 6
23 #define APPLY_BLOCK 7
24
25 /*
26  * extobj.
27  *
28  * extobj OBJ_NAME instanceof OBJ_TYPE [ pragma OBJ_CREATE_ARGS ]
29  */
30 struct extobj_spec {
31         char *name;
32         char *extern_type_name;
33         char *pragma;
34 };
35
36 static void
37 extobj_spec_free(struct extobj_spec *s)
38 {
39         if (!s)
40                 return;
41
42         free(s->name);
43         s->name = NULL;
44
45         free(s->extern_type_name);
46         s->extern_type_name = NULL;
47
48         free(s->pragma);
49         s->pragma = NULL;
50 }
51
52 static int
53 extobj_statement_parse(struct extobj_spec *s,
54                        char **tokens,
55                        uint32_t n_tokens,
56                        uint32_t n_lines,
57                        uint32_t *err_line,
58                        const char **err_msg)
59 {
60         /* Check format. */
61         if (((n_tokens != 4) && (n_tokens != 6)) ||
62             ((n_tokens == 4) && strcmp(tokens[2], "instanceof")) ||
63             ((n_tokens == 6) && (strcmp(tokens[2], "instanceof") ||
64                                  strcmp(tokens[4], "pragma")))) {
65                 if (err_line)
66                         *err_line = n_lines;
67                 if (err_msg)
68                         *err_msg = "Invalid extobj statement.";
69                 return -EINVAL;
70         }
71
72         /* spec. */
73         s->name = strdup(tokens[1]);
74         s->extern_type_name = strdup(tokens[3]);
75         s->pragma = (n_tokens == 6) ? strdup(tokens[5]) : NULL;
76
77         if (!s->name ||
78             !s->extern_type_name ||
79             ((n_tokens == 6) && !s->pragma)) {
80                 free(s->name);
81                 free(s->extern_type_name);
82                 free(s->pragma);
83
84                 if (err_line)
85                         *err_line = n_lines;
86                 if (err_msg)
87                         *err_msg = "Memory allocation failed.";
88                 return -ENOMEM;
89         }
90
91         return 0;
92 }
93
94 /*
95  * struct.
96  *
97  * struct STRUCT_TYPE_NAME {
98  *      bit<SIZE> | varbit<SIZE> FIELD_NAME
99  *      ...
100  * }
101  */
102 struct struct_spec {
103         char *name;
104         struct rte_swx_field_params *fields;
105         uint32_t n_fields;
106         int varbit;
107 };
108
109 static void
110 struct_spec_free(struct struct_spec *s)
111 {
112         uint32_t i;
113
114         if (!s)
115                 return;
116
117         free(s->name);
118         s->name = NULL;
119
120         for (i = 0; i < s->n_fields; i++) {
121                 uintptr_t name = (uintptr_t)s->fields[i].name;
122
123                 free((void *)name);
124         }
125
126         free(s->fields);
127         s->fields = NULL;
128
129         s->n_fields = 0;
130
131         s->varbit = 0;
132 }
133
134 static int
135 struct_statement_parse(struct struct_spec *s,
136                        uint32_t *block_mask,
137                        char **tokens,
138                        uint32_t n_tokens,
139                        uint32_t n_lines,
140                        uint32_t *err_line,
141                        const char **err_msg)
142 {
143         /* Check format. */
144         if ((n_tokens != 3) || strcmp(tokens[2], "{")) {
145                 if (err_line)
146                         *err_line = n_lines;
147                 if (err_msg)
148                         *err_msg = "Invalid struct statement.";
149                 return -EINVAL;
150         }
151
152         /* spec. */
153         s->name = strdup(tokens[1]);
154         if (!s->name) {
155                 if (err_line)
156                         *err_line = n_lines;
157                 if (err_msg)
158                         *err_msg = "Memory allocation failed.";
159                 return -ENOMEM;
160         }
161
162         /* block_mask. */
163         *block_mask |= 1 << STRUCT_BLOCK;
164
165         return 0;
166 }
167
168 static int
169 struct_block_parse(struct struct_spec *s,
170                    uint32_t *block_mask,
171                    char **tokens,
172                    uint32_t n_tokens,
173                    uint32_t n_lines,
174                    uint32_t *err_line,
175                    const char **err_msg)
176 {
177         struct rte_swx_field_params *new_fields;
178         char *p = tokens[0], *name = NULL;
179         uint32_t n_bits;
180         int varbit = 0, error = 0, error_size_invalid = 0, error_varbit_not_last = 0;
181
182         /* Handle end of block. */
183         if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
184                 *block_mask &= ~(1 << STRUCT_BLOCK);
185                 return 0;
186         }
187
188         /* Check format. */
189         if (n_tokens != 2) {
190                 error = -EINVAL;
191                 goto error;
192         }
193
194         if (s->varbit) {
195                 error = -EINVAL;
196                 error_varbit_not_last = 1;
197                 goto error;
198         }
199
200         if (!strncmp(p, "bit<", strlen("bit<"))) {
201                 size_t len = strlen(p);
202
203                 if ((len < strlen("bit< >")) || (p[len - 1] != '>')) {
204                         error = -EINVAL;
205                         goto error;
206                 }
207
208                 /* Remove the "bit<" and ">". */
209                 p[strlen(p) - 1] = 0;
210                 p += strlen("bit<");
211         } else if (!strncmp(p, "varbit<", strlen("varbit<"))) {
212                 size_t len = strlen(p);
213
214                 if ((len < strlen("varbit< >")) || (p[len - 1] != '>')) {
215                         error = -EINVAL;
216                         goto error;
217                 }
218
219                 /* Remove the "varbit<" and ">". */
220                 p[strlen(p) - 1] = 0;
221                 p += strlen("varbit<");
222
223                 /* Set the varbit flag. */
224                 varbit = 1;
225         } else {
226                 error = -EINVAL;
227                 goto error;
228         }
229
230         n_bits = strtoul(p, &p, 0);
231         if ((p[0]) ||
232             !n_bits ||
233             (n_bits % 8) ||
234             ((n_bits > 64) && !varbit)) {
235                 error = -EINVAL;
236                 error_size_invalid = 1;
237                 goto error;
238         }
239
240         /* spec. */
241         name = strdup(tokens[1]);
242         if (!name) {
243                 error = -ENOMEM;
244                 goto error;
245         }
246
247         new_fields = realloc(s->fields, (s->n_fields + 1) * sizeof(struct rte_swx_field_params));
248         if (!new_fields) {
249                 error = -ENOMEM;
250                 goto error;
251         }
252
253         s->fields = new_fields;
254         s->fields[s->n_fields].name = name;
255         s->fields[s->n_fields].n_bits = n_bits;
256         s->n_fields++;
257         s->varbit = varbit;
258
259         return 0;
260
261 error:
262         free(name);
263
264         if (err_line)
265                 *err_line = n_lines;
266
267         if (err_msg) {
268                 *err_msg = "Invalid struct field statement.";
269
270                 if ((error == -EINVAL) && error_varbit_not_last)
271                         *err_msg = "Varbit field is not the last struct field.";
272
273                 if ((error == -EINVAL) && error_size_invalid)
274                         *err_msg = "Invalid struct field size.";
275
276                 if (error == -ENOMEM)
277                         *err_msg = "Memory allocation failed.";
278         }
279
280         return error;
281 }
282
283 /*
284  * header.
285  *
286  * header HEADER_NAME instanceof STRUCT_TYPE_NAME
287  */
288 struct header_spec {
289         char *name;
290         char *struct_type_name;
291 };
292
293 static void
294 header_spec_free(struct header_spec *s)
295 {
296         if (!s)
297                 return;
298
299         free(s->name);
300         s->name = NULL;
301
302         free(s->struct_type_name);
303         s->struct_type_name = NULL;
304 }
305
306 static int
307 header_statement_parse(struct header_spec *s,
308                        char **tokens,
309                        uint32_t n_tokens,
310                        uint32_t n_lines,
311                        uint32_t *err_line,
312                        const char **err_msg)
313 {
314         /* Check format. */
315         if ((n_tokens != 4) || strcmp(tokens[2], "instanceof")) {
316                 if (err_line)
317                         *err_line = n_lines;
318                 if (err_msg)
319                         *err_msg = "Invalid header statement.";
320                 return -EINVAL;
321         }
322
323         /* spec. */
324         s->name = strdup(tokens[1]);
325         s->struct_type_name = strdup(tokens[3]);
326
327         if (!s->name || !s->struct_type_name) {
328                 free(s->name);
329                 free(s->struct_type_name);
330
331                 if (err_line)
332                         *err_line = n_lines;
333                 if (err_msg)
334                         *err_msg = "Memory allocation failed.";
335                 return -ENOMEM;
336         }
337
338         return 0;
339 }
340
341 /*
342  * metadata.
343  *
344  * metadata instanceof STRUCT_TYPE_NAME
345  */
346 struct metadata_spec {
347         char *struct_type_name;
348 };
349
350 static void
351 metadata_spec_free(struct metadata_spec *s)
352 {
353         if (!s)
354                 return;
355
356         free(s->struct_type_name);
357         s->struct_type_name = NULL;
358 }
359
360 static int
361 metadata_statement_parse(struct metadata_spec *s,
362                          char **tokens,
363                          uint32_t n_tokens,
364                          uint32_t n_lines,
365                          uint32_t *err_line,
366                          const char **err_msg)
367 {
368         /* Check format. */
369         if ((n_tokens != 3) || strcmp(tokens[1], "instanceof")) {
370                 if (err_line)
371                         *err_line = n_lines;
372                 if (err_msg)
373                         *err_msg = "Invalid metadata statement.";
374                 return -EINVAL;
375         }
376
377         /* spec. */
378         s->struct_type_name = strdup(tokens[2]);
379         if (!s->struct_type_name) {
380                 if (err_line)
381                         *err_line = n_lines;
382                 if (err_msg)
383                         *err_msg = "Memory allocation failed.";
384                 return -ENOMEM;
385         }
386
387         return 0;
388 }
389
390 /*
391  * action.
392  *
393  * action ACTION_NAME args none | instanceof STRUCT_TYPE_NAME {
394  *      INSTRUCTION
395  *      ...
396  * }
397  */
398 struct action_spec {
399         char *name;
400         char *args_struct_type_name;
401         const char **instructions;
402         uint32_t n_instructions;
403 };
404
405 static void
406 action_spec_free(struct action_spec *s)
407 {
408         uint32_t i;
409
410         if (!s)
411                 return;
412
413         free(s->name);
414         s->name = NULL;
415
416         free(s->args_struct_type_name);
417         s->args_struct_type_name = NULL;
418
419         for (i = 0; i < s->n_instructions; i++) {
420                 uintptr_t instr = (uintptr_t)s->instructions[i];
421
422                 free((void *)instr);
423         }
424
425         free(s->instructions);
426         s->instructions = NULL;
427
428         s->n_instructions = 0;
429 }
430
431 static int
432 action_statement_parse(struct action_spec *s,
433                        uint32_t *block_mask,
434                        char **tokens,
435                        uint32_t n_tokens,
436                        uint32_t n_lines,
437                        uint32_t *err_line,
438                        const char **err_msg)
439 {
440         /* Check format. */
441         if (((n_tokens != 5) && (n_tokens != 6)) ||
442             ((n_tokens == 5) &&
443              (strcmp(tokens[2], "args") ||
444               strcmp(tokens[3], "none") ||
445               strcmp(tokens[4], "{"))) ||
446             ((n_tokens == 6) &&
447              (strcmp(tokens[2], "args") ||
448               strcmp(tokens[3], "instanceof") ||
449               strcmp(tokens[5], "{")))) {
450                 if (err_line)
451                         *err_line = n_lines;
452                 if (err_msg)
453                         *err_msg = "Invalid action statement.";
454                 return -EINVAL;
455         }
456
457         /* spec. */
458         s->name = strdup(tokens[1]);
459         s->args_struct_type_name = (n_tokens == 6) ? strdup(tokens[4]) : NULL;
460
461         if ((!s->name) || ((n_tokens == 6) && !s->args_struct_type_name)) {
462                 if (err_line)
463                         *err_line = n_lines;
464                 if (err_msg)
465                         *err_msg = "Memory allocation failed.";
466                 return -ENOMEM;
467         }
468
469         /* block_mask. */
470         *block_mask |= 1 << ACTION_BLOCK;
471
472         return 0;
473 }
474
475 static int
476 action_block_parse(struct action_spec *s,
477                    uint32_t *block_mask,
478                    char **tokens,
479                    uint32_t n_tokens,
480                    uint32_t n_lines,
481                    uint32_t *err_line,
482                    const char **err_msg)
483 {
484         char buffer[RTE_SWX_INSTRUCTION_SIZE], *instr;
485         const char **new_instructions;
486         uint32_t i;
487
488         /* Handle end of block. */
489         if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
490                 *block_mask &= ~(1 << ACTION_BLOCK);
491                 return 0;
492         }
493
494         /* spec. */
495         buffer[0] = 0;
496         for (i = 0; i < n_tokens; i++) {
497                 if (i)
498                         strcat(buffer, " ");
499                 strcat(buffer, tokens[i]);
500         }
501
502         instr = strdup(buffer);
503         if (!instr) {
504                 if (err_line)
505                         *err_line = n_lines;
506                 if (err_msg)
507                         *err_msg = "Memory allocation failed.";
508                 return -ENOMEM;
509         }
510
511         new_instructions = realloc(s->instructions,
512                                    (s->n_instructions + 1) * sizeof(char *));
513         if (!new_instructions) {
514                 free(instr);
515
516                 if (err_line)
517                         *err_line = n_lines;
518                 if (err_msg)
519                         *err_msg = "Memory allocation failed.";
520                 return -ENOMEM;
521         }
522
523         s->instructions = new_instructions;
524         s->instructions[s->n_instructions] = instr;
525         s->n_instructions++;
526
527         return 0;
528 }
529
530 /*
531  * table.
532  *
533  * table {
534  *      key {
535  *              MATCH_FIELD_NAME exact | wildcard | lpm
536  *              ...
537  *      }
538  *      actions {
539  *              ACTION_NAME
540  *              ...
541  *      }
542  *      default_action ACTION_NAME args none | ARGS_BYTE_ARRAY [ const ]
543  *      instanceof TABLE_TYPE_NAME
544  *      pragma ARGS
545  *      size SIZE
546  * }
547  */
548 struct table_spec {
549         char *name;
550         struct rte_swx_pipeline_table_params params;
551         char *recommended_table_type_name;
552         char *args;
553         uint32_t size;
554 };
555
556 static void
557 table_spec_free(struct table_spec *s)
558 {
559         uintptr_t default_action_name;
560         uint32_t i;
561
562         if (!s)
563                 return;
564
565         free(s->name);
566         s->name = NULL;
567
568         for (i = 0; i < s->params.n_fields; i++) {
569                 uintptr_t name = (uintptr_t)s->params.fields[i].name;
570
571                 free((void *)name);
572         }
573
574         free(s->params.fields);
575         s->params.fields = NULL;
576
577         s->params.n_fields = 0;
578
579         for (i = 0; i < s->params.n_actions; i++) {
580                 uintptr_t name = (uintptr_t)s->params.action_names[i];
581
582                 free((void *)name);
583         }
584
585         free(s->params.action_names);
586         s->params.action_names = NULL;
587
588         s->params.n_actions = 0;
589
590         default_action_name = (uintptr_t)s->params.default_action_name;
591         free((void *)default_action_name);
592         s->params.default_action_name = NULL;
593
594         free(s->params.default_action_data);
595         s->params.default_action_data = NULL;
596
597         s->params.default_action_is_const = 0;
598
599         free(s->recommended_table_type_name);
600         s->recommended_table_type_name = NULL;
601
602         free(s->args);
603         s->args = NULL;
604
605         s->size = 0;
606 }
607
608 static int
609 table_key_statement_parse(uint32_t *block_mask,
610                           char **tokens,
611                           uint32_t n_tokens,
612                           uint32_t n_lines,
613                           uint32_t *err_line,
614                           const char **err_msg)
615 {
616         /* Check format. */
617         if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
618                 if (err_line)
619                         *err_line = n_lines;
620                 if (err_msg)
621                         *err_msg = "Invalid key statement.";
622                 return -EINVAL;
623         }
624
625         /* block_mask. */
626         *block_mask |= 1 << TABLE_KEY_BLOCK;
627
628         return 0;
629 }
630
631 static int
632 table_key_block_parse(struct table_spec *s,
633                       uint32_t *block_mask,
634                       char **tokens,
635                       uint32_t n_tokens,
636                       uint32_t n_lines,
637                       uint32_t *err_line,
638                       const char **err_msg)
639 {
640         struct rte_swx_match_field_params *new_fields;
641         enum rte_swx_table_match_type match_type = RTE_SWX_TABLE_MATCH_WILDCARD;
642         char *name;
643
644         /* Handle end of block. */
645         if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
646                 *block_mask &= ~(1 << TABLE_KEY_BLOCK);
647                 return 0;
648         }
649
650         /* Check input arguments. */
651         if ((n_tokens != 2) ||
652             (strcmp(tokens[1], "exact") &&
653              strcmp(tokens[1], "wildcard") &&
654              strcmp(tokens[1], "lpm"))) {
655                 if (err_line)
656                         *err_line = n_lines;
657                 if (err_msg)
658                         *err_msg = "Invalid match field statement.";
659                 return -EINVAL;
660         }
661
662         if (!strcmp(tokens[1], "wildcard"))
663                 match_type = RTE_SWX_TABLE_MATCH_WILDCARD;
664         if (!strcmp(tokens[1], "lpm"))
665                 match_type = RTE_SWX_TABLE_MATCH_LPM;
666         if (!strcmp(tokens[1], "exact"))
667                 match_type = RTE_SWX_TABLE_MATCH_EXACT;
668
669         name = strdup(tokens[0]);
670         if (!name) {
671                 if (err_line)
672                         *err_line = n_lines;
673                 if (err_msg)
674                         *err_msg = "Memory allocation failed.";
675                 return -ENOMEM;
676         }
677
678         new_fields = realloc(s->params.fields,
679                              (s->params.n_fields + 1) * sizeof(struct rte_swx_match_field_params));
680         if (!new_fields) {
681                 free(name);
682
683                 if (err_line)
684                         *err_line = n_lines;
685                 if (err_msg)
686                         *err_msg = "Memory allocation failed.";
687                 return -ENOMEM;
688         }
689
690         s->params.fields = new_fields;
691         s->params.fields[s->params.n_fields].name = name;
692         s->params.fields[s->params.n_fields].match_type = match_type;
693         s->params.n_fields++;
694
695         return 0;
696 }
697
698 static int
699 table_actions_statement_parse(uint32_t *block_mask,
700                               char **tokens,
701                               uint32_t n_tokens,
702                               uint32_t n_lines,
703                               uint32_t *err_line,
704                               const char **err_msg)
705 {
706         /* Check format. */
707         if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
708                 if (err_line)
709                         *err_line = n_lines;
710                 if (err_msg)
711                         *err_msg = "Invalid actions statement.";
712                 return -EINVAL;
713         }
714
715         /* block_mask. */
716         *block_mask |= 1 << TABLE_ACTIONS_BLOCK;
717
718         return 0;
719 }
720
721 static int
722 table_actions_block_parse(struct table_spec *s,
723                           uint32_t *block_mask,
724                           char **tokens,
725                           uint32_t n_tokens,
726                           uint32_t n_lines,
727                           uint32_t *err_line,
728                           const char **err_msg)
729 {
730         const char **new_action_names;
731         char *name;
732
733         /* Handle end of block. */
734         if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
735                 *block_mask &= ~(1 << TABLE_ACTIONS_BLOCK);
736                 return 0;
737         }
738
739         /* Check input arguments. */
740         if (n_tokens != 1) {
741                 if (err_line)
742                         *err_line = n_lines;
743                 if (err_msg)
744                         *err_msg = "Invalid action name statement.";
745                 return -EINVAL;
746         }
747
748         name = strdup(tokens[0]);
749         if (!name) {
750                 if (err_line)
751                         *err_line = n_lines;
752                 if (err_msg)
753                         *err_msg = "Memory allocation failed.";
754                 return -ENOMEM;
755         }
756
757         new_action_names = realloc(s->params.action_names,
758                                    (s->params.n_actions + 1) * sizeof(char *));
759         if (!new_action_names) {
760                 free(name);
761
762                 if (err_line)
763                         *err_line = n_lines;
764                 if (err_msg)
765                         *err_msg = "Memory allocation failed.";
766                 return -ENOMEM;
767         }
768
769         s->params.action_names = new_action_names;
770         s->params.action_names[s->params.n_actions] = name;
771         s->params.n_actions++;
772
773         return 0;
774 }
775
776 static int
777 table_statement_parse(struct table_spec *s,
778                       uint32_t *block_mask,
779                       char **tokens,
780                       uint32_t n_tokens,
781                       uint32_t n_lines,
782                       uint32_t *err_line,
783                       const char **err_msg)
784 {
785         /* Check format. */
786         if ((n_tokens != 3) || strcmp(tokens[2], "{")) {
787                 if (err_line)
788                         *err_line = n_lines;
789                 if (err_msg)
790                         *err_msg = "Invalid table statement.";
791                 return -EINVAL;
792         }
793
794         /* spec. */
795         s->name = strdup(tokens[1]);
796         if (!s->name) {
797                 if (err_line)
798                         *err_line = n_lines;
799                 if (err_msg)
800                         *err_msg = "Memory allocation failed.";
801                 return -ENOMEM;
802         }
803
804         /* block_mask. */
805         *block_mask |= 1 << TABLE_BLOCK;
806
807         return 0;
808 }
809
810 static int
811 table_block_parse(struct table_spec *s,
812                   uint32_t *block_mask,
813                   char **tokens,
814                   uint32_t n_tokens,
815                   uint32_t n_lines,
816                   uint32_t *err_line,
817                   const char **err_msg)
818 {
819         if (*block_mask & (1 << TABLE_KEY_BLOCK))
820                 return table_key_block_parse(s,
821                                              block_mask,
822                                              tokens,
823                                              n_tokens,
824                                              n_lines,
825                                              err_line,
826                                              err_msg);
827
828         if (*block_mask & (1 << TABLE_ACTIONS_BLOCK))
829                 return table_actions_block_parse(s,
830                                                  block_mask,
831                                                  tokens,
832                                                  n_tokens,
833                                                  n_lines,
834                                                  err_line,
835                                                  err_msg);
836
837         /* Handle end of block. */
838         if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
839                 *block_mask &= ~(1 << TABLE_BLOCK);
840                 return 0;
841         }
842
843         if (!strcmp(tokens[0], "key"))
844                 return table_key_statement_parse(block_mask,
845                                                  tokens,
846                                                  n_tokens,
847                                                  n_lines,
848                                                  err_line,
849                                                  err_msg);
850
851         if (!strcmp(tokens[0], "actions"))
852                 return table_actions_statement_parse(block_mask,
853                                                      tokens,
854                                                      n_tokens,
855                                                      n_lines,
856                                                      err_line,
857                                                      err_msg);
858
859         if (!strcmp(tokens[0], "default_action")) {
860                 if (((n_tokens != 4) && (n_tokens != 5)) ||
861                     strcmp(tokens[2], "args") ||
862                     strcmp(tokens[3], "none") ||
863                     ((n_tokens == 5) && strcmp(tokens[4], "const"))) {
864                         if (err_line)
865                                 *err_line = n_lines;
866                         if (err_msg)
867                                 *err_msg = "Invalid default_action statement.";
868                         return -EINVAL;
869                 }
870
871                 if (s->params.default_action_name) {
872                         if (err_line)
873                                 *err_line = n_lines;
874                         if (err_msg)
875                                 *err_msg = "Duplicate default_action stmt.";
876                         return -EINVAL;
877                 }
878
879                 s->params.default_action_name = strdup(tokens[1]);
880                 if (!s->params.default_action_name) {
881                         if (err_line)
882                                 *err_line = n_lines;
883                         if (err_msg)
884                                 *err_msg = "Memory allocation failed.";
885                         return -ENOMEM;
886                 }
887
888                 if (n_tokens == 5)
889                         s->params.default_action_is_const = 1;
890
891                 return 0;
892         }
893
894         if (!strcmp(tokens[0], "instanceof")) {
895                 if (n_tokens != 2) {
896                         if (err_line)
897                                 *err_line = n_lines;
898                         if (err_msg)
899                                 *err_msg = "Invalid instanceof statement.";
900                         return -EINVAL;
901                 }
902
903                 if (s->recommended_table_type_name) {
904                         if (err_line)
905                                 *err_line = n_lines;
906                         if (err_msg)
907                                 *err_msg = "Duplicate instanceof statement.";
908                         return -EINVAL;
909                 }
910
911                 s->recommended_table_type_name = strdup(tokens[1]);
912                 if (!s->recommended_table_type_name) {
913                         if (err_line)
914                                 *err_line = n_lines;
915                         if (err_msg)
916                                 *err_msg = "Memory allocation failed.";
917                         return -ENOMEM;
918                 }
919
920                 return 0;
921         }
922
923         if (!strcmp(tokens[0], "pragma")) {
924                 if (n_tokens != 2) {
925                         if (err_line)
926                                 *err_line = n_lines;
927                         if (err_msg)
928                                 *err_msg = "Invalid pragma statement.";
929                         return -EINVAL;
930                 }
931
932                 if (s->args) {
933                         if (err_line)
934                                 *err_line = n_lines;
935                         if (err_msg)
936                                 *err_msg = "Duplicate pragma statement.";
937                         return -EINVAL;
938                 }
939
940                 s->args = strdup(tokens[1]);
941                 if (!s->args) {
942                         if (err_line)
943                                 *err_line = n_lines;
944                         if (err_msg)
945                                 *err_msg = "Memory allocation failed.";
946                         return -ENOMEM;
947                 }
948
949                 return 0;
950         }
951
952         if (!strcmp(tokens[0], "size")) {
953                 char *p = tokens[1];
954
955                 if (n_tokens != 2) {
956                         if (err_line)
957                                 *err_line = n_lines;
958                         if (err_msg)
959                                 *err_msg = "Invalid pragma statement.";
960                         return -EINVAL;
961                 }
962
963                 s->size = strtoul(p, &p, 0);
964                 if (p[0]) {
965                         if (err_line)
966                                 *err_line = n_lines;
967                         if (err_msg)
968                                 *err_msg = "Invalid size argument.";
969                         return -EINVAL;
970                 }
971
972                 return 0;
973         }
974
975         /* Anything else. */
976         if (err_line)
977                 *err_line = n_lines;
978         if (err_msg)
979                 *err_msg = "Invalid statement.";
980         return -EINVAL;
981 }
982
983 /*
984  * selector.
985  *
986  * selector SELECTOR_NAME {
987  *      group_id FIELD_NAME
988  *      selector {
989  *              FIELD_NAME
990  *              ...
991  *      }
992  *      member_id FIELD_NAME
993  *      n_groups N_GROUPS
994  *      n_members_per_group N_MEMBERS_PER_GROUP
995  * }
996  */
997 struct selector_spec {
998         char *name;
999         struct rte_swx_pipeline_selector_params params;
1000 };
1001
1002 static void
1003 selector_spec_free(struct selector_spec *s)
1004 {
1005         uintptr_t field_name;
1006         uint32_t i;
1007
1008         if (!s)
1009                 return;
1010
1011         /* name. */
1012         free(s->name);
1013         s->name = NULL;
1014
1015         /* params->group_id_field_name. */
1016         field_name = (uintptr_t)s->params.group_id_field_name;
1017         free((void *)field_name);
1018         s->params.group_id_field_name = NULL;
1019
1020         /* params->selector_field_names. */
1021         for (i = 0; i < s->params.n_selector_fields; i++) {
1022                 field_name = (uintptr_t)s->params.selector_field_names[i];
1023
1024                 free((void *)field_name);
1025         }
1026
1027         free(s->params.selector_field_names);
1028         s->params.selector_field_names = NULL;
1029
1030         s->params.n_selector_fields = 0;
1031
1032         /* params->member_id_field_name. */
1033         field_name = (uintptr_t)s->params.member_id_field_name;
1034         free((void *)field_name);
1035         s->params.member_id_field_name = NULL;
1036
1037         /* params->n_groups_max. */
1038         s->params.n_groups_max = 0;
1039
1040         /* params->n_members_per_group_max. */
1041         s->params.n_members_per_group_max = 0;
1042 }
1043
1044 static int
1045 selector_statement_parse(struct selector_spec *s,
1046                          uint32_t *block_mask,
1047                          char **tokens,
1048                          uint32_t n_tokens,
1049                          uint32_t n_lines,
1050                          uint32_t *err_line,
1051                          const char **err_msg)
1052 {
1053         /* Check format. */
1054         if ((n_tokens != 3) || strcmp(tokens[2], "{")) {
1055                 if (err_line)
1056                         *err_line = n_lines;
1057                 if (err_msg)
1058                         *err_msg = "Invalid selector statement.";
1059                 return -EINVAL;
1060         }
1061
1062         /* spec. */
1063         s->name = strdup(tokens[1]);
1064         if (!s->name) {
1065                 if (err_line)
1066                         *err_line = n_lines;
1067                 if (err_msg)
1068                         *err_msg = "Memory allocation failed.";
1069                 return -ENOMEM;
1070         }
1071
1072         /* block_mask. */
1073         *block_mask |= 1 << SELECTOR_BLOCK;
1074
1075         return 0;
1076 }
1077
1078 static int
1079 selector_selector_statement_parse(uint32_t *block_mask,
1080                                   char **tokens,
1081                                   uint32_t n_tokens,
1082                                   uint32_t n_lines,
1083                                   uint32_t *err_line,
1084                                   const char **err_msg)
1085 {
1086         /* Check format. */
1087         if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
1088                 if (err_line)
1089                         *err_line = n_lines;
1090                 if (err_msg)
1091                         *err_msg = "Invalid selector statement.";
1092                 return -EINVAL;
1093         }
1094
1095         /* block_mask. */
1096         *block_mask |= 1 << SELECTOR_SELECTOR_BLOCK;
1097
1098         return 0;
1099 }
1100
1101 static int
1102 selector_selector_block_parse(struct selector_spec *s,
1103                               uint32_t *block_mask,
1104                               char **tokens,
1105                               uint32_t n_tokens,
1106                               uint32_t n_lines,
1107                               uint32_t *err_line,
1108                               const char **err_msg)
1109 {
1110         const char **new_fields;
1111         char *name;
1112
1113         /* Handle end of block. */
1114         if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1115                 *block_mask &= ~(1 << SELECTOR_SELECTOR_BLOCK);
1116                 return 0;
1117         }
1118
1119         /* Check input arguments. */
1120         if (n_tokens != 1) {
1121                 if (err_line)
1122                         *err_line = n_lines;
1123                 if (err_msg)
1124                         *err_msg = "Invalid selector field statement.";
1125                 return -EINVAL;
1126         }
1127
1128         name = strdup(tokens[0]);
1129         if (!name) {
1130                 if (err_line)
1131                         *err_line = n_lines;
1132                 if (err_msg)
1133                         *err_msg = "Memory allocation failed.";
1134                 return -ENOMEM;
1135         }
1136
1137         new_fields = realloc(s->params.selector_field_names,
1138                              (s->params.n_selector_fields + 1) * sizeof(char *));
1139         if (!new_fields) {
1140                 free(name);
1141
1142                 if (err_line)
1143                         *err_line = n_lines;
1144                 if (err_msg)
1145                         *err_msg = "Memory allocation failed.";
1146                 return -ENOMEM;
1147         }
1148
1149         s->params.selector_field_names = new_fields;
1150         s->params.selector_field_names[s->params.n_selector_fields] = name;
1151         s->params.n_selector_fields++;
1152
1153         return 0;
1154 }
1155
1156 static int
1157 selector_block_parse(struct selector_spec *s,
1158                      uint32_t *block_mask,
1159                      char **tokens,
1160                      uint32_t n_tokens,
1161                      uint32_t n_lines,
1162                      uint32_t *err_line,
1163                      const char **err_msg)
1164 {
1165         if (*block_mask & (1 << SELECTOR_SELECTOR_BLOCK))
1166                 return selector_selector_block_parse(s,
1167                                                      block_mask,
1168                                                      tokens,
1169                                                      n_tokens,
1170                                                      n_lines,
1171                                                      err_line,
1172                                                      err_msg);
1173
1174         /* Handle end of block. */
1175         if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1176                 *block_mask &= ~(1 << SELECTOR_BLOCK);
1177                 return 0;
1178         }
1179
1180         if (!strcmp(tokens[0], "group_id")) {
1181                 if (n_tokens != 2) {
1182                         if (err_line)
1183                                 *err_line = n_lines;
1184                         if (err_msg)
1185                                 *err_msg = "Invalid group_id statement.";
1186                         return -EINVAL;
1187                 }
1188
1189                 s->params.group_id_field_name = strdup(tokens[1]);
1190                 if (!s->params.group_id_field_name) {
1191                         if (err_line)
1192                                 *err_line = n_lines;
1193                         if (err_msg)
1194                                 *err_msg = "Memory allocation failed.";
1195                         return -ENOMEM;
1196                 }
1197
1198                 return 0;
1199         }
1200
1201         if (!strcmp(tokens[0], "selector"))
1202                 return selector_selector_statement_parse(block_mask,
1203                                                          tokens,
1204                                                          n_tokens,
1205                                                          n_lines,
1206                                                          err_line,
1207                                                          err_msg);
1208
1209         if (!strcmp(tokens[0], "member_id")) {
1210                 if (n_tokens != 2) {
1211                         if (err_line)
1212                                 *err_line = n_lines;
1213                         if (err_msg)
1214                                 *err_msg = "Invalid member_id statement.";
1215                         return -EINVAL;
1216                 }
1217
1218                 s->params.member_id_field_name = strdup(tokens[1]);
1219                 if (!s->params.member_id_field_name) {
1220                         if (err_line)
1221                                 *err_line = n_lines;
1222                         if (err_msg)
1223                                 *err_msg = "Memory allocation failed.";
1224                         return -ENOMEM;
1225                 }
1226
1227                 return 0;
1228         }
1229
1230         if (!strcmp(tokens[0], "n_groups_max")) {
1231                 char *p = tokens[1];
1232
1233                 if (n_tokens != 2) {
1234                         if (err_line)
1235                                 *err_line = n_lines;
1236                         if (err_msg)
1237                                 *err_msg = "Invalid n_groups statement.";
1238                         return -EINVAL;
1239                 }
1240
1241                 s->params.n_groups_max = strtoul(p, &p, 0);
1242                 if (p[0]) {
1243                         if (err_line)
1244                                 *err_line = n_lines;
1245                         if (err_msg)
1246                                 *err_msg = "Invalid n_groups argument.";
1247                         return -EINVAL;
1248                 }
1249
1250                 return 0;
1251         }
1252
1253         if (!strcmp(tokens[0], "n_members_per_group_max")) {
1254                 char *p = tokens[1];
1255
1256                 if (n_tokens != 2) {
1257                         if (err_line)
1258                                 *err_line = n_lines;
1259                         if (err_msg)
1260                                 *err_msg = "Invalid n_members_per_group statement.";
1261                         return -EINVAL;
1262                 }
1263
1264                 s->params.n_members_per_group_max = strtoul(p, &p, 0);
1265                 if (p[0]) {
1266                         if (err_line)
1267                                 *err_line = n_lines;
1268                         if (err_msg)
1269                                 *err_msg = "Invalid n_members_per_group argument.";
1270                         return -EINVAL;
1271                 }
1272
1273                 return 0;
1274         }
1275
1276         /* Anything else. */
1277         if (err_line)
1278                 *err_line = n_lines;
1279         if (err_msg)
1280                 *err_msg = "Invalid statement.";
1281         return -EINVAL;
1282 }
1283
1284 /*
1285  * regarray.
1286  *
1287  * regarray NAME size SIZE initval INITVAL
1288  */
1289 struct regarray_spec {
1290         char *name;
1291         uint64_t init_val;
1292         uint32_t size;
1293 };
1294
1295 static void
1296 regarray_spec_free(struct regarray_spec *s)
1297 {
1298         if (!s)
1299                 return;
1300
1301         free(s->name);
1302         s->name = NULL;
1303 }
1304
1305 static int
1306 regarray_statement_parse(struct regarray_spec *s,
1307                          char **tokens,
1308                          uint32_t n_tokens,
1309                          uint32_t n_lines,
1310                          uint32_t *err_line,
1311                          const char **err_msg)
1312 {
1313         char *p;
1314
1315         /* Check format. */
1316         if ((n_tokens != 6) ||
1317              strcmp(tokens[2], "size") ||
1318              strcmp(tokens[4], "initval")) {
1319                 if (err_line)
1320                         *err_line = n_lines;
1321                 if (err_msg)
1322                         *err_msg = "Invalid regarray statement.";
1323                 return -EINVAL;
1324         }
1325
1326         /* spec. */
1327         s->name = strdup(tokens[1]);
1328         if (!s->name) {
1329                 if (err_line)
1330                         *err_line = n_lines;
1331                 if (err_msg)
1332                         *err_msg = "Memory allocation failed.";
1333                 return -ENOMEM;
1334         }
1335
1336         p = tokens[3];
1337         s->size = strtoul(p, &p, 0);
1338         if (p[0] || !s->size) {
1339                 if (err_line)
1340                         *err_line = n_lines;
1341                 if (err_msg)
1342                         *err_msg = "Invalid size argument.";
1343                 return -EINVAL;
1344         }
1345
1346         p = tokens[5];
1347         s->init_val = strtoull(p, &p, 0);
1348         if (p[0]) {
1349                 if (err_line)
1350                         *err_line = n_lines;
1351                 if (err_msg)
1352                         *err_msg = "Invalid initval argument.";
1353                 return -EINVAL;
1354         }
1355
1356         return 0;
1357 }
1358
1359 /*
1360  * metarray.
1361  *
1362  * metarray NAME size SIZE
1363  */
1364 struct metarray_spec {
1365         char *name;
1366         uint32_t size;
1367 };
1368
1369 static void
1370 metarray_spec_free(struct metarray_spec *s)
1371 {
1372         if (!s)
1373                 return;
1374
1375         free(s->name);
1376         s->name = NULL;
1377 }
1378
1379 static int
1380 metarray_statement_parse(struct metarray_spec *s,
1381                          char **tokens,
1382                          uint32_t n_tokens,
1383                          uint32_t n_lines,
1384                          uint32_t *err_line,
1385                          const char **err_msg)
1386 {
1387         char *p;
1388
1389         /* Check format. */
1390         if ((n_tokens != 4) || strcmp(tokens[2], "size")) {
1391                 if (err_line)
1392                         *err_line = n_lines;
1393                 if (err_msg)
1394                         *err_msg = "Invalid metarray statement.";
1395                 return -EINVAL;
1396         }
1397
1398         /* spec. */
1399         s->name = strdup(tokens[1]);
1400         if (!s->name) {
1401                 if (err_line)
1402                         *err_line = n_lines;
1403                 if (err_msg)
1404                         *err_msg = "Memory allocation failed.";
1405                 return -ENOMEM;
1406         }
1407
1408         p = tokens[3];
1409         s->size = strtoul(p, &p, 0);
1410         if (p[0] || !s->size) {
1411                 if (err_line)
1412                         *err_line = n_lines;
1413                 if (err_msg)
1414                         *err_msg = "Invalid size argument.";
1415                 return -EINVAL;
1416         }
1417
1418         return 0;
1419 }
1420
1421 /*
1422  * apply.
1423  *
1424  * apply {
1425  *      INSTRUCTION
1426  *      ...
1427  * }
1428  */
1429 struct apply_spec {
1430         const char **instructions;
1431         uint32_t n_instructions;
1432 };
1433
1434 static void
1435 apply_spec_free(struct apply_spec *s)
1436 {
1437         uint32_t i;
1438
1439         if (!s)
1440                 return;
1441
1442         for (i = 0; i < s->n_instructions; i++) {
1443                 uintptr_t instr = (uintptr_t)s->instructions[i];
1444
1445                 free((void *)instr);
1446         }
1447
1448         free(s->instructions);
1449         s->instructions = NULL;
1450
1451         s->n_instructions = 0;
1452 }
1453
1454 static int
1455 apply_statement_parse(uint32_t *block_mask,
1456                       char **tokens,
1457                       uint32_t n_tokens,
1458                       uint32_t n_lines,
1459                       uint32_t *err_line,
1460                       const char **err_msg)
1461 {
1462         /* Check format. */
1463         if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
1464                 if (err_line)
1465                         *err_line = n_lines;
1466                 if (err_msg)
1467                         *err_msg = "Invalid apply statement.";
1468                 return -EINVAL;
1469         }
1470
1471         /* block_mask. */
1472         *block_mask |= 1 << APPLY_BLOCK;
1473
1474         return 0;
1475 }
1476
1477 static int
1478 apply_block_parse(struct apply_spec *s,
1479                   uint32_t *block_mask,
1480                   char **tokens,
1481                   uint32_t n_tokens,
1482                   uint32_t n_lines,
1483                   uint32_t *err_line,
1484                   const char **err_msg)
1485 {
1486         char buffer[RTE_SWX_INSTRUCTION_SIZE], *instr;
1487         const char **new_instructions;
1488         uint32_t i;
1489
1490         /* Handle end of block. */
1491         if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1492                 *block_mask &= ~(1 << APPLY_BLOCK);
1493                 return 0;
1494         }
1495
1496         /* spec. */
1497         buffer[0] = 0;
1498         for (i = 0; i < n_tokens; i++) {
1499                 if (i)
1500                         strcat(buffer, " ");
1501                 strcat(buffer, tokens[i]);
1502         }
1503
1504         instr = strdup(buffer);
1505         if (!instr) {
1506                 if (err_line)
1507                         *err_line = n_lines;
1508                 if (err_msg)
1509                         *err_msg = "Memory allocation failed.";
1510                 return -ENOMEM;
1511         }
1512
1513         new_instructions = realloc(s->instructions,
1514                                    (s->n_instructions + 1) * sizeof(char *));
1515         if (!new_instructions) {
1516                 free(instr);
1517
1518                 if (err_line)
1519                         *err_line = n_lines;
1520                 if (err_msg)
1521                         *err_msg = "Memory allocation failed.";
1522                 return -ENOMEM;
1523         }
1524
1525         s->instructions = new_instructions;
1526         s->instructions[s->n_instructions] = instr;
1527         s->n_instructions++;
1528
1529         return 0;
1530 }
1531
1532 /*
1533  * Pipeline.
1534  */
1535 int
1536 rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
1537                                  FILE *spec,
1538                                  uint32_t *err_line,
1539                                  const char **err_msg)
1540 {
1541         struct extobj_spec extobj_spec = {0};
1542         struct struct_spec struct_spec = {0};
1543         struct header_spec header_spec = {0};
1544         struct metadata_spec metadata_spec = {0};
1545         struct action_spec action_spec = {0};
1546         struct table_spec table_spec = {0};
1547         struct selector_spec selector_spec = {0};
1548         struct regarray_spec regarray_spec = {0};
1549         struct metarray_spec metarray_spec = {0};
1550         struct apply_spec apply_spec = {0};
1551         uint32_t n_lines;
1552         uint32_t block_mask = 0;
1553         int status;
1554
1555         /* Check the input arguments. */
1556         if (!p) {
1557                 if (err_line)
1558                         *err_line = 0;
1559                 if (err_msg)
1560                         *err_msg = "Null pipeline arument.";
1561                 status = -EINVAL;
1562                 goto error;
1563         }
1564
1565         if (!spec) {
1566                 if (err_line)
1567                         *err_line = 0;
1568                 if (err_msg)
1569                         *err_msg = "Null specification file argument.";
1570                 status = -EINVAL;
1571                 goto error;
1572         }
1573
1574         for (n_lines = 1; ; n_lines++) {
1575                 char line[MAX_LINE_LENGTH];
1576                 char *tokens[MAX_TOKENS], *ptr = line;
1577                 uint32_t n_tokens = 0;
1578
1579                 /* Read next line. */
1580                 if (!fgets(line, sizeof(line), spec))
1581                         break;
1582
1583                 /* Parse the line into tokens. */
1584                 for ( ; ; ) {
1585                         char *token;
1586
1587                         /* Get token. */
1588                         token = strtok_r(ptr, " \f\n\r\t\v", &ptr);
1589                         if (!token)
1590                                 break;
1591
1592                         /* Handle comments. */
1593                         if ((token[0] == '#') ||
1594                             (token[0] == ';') ||
1595                             ((token[0] == '/') && (token[1] == '/'))) {
1596                                 break;
1597                         }
1598
1599                         /* Handle excessively long lines. */
1600                         if (n_tokens >= MAX_TOKENS) {
1601                                 if (err_line)
1602                                         *err_line = n_lines;
1603                                 if (err_msg)
1604                                         *err_msg = "Too many tokens.";
1605                                 status = -EINVAL;
1606                                 goto error;
1607                         }
1608
1609                         /* Handle excessively long tokens. */
1610                         if (strnlen(token, RTE_SWX_NAME_SIZE) >=
1611                             RTE_SWX_NAME_SIZE) {
1612                                 if (err_line)
1613                                         *err_line = n_lines;
1614                                 if (err_msg)
1615                                         *err_msg = "Token too big.";
1616                                 status = -EINVAL;
1617                                 goto error;
1618                         }
1619
1620                         /* Save token. */
1621                         tokens[n_tokens] = token;
1622                         n_tokens++;
1623                 }
1624
1625                 /* Handle empty lines. */
1626                 if (!n_tokens)
1627                         continue;
1628
1629                 /* struct block. */
1630                 if (block_mask & (1 << STRUCT_BLOCK)) {
1631                         status = struct_block_parse(&struct_spec,
1632                                                     &block_mask,
1633                                                     tokens,
1634                                                     n_tokens,
1635                                                     n_lines,
1636                                                     err_line,
1637                                                     err_msg);
1638                         if (status)
1639                                 goto error;
1640
1641                         if (block_mask & (1 << STRUCT_BLOCK))
1642                                 continue;
1643
1644                         /* End of block. */
1645                         status = rte_swx_pipeline_struct_type_register(p,
1646                                 struct_spec.name,
1647                                 struct_spec.fields,
1648                                 struct_spec.n_fields,
1649                                 struct_spec.varbit);
1650                         if (status) {
1651                                 if (err_line)
1652                                         *err_line = n_lines;
1653                                 if (err_msg)
1654                                         *err_msg = "Struct registration error.";
1655                                 goto error;
1656                         }
1657
1658                         struct_spec_free(&struct_spec);
1659
1660                         continue;
1661                 }
1662
1663                 /* action block. */
1664                 if (block_mask & (1 << ACTION_BLOCK)) {
1665                         status = action_block_parse(&action_spec,
1666                                                     &block_mask,
1667                                                     tokens,
1668                                                     n_tokens,
1669                                                     n_lines,
1670                                                     err_line,
1671                                                     err_msg);
1672                         if (status)
1673                                 goto error;
1674
1675                         if (block_mask & (1 << ACTION_BLOCK))
1676                                 continue;
1677
1678                         /* End of block. */
1679                         status = rte_swx_pipeline_action_config(p,
1680                                 action_spec.name,
1681                                 action_spec.args_struct_type_name,
1682                                 action_spec.instructions,
1683                                 action_spec.n_instructions);
1684                         if (status) {
1685                                 if (err_line)
1686                                         *err_line = n_lines;
1687                                 if (err_msg)
1688                                         *err_msg = "Action config error.";
1689                                 goto error;
1690                         }
1691
1692                         action_spec_free(&action_spec);
1693
1694                         continue;
1695                 }
1696
1697                 /* table block. */
1698                 if (block_mask & (1 << TABLE_BLOCK)) {
1699                         status = table_block_parse(&table_spec,
1700                                                    &block_mask,
1701                                                    tokens,
1702                                                    n_tokens,
1703                                                    n_lines,
1704                                                    err_line,
1705                                                    err_msg);
1706                         if (status)
1707                                 goto error;
1708
1709                         if (block_mask & (1 << TABLE_BLOCK))
1710                                 continue;
1711
1712                         /* End of block. */
1713                         status = rte_swx_pipeline_table_config(p,
1714                                 table_spec.name,
1715                                 &table_spec.params,
1716                                 table_spec.recommended_table_type_name,
1717                                 table_spec.args,
1718                                 table_spec.size);
1719                         if (status) {
1720                                 if (err_line)
1721                                         *err_line = n_lines;
1722                                 if (err_msg)
1723                                         *err_msg = "Table configuration error.";
1724                                 goto error;
1725                         }
1726
1727                         table_spec_free(&table_spec);
1728
1729                         continue;
1730                 }
1731
1732                 /* selector block. */
1733                 if (block_mask & (1 << SELECTOR_BLOCK)) {
1734                         status = selector_block_parse(&selector_spec,
1735                                                       &block_mask,
1736                                                       tokens,
1737                                                       n_tokens,
1738                                                       n_lines,
1739                                                       err_line,
1740                                                       err_msg);
1741                         if (status)
1742                                 goto error;
1743
1744                         if (block_mask & (1 << SELECTOR_BLOCK))
1745                                 continue;
1746
1747                         /* End of block. */
1748                         status = rte_swx_pipeline_selector_config(p,
1749                                 selector_spec.name,
1750                                 &selector_spec.params);
1751                         if (status) {
1752                                 if (err_line)
1753                                         *err_line = n_lines;
1754                                 if (err_msg)
1755                                         *err_msg = "Selector configuration error.";
1756                                 goto error;
1757                         }
1758
1759                         selector_spec_free(&selector_spec);
1760
1761                         continue;
1762                 }
1763
1764                 /* apply block. */
1765                 if (block_mask & (1 << APPLY_BLOCK)) {
1766                         status = apply_block_parse(&apply_spec,
1767                                                    &block_mask,
1768                                                    tokens,
1769                                                    n_tokens,
1770                                                    n_lines,
1771                                                    err_line,
1772                                                    err_msg);
1773                         if (status)
1774                                 goto error;
1775
1776                         if (block_mask & (1 << APPLY_BLOCK))
1777                                 continue;
1778
1779                         /* End of block. */
1780                         status = rte_swx_pipeline_instructions_config(p,
1781                                 apply_spec.instructions,
1782                                 apply_spec.n_instructions);
1783                         if (status) {
1784                                 if (err_line)
1785                                         *err_line = n_lines;
1786                                 if (err_msg)
1787                                         *err_msg = "Pipeline instructions err.";
1788                                 goto error;
1789                         }
1790
1791                         apply_spec_free(&apply_spec);
1792
1793                         continue;
1794                 }
1795
1796                 /* extobj. */
1797                 if (!strcmp(tokens[0], "extobj")) {
1798                         status = extobj_statement_parse(&extobj_spec,
1799                                                         tokens,
1800                                                         n_tokens,
1801                                                         n_lines,
1802                                                         err_line,
1803                                                         err_msg);
1804                         if (status)
1805                                 goto error;
1806
1807                         status = rte_swx_pipeline_extern_object_config(p,
1808                                 extobj_spec.name,
1809                                 extobj_spec.extern_type_name,
1810                                 extobj_spec.pragma);
1811                         if (status) {
1812                                 if (err_line)
1813                                         *err_line = n_lines;
1814                                 if (err_msg)
1815                                         *err_msg = "Extern object config err.";
1816                                 goto error;
1817                         }
1818
1819                         extobj_spec_free(&extobj_spec);
1820
1821                         continue;
1822                 }
1823
1824                 /* struct. */
1825                 if (!strcmp(tokens[0], "struct")) {
1826                         status = struct_statement_parse(&struct_spec,
1827                                                         &block_mask,
1828                                                         tokens,
1829                                                         n_tokens,
1830                                                         n_lines,
1831                                                         err_line,
1832                                                         err_msg);
1833                         if (status)
1834                                 goto error;
1835
1836                         continue;
1837                 }
1838
1839                 /* header. */
1840                 if (!strcmp(tokens[0], "header")) {
1841                         status = header_statement_parse(&header_spec,
1842                                                         tokens,
1843                                                         n_tokens,
1844                                                         n_lines,
1845                                                         err_line,
1846                                                         err_msg);
1847                         if (status)
1848                                 goto error;
1849
1850                         status = rte_swx_pipeline_packet_header_register(p,
1851                                 header_spec.name,
1852                                 header_spec.struct_type_name);
1853                         if (status) {
1854                                 if (err_line)
1855                                         *err_line = n_lines;
1856                                 if (err_msg)
1857                                         *err_msg = "Header registration error.";
1858                                 goto error;
1859                         }
1860
1861                         header_spec_free(&header_spec);
1862
1863                         continue;
1864                 }
1865
1866                 /* metadata. */
1867                 if (!strcmp(tokens[0], "metadata")) {
1868                         status = metadata_statement_parse(&metadata_spec,
1869                                                           tokens,
1870                                                           n_tokens,
1871                                                           n_lines,
1872                                                           err_line,
1873                                                           err_msg);
1874                         if (status)
1875                                 goto error;
1876
1877                         status = rte_swx_pipeline_packet_metadata_register(p,
1878                                 metadata_spec.struct_type_name);
1879                         if (status) {
1880                                 if (err_line)
1881                                         *err_line = n_lines;
1882                                 if (err_msg)
1883                                         *err_msg = "Meta-data reg err.";
1884                                 goto error;
1885                         }
1886
1887                         metadata_spec_free(&metadata_spec);
1888
1889                         continue;
1890                 }
1891
1892                 /* action. */
1893                 if (!strcmp(tokens[0], "action")) {
1894                         status = action_statement_parse(&action_spec,
1895                                                         &block_mask,
1896                                                         tokens,
1897                                                         n_tokens,
1898                                                         n_lines,
1899                                                         err_line,
1900                                                         err_msg);
1901                         if (status)
1902                                 goto error;
1903
1904                         continue;
1905                 }
1906
1907                 /* table. */
1908                 if (!strcmp(tokens[0], "table")) {
1909                         status = table_statement_parse(&table_spec,
1910                                                        &block_mask,
1911                                                        tokens,
1912                                                        n_tokens,
1913                                                        n_lines,
1914                                                        err_line,
1915                                                        err_msg);
1916                         if (status)
1917                                 goto error;
1918
1919                         continue;
1920                 }
1921
1922                 /* selector. */
1923                 if (!strcmp(tokens[0], "selector")) {
1924                         status = selector_statement_parse(&selector_spec,
1925                                                           &block_mask,
1926                                                           tokens,
1927                                                           n_tokens,
1928                                                           n_lines,
1929                                                           err_line,
1930                                                           err_msg);
1931                         if (status)
1932                                 goto error;
1933
1934                         continue;
1935                 }
1936
1937                 /* regarray. */
1938                 if (!strcmp(tokens[0], "regarray")) {
1939                         status = regarray_statement_parse(&regarray_spec,
1940                                                           tokens,
1941                                                           n_tokens,
1942                                                           n_lines,
1943                                                           err_line,
1944                                                           err_msg);
1945                         if (status)
1946                                 goto error;
1947
1948                         status = rte_swx_pipeline_regarray_config(p,
1949                                 regarray_spec.name,
1950                                 regarray_spec.size,
1951                                 regarray_spec.init_val);
1952                         if (status) {
1953                                 if (err_line)
1954                                         *err_line = n_lines;
1955                                 if (err_msg)
1956                                         *err_msg = "Register array configuration error.";
1957                                 goto error;
1958                         }
1959
1960                         regarray_spec_free(&regarray_spec);
1961
1962                         continue;
1963                 }
1964
1965                 /* metarray. */
1966                 if (!strcmp(tokens[0], "metarray")) {
1967                         status = metarray_statement_parse(&metarray_spec,
1968                                                           tokens,
1969                                                           n_tokens,
1970                                                           n_lines,
1971                                                           err_line,
1972                                                           err_msg);
1973                         if (status)
1974                                 goto error;
1975
1976                         status = rte_swx_pipeline_metarray_config(p,
1977                                 metarray_spec.name,
1978                                 metarray_spec.size);
1979                         if (status) {
1980                                 if (err_line)
1981                                         *err_line = n_lines;
1982                                 if (err_msg)
1983                                         *err_msg = "Meter array configuration error.";
1984                                 goto error;
1985                         }
1986
1987                         metarray_spec_free(&metarray_spec);
1988
1989                         continue;
1990                 }
1991
1992                 /* apply. */
1993                 if (!strcmp(tokens[0], "apply")) {
1994                         status = apply_statement_parse(&block_mask,
1995                                                        tokens,
1996                                                        n_tokens,
1997                                                        n_lines,
1998                                                        err_line,
1999                                                        err_msg);
2000                         if (status)
2001                                 goto error;
2002
2003                         continue;
2004                 }
2005
2006                 /* Anything else. */
2007                 if (err_line)
2008                         *err_line = n_lines;
2009                 if (err_msg)
2010                         *err_msg = "Unknown statement.";
2011                 status = -EINVAL;
2012                 goto error;
2013         }
2014
2015         /* Handle unfinished block. */
2016         if (block_mask) {
2017                 if (err_line)
2018                         *err_line = n_lines;
2019                 if (err_msg)
2020                         *err_msg = "Missing }.";
2021                 status = -EINVAL;
2022                 goto error;
2023         }
2024
2025         /* Pipeline build. */
2026         status = rte_swx_pipeline_build(p);
2027         if (status) {
2028                 if (err_line)
2029                         *err_line = n_lines;
2030                 if (err_msg)
2031                         *err_msg = "Pipeline build error.";
2032                 goto error;
2033         }
2034
2035         return 0;
2036
2037 error:
2038         extobj_spec_free(&extobj_spec);
2039         struct_spec_free(&struct_spec);
2040         header_spec_free(&header_spec);
2041         metadata_spec_free(&metadata_spec);
2042         action_spec_free(&action_spec);
2043         table_spec_free(&table_spec);
2044         selector_spec_free(&selector_spec);
2045         regarray_spec_free(&regarray_spec);
2046         metarray_spec_free(&metarray_spec);
2047         apply_spec_free(&apply_spec);
2048         return status;
2049 }