xref: /dpdk/lib/pipeline/rte_swx_pipeline_spec.c (revision 9c30a6f3c9a456e8111a2b1e5f6c2c02a62025b6)
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 }
2011