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