xref: /dpdk/lib/pipeline/rte_swx_pipeline_spec.c (revision 0594ae0c42773d62aff870df25e73394f7f0a5a5)
199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
299a2dd95SBruce Richardson  * Copyright(c) 2020 Intel Corporation
399a2dd95SBruce Richardson  */
499a2dd95SBruce Richardson #include <stdint.h>
5894c93e1SCristian Dumitrescu #include <inttypes.h>
699a2dd95SBruce Richardson #include <stdlib.h>
799a2dd95SBruce Richardson #include <stdio.h>
899a2dd95SBruce Richardson #include <string.h>
999a2dd95SBruce Richardson #include <errno.h>
1099a2dd95SBruce Richardson 
1173d94b00SCristian Dumitrescu #include <rte_common.h>
1254cae37eSCristian Dumitrescu #include <rte_mempool.h>
1354cae37eSCristian Dumitrescu 
1454cae37eSCristian Dumitrescu #include <rte_swx_port_ethdev.h>
1554cae37eSCristian Dumitrescu #include <rte_swx_port_ring.h>
1654cae37eSCristian Dumitrescu #include <rte_swx_port_source_sink.h>
1754cae37eSCristian Dumitrescu #include <rte_swx_port_fd.h>
1873d94b00SCristian Dumitrescu 
193421eb42SCristian Dumitrescu #include "rte_swx_pipeline_spec.h"
2099a2dd95SBruce Richardson 
2173d94b00SCristian Dumitrescu #ifndef MAX_LINE_LENGTH
2273d94b00SCristian Dumitrescu #define MAX_LINE_LENGTH 2048
2373d94b00SCristian Dumitrescu #endif
2473d94b00SCristian Dumitrescu 
2573d94b00SCristian Dumitrescu #ifndef MAX_TOKENS
2673d94b00SCristian Dumitrescu #define MAX_TOKENS 256
2773d94b00SCristian Dumitrescu #endif
2899a2dd95SBruce Richardson 
2999a2dd95SBruce Richardson #define STRUCT_BLOCK 0
3099a2dd95SBruce Richardson #define ACTION_BLOCK 1
3199a2dd95SBruce Richardson #define TABLE_BLOCK 2
3299a2dd95SBruce Richardson #define TABLE_KEY_BLOCK 3
3399a2dd95SBruce Richardson #define TABLE_ACTIONS_BLOCK 4
34cdaa937dSCristian Dumitrescu #define SELECTOR_BLOCK 5
35cdaa937dSCristian Dumitrescu #define SELECTOR_SELECTOR_BLOCK 6
364f59d372SCristian Dumitrescu #define LEARNER_BLOCK 7
374f59d372SCristian Dumitrescu #define LEARNER_KEY_BLOCK 8
384f59d372SCristian Dumitrescu #define LEARNER_ACTIONS_BLOCK 9
39e2ecc535SCristian Dumitrescu #define LEARNER_TIMEOUT_BLOCK 10
40e2ecc535SCristian Dumitrescu #define APPLY_BLOCK 11
4199a2dd95SBruce Richardson 
4299a2dd95SBruce Richardson /*
4399a2dd95SBruce Richardson  * extobj.
4499a2dd95SBruce Richardson  */
4599a2dd95SBruce Richardson static void
extobj_spec_free(struct extobj_spec * s)4699a2dd95SBruce Richardson extobj_spec_free(struct extobj_spec *s)
4799a2dd95SBruce Richardson {
4899a2dd95SBruce Richardson 	if (!s)
4999a2dd95SBruce Richardson 		return;
5099a2dd95SBruce Richardson 
5199a2dd95SBruce Richardson 	free(s->name);
5299a2dd95SBruce Richardson 	s->name = NULL;
5399a2dd95SBruce Richardson 
5499a2dd95SBruce Richardson 	free(s->extern_type_name);
5599a2dd95SBruce Richardson 	s->extern_type_name = NULL;
5699a2dd95SBruce Richardson 
5799a2dd95SBruce Richardson 	free(s->pragma);
5899a2dd95SBruce Richardson 	s->pragma = NULL;
5999a2dd95SBruce Richardson }
6099a2dd95SBruce Richardson 
6199a2dd95SBruce Richardson static int
extobj_statement_parse(struct extobj_spec * s,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)6299a2dd95SBruce Richardson extobj_statement_parse(struct extobj_spec *s,
6399a2dd95SBruce Richardson 		       char **tokens,
6499a2dd95SBruce Richardson 		       uint32_t n_tokens,
6599a2dd95SBruce Richardson 		       uint32_t n_lines,
6699a2dd95SBruce Richardson 		       uint32_t *err_line,
6799a2dd95SBruce Richardson 		       const char **err_msg)
6899a2dd95SBruce Richardson {
6999a2dd95SBruce Richardson 	/* Check format. */
7099a2dd95SBruce Richardson 	if (((n_tokens != 4) && (n_tokens != 6)) ||
7199a2dd95SBruce Richardson 	    ((n_tokens == 4) && strcmp(tokens[2], "instanceof")) ||
7299a2dd95SBruce Richardson 	    ((n_tokens == 6) && (strcmp(tokens[2], "instanceof") ||
7399a2dd95SBruce Richardson 				 strcmp(tokens[4], "pragma")))) {
7499a2dd95SBruce Richardson 		if (err_line)
7599a2dd95SBruce Richardson 			*err_line = n_lines;
7699a2dd95SBruce Richardson 		if (err_msg)
7799a2dd95SBruce Richardson 			*err_msg = "Invalid extobj statement.";
7899a2dd95SBruce Richardson 		return -EINVAL;
7999a2dd95SBruce Richardson 	}
8099a2dd95SBruce Richardson 
8199a2dd95SBruce Richardson 	/* spec. */
8299a2dd95SBruce Richardson 	s->name = strdup(tokens[1]);
8399a2dd95SBruce Richardson 	s->extern_type_name = strdup(tokens[3]);
8499a2dd95SBruce Richardson 	s->pragma = (n_tokens == 6) ? strdup(tokens[5]) : NULL;
8599a2dd95SBruce Richardson 
8699a2dd95SBruce Richardson 	if (!s->name ||
8799a2dd95SBruce Richardson 	    !s->extern_type_name ||
8899a2dd95SBruce Richardson 	    ((n_tokens == 6) && !s->pragma)) {
8999a2dd95SBruce Richardson 		free(s->name);
9099a2dd95SBruce Richardson 		free(s->extern_type_name);
9199a2dd95SBruce Richardson 		free(s->pragma);
9299a2dd95SBruce Richardson 
9399a2dd95SBruce Richardson 		if (err_line)
9499a2dd95SBruce Richardson 			*err_line = n_lines;
9599a2dd95SBruce Richardson 		if (err_msg)
9699a2dd95SBruce Richardson 			*err_msg = "Memory allocation failed.";
9799a2dd95SBruce Richardson 		return -ENOMEM;
9899a2dd95SBruce Richardson 	}
9999a2dd95SBruce Richardson 
10099a2dd95SBruce Richardson 	return 0;
10199a2dd95SBruce Richardson }
10299a2dd95SBruce Richardson 
10399a2dd95SBruce Richardson /*
10499a2dd95SBruce Richardson  * struct.
10599a2dd95SBruce Richardson  */
10699a2dd95SBruce Richardson static void
struct_spec_free(struct struct_spec * s)10799a2dd95SBruce Richardson struct_spec_free(struct struct_spec *s)
10899a2dd95SBruce Richardson {
10999a2dd95SBruce Richardson 	uint32_t i;
11099a2dd95SBruce Richardson 
11199a2dd95SBruce Richardson 	if (!s)
11299a2dd95SBruce Richardson 		return;
11399a2dd95SBruce Richardson 
11499a2dd95SBruce Richardson 	free(s->name);
11599a2dd95SBruce Richardson 	s->name = NULL;
11699a2dd95SBruce Richardson 
11799a2dd95SBruce Richardson 	for (i = 0; i < s->n_fields; i++) {
11899a2dd95SBruce Richardson 		uintptr_t name = (uintptr_t)s->fields[i].name;
11999a2dd95SBruce Richardson 
12099a2dd95SBruce Richardson 		free((void *)name);
12199a2dd95SBruce Richardson 	}
12299a2dd95SBruce Richardson 
12399a2dd95SBruce Richardson 	free(s->fields);
12499a2dd95SBruce Richardson 	s->fields = NULL;
12599a2dd95SBruce Richardson 
12699a2dd95SBruce Richardson 	s->n_fields = 0;
127cef38969SCristian Dumitrescu 
128cef38969SCristian Dumitrescu 	s->varbit = 0;
12999a2dd95SBruce Richardson }
13099a2dd95SBruce Richardson 
13199a2dd95SBruce Richardson static int
struct_statement_parse(struct struct_spec * s,uint32_t * block_mask,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)13299a2dd95SBruce Richardson struct_statement_parse(struct struct_spec *s,
13399a2dd95SBruce Richardson 		       uint32_t *block_mask,
13499a2dd95SBruce Richardson 		       char **tokens,
13599a2dd95SBruce Richardson 		       uint32_t n_tokens,
13699a2dd95SBruce Richardson 		       uint32_t n_lines,
13799a2dd95SBruce Richardson 		       uint32_t *err_line,
13899a2dd95SBruce Richardson 		       const char **err_msg)
13999a2dd95SBruce Richardson {
14099a2dd95SBruce Richardson 	/* Check format. */
14199a2dd95SBruce Richardson 	if ((n_tokens != 3) || strcmp(tokens[2], "{")) {
14299a2dd95SBruce Richardson 		if (err_line)
14399a2dd95SBruce Richardson 			*err_line = n_lines;
14499a2dd95SBruce Richardson 		if (err_msg)
14599a2dd95SBruce Richardson 			*err_msg = "Invalid struct statement.";
14699a2dd95SBruce Richardson 		return -EINVAL;
14799a2dd95SBruce Richardson 	}
14899a2dd95SBruce Richardson 
14999a2dd95SBruce Richardson 	/* spec. */
15099a2dd95SBruce Richardson 	s->name = strdup(tokens[1]);
15199a2dd95SBruce Richardson 	if (!s->name) {
15299a2dd95SBruce Richardson 		if (err_line)
15399a2dd95SBruce Richardson 			*err_line = n_lines;
15499a2dd95SBruce Richardson 		if (err_msg)
15599a2dd95SBruce Richardson 			*err_msg = "Memory allocation failed.";
15699a2dd95SBruce Richardson 		return -ENOMEM;
15799a2dd95SBruce Richardson 	}
15899a2dd95SBruce Richardson 
15999a2dd95SBruce Richardson 	/* block_mask. */
16099a2dd95SBruce Richardson 	*block_mask |= 1 << STRUCT_BLOCK;
16199a2dd95SBruce Richardson 
16299a2dd95SBruce Richardson 	return 0;
16399a2dd95SBruce Richardson }
16499a2dd95SBruce Richardson 
16599a2dd95SBruce Richardson static int
struct_block_parse(struct struct_spec * s,uint32_t * block_mask,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)16699a2dd95SBruce Richardson struct_block_parse(struct struct_spec *s,
16799a2dd95SBruce Richardson 		   uint32_t *block_mask,
16899a2dd95SBruce Richardson 		   char **tokens,
16999a2dd95SBruce Richardson 		   uint32_t n_tokens,
17099a2dd95SBruce Richardson 		   uint32_t n_lines,
17199a2dd95SBruce Richardson 		   uint32_t *err_line,
17299a2dd95SBruce Richardson 		   const char **err_msg)
17399a2dd95SBruce Richardson {
17499a2dd95SBruce Richardson 	struct rte_swx_field_params *new_fields;
175cef38969SCristian Dumitrescu 	char *p = tokens[0], *name = NULL;
17699a2dd95SBruce Richardson 	uint32_t n_bits;
177cef38969SCristian Dumitrescu 	int varbit = 0, error = 0, error_size_invalid = 0, error_varbit_not_last = 0;
17899a2dd95SBruce Richardson 
17999a2dd95SBruce Richardson 	/* Handle end of block. */
18099a2dd95SBruce Richardson 	if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
18199a2dd95SBruce Richardson 		*block_mask &= ~(1 << STRUCT_BLOCK);
18299a2dd95SBruce Richardson 		return 0;
18399a2dd95SBruce Richardson 	}
18499a2dd95SBruce Richardson 
18599a2dd95SBruce Richardson 	/* Check format. */
186cef38969SCristian Dumitrescu 	if (n_tokens != 2) {
187cef38969SCristian Dumitrescu 		error = -EINVAL;
188cef38969SCristian Dumitrescu 		goto error;
189cef38969SCristian Dumitrescu 	}
190cef38969SCristian Dumitrescu 
191cef38969SCristian Dumitrescu 	if (s->varbit) {
192cef38969SCristian Dumitrescu 		error = -EINVAL;
193cef38969SCristian Dumitrescu 		error_varbit_not_last = 1;
194cef38969SCristian Dumitrescu 		goto error;
195cef38969SCristian Dumitrescu 	}
196cef38969SCristian Dumitrescu 
197cef38969SCristian Dumitrescu 	if (!strncmp(p, "bit<", strlen("bit<"))) {
198cef38969SCristian Dumitrescu 		size_t len = strlen(p);
199cef38969SCristian Dumitrescu 
200cef38969SCristian Dumitrescu 		if ((len < strlen("bit< >")) || (p[len - 1] != '>')) {
201cef38969SCristian Dumitrescu 			error = -EINVAL;
202cef38969SCristian Dumitrescu 			goto error;
20399a2dd95SBruce Richardson 		}
20499a2dd95SBruce Richardson 
20599a2dd95SBruce Richardson 		/* Remove the "bit<" and ">". */
20699a2dd95SBruce Richardson 		p[strlen(p) - 1] = 0;
207cef38969SCristian Dumitrescu 		p += strlen("bit<");
208cef38969SCristian Dumitrescu 	} else if (!strncmp(p, "varbit<", strlen("varbit<"))) {
209cef38969SCristian Dumitrescu 		size_t len = strlen(p);
210cef38969SCristian Dumitrescu 
211cef38969SCristian Dumitrescu 		if ((len < strlen("varbit< >")) || (p[len - 1] != '>')) {
212cef38969SCristian Dumitrescu 			error = -EINVAL;
213cef38969SCristian Dumitrescu 			goto error;
214cef38969SCristian Dumitrescu 		}
215cef38969SCristian Dumitrescu 
216cef38969SCristian Dumitrescu 		/* Remove the "varbit<" and ">". */
217cef38969SCristian Dumitrescu 		p[strlen(p) - 1] = 0;
218cef38969SCristian Dumitrescu 		p += strlen("varbit<");
219cef38969SCristian Dumitrescu 
220cef38969SCristian Dumitrescu 		/* Set the varbit flag. */
221cef38969SCristian Dumitrescu 		varbit = 1;
222cef38969SCristian Dumitrescu 	} else {
223cef38969SCristian Dumitrescu 		error = -EINVAL;
224cef38969SCristian Dumitrescu 		goto error;
225cef38969SCristian Dumitrescu 	}
22699a2dd95SBruce Richardson 
22799a2dd95SBruce Richardson 	n_bits = strtoul(p, &p, 0);
22899a2dd95SBruce Richardson 	if ((p[0]) ||
22999a2dd95SBruce Richardson 	    !n_bits ||
230076d6128SCristian Dumitrescu 	    (n_bits % 8)) {
231cef38969SCristian Dumitrescu 		error = -EINVAL;
232cef38969SCristian Dumitrescu 		error_size_invalid = 1;
233cef38969SCristian Dumitrescu 		goto error;
23499a2dd95SBruce Richardson 	}
23599a2dd95SBruce Richardson 
23699a2dd95SBruce Richardson 	/* spec. */
23799a2dd95SBruce Richardson 	name = strdup(tokens[1]);
23899a2dd95SBruce Richardson 	if (!name) {
239cef38969SCristian Dumitrescu 		error = -ENOMEM;
240cef38969SCristian Dumitrescu 		goto error;
24199a2dd95SBruce Richardson 	}
24299a2dd95SBruce Richardson 
243cef38969SCristian Dumitrescu 	new_fields = realloc(s->fields, (s->n_fields + 1) * sizeof(struct rte_swx_field_params));
24499a2dd95SBruce Richardson 	if (!new_fields) {
245cef38969SCristian Dumitrescu 		error = -ENOMEM;
246cef38969SCristian Dumitrescu 		goto error;
24799a2dd95SBruce Richardson 	}
24899a2dd95SBruce Richardson 
24999a2dd95SBruce Richardson 	s->fields = new_fields;
25099a2dd95SBruce Richardson 	s->fields[s->n_fields].name = name;
25199a2dd95SBruce Richardson 	s->fields[s->n_fields].n_bits = n_bits;
25299a2dd95SBruce Richardson 	s->n_fields++;
253cef38969SCristian Dumitrescu 	s->varbit = varbit;
25499a2dd95SBruce Richardson 
25599a2dd95SBruce Richardson 	return 0;
256cef38969SCristian Dumitrescu 
257cef38969SCristian Dumitrescu error:
258cef38969SCristian Dumitrescu 	free(name);
259cef38969SCristian Dumitrescu 
260cef38969SCristian Dumitrescu 	if (err_line)
261cef38969SCristian Dumitrescu 		*err_line = n_lines;
262cef38969SCristian Dumitrescu 
263cef38969SCristian Dumitrescu 	if (err_msg) {
264cef38969SCristian Dumitrescu 		*err_msg = "Invalid struct field statement.";
265cef38969SCristian Dumitrescu 
266cef38969SCristian Dumitrescu 		if ((error == -EINVAL) && error_varbit_not_last)
267cef38969SCristian Dumitrescu 			*err_msg = "Varbit field is not the last struct field.";
268cef38969SCristian Dumitrescu 
269cef38969SCristian Dumitrescu 		if ((error == -EINVAL) && error_size_invalid)
270cef38969SCristian Dumitrescu 			*err_msg = "Invalid struct field size.";
271cef38969SCristian Dumitrescu 
272cef38969SCristian Dumitrescu 		if (error == -ENOMEM)
273cef38969SCristian Dumitrescu 			*err_msg = "Memory allocation failed.";
274cef38969SCristian Dumitrescu 	}
275cef38969SCristian Dumitrescu 
276cef38969SCristian Dumitrescu 	return error;
27799a2dd95SBruce Richardson }
27899a2dd95SBruce Richardson 
27999a2dd95SBruce Richardson /*
28099a2dd95SBruce Richardson  * header.
28199a2dd95SBruce Richardson  */
28299a2dd95SBruce Richardson static void
header_spec_free(struct header_spec * s)28399a2dd95SBruce Richardson header_spec_free(struct header_spec *s)
28499a2dd95SBruce Richardson {
28599a2dd95SBruce Richardson 	if (!s)
28699a2dd95SBruce Richardson 		return;
28799a2dd95SBruce Richardson 
28899a2dd95SBruce Richardson 	free(s->name);
28999a2dd95SBruce Richardson 	s->name = NULL;
29099a2dd95SBruce Richardson 
29199a2dd95SBruce Richardson 	free(s->struct_type_name);
29299a2dd95SBruce Richardson 	s->struct_type_name = NULL;
29399a2dd95SBruce Richardson }
29499a2dd95SBruce Richardson 
29599a2dd95SBruce Richardson static int
header_statement_parse(struct header_spec * s,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)29699a2dd95SBruce Richardson header_statement_parse(struct header_spec *s,
29799a2dd95SBruce Richardson 		       char **tokens,
29899a2dd95SBruce Richardson 		       uint32_t n_tokens,
29999a2dd95SBruce Richardson 		       uint32_t n_lines,
30099a2dd95SBruce Richardson 		       uint32_t *err_line,
30199a2dd95SBruce Richardson 		       const char **err_msg)
30299a2dd95SBruce Richardson {
30399a2dd95SBruce Richardson 	/* Check format. */
30499a2dd95SBruce Richardson 	if ((n_tokens != 4) || strcmp(tokens[2], "instanceof")) {
30599a2dd95SBruce Richardson 		if (err_line)
30699a2dd95SBruce Richardson 			*err_line = n_lines;
30799a2dd95SBruce Richardson 		if (err_msg)
30899a2dd95SBruce Richardson 			*err_msg = "Invalid header statement.";
30999a2dd95SBruce Richardson 		return -EINVAL;
31099a2dd95SBruce Richardson 	}
31199a2dd95SBruce Richardson 
31299a2dd95SBruce Richardson 	/* spec. */
31399a2dd95SBruce Richardson 	s->name = strdup(tokens[1]);
31499a2dd95SBruce Richardson 	s->struct_type_name = strdup(tokens[3]);
31599a2dd95SBruce Richardson 
31699a2dd95SBruce Richardson 	if (!s->name || !s->struct_type_name) {
31799a2dd95SBruce Richardson 		free(s->name);
31899a2dd95SBruce Richardson 		free(s->struct_type_name);
31999a2dd95SBruce Richardson 
32099a2dd95SBruce Richardson 		if (err_line)
32199a2dd95SBruce Richardson 			*err_line = n_lines;
32299a2dd95SBruce Richardson 		if (err_msg)
32399a2dd95SBruce Richardson 			*err_msg = "Memory allocation failed.";
32499a2dd95SBruce Richardson 		return -ENOMEM;
32599a2dd95SBruce Richardson 	}
32699a2dd95SBruce Richardson 
32799a2dd95SBruce Richardson 	return 0;
32899a2dd95SBruce Richardson }
32999a2dd95SBruce Richardson 
33099a2dd95SBruce Richardson /*
33199a2dd95SBruce Richardson  * metadata.
33299a2dd95SBruce Richardson  */
33399a2dd95SBruce Richardson static void
metadata_spec_free(struct metadata_spec * s)33499a2dd95SBruce Richardson metadata_spec_free(struct metadata_spec *s)
33599a2dd95SBruce Richardson {
33699a2dd95SBruce Richardson 	if (!s)
33799a2dd95SBruce Richardson 		return;
33899a2dd95SBruce Richardson 
33999a2dd95SBruce Richardson 	free(s->struct_type_name);
34099a2dd95SBruce Richardson 	s->struct_type_name = NULL;
34199a2dd95SBruce Richardson }
34299a2dd95SBruce Richardson 
34399a2dd95SBruce Richardson static int
metadata_statement_parse(struct metadata_spec * s,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)34499a2dd95SBruce Richardson metadata_statement_parse(struct metadata_spec *s,
34599a2dd95SBruce Richardson 			 char **tokens,
34699a2dd95SBruce Richardson 			 uint32_t n_tokens,
34799a2dd95SBruce Richardson 			 uint32_t n_lines,
34899a2dd95SBruce Richardson 			 uint32_t *err_line,
34999a2dd95SBruce Richardson 			 const char **err_msg)
35099a2dd95SBruce Richardson {
35199a2dd95SBruce Richardson 	/* Check format. */
35299a2dd95SBruce Richardson 	if ((n_tokens != 3) || strcmp(tokens[1], "instanceof")) {
35399a2dd95SBruce Richardson 		if (err_line)
35499a2dd95SBruce Richardson 			*err_line = n_lines;
35599a2dd95SBruce Richardson 		if (err_msg)
35699a2dd95SBruce Richardson 			*err_msg = "Invalid metadata statement.";
35799a2dd95SBruce Richardson 		return -EINVAL;
35899a2dd95SBruce Richardson 	}
35999a2dd95SBruce Richardson 
36099a2dd95SBruce Richardson 	/* spec. */
36199a2dd95SBruce Richardson 	s->struct_type_name = strdup(tokens[2]);
36299a2dd95SBruce Richardson 	if (!s->struct_type_name) {
36399a2dd95SBruce Richardson 		if (err_line)
36499a2dd95SBruce Richardson 			*err_line = n_lines;
36599a2dd95SBruce Richardson 		if (err_msg)
36699a2dd95SBruce Richardson 			*err_msg = "Memory allocation failed.";
36799a2dd95SBruce Richardson 		return -ENOMEM;
36899a2dd95SBruce Richardson 	}
36999a2dd95SBruce Richardson 
37099a2dd95SBruce Richardson 	return 0;
37199a2dd95SBruce Richardson }
37299a2dd95SBruce Richardson 
37399a2dd95SBruce Richardson /*
37499a2dd95SBruce Richardson  * action.
37599a2dd95SBruce Richardson  */
37699a2dd95SBruce Richardson static void
action_spec_free(struct action_spec * s)37799a2dd95SBruce Richardson action_spec_free(struct action_spec *s)
37899a2dd95SBruce Richardson {
37999a2dd95SBruce Richardson 	uint32_t i;
38099a2dd95SBruce Richardson 
38199a2dd95SBruce Richardson 	if (!s)
38299a2dd95SBruce Richardson 		return;
38399a2dd95SBruce Richardson 
38499a2dd95SBruce Richardson 	free(s->name);
38599a2dd95SBruce Richardson 	s->name = NULL;
38699a2dd95SBruce Richardson 
38799a2dd95SBruce Richardson 	free(s->args_struct_type_name);
38899a2dd95SBruce Richardson 	s->args_struct_type_name = NULL;
38999a2dd95SBruce Richardson 
39099a2dd95SBruce Richardson 	for (i = 0; i < s->n_instructions; i++) {
39199a2dd95SBruce Richardson 		uintptr_t instr = (uintptr_t)s->instructions[i];
39299a2dd95SBruce Richardson 
39399a2dd95SBruce Richardson 		free((void *)instr);
39499a2dd95SBruce Richardson 	}
39599a2dd95SBruce Richardson 
39699a2dd95SBruce Richardson 	free(s->instructions);
39799a2dd95SBruce Richardson 	s->instructions = NULL;
39899a2dd95SBruce Richardson 
39999a2dd95SBruce Richardson 	s->n_instructions = 0;
40099a2dd95SBruce Richardson }
40199a2dd95SBruce Richardson 
40299a2dd95SBruce Richardson static int
action_statement_parse(struct action_spec * s,uint32_t * block_mask,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)40399a2dd95SBruce Richardson action_statement_parse(struct action_spec *s,
40499a2dd95SBruce Richardson 		       uint32_t *block_mask,
40599a2dd95SBruce Richardson 		       char **tokens,
40699a2dd95SBruce Richardson 		       uint32_t n_tokens,
40799a2dd95SBruce Richardson 		       uint32_t n_lines,
40899a2dd95SBruce Richardson 		       uint32_t *err_line,
40999a2dd95SBruce Richardson 		       const char **err_msg)
41099a2dd95SBruce Richardson {
41199a2dd95SBruce Richardson 	/* Check format. */
41299a2dd95SBruce Richardson 	if (((n_tokens != 5) && (n_tokens != 6)) ||
41399a2dd95SBruce Richardson 	    ((n_tokens == 5) &&
41499a2dd95SBruce Richardson 	     (strcmp(tokens[2], "args") ||
41599a2dd95SBruce Richardson 	      strcmp(tokens[3], "none") ||
41699a2dd95SBruce Richardson 	      strcmp(tokens[4], "{"))) ||
41799a2dd95SBruce Richardson 	    ((n_tokens == 6) &&
41899a2dd95SBruce Richardson 	     (strcmp(tokens[2], "args") ||
41999a2dd95SBruce Richardson 	      strcmp(tokens[3], "instanceof") ||
42099a2dd95SBruce Richardson 	      strcmp(tokens[5], "{")))) {
42199a2dd95SBruce Richardson 		if (err_line)
42299a2dd95SBruce Richardson 			*err_line = n_lines;
42399a2dd95SBruce Richardson 		if (err_msg)
42499a2dd95SBruce Richardson 			*err_msg = "Invalid action statement.";
42599a2dd95SBruce Richardson 		return -EINVAL;
42699a2dd95SBruce Richardson 	}
42799a2dd95SBruce Richardson 
42899a2dd95SBruce Richardson 	/* spec. */
42999a2dd95SBruce Richardson 	s->name = strdup(tokens[1]);
43099a2dd95SBruce Richardson 	s->args_struct_type_name = (n_tokens == 6) ? strdup(tokens[4]) : NULL;
43199a2dd95SBruce Richardson 
43299a2dd95SBruce Richardson 	if ((!s->name) || ((n_tokens == 6) && !s->args_struct_type_name)) {
43399a2dd95SBruce Richardson 		if (err_line)
43499a2dd95SBruce Richardson 			*err_line = n_lines;
43599a2dd95SBruce Richardson 		if (err_msg)
43699a2dd95SBruce Richardson 			*err_msg = "Memory allocation failed.";
43799a2dd95SBruce Richardson 		return -ENOMEM;
43899a2dd95SBruce Richardson 	}
43999a2dd95SBruce Richardson 
44099a2dd95SBruce Richardson 	/* block_mask. */
44199a2dd95SBruce Richardson 	*block_mask |= 1 << ACTION_BLOCK;
44299a2dd95SBruce Richardson 
44399a2dd95SBruce Richardson 	return 0;
44499a2dd95SBruce Richardson }
44599a2dd95SBruce Richardson 
44699a2dd95SBruce Richardson static int
action_block_parse(struct action_spec * s,uint32_t * block_mask,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)44799a2dd95SBruce Richardson action_block_parse(struct action_spec *s,
44899a2dd95SBruce Richardson 		   uint32_t *block_mask,
44999a2dd95SBruce Richardson 		   char **tokens,
45099a2dd95SBruce Richardson 		   uint32_t n_tokens,
45199a2dd95SBruce Richardson 		   uint32_t n_lines,
45299a2dd95SBruce Richardson 		   uint32_t *err_line,
45399a2dd95SBruce Richardson 		   const char **err_msg)
45499a2dd95SBruce Richardson {
45599a2dd95SBruce Richardson 	char buffer[RTE_SWX_INSTRUCTION_SIZE], *instr;
45699a2dd95SBruce Richardson 	const char **new_instructions;
45799a2dd95SBruce Richardson 	uint32_t i;
45899a2dd95SBruce Richardson 
45999a2dd95SBruce Richardson 	/* Handle end of block. */
46099a2dd95SBruce Richardson 	if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
46199a2dd95SBruce Richardson 		*block_mask &= ~(1 << ACTION_BLOCK);
46299a2dd95SBruce Richardson 		return 0;
46399a2dd95SBruce Richardson 	}
46499a2dd95SBruce Richardson 
46599a2dd95SBruce Richardson 	/* spec. */
46699a2dd95SBruce Richardson 	buffer[0] = 0;
46799a2dd95SBruce Richardson 	for (i = 0; i < n_tokens; i++) {
46899a2dd95SBruce Richardson 		if (i)
46999a2dd95SBruce Richardson 			strcat(buffer, " ");
47099a2dd95SBruce Richardson 		strcat(buffer, tokens[i]);
47199a2dd95SBruce Richardson 	}
47299a2dd95SBruce Richardson 
47399a2dd95SBruce Richardson 	instr = strdup(buffer);
47499a2dd95SBruce Richardson 	if (!instr) {
47599a2dd95SBruce Richardson 		if (err_line)
47699a2dd95SBruce Richardson 			*err_line = n_lines;
47799a2dd95SBruce Richardson 		if (err_msg)
47899a2dd95SBruce Richardson 			*err_msg = "Memory allocation failed.";
47999a2dd95SBruce Richardson 		return -ENOMEM;
48099a2dd95SBruce Richardson 	}
48199a2dd95SBruce Richardson 
48299a2dd95SBruce Richardson 	new_instructions = realloc(s->instructions,
48399a2dd95SBruce Richardson 				   (s->n_instructions + 1) * sizeof(char *));
48499a2dd95SBruce Richardson 	if (!new_instructions) {
48599a2dd95SBruce Richardson 		free(instr);
48699a2dd95SBruce Richardson 
48799a2dd95SBruce Richardson 		if (err_line)
48899a2dd95SBruce Richardson 			*err_line = n_lines;
48999a2dd95SBruce Richardson 		if (err_msg)
49099a2dd95SBruce Richardson 			*err_msg = "Memory allocation failed.";
49199a2dd95SBruce Richardson 		return -ENOMEM;
49299a2dd95SBruce Richardson 	}
49399a2dd95SBruce Richardson 
49499a2dd95SBruce Richardson 	s->instructions = new_instructions;
49599a2dd95SBruce Richardson 	s->instructions[s->n_instructions] = instr;
49699a2dd95SBruce Richardson 	s->n_instructions++;
49799a2dd95SBruce Richardson 
49899a2dd95SBruce Richardson 	return 0;
49999a2dd95SBruce Richardson }
50099a2dd95SBruce Richardson 
50199a2dd95SBruce Richardson /*
50299a2dd95SBruce Richardson  * table.
50399a2dd95SBruce Richardson  */
50499a2dd95SBruce Richardson static void
table_spec_free(struct table_spec * s)50599a2dd95SBruce Richardson table_spec_free(struct table_spec *s)
50699a2dd95SBruce Richardson {
5079560a329SCristian Dumitrescu 	uintptr_t default_action_name, default_action_args, hash_func_name;
50899a2dd95SBruce Richardson 	uint32_t i;
50999a2dd95SBruce Richardson 
51099a2dd95SBruce Richardson 	if (!s)
51199a2dd95SBruce Richardson 		return;
51299a2dd95SBruce Richardson 
51399a2dd95SBruce Richardson 	free(s->name);
51499a2dd95SBruce Richardson 	s->name = NULL;
51599a2dd95SBruce Richardson 
51699a2dd95SBruce Richardson 	for (i = 0; i < s->params.n_fields; i++) {
51799a2dd95SBruce Richardson 		uintptr_t name = (uintptr_t)s->params.fields[i].name;
51899a2dd95SBruce Richardson 
51999a2dd95SBruce Richardson 		free((void *)name);
52099a2dd95SBruce Richardson 	}
52199a2dd95SBruce Richardson 
52299a2dd95SBruce Richardson 	free(s->params.fields);
52399a2dd95SBruce Richardson 	s->params.fields = NULL;
52499a2dd95SBruce Richardson 
52599a2dd95SBruce Richardson 	s->params.n_fields = 0;
52699a2dd95SBruce Richardson 
52799a2dd95SBruce Richardson 	for (i = 0; i < s->params.n_actions; i++) {
52899a2dd95SBruce Richardson 		uintptr_t name = (uintptr_t)s->params.action_names[i];
52999a2dd95SBruce Richardson 
53099a2dd95SBruce Richardson 		free((void *)name);
53199a2dd95SBruce Richardson 	}
53299a2dd95SBruce Richardson 
53399a2dd95SBruce Richardson 	free(s->params.action_names);
53499a2dd95SBruce Richardson 	s->params.action_names = NULL;
53599a2dd95SBruce Richardson 
53699a2dd95SBruce Richardson 	s->params.n_actions = 0;
53799a2dd95SBruce Richardson 
53899a2dd95SBruce Richardson 	default_action_name = (uintptr_t)s->params.default_action_name;
53999a2dd95SBruce Richardson 	free((void *)default_action_name);
54099a2dd95SBruce Richardson 	s->params.default_action_name = NULL;
54199a2dd95SBruce Richardson 
54273d94b00SCristian Dumitrescu 	default_action_args = (uintptr_t)s->params.default_action_args;
54373d94b00SCristian Dumitrescu 	free((void *)default_action_args);
54473d94b00SCristian Dumitrescu 	s->params.default_action_args = NULL;
54599a2dd95SBruce Richardson 
546cd79e020SYogesh Jangra 	free(s->params.action_is_for_table_entries);
547cd79e020SYogesh Jangra 	s->params.action_is_for_table_entries = NULL;
548cd79e020SYogesh Jangra 
549cd79e020SYogesh Jangra 	free(s->params.action_is_for_default_entry);
550cd79e020SYogesh Jangra 	s->params.action_is_for_default_entry = NULL;
551cd79e020SYogesh Jangra 
55299a2dd95SBruce Richardson 	s->params.default_action_is_const = 0;
55399a2dd95SBruce Richardson 
5549560a329SCristian Dumitrescu 	hash_func_name = (uintptr_t)s->params.hash_func_name;
5559560a329SCristian Dumitrescu 	free((void *)hash_func_name);
5569560a329SCristian Dumitrescu 	s->params.hash_func_name = NULL;
5579560a329SCristian Dumitrescu 
55899a2dd95SBruce Richardson 	free(s->recommended_table_type_name);
55999a2dd95SBruce Richardson 	s->recommended_table_type_name = NULL;
56099a2dd95SBruce Richardson 
56199a2dd95SBruce Richardson 	free(s->args);
56299a2dd95SBruce Richardson 	s->args = NULL;
56399a2dd95SBruce Richardson 
56499a2dd95SBruce Richardson 	s->size = 0;
56599a2dd95SBruce Richardson }
56699a2dd95SBruce Richardson 
56799a2dd95SBruce Richardson static int
table_key_statement_parse(uint32_t * block_mask,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)56899a2dd95SBruce Richardson table_key_statement_parse(uint32_t *block_mask,
56999a2dd95SBruce Richardson 			  char **tokens,
57099a2dd95SBruce Richardson 			  uint32_t n_tokens,
57199a2dd95SBruce Richardson 			  uint32_t n_lines,
57299a2dd95SBruce Richardson 			  uint32_t *err_line,
57399a2dd95SBruce Richardson 			  const char **err_msg)
57499a2dd95SBruce Richardson {
57599a2dd95SBruce Richardson 	/* Check format. */
57699a2dd95SBruce Richardson 	if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
57799a2dd95SBruce Richardson 		if (err_line)
57899a2dd95SBruce Richardson 			*err_line = n_lines;
57999a2dd95SBruce Richardson 		if (err_msg)
58099a2dd95SBruce Richardson 			*err_msg = "Invalid key statement.";
58199a2dd95SBruce Richardson 		return -EINVAL;
58299a2dd95SBruce Richardson 	}
58399a2dd95SBruce Richardson 
58499a2dd95SBruce Richardson 	/* block_mask. */
58599a2dd95SBruce Richardson 	*block_mask |= 1 << TABLE_KEY_BLOCK;
58699a2dd95SBruce Richardson 
58799a2dd95SBruce Richardson 	return 0;
58899a2dd95SBruce Richardson }
58999a2dd95SBruce Richardson 
59099a2dd95SBruce Richardson static int
table_key_block_parse(struct table_spec * s,uint32_t * block_mask,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)59199a2dd95SBruce Richardson table_key_block_parse(struct table_spec *s,
59299a2dd95SBruce Richardson 		      uint32_t *block_mask,
59399a2dd95SBruce Richardson 		      char **tokens,
59499a2dd95SBruce Richardson 		      uint32_t n_tokens,
59599a2dd95SBruce Richardson 		      uint32_t n_lines,
59699a2dd95SBruce Richardson 		      uint32_t *err_line,
59799a2dd95SBruce Richardson 		      const char **err_msg)
59899a2dd95SBruce Richardson {
59999a2dd95SBruce Richardson 	struct rte_swx_match_field_params *new_fields;
60099a2dd95SBruce Richardson 	enum rte_swx_table_match_type match_type = RTE_SWX_TABLE_MATCH_WILDCARD;
60199a2dd95SBruce Richardson 	char *name;
60299a2dd95SBruce Richardson 
60399a2dd95SBruce Richardson 	/* Handle end of block. */
60499a2dd95SBruce Richardson 	if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
60599a2dd95SBruce Richardson 		*block_mask &= ~(1 << TABLE_KEY_BLOCK);
60699a2dd95SBruce Richardson 		return 0;
60799a2dd95SBruce Richardson 	}
60899a2dd95SBruce Richardson 
60999a2dd95SBruce Richardson 	/* Check input arguments. */
61099a2dd95SBruce Richardson 	if ((n_tokens != 2) ||
61199a2dd95SBruce Richardson 	    (strcmp(tokens[1], "exact") &&
61299a2dd95SBruce Richardson 	     strcmp(tokens[1], "wildcard") &&
61399a2dd95SBruce Richardson 	     strcmp(tokens[1], "lpm"))) {
61499a2dd95SBruce Richardson 		if (err_line)
61599a2dd95SBruce Richardson 			*err_line = n_lines;
61699a2dd95SBruce Richardson 		if (err_msg)
61799a2dd95SBruce Richardson 			*err_msg = "Invalid match field statement.";
61899a2dd95SBruce Richardson 		return -EINVAL;
61999a2dd95SBruce Richardson 	}
62099a2dd95SBruce Richardson 
62199a2dd95SBruce Richardson 	if (!strcmp(tokens[1], "wildcard"))
62299a2dd95SBruce Richardson 		match_type = RTE_SWX_TABLE_MATCH_WILDCARD;
62399a2dd95SBruce Richardson 	if (!strcmp(tokens[1], "lpm"))
62499a2dd95SBruce Richardson 		match_type = RTE_SWX_TABLE_MATCH_LPM;
62599a2dd95SBruce Richardson 	if (!strcmp(tokens[1], "exact"))
62699a2dd95SBruce Richardson 		match_type = RTE_SWX_TABLE_MATCH_EXACT;
62799a2dd95SBruce Richardson 
62899a2dd95SBruce Richardson 	name = strdup(tokens[0]);
62999a2dd95SBruce Richardson 	if (!name) {
63099a2dd95SBruce Richardson 		if (err_line)
63199a2dd95SBruce Richardson 			*err_line = n_lines;
63299a2dd95SBruce Richardson 		if (err_msg)
63399a2dd95SBruce Richardson 			*err_msg = "Memory allocation failed.";
63499a2dd95SBruce Richardson 		return -ENOMEM;
63599a2dd95SBruce Richardson 	}
63699a2dd95SBruce Richardson 
63799a2dd95SBruce Richardson 	new_fields = realloc(s->params.fields,
63899a2dd95SBruce Richardson 			     (s->params.n_fields + 1) * sizeof(struct rte_swx_match_field_params));
63999a2dd95SBruce Richardson 	if (!new_fields) {
64099a2dd95SBruce Richardson 		free(name);
64199a2dd95SBruce Richardson 
64299a2dd95SBruce Richardson 		if (err_line)
64399a2dd95SBruce Richardson 			*err_line = n_lines;
64499a2dd95SBruce Richardson 		if (err_msg)
64599a2dd95SBruce Richardson 			*err_msg = "Memory allocation failed.";
64699a2dd95SBruce Richardson 		return -ENOMEM;
64799a2dd95SBruce Richardson 	}
64899a2dd95SBruce Richardson 
64999a2dd95SBruce Richardson 	s->params.fields = new_fields;
65099a2dd95SBruce Richardson 	s->params.fields[s->params.n_fields].name = name;
65199a2dd95SBruce Richardson 	s->params.fields[s->params.n_fields].match_type = match_type;
65299a2dd95SBruce Richardson 	s->params.n_fields++;
65399a2dd95SBruce Richardson 
65499a2dd95SBruce Richardson 	return 0;
65599a2dd95SBruce Richardson }
65699a2dd95SBruce Richardson 
65799a2dd95SBruce Richardson static int
table_actions_statement_parse(uint32_t * block_mask,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)65899a2dd95SBruce Richardson table_actions_statement_parse(uint32_t *block_mask,
65999a2dd95SBruce Richardson 			      char **tokens,
66099a2dd95SBruce Richardson 			      uint32_t n_tokens,
66199a2dd95SBruce Richardson 			      uint32_t n_lines,
66299a2dd95SBruce Richardson 			      uint32_t *err_line,
66399a2dd95SBruce Richardson 			      const char **err_msg)
66499a2dd95SBruce Richardson {
66599a2dd95SBruce Richardson 	/* Check format. */
66699a2dd95SBruce Richardson 	if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
66799a2dd95SBruce Richardson 		if (err_line)
66899a2dd95SBruce Richardson 			*err_line = n_lines;
66999a2dd95SBruce Richardson 		if (err_msg)
67099a2dd95SBruce Richardson 			*err_msg = "Invalid actions statement.";
67199a2dd95SBruce Richardson 		return -EINVAL;
67299a2dd95SBruce Richardson 	}
67399a2dd95SBruce Richardson 
67499a2dd95SBruce Richardson 	/* block_mask. */
67599a2dd95SBruce Richardson 	*block_mask |= 1 << TABLE_ACTIONS_BLOCK;
67699a2dd95SBruce Richardson 
67799a2dd95SBruce Richardson 	return 0;
67899a2dd95SBruce Richardson }
67999a2dd95SBruce Richardson 
68099a2dd95SBruce Richardson static int
table_actions_block_parse(struct table_spec * s,uint32_t * block_mask,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)68199a2dd95SBruce Richardson table_actions_block_parse(struct table_spec *s,
68299a2dd95SBruce Richardson 			  uint32_t *block_mask,
68399a2dd95SBruce Richardson 			  char **tokens,
68499a2dd95SBruce Richardson 			  uint32_t n_tokens,
68599a2dd95SBruce Richardson 			  uint32_t n_lines,
68699a2dd95SBruce Richardson 			  uint32_t *err_line,
68799a2dd95SBruce Richardson 			  const char **err_msg)
68899a2dd95SBruce Richardson {
689cd79e020SYogesh Jangra 	const char **new_action_names = NULL;
690cd79e020SYogesh Jangra 	int *new_action_is_for_table_entries = NULL, *new_action_is_for_default_entry = NULL;
691cd79e020SYogesh Jangra 	char *name = NULL;
692cd79e020SYogesh Jangra 	int action_is_for_table_entries = 1, action_is_for_default_entry = 1;
69399a2dd95SBruce Richardson 
69499a2dd95SBruce Richardson 	/* Handle end of block. */
69599a2dd95SBruce Richardson 	if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
69699a2dd95SBruce Richardson 		*block_mask &= ~(1 << TABLE_ACTIONS_BLOCK);
69799a2dd95SBruce Richardson 		return 0;
69899a2dd95SBruce Richardson 	}
69999a2dd95SBruce Richardson 
70099a2dd95SBruce Richardson 	/* Check input arguments. */
701cd79e020SYogesh Jangra 	if ((n_tokens > 2) ||
702cd79e020SYogesh Jangra 	    ((n_tokens == 2) && strcmp(tokens[1], "@tableonly") &&
703cd79e020SYogesh Jangra 	      strcmp(tokens[1], "@defaultonly"))) {
70499a2dd95SBruce Richardson 		if (err_line)
70599a2dd95SBruce Richardson 			*err_line = n_lines;
70699a2dd95SBruce Richardson 		if (err_msg)
70799a2dd95SBruce Richardson 			*err_msg = "Invalid action name statement.";
70899a2dd95SBruce Richardson 		return -EINVAL;
70999a2dd95SBruce Richardson 	}
71099a2dd95SBruce Richardson 
71199a2dd95SBruce Richardson 	name = strdup(tokens[0]);
712cd79e020SYogesh Jangra 
713cd79e020SYogesh Jangra 	if (n_tokens == 2) {
714cd79e020SYogesh Jangra 		if (!strcmp(tokens[1], "@tableonly"))
715cd79e020SYogesh Jangra 			action_is_for_default_entry = 0;
716cd79e020SYogesh Jangra 
717cd79e020SYogesh Jangra 		if (!strcmp(tokens[1], "@defaultonly"))
718cd79e020SYogesh Jangra 			action_is_for_table_entries = 0;
71999a2dd95SBruce Richardson 	}
72099a2dd95SBruce Richardson 
72199a2dd95SBruce Richardson 	new_action_names = realloc(s->params.action_names,
72299a2dd95SBruce Richardson 				   (s->params.n_actions + 1) * sizeof(char *));
723cd79e020SYogesh Jangra 	new_action_is_for_table_entries = realloc(s->params.action_is_for_table_entries,
724cd79e020SYogesh Jangra 						  (s->params.n_actions + 1) * sizeof(int));
725cd79e020SYogesh Jangra 	new_action_is_for_default_entry = realloc(s->params.action_is_for_default_entry,
726cd79e020SYogesh Jangra 						  (s->params.n_actions + 1) * sizeof(int));
727cd79e020SYogesh Jangra 
728cd79e020SYogesh Jangra 	if (!name ||
729cd79e020SYogesh Jangra 	    !new_action_names ||
730cd79e020SYogesh Jangra 	    !new_action_is_for_table_entries ||
731cd79e020SYogesh Jangra 	    !new_action_is_for_default_entry) {
73299a2dd95SBruce Richardson 		free(name);
733cd79e020SYogesh Jangra 		free(new_action_names);
734cd79e020SYogesh Jangra 		free(new_action_is_for_table_entries);
735cd79e020SYogesh Jangra 		free(new_action_is_for_default_entry);
73699a2dd95SBruce Richardson 
73799a2dd95SBruce Richardson 		if (err_line)
73899a2dd95SBruce Richardson 			*err_line = n_lines;
73999a2dd95SBruce Richardson 		if (err_msg)
74099a2dd95SBruce Richardson 			*err_msg = "Memory allocation failed.";
74199a2dd95SBruce Richardson 		return -ENOMEM;
74299a2dd95SBruce Richardson 	}
74399a2dd95SBruce Richardson 
74499a2dd95SBruce Richardson 	s->params.action_names = new_action_names;
74599a2dd95SBruce Richardson 	s->params.action_names[s->params.n_actions] = name;
746cd79e020SYogesh Jangra 
747cd79e020SYogesh Jangra 	s->params.action_is_for_table_entries = new_action_is_for_table_entries;
748cd79e020SYogesh Jangra 	s->params.action_is_for_table_entries[s->params.n_actions] = action_is_for_table_entries;
749cd79e020SYogesh Jangra 
750cd79e020SYogesh Jangra 	s->params.action_is_for_default_entry = new_action_is_for_default_entry;
751cd79e020SYogesh Jangra 	s->params.action_is_for_default_entry[s->params.n_actions] = action_is_for_default_entry;
752cd79e020SYogesh Jangra 
75399a2dd95SBruce Richardson 	s->params.n_actions++;
75499a2dd95SBruce Richardson 
75599a2dd95SBruce Richardson 	return 0;
75699a2dd95SBruce Richardson }
75799a2dd95SBruce Richardson 
75899a2dd95SBruce Richardson static int
table_default_action_statement_parse(struct table_spec * s,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)75973d94b00SCristian Dumitrescu table_default_action_statement_parse(struct table_spec *s,
76073d94b00SCristian Dumitrescu 				     char **tokens,
76173d94b00SCristian Dumitrescu 				     uint32_t n_tokens,
76273d94b00SCristian Dumitrescu 				     uint32_t n_lines,
76373d94b00SCristian Dumitrescu 				     uint32_t *err_line,
76473d94b00SCristian Dumitrescu 				     const char **err_msg)
76573d94b00SCristian Dumitrescu {
76673d94b00SCristian Dumitrescu 	uint32_t i;
76773d94b00SCristian Dumitrescu 	int status = 0, duplicate = 0;
76873d94b00SCristian Dumitrescu 
76973d94b00SCristian Dumitrescu 	/* Check format. */
77073d94b00SCristian Dumitrescu 	if ((n_tokens < 4) ||
77173d94b00SCristian Dumitrescu 	    strcmp(tokens[2], "args")) {
77273d94b00SCristian Dumitrescu 		status = -EINVAL;
77373d94b00SCristian Dumitrescu 		goto error;
77473d94b00SCristian Dumitrescu 	}
77573d94b00SCristian Dumitrescu 
77673d94b00SCristian Dumitrescu 	if (s->params.default_action_name) {
77773d94b00SCristian Dumitrescu 		duplicate = 1;
77873d94b00SCristian Dumitrescu 		status = -EINVAL;
77973d94b00SCristian Dumitrescu 		goto error;
78073d94b00SCristian Dumitrescu 	}
78173d94b00SCristian Dumitrescu 
78273d94b00SCristian Dumitrescu 	s->params.default_action_name = strdup(tokens[1]);
78373d94b00SCristian Dumitrescu 	if (!s->params.default_action_name) {
78473d94b00SCristian Dumitrescu 		status = -ENOMEM;
78573d94b00SCristian Dumitrescu 		goto error;
78673d94b00SCristian Dumitrescu 	}
78773d94b00SCristian Dumitrescu 
78873d94b00SCristian Dumitrescu 	if (strcmp(tokens[3], "none")) {
78973d94b00SCristian Dumitrescu 		char buffer[MAX_LINE_LENGTH];
79073d94b00SCristian Dumitrescu 		uint32_t n_tokens_args = n_tokens - 3;
79173d94b00SCristian Dumitrescu 
79273d94b00SCristian Dumitrescu 		if (!strcmp(tokens[n_tokens - 1], "const"))
79373d94b00SCristian Dumitrescu 			n_tokens_args--;
79473d94b00SCristian Dumitrescu 
79573d94b00SCristian Dumitrescu 		if (!n_tokens_args) {
79673d94b00SCristian Dumitrescu 			status = -EINVAL;
79773d94b00SCristian Dumitrescu 			goto error;
79873d94b00SCristian Dumitrescu 		}
79973d94b00SCristian Dumitrescu 
80073d94b00SCristian Dumitrescu 		buffer[0] = 0;
80173d94b00SCristian Dumitrescu 		for (i = 0; i < n_tokens_args; i++) {
80273d94b00SCristian Dumitrescu 			if (i)
80373d94b00SCristian Dumitrescu 				strcat(buffer, " ");
80473d94b00SCristian Dumitrescu 
80573d94b00SCristian Dumitrescu 			strcat(buffer, tokens[3 + i]);
80673d94b00SCristian Dumitrescu 		}
80773d94b00SCristian Dumitrescu 
80873d94b00SCristian Dumitrescu 		s->params.default_action_args = strdup(buffer);
80973d94b00SCristian Dumitrescu 		if (!s->params.default_action_args) {
81073d94b00SCristian Dumitrescu 			status = -ENOMEM;
81173d94b00SCristian Dumitrescu 			goto error;
81273d94b00SCristian Dumitrescu 		}
81373d94b00SCristian Dumitrescu 	} else {
81473d94b00SCristian Dumitrescu 		if (((n_tokens != 4) && (n_tokens != 5)) ||
81573d94b00SCristian Dumitrescu 		    ((n_tokens == 5) && (strcmp(tokens[4], "const")))) {
81673d94b00SCristian Dumitrescu 			status = -EINVAL;
81773d94b00SCristian Dumitrescu 			goto error;
81873d94b00SCristian Dumitrescu 		}
81973d94b00SCristian Dumitrescu 	}
82073d94b00SCristian Dumitrescu 
82173d94b00SCristian Dumitrescu 	if (!strcmp(tokens[n_tokens - 1], "const"))
82273d94b00SCristian Dumitrescu 		s->params.default_action_is_const = 1;
82373d94b00SCristian Dumitrescu 
82473d94b00SCristian Dumitrescu 	return 0;
82573d94b00SCristian Dumitrescu 
82673d94b00SCristian Dumitrescu error:
82773d94b00SCristian Dumitrescu 	if (err_line)
82873d94b00SCristian Dumitrescu 		*err_line = n_lines;
82973d94b00SCristian Dumitrescu 
83073d94b00SCristian Dumitrescu 	if (err_msg)
83173d94b00SCristian Dumitrescu 		switch (status) {
83273d94b00SCristian Dumitrescu 		case -ENOMEM:
83373d94b00SCristian Dumitrescu 			*err_msg = "Memory allocation failed.";
83473d94b00SCristian Dumitrescu 			break;
83573d94b00SCristian Dumitrescu 
83673d94b00SCristian Dumitrescu 		default:
83773d94b00SCristian Dumitrescu 			if (duplicate)
83873d94b00SCristian Dumitrescu 				*err_msg = "Duplicate default_action statement.";
83973d94b00SCristian Dumitrescu 
84073d94b00SCristian Dumitrescu 			*err_msg = "Invalid default_action statement.";
84173d94b00SCristian Dumitrescu 		}
84273d94b00SCristian Dumitrescu 
84373d94b00SCristian Dumitrescu 	return status;
84473d94b00SCristian Dumitrescu }
84573d94b00SCristian Dumitrescu 
84673d94b00SCristian Dumitrescu static int
table_statement_parse(struct table_spec * s,uint32_t * block_mask,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)84799a2dd95SBruce Richardson table_statement_parse(struct table_spec *s,
84899a2dd95SBruce Richardson 		      uint32_t *block_mask,
84999a2dd95SBruce Richardson 		      char **tokens,
85099a2dd95SBruce Richardson 		      uint32_t n_tokens,
85199a2dd95SBruce Richardson 		      uint32_t n_lines,
85299a2dd95SBruce Richardson 		      uint32_t *err_line,
85399a2dd95SBruce Richardson 		      const char **err_msg)
85499a2dd95SBruce Richardson {
85599a2dd95SBruce Richardson 	/* Check format. */
85699a2dd95SBruce Richardson 	if ((n_tokens != 3) || strcmp(tokens[2], "{")) {
85799a2dd95SBruce Richardson 		if (err_line)
85899a2dd95SBruce Richardson 			*err_line = n_lines;
85999a2dd95SBruce Richardson 		if (err_msg)
86099a2dd95SBruce Richardson 			*err_msg = "Invalid table statement.";
86199a2dd95SBruce Richardson 		return -EINVAL;
86299a2dd95SBruce Richardson 	}
86399a2dd95SBruce Richardson 
86499a2dd95SBruce Richardson 	/* spec. */
86599a2dd95SBruce Richardson 	s->name = strdup(tokens[1]);
86699a2dd95SBruce Richardson 	if (!s->name) {
86799a2dd95SBruce Richardson 		if (err_line)
86899a2dd95SBruce Richardson 			*err_line = n_lines;
86999a2dd95SBruce Richardson 		if (err_msg)
87099a2dd95SBruce Richardson 			*err_msg = "Memory allocation failed.";
87199a2dd95SBruce Richardson 		return -ENOMEM;
87299a2dd95SBruce Richardson 	}
87399a2dd95SBruce Richardson 
87499a2dd95SBruce Richardson 	/* block_mask. */
87599a2dd95SBruce Richardson 	*block_mask |= 1 << TABLE_BLOCK;
87699a2dd95SBruce Richardson 
87799a2dd95SBruce Richardson 	return 0;
87899a2dd95SBruce Richardson }
87999a2dd95SBruce Richardson 
88099a2dd95SBruce Richardson static int
table_block_parse(struct table_spec * s,uint32_t * block_mask,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)88199a2dd95SBruce Richardson table_block_parse(struct table_spec *s,
88299a2dd95SBruce Richardson 		  uint32_t *block_mask,
88399a2dd95SBruce Richardson 		  char **tokens,
88499a2dd95SBruce Richardson 		  uint32_t n_tokens,
88599a2dd95SBruce Richardson 		  uint32_t n_lines,
88699a2dd95SBruce Richardson 		  uint32_t *err_line,
88799a2dd95SBruce Richardson 		  const char **err_msg)
88899a2dd95SBruce Richardson {
88999a2dd95SBruce Richardson 	if (*block_mask & (1 << TABLE_KEY_BLOCK))
89099a2dd95SBruce Richardson 		return table_key_block_parse(s,
89199a2dd95SBruce Richardson 					     block_mask,
89299a2dd95SBruce Richardson 					     tokens,
89399a2dd95SBruce Richardson 					     n_tokens,
89499a2dd95SBruce Richardson 					     n_lines,
89599a2dd95SBruce Richardson 					     err_line,
89699a2dd95SBruce Richardson 					     err_msg);
89799a2dd95SBruce Richardson 
89899a2dd95SBruce Richardson 	if (*block_mask & (1 << TABLE_ACTIONS_BLOCK))
89999a2dd95SBruce Richardson 		return table_actions_block_parse(s,
90099a2dd95SBruce Richardson 						 block_mask,
90199a2dd95SBruce Richardson 						 tokens,
90299a2dd95SBruce Richardson 						 n_tokens,
90399a2dd95SBruce Richardson 						 n_lines,
90499a2dd95SBruce Richardson 						 err_line,
90599a2dd95SBruce Richardson 						 err_msg);
90699a2dd95SBruce Richardson 
90799a2dd95SBruce Richardson 	/* Handle end of block. */
90899a2dd95SBruce Richardson 	if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
90999a2dd95SBruce Richardson 		*block_mask &= ~(1 << TABLE_BLOCK);
91099a2dd95SBruce Richardson 		return 0;
91199a2dd95SBruce Richardson 	}
91299a2dd95SBruce Richardson 
91399a2dd95SBruce Richardson 	if (!strcmp(tokens[0], "key"))
91499a2dd95SBruce Richardson 		return table_key_statement_parse(block_mask,
91599a2dd95SBruce Richardson 						 tokens,
91699a2dd95SBruce Richardson 						 n_tokens,
91799a2dd95SBruce Richardson 						 n_lines,
91899a2dd95SBruce Richardson 						 err_line,
91999a2dd95SBruce Richardson 						 err_msg);
92099a2dd95SBruce Richardson 
92199a2dd95SBruce Richardson 	if (!strcmp(tokens[0], "actions"))
92299a2dd95SBruce Richardson 		return table_actions_statement_parse(block_mask,
92399a2dd95SBruce Richardson 						     tokens,
92499a2dd95SBruce Richardson 						     n_tokens,
92599a2dd95SBruce Richardson 						     n_lines,
92699a2dd95SBruce Richardson 						     err_line,
92799a2dd95SBruce Richardson 						     err_msg);
92899a2dd95SBruce Richardson 
92973d94b00SCristian Dumitrescu 	if (!strcmp(tokens[0], "default_action"))
93073d94b00SCristian Dumitrescu 		return table_default_action_statement_parse(s,
93173d94b00SCristian Dumitrescu 							    tokens,
93273d94b00SCristian Dumitrescu 							    n_tokens,
93373d94b00SCristian Dumitrescu 							    n_lines,
93473d94b00SCristian Dumitrescu 							    err_line,
93573d94b00SCristian Dumitrescu 							    err_msg);
93699a2dd95SBruce Richardson 
9379560a329SCristian Dumitrescu 	if (!strcmp(tokens[0], "hash")) {
9389560a329SCristian Dumitrescu 		if (n_tokens != 2) {
9399560a329SCristian Dumitrescu 			if (err_line)
9409560a329SCristian Dumitrescu 				*err_line = n_lines;
9419560a329SCristian Dumitrescu 			if (err_msg)
9429560a329SCristian Dumitrescu 				*err_msg = "Invalid hash statement.";
9439560a329SCristian Dumitrescu 			return -EINVAL;
9449560a329SCristian Dumitrescu 		}
9459560a329SCristian Dumitrescu 
9469560a329SCristian Dumitrescu 		if (s->params.hash_func_name) {
9479560a329SCristian Dumitrescu 			if (err_line)
9489560a329SCristian Dumitrescu 				*err_line = n_lines;
9499560a329SCristian Dumitrescu 			if (err_msg)
9509560a329SCristian Dumitrescu 				*err_msg = "Duplicate hash statement.";
9519560a329SCristian Dumitrescu 			return -EINVAL;
9529560a329SCristian Dumitrescu 		}
9539560a329SCristian Dumitrescu 
9549560a329SCristian Dumitrescu 		s->params.hash_func_name = strdup(tokens[1]);
9559560a329SCristian Dumitrescu 		if (!s->params.hash_func_name) {
9569560a329SCristian Dumitrescu 			if (err_line)
9579560a329SCristian Dumitrescu 				*err_line = n_lines;
9589560a329SCristian Dumitrescu 			if (err_msg)
9599560a329SCristian Dumitrescu 				*err_msg = "Memory allocation failed.";
9609560a329SCristian Dumitrescu 			return -ENOMEM;
9619560a329SCristian Dumitrescu 		}
9629560a329SCristian Dumitrescu 
9639560a329SCristian Dumitrescu 		return 0;
9649560a329SCristian Dumitrescu 	}
9659560a329SCristian Dumitrescu 
96699a2dd95SBruce Richardson 	if (!strcmp(tokens[0], "instanceof")) {
96799a2dd95SBruce Richardson 		if (n_tokens != 2) {
96899a2dd95SBruce Richardson 			if (err_line)
96999a2dd95SBruce Richardson 				*err_line = n_lines;
97099a2dd95SBruce Richardson 			if (err_msg)
97199a2dd95SBruce Richardson 				*err_msg = "Invalid instanceof statement.";
97299a2dd95SBruce Richardson 			return -EINVAL;
97399a2dd95SBruce Richardson 		}
97499a2dd95SBruce Richardson 
97599a2dd95SBruce Richardson 		if (s->recommended_table_type_name) {
97699a2dd95SBruce Richardson 			if (err_line)
97799a2dd95SBruce Richardson 				*err_line = n_lines;
97899a2dd95SBruce Richardson 			if (err_msg)
97999a2dd95SBruce Richardson 				*err_msg = "Duplicate instanceof statement.";
98099a2dd95SBruce Richardson 			return -EINVAL;
98199a2dd95SBruce Richardson 		}
98299a2dd95SBruce Richardson 
98399a2dd95SBruce Richardson 		s->recommended_table_type_name = strdup(tokens[1]);
98499a2dd95SBruce Richardson 		if (!s->recommended_table_type_name) {
98599a2dd95SBruce Richardson 			if (err_line)
98699a2dd95SBruce Richardson 				*err_line = n_lines;
98799a2dd95SBruce Richardson 			if (err_msg)
98899a2dd95SBruce Richardson 				*err_msg = "Memory allocation failed.";
98999a2dd95SBruce Richardson 			return -ENOMEM;
99099a2dd95SBruce Richardson 		}
99199a2dd95SBruce Richardson 
99299a2dd95SBruce Richardson 		return 0;
99399a2dd95SBruce Richardson 	}
99499a2dd95SBruce Richardson 
99599a2dd95SBruce Richardson 	if (!strcmp(tokens[0], "pragma")) {
99699a2dd95SBruce Richardson 		if (n_tokens != 2) {
99799a2dd95SBruce Richardson 			if (err_line)
99899a2dd95SBruce Richardson 				*err_line = n_lines;
99999a2dd95SBruce Richardson 			if (err_msg)
100099a2dd95SBruce Richardson 				*err_msg = "Invalid pragma statement.";
100199a2dd95SBruce Richardson 			return -EINVAL;
100299a2dd95SBruce Richardson 		}
100399a2dd95SBruce Richardson 
100499a2dd95SBruce Richardson 		if (s->args) {
100599a2dd95SBruce Richardson 			if (err_line)
100699a2dd95SBruce Richardson 				*err_line = n_lines;
100799a2dd95SBruce Richardson 			if (err_msg)
100899a2dd95SBruce Richardson 				*err_msg = "Duplicate pragma statement.";
100999a2dd95SBruce Richardson 			return -EINVAL;
101099a2dd95SBruce Richardson 		}
101199a2dd95SBruce Richardson 
101299a2dd95SBruce Richardson 		s->args = strdup(tokens[1]);
101399a2dd95SBruce Richardson 		if (!s->args) {
101499a2dd95SBruce Richardson 			if (err_line)
101599a2dd95SBruce Richardson 				*err_line = n_lines;
101699a2dd95SBruce Richardson 			if (err_msg)
101799a2dd95SBruce Richardson 				*err_msg = "Memory allocation failed.";
101899a2dd95SBruce Richardson 			return -ENOMEM;
101999a2dd95SBruce Richardson 		}
102099a2dd95SBruce Richardson 
102199a2dd95SBruce Richardson 		return 0;
102299a2dd95SBruce Richardson 	}
102399a2dd95SBruce Richardson 
102499a2dd95SBruce Richardson 	if (!strcmp(tokens[0], "size")) {
102599a2dd95SBruce Richardson 		char *p = tokens[1];
102699a2dd95SBruce Richardson 
102799a2dd95SBruce Richardson 		if (n_tokens != 2) {
102899a2dd95SBruce Richardson 			if (err_line)
102999a2dd95SBruce Richardson 				*err_line = n_lines;
103099a2dd95SBruce Richardson 			if (err_msg)
103199a2dd95SBruce Richardson 				*err_msg = "Invalid pragma statement.";
103299a2dd95SBruce Richardson 			return -EINVAL;
103399a2dd95SBruce Richardson 		}
103499a2dd95SBruce Richardson 
103599a2dd95SBruce Richardson 		s->size = strtoul(p, &p, 0);
103699a2dd95SBruce Richardson 		if (p[0]) {
103799a2dd95SBruce Richardson 			if (err_line)
103899a2dd95SBruce Richardson 				*err_line = n_lines;
103999a2dd95SBruce Richardson 			if (err_msg)
104099a2dd95SBruce Richardson 				*err_msg = "Invalid size argument.";
104199a2dd95SBruce Richardson 			return -EINVAL;
104299a2dd95SBruce Richardson 		}
104399a2dd95SBruce Richardson 
104499a2dd95SBruce Richardson 		return 0;
104599a2dd95SBruce Richardson 	}
104699a2dd95SBruce Richardson 
104799a2dd95SBruce Richardson 	/* Anything else. */
104899a2dd95SBruce Richardson 	if (err_line)
104999a2dd95SBruce Richardson 		*err_line = n_lines;
105099a2dd95SBruce Richardson 	if (err_msg)
105199a2dd95SBruce Richardson 		*err_msg = "Invalid statement.";
105299a2dd95SBruce Richardson 	return -EINVAL;
105399a2dd95SBruce Richardson }
105499a2dd95SBruce Richardson 
105599a2dd95SBruce Richardson /*
1056cdaa937dSCristian Dumitrescu  * selector.
1057cdaa937dSCristian Dumitrescu  */
1058cdaa937dSCristian Dumitrescu static void
selector_spec_free(struct selector_spec * s)1059cdaa937dSCristian Dumitrescu selector_spec_free(struct selector_spec *s)
1060cdaa937dSCristian Dumitrescu {
1061cdaa937dSCristian Dumitrescu 	uintptr_t field_name;
1062cdaa937dSCristian Dumitrescu 	uint32_t i;
1063cdaa937dSCristian Dumitrescu 
1064cdaa937dSCristian Dumitrescu 	if (!s)
1065cdaa937dSCristian Dumitrescu 		return;
1066cdaa937dSCristian Dumitrescu 
1067cdaa937dSCristian Dumitrescu 	/* name. */
1068cdaa937dSCristian Dumitrescu 	free(s->name);
1069cdaa937dSCristian Dumitrescu 	s->name = NULL;
1070cdaa937dSCristian Dumitrescu 
1071cdaa937dSCristian Dumitrescu 	/* params->group_id_field_name. */
1072cdaa937dSCristian Dumitrescu 	field_name = (uintptr_t)s->params.group_id_field_name;
1073cdaa937dSCristian Dumitrescu 	free((void *)field_name);
1074cdaa937dSCristian Dumitrescu 	s->params.group_id_field_name = NULL;
1075cdaa937dSCristian Dumitrescu 
1076cdaa937dSCristian Dumitrescu 	/* params->selector_field_names. */
1077cdaa937dSCristian Dumitrescu 	for (i = 0; i < s->params.n_selector_fields; i++) {
1078cdaa937dSCristian Dumitrescu 		field_name = (uintptr_t)s->params.selector_field_names[i];
1079cdaa937dSCristian Dumitrescu 
1080cdaa937dSCristian Dumitrescu 		free((void *)field_name);
1081cdaa937dSCristian Dumitrescu 	}
1082cdaa937dSCristian Dumitrescu 
1083cdaa937dSCristian Dumitrescu 	free(s->params.selector_field_names);
1084cdaa937dSCristian Dumitrescu 	s->params.selector_field_names = NULL;
1085cdaa937dSCristian Dumitrescu 
1086cdaa937dSCristian Dumitrescu 	s->params.n_selector_fields = 0;
1087cdaa937dSCristian Dumitrescu 
1088cdaa937dSCristian Dumitrescu 	/* params->member_id_field_name. */
1089cdaa937dSCristian Dumitrescu 	field_name = (uintptr_t)s->params.member_id_field_name;
1090cdaa937dSCristian Dumitrescu 	free((void *)field_name);
1091cdaa937dSCristian Dumitrescu 	s->params.member_id_field_name = NULL;
1092cdaa937dSCristian Dumitrescu 
1093cdaa937dSCristian Dumitrescu 	/* params->n_groups_max. */
1094cdaa937dSCristian Dumitrescu 	s->params.n_groups_max = 0;
1095cdaa937dSCristian Dumitrescu 
1096cdaa937dSCristian Dumitrescu 	/* params->n_members_per_group_max. */
1097cdaa937dSCristian Dumitrescu 	s->params.n_members_per_group_max = 0;
1098cdaa937dSCristian Dumitrescu }
1099cdaa937dSCristian Dumitrescu 
1100cdaa937dSCristian Dumitrescu static int
selector_statement_parse(struct selector_spec * s,uint32_t * block_mask,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)1101cdaa937dSCristian Dumitrescu selector_statement_parse(struct selector_spec *s,
1102cdaa937dSCristian Dumitrescu 			 uint32_t *block_mask,
1103cdaa937dSCristian Dumitrescu 			 char **tokens,
1104cdaa937dSCristian Dumitrescu 			 uint32_t n_tokens,
1105cdaa937dSCristian Dumitrescu 			 uint32_t n_lines,
1106cdaa937dSCristian Dumitrescu 			 uint32_t *err_line,
1107cdaa937dSCristian Dumitrescu 			 const char **err_msg)
1108cdaa937dSCristian Dumitrescu {
1109cdaa937dSCristian Dumitrescu 	/* Check format. */
1110cdaa937dSCristian Dumitrescu 	if ((n_tokens != 3) || strcmp(tokens[2], "{")) {
1111cdaa937dSCristian Dumitrescu 		if (err_line)
1112cdaa937dSCristian Dumitrescu 			*err_line = n_lines;
1113cdaa937dSCristian Dumitrescu 		if (err_msg)
1114cdaa937dSCristian Dumitrescu 			*err_msg = "Invalid selector statement.";
1115cdaa937dSCristian Dumitrescu 		return -EINVAL;
1116cdaa937dSCristian Dumitrescu 	}
1117cdaa937dSCristian Dumitrescu 
1118cdaa937dSCristian Dumitrescu 	/* spec. */
1119cdaa937dSCristian Dumitrescu 	s->name = strdup(tokens[1]);
1120cdaa937dSCristian Dumitrescu 	if (!s->name) {
1121cdaa937dSCristian Dumitrescu 		if (err_line)
1122cdaa937dSCristian Dumitrescu 			*err_line = n_lines;
1123cdaa937dSCristian Dumitrescu 		if (err_msg)
1124cdaa937dSCristian Dumitrescu 			*err_msg = "Memory allocation failed.";
1125cdaa937dSCristian Dumitrescu 		return -ENOMEM;
1126cdaa937dSCristian Dumitrescu 	}
1127cdaa937dSCristian Dumitrescu 
1128cdaa937dSCristian Dumitrescu 	/* block_mask. */
1129cdaa937dSCristian Dumitrescu 	*block_mask |= 1 << SELECTOR_BLOCK;
1130cdaa937dSCristian Dumitrescu 
1131cdaa937dSCristian Dumitrescu 	return 0;
1132cdaa937dSCristian Dumitrescu }
1133cdaa937dSCristian Dumitrescu 
1134cdaa937dSCristian Dumitrescu static int
selector_selector_statement_parse(uint32_t * block_mask,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)1135cdaa937dSCristian Dumitrescu selector_selector_statement_parse(uint32_t *block_mask,
1136cdaa937dSCristian Dumitrescu 				  char **tokens,
1137cdaa937dSCristian Dumitrescu 				  uint32_t n_tokens,
1138cdaa937dSCristian Dumitrescu 				  uint32_t n_lines,
1139cdaa937dSCristian Dumitrescu 				  uint32_t *err_line,
1140cdaa937dSCristian Dumitrescu 				  const char **err_msg)
1141cdaa937dSCristian Dumitrescu {
1142cdaa937dSCristian Dumitrescu 	/* Check format. */
1143cdaa937dSCristian Dumitrescu 	if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
1144cdaa937dSCristian Dumitrescu 		if (err_line)
1145cdaa937dSCristian Dumitrescu 			*err_line = n_lines;
1146cdaa937dSCristian Dumitrescu 		if (err_msg)
1147cdaa937dSCristian Dumitrescu 			*err_msg = "Invalid selector statement.";
1148cdaa937dSCristian Dumitrescu 		return -EINVAL;
1149cdaa937dSCristian Dumitrescu 	}
1150cdaa937dSCristian Dumitrescu 
1151cdaa937dSCristian Dumitrescu 	/* block_mask. */
1152cdaa937dSCristian Dumitrescu 	*block_mask |= 1 << SELECTOR_SELECTOR_BLOCK;
1153cdaa937dSCristian Dumitrescu 
1154cdaa937dSCristian Dumitrescu 	return 0;
1155cdaa937dSCristian Dumitrescu }
1156cdaa937dSCristian Dumitrescu 
1157cdaa937dSCristian Dumitrescu static int
selector_selector_block_parse(struct selector_spec * s,uint32_t * block_mask,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)1158cdaa937dSCristian Dumitrescu selector_selector_block_parse(struct selector_spec *s,
1159cdaa937dSCristian Dumitrescu 			      uint32_t *block_mask,
1160cdaa937dSCristian Dumitrescu 			      char **tokens,
1161cdaa937dSCristian Dumitrescu 			      uint32_t n_tokens,
1162cdaa937dSCristian Dumitrescu 			      uint32_t n_lines,
1163cdaa937dSCristian Dumitrescu 			      uint32_t *err_line,
1164cdaa937dSCristian Dumitrescu 			      const char **err_msg)
1165cdaa937dSCristian Dumitrescu {
1166cdaa937dSCristian Dumitrescu 	const char **new_fields;
1167cdaa937dSCristian Dumitrescu 	char *name;
1168cdaa937dSCristian Dumitrescu 
1169cdaa937dSCristian Dumitrescu 	/* Handle end of block. */
1170cdaa937dSCristian Dumitrescu 	if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1171cdaa937dSCristian Dumitrescu 		*block_mask &= ~(1 << SELECTOR_SELECTOR_BLOCK);
1172cdaa937dSCristian Dumitrescu 		return 0;
1173cdaa937dSCristian Dumitrescu 	}
1174cdaa937dSCristian Dumitrescu 
1175cdaa937dSCristian Dumitrescu 	/* Check input arguments. */
1176cdaa937dSCristian Dumitrescu 	if (n_tokens != 1) {
1177cdaa937dSCristian Dumitrescu 		if (err_line)
1178cdaa937dSCristian Dumitrescu 			*err_line = n_lines;
1179cdaa937dSCristian Dumitrescu 		if (err_msg)
1180cdaa937dSCristian Dumitrescu 			*err_msg = "Invalid selector field statement.";
1181cdaa937dSCristian Dumitrescu 		return -EINVAL;
1182cdaa937dSCristian Dumitrescu 	}
1183cdaa937dSCristian Dumitrescu 
1184cdaa937dSCristian Dumitrescu 	name = strdup(tokens[0]);
1185cdaa937dSCristian Dumitrescu 	if (!name) {
1186cdaa937dSCristian Dumitrescu 		if (err_line)
1187cdaa937dSCristian Dumitrescu 			*err_line = n_lines;
1188cdaa937dSCristian Dumitrescu 		if (err_msg)
1189cdaa937dSCristian Dumitrescu 			*err_msg = "Memory allocation failed.";
1190cdaa937dSCristian Dumitrescu 		return -ENOMEM;
1191cdaa937dSCristian Dumitrescu 	}
1192cdaa937dSCristian Dumitrescu 
1193cdaa937dSCristian Dumitrescu 	new_fields = realloc(s->params.selector_field_names,
1194cdaa937dSCristian Dumitrescu 			     (s->params.n_selector_fields + 1) * sizeof(char *));
1195cdaa937dSCristian Dumitrescu 	if (!new_fields) {
1196cdaa937dSCristian Dumitrescu 		free(name);
1197cdaa937dSCristian Dumitrescu 
1198cdaa937dSCristian Dumitrescu 		if (err_line)
1199cdaa937dSCristian Dumitrescu 			*err_line = n_lines;
1200cdaa937dSCristian Dumitrescu 		if (err_msg)
1201cdaa937dSCristian Dumitrescu 			*err_msg = "Memory allocation failed.";
1202cdaa937dSCristian Dumitrescu 		return -ENOMEM;
1203cdaa937dSCristian Dumitrescu 	}
1204cdaa937dSCristian Dumitrescu 
1205cdaa937dSCristian Dumitrescu 	s->params.selector_field_names = new_fields;
1206cdaa937dSCristian Dumitrescu 	s->params.selector_field_names[s->params.n_selector_fields] = name;
1207cdaa937dSCristian Dumitrescu 	s->params.n_selector_fields++;
1208cdaa937dSCristian Dumitrescu 
1209cdaa937dSCristian Dumitrescu 	return 0;
1210cdaa937dSCristian Dumitrescu }
1211cdaa937dSCristian Dumitrescu 
1212cdaa937dSCristian Dumitrescu static int
selector_block_parse(struct selector_spec * s,uint32_t * block_mask,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)1213cdaa937dSCristian Dumitrescu selector_block_parse(struct selector_spec *s,
1214cdaa937dSCristian Dumitrescu 		     uint32_t *block_mask,
1215cdaa937dSCristian Dumitrescu 		     char **tokens,
1216cdaa937dSCristian Dumitrescu 		     uint32_t n_tokens,
1217cdaa937dSCristian Dumitrescu 		     uint32_t n_lines,
1218cdaa937dSCristian Dumitrescu 		     uint32_t *err_line,
1219cdaa937dSCristian Dumitrescu 		     const char **err_msg)
1220cdaa937dSCristian Dumitrescu {
1221cdaa937dSCristian Dumitrescu 	if (*block_mask & (1 << SELECTOR_SELECTOR_BLOCK))
1222cdaa937dSCristian Dumitrescu 		return selector_selector_block_parse(s,
1223cdaa937dSCristian Dumitrescu 						     block_mask,
1224cdaa937dSCristian Dumitrescu 						     tokens,
1225cdaa937dSCristian Dumitrescu 						     n_tokens,
1226cdaa937dSCristian Dumitrescu 						     n_lines,
1227cdaa937dSCristian Dumitrescu 						     err_line,
1228cdaa937dSCristian Dumitrescu 						     err_msg);
1229cdaa937dSCristian Dumitrescu 
1230cdaa937dSCristian Dumitrescu 	/* Handle end of block. */
1231cdaa937dSCristian Dumitrescu 	if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1232cdaa937dSCristian Dumitrescu 		*block_mask &= ~(1 << SELECTOR_BLOCK);
1233cdaa937dSCristian Dumitrescu 		return 0;
1234cdaa937dSCristian Dumitrescu 	}
1235cdaa937dSCristian Dumitrescu 
1236cdaa937dSCristian Dumitrescu 	if (!strcmp(tokens[0], "group_id")) {
1237cdaa937dSCristian Dumitrescu 		if (n_tokens != 2) {
1238cdaa937dSCristian Dumitrescu 			if (err_line)
1239cdaa937dSCristian Dumitrescu 				*err_line = n_lines;
1240cdaa937dSCristian Dumitrescu 			if (err_msg)
1241cdaa937dSCristian Dumitrescu 				*err_msg = "Invalid group_id statement.";
1242cdaa937dSCristian Dumitrescu 			return -EINVAL;
1243cdaa937dSCristian Dumitrescu 		}
1244cdaa937dSCristian Dumitrescu 
1245cdaa937dSCristian Dumitrescu 		s->params.group_id_field_name = strdup(tokens[1]);
1246cdaa937dSCristian Dumitrescu 		if (!s->params.group_id_field_name) {
1247cdaa937dSCristian Dumitrescu 			if (err_line)
1248cdaa937dSCristian Dumitrescu 				*err_line = n_lines;
1249cdaa937dSCristian Dumitrescu 			if (err_msg)
1250cdaa937dSCristian Dumitrescu 				*err_msg = "Memory allocation failed.";
1251cdaa937dSCristian Dumitrescu 			return -ENOMEM;
1252cdaa937dSCristian Dumitrescu 		}
1253cdaa937dSCristian Dumitrescu 
1254cdaa937dSCristian Dumitrescu 		return 0;
1255cdaa937dSCristian Dumitrescu 	}
1256cdaa937dSCristian Dumitrescu 
1257cdaa937dSCristian Dumitrescu 	if (!strcmp(tokens[0], "selector"))
1258cdaa937dSCristian Dumitrescu 		return selector_selector_statement_parse(block_mask,
1259cdaa937dSCristian Dumitrescu 							 tokens,
1260cdaa937dSCristian Dumitrescu 							 n_tokens,
1261cdaa937dSCristian Dumitrescu 							 n_lines,
1262cdaa937dSCristian Dumitrescu 							 err_line,
1263cdaa937dSCristian Dumitrescu 							 err_msg);
1264cdaa937dSCristian Dumitrescu 
1265cdaa937dSCristian Dumitrescu 	if (!strcmp(tokens[0], "member_id")) {
1266cdaa937dSCristian Dumitrescu 		if (n_tokens != 2) {
1267cdaa937dSCristian Dumitrescu 			if (err_line)
1268cdaa937dSCristian Dumitrescu 				*err_line = n_lines;
1269cdaa937dSCristian Dumitrescu 			if (err_msg)
1270cdaa937dSCristian Dumitrescu 				*err_msg = "Invalid member_id statement.";
1271cdaa937dSCristian Dumitrescu 			return -EINVAL;
1272cdaa937dSCristian Dumitrescu 		}
1273cdaa937dSCristian Dumitrescu 
1274cdaa937dSCristian Dumitrescu 		s->params.member_id_field_name = strdup(tokens[1]);
1275cdaa937dSCristian Dumitrescu 		if (!s->params.member_id_field_name) {
1276cdaa937dSCristian Dumitrescu 			if (err_line)
1277cdaa937dSCristian Dumitrescu 				*err_line = n_lines;
1278cdaa937dSCristian Dumitrescu 			if (err_msg)
1279cdaa937dSCristian Dumitrescu 				*err_msg = "Memory allocation failed.";
1280cdaa937dSCristian Dumitrescu 			return -ENOMEM;
1281cdaa937dSCristian Dumitrescu 		}
1282cdaa937dSCristian Dumitrescu 
1283cdaa937dSCristian Dumitrescu 		return 0;
1284cdaa937dSCristian Dumitrescu 	}
1285cdaa937dSCristian Dumitrescu 
1286cdaa937dSCristian Dumitrescu 	if (!strcmp(tokens[0], "n_groups_max")) {
1287cdaa937dSCristian Dumitrescu 		char *p = tokens[1];
1288cdaa937dSCristian Dumitrescu 
1289cdaa937dSCristian Dumitrescu 		if (n_tokens != 2) {
1290cdaa937dSCristian Dumitrescu 			if (err_line)
1291cdaa937dSCristian Dumitrescu 				*err_line = n_lines;
1292cdaa937dSCristian Dumitrescu 			if (err_msg)
1293cdaa937dSCristian Dumitrescu 				*err_msg = "Invalid n_groups statement.";
1294cdaa937dSCristian Dumitrescu 			return -EINVAL;
1295cdaa937dSCristian Dumitrescu 		}
1296cdaa937dSCristian Dumitrescu 
1297cdaa937dSCristian Dumitrescu 		s->params.n_groups_max = strtoul(p, &p, 0);
1298cdaa937dSCristian Dumitrescu 		if (p[0]) {
1299cdaa937dSCristian Dumitrescu 			if (err_line)
1300cdaa937dSCristian Dumitrescu 				*err_line = n_lines;
1301cdaa937dSCristian Dumitrescu 			if (err_msg)
1302cdaa937dSCristian Dumitrescu 				*err_msg = "Invalid n_groups argument.";
1303cdaa937dSCristian Dumitrescu 			return -EINVAL;
1304cdaa937dSCristian Dumitrescu 		}
1305cdaa937dSCristian Dumitrescu 
1306cdaa937dSCristian Dumitrescu 		return 0;
1307cdaa937dSCristian Dumitrescu 	}
1308cdaa937dSCristian Dumitrescu 
1309cdaa937dSCristian Dumitrescu 	if (!strcmp(tokens[0], "n_members_per_group_max")) {
1310cdaa937dSCristian Dumitrescu 		char *p = tokens[1];
1311cdaa937dSCristian Dumitrescu 
1312cdaa937dSCristian Dumitrescu 		if (n_tokens != 2) {
1313cdaa937dSCristian Dumitrescu 			if (err_line)
1314cdaa937dSCristian Dumitrescu 				*err_line = n_lines;
1315cdaa937dSCristian Dumitrescu 			if (err_msg)
1316cdaa937dSCristian Dumitrescu 				*err_msg = "Invalid n_members_per_group statement.";
1317cdaa937dSCristian Dumitrescu 			return -EINVAL;
1318cdaa937dSCristian Dumitrescu 		}
1319cdaa937dSCristian Dumitrescu 
1320cdaa937dSCristian Dumitrescu 		s->params.n_members_per_group_max = strtoul(p, &p, 0);
1321cdaa937dSCristian Dumitrescu 		if (p[0]) {
1322cdaa937dSCristian Dumitrescu 			if (err_line)
1323cdaa937dSCristian Dumitrescu 				*err_line = n_lines;
1324cdaa937dSCristian Dumitrescu 			if (err_msg)
1325cdaa937dSCristian Dumitrescu 				*err_msg = "Invalid n_members_per_group argument.";
1326cdaa937dSCristian Dumitrescu 			return -EINVAL;
1327cdaa937dSCristian Dumitrescu 		}
1328cdaa937dSCristian Dumitrescu 
1329cdaa937dSCristian Dumitrescu 		return 0;
1330cdaa937dSCristian Dumitrescu 	}
1331cdaa937dSCristian Dumitrescu 
1332cdaa937dSCristian Dumitrescu 	/* Anything else. */
1333cdaa937dSCristian Dumitrescu 	if (err_line)
1334cdaa937dSCristian Dumitrescu 		*err_line = n_lines;
1335cdaa937dSCristian Dumitrescu 	if (err_msg)
1336cdaa937dSCristian Dumitrescu 		*err_msg = "Invalid statement.";
1337cdaa937dSCristian Dumitrescu 	return -EINVAL;
1338cdaa937dSCristian Dumitrescu }
1339cdaa937dSCristian Dumitrescu 
1340cdaa937dSCristian Dumitrescu /*
13414f59d372SCristian Dumitrescu  * learner.
13424f59d372SCristian Dumitrescu  */
13434f59d372SCristian Dumitrescu static void
learner_spec_free(struct learner_spec * s)13444f59d372SCristian Dumitrescu learner_spec_free(struct learner_spec *s)
13454f59d372SCristian Dumitrescu {
1346fa7723b5SCristian Dumitrescu 	uintptr_t default_action_name, default_action_args, hash_func_name;
13474f59d372SCristian Dumitrescu 	uint32_t i;
13484f59d372SCristian Dumitrescu 
13494f59d372SCristian Dumitrescu 	if (!s)
13504f59d372SCristian Dumitrescu 		return;
13514f59d372SCristian Dumitrescu 
13524f59d372SCristian Dumitrescu 	free(s->name);
13534f59d372SCristian Dumitrescu 	s->name = NULL;
13544f59d372SCristian Dumitrescu 
13554f59d372SCristian Dumitrescu 	for (i = 0; i < s->params.n_fields; i++) {
13564f59d372SCristian Dumitrescu 		uintptr_t name = (uintptr_t)s->params.field_names[i];
13574f59d372SCristian Dumitrescu 
13584f59d372SCristian Dumitrescu 		free((void *)name);
13594f59d372SCristian Dumitrescu 	}
13604f59d372SCristian Dumitrescu 
13614f59d372SCristian Dumitrescu 	free(s->params.field_names);
13624f59d372SCristian Dumitrescu 	s->params.field_names = NULL;
13634f59d372SCristian Dumitrescu 
13644f59d372SCristian Dumitrescu 	s->params.n_fields = 0;
13654f59d372SCristian Dumitrescu 
13664f59d372SCristian Dumitrescu 	for (i = 0; i < s->params.n_actions; i++) {
13674f59d372SCristian Dumitrescu 		uintptr_t name = (uintptr_t)s->params.action_names[i];
13684f59d372SCristian Dumitrescu 
13694f59d372SCristian Dumitrescu 		free((void *)name);
13704f59d372SCristian Dumitrescu 	}
13714f59d372SCristian Dumitrescu 
13724f59d372SCristian Dumitrescu 	free(s->params.action_names);
13734f59d372SCristian Dumitrescu 	s->params.action_names = NULL;
13744f59d372SCristian Dumitrescu 
13754f59d372SCristian Dumitrescu 	s->params.n_actions = 0;
13764f59d372SCristian Dumitrescu 
13774f59d372SCristian Dumitrescu 	default_action_name = (uintptr_t)s->params.default_action_name;
13784f59d372SCristian Dumitrescu 	free((void *)default_action_name);
13794f59d372SCristian Dumitrescu 	s->params.default_action_name = NULL;
13804f59d372SCristian Dumitrescu 
138173d94b00SCristian Dumitrescu 	default_action_args = (uintptr_t)s->params.default_action_args;
138273d94b00SCristian Dumitrescu 	free((void *)default_action_args);
138373d94b00SCristian Dumitrescu 	s->params.default_action_args = NULL;
13844f59d372SCristian Dumitrescu 
1385cd79e020SYogesh Jangra 	free(s->params.action_is_for_table_entries);
1386cd79e020SYogesh Jangra 	s->params.action_is_for_table_entries = NULL;
1387cd79e020SYogesh Jangra 
1388cd79e020SYogesh Jangra 	free(s->params.action_is_for_default_entry);
1389cd79e020SYogesh Jangra 	s->params.action_is_for_default_entry = NULL;
1390cd79e020SYogesh Jangra 
13914f59d372SCristian Dumitrescu 	s->params.default_action_is_const = 0;
13924f59d372SCristian Dumitrescu 
1393fa7723b5SCristian Dumitrescu 	hash_func_name = (uintptr_t)s->params.hash_func_name;
1394fa7723b5SCristian Dumitrescu 	free((void *)hash_func_name);
1395fa7723b5SCristian Dumitrescu 	s->params.hash_func_name = NULL;
1396fa7723b5SCristian Dumitrescu 
13974f59d372SCristian Dumitrescu 	s->size = 0;
13984f59d372SCristian Dumitrescu 
1399e2ecc535SCristian Dumitrescu 	free(s->timeout);
1400e2ecc535SCristian Dumitrescu 	s->timeout = NULL;
1401e2ecc535SCristian Dumitrescu 
1402e2ecc535SCristian Dumitrescu 	s->n_timeouts = 0;
14034f59d372SCristian Dumitrescu }
14044f59d372SCristian Dumitrescu 
14054f59d372SCristian Dumitrescu static int
learner_key_statement_parse(uint32_t * block_mask,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)14064f59d372SCristian Dumitrescu learner_key_statement_parse(uint32_t *block_mask,
14074f59d372SCristian Dumitrescu 			    char **tokens,
14084f59d372SCristian Dumitrescu 			    uint32_t n_tokens,
14094f59d372SCristian Dumitrescu 			    uint32_t n_lines,
14104f59d372SCristian Dumitrescu 			    uint32_t *err_line,
14114f59d372SCristian Dumitrescu 			    const char **err_msg)
14124f59d372SCristian Dumitrescu {
14134f59d372SCristian Dumitrescu 	/* Check format. */
14144f59d372SCristian Dumitrescu 	if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
14154f59d372SCristian Dumitrescu 		if (err_line)
14164f59d372SCristian Dumitrescu 			*err_line = n_lines;
14174f59d372SCristian Dumitrescu 		if (err_msg)
14184f59d372SCristian Dumitrescu 			*err_msg = "Invalid key statement.";
14194f59d372SCristian Dumitrescu 		return -EINVAL;
14204f59d372SCristian Dumitrescu 	}
14214f59d372SCristian Dumitrescu 
14224f59d372SCristian Dumitrescu 	/* block_mask. */
14234f59d372SCristian Dumitrescu 	*block_mask |= 1 << LEARNER_KEY_BLOCK;
14244f59d372SCristian Dumitrescu 
14254f59d372SCristian Dumitrescu 	return 0;
14264f59d372SCristian Dumitrescu }
14274f59d372SCristian Dumitrescu 
14284f59d372SCristian Dumitrescu static int
learner_key_block_parse(struct learner_spec * s,uint32_t * block_mask,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)14294f59d372SCristian Dumitrescu learner_key_block_parse(struct learner_spec *s,
14304f59d372SCristian Dumitrescu 			uint32_t *block_mask,
14314f59d372SCristian Dumitrescu 			char **tokens,
14324f59d372SCristian Dumitrescu 			uint32_t n_tokens,
14334f59d372SCristian Dumitrescu 			uint32_t n_lines,
14344f59d372SCristian Dumitrescu 			uint32_t *err_line,
14354f59d372SCristian Dumitrescu 			const char **err_msg)
14364f59d372SCristian Dumitrescu {
14374f59d372SCristian Dumitrescu 	const char **new_field_names = NULL;
14384f59d372SCristian Dumitrescu 	char *field_name = NULL;
14394f59d372SCristian Dumitrescu 
14404f59d372SCristian Dumitrescu 	/* Handle end of block. */
14414f59d372SCristian Dumitrescu 	if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
14424f59d372SCristian Dumitrescu 		*block_mask &= ~(1 << LEARNER_KEY_BLOCK);
14434f59d372SCristian Dumitrescu 		return 0;
14444f59d372SCristian Dumitrescu 	}
14454f59d372SCristian Dumitrescu 
14464f59d372SCristian Dumitrescu 	/* Check input arguments. */
14474f59d372SCristian Dumitrescu 	if (n_tokens != 1) {
14484f59d372SCristian Dumitrescu 		if (err_line)
14494f59d372SCristian Dumitrescu 			*err_line = n_lines;
14504f59d372SCristian Dumitrescu 		if (err_msg)
14514f59d372SCristian Dumitrescu 			*err_msg = "Invalid match field statement.";
14524f59d372SCristian Dumitrescu 		return -EINVAL;
14534f59d372SCristian Dumitrescu 	}
14544f59d372SCristian Dumitrescu 
14554f59d372SCristian Dumitrescu 	field_name = strdup(tokens[0]);
14564f59d372SCristian Dumitrescu 	new_field_names = realloc(s->params.field_names, (s->params.n_fields + 1) * sizeof(char *));
14574f59d372SCristian Dumitrescu 	if (!field_name || !new_field_names) {
14584f59d372SCristian Dumitrescu 		free(field_name);
14594f59d372SCristian Dumitrescu 		free(new_field_names);
14604f59d372SCristian Dumitrescu 
14614f59d372SCristian Dumitrescu 		if (err_line)
14624f59d372SCristian Dumitrescu 			*err_line = n_lines;
14634f59d372SCristian Dumitrescu 		if (err_msg)
14644f59d372SCristian Dumitrescu 			*err_msg = "Memory allocation failed.";
14654f59d372SCristian Dumitrescu 		return -ENOMEM;
14664f59d372SCristian Dumitrescu 	}
14674f59d372SCristian Dumitrescu 
14684f59d372SCristian Dumitrescu 	s->params.field_names = new_field_names;
14694f59d372SCristian Dumitrescu 	s->params.field_names[s->params.n_fields] = field_name;
14704f59d372SCristian Dumitrescu 	s->params.n_fields++;
14714f59d372SCristian Dumitrescu 
14724f59d372SCristian Dumitrescu 	return 0;
14734f59d372SCristian Dumitrescu }
14744f59d372SCristian Dumitrescu 
14754f59d372SCristian Dumitrescu static int
learner_actions_statement_parse(uint32_t * block_mask,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)14764f59d372SCristian Dumitrescu learner_actions_statement_parse(uint32_t *block_mask,
14774f59d372SCristian Dumitrescu 				char **tokens,
14784f59d372SCristian Dumitrescu 				uint32_t n_tokens,
14794f59d372SCristian Dumitrescu 				uint32_t n_lines,
14804f59d372SCristian Dumitrescu 				uint32_t *err_line,
14814f59d372SCristian Dumitrescu 				const char **err_msg)
14824f59d372SCristian Dumitrescu {
14834f59d372SCristian Dumitrescu 	/* Check format. */
14844f59d372SCristian Dumitrescu 	if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
14854f59d372SCristian Dumitrescu 		if (err_line)
14864f59d372SCristian Dumitrescu 			*err_line = n_lines;
14874f59d372SCristian Dumitrescu 		if (err_msg)
14884f59d372SCristian Dumitrescu 			*err_msg = "Invalid actions statement.";
14894f59d372SCristian Dumitrescu 		return -EINVAL;
14904f59d372SCristian Dumitrescu 	}
14914f59d372SCristian Dumitrescu 
14924f59d372SCristian Dumitrescu 	/* block_mask. */
14934f59d372SCristian Dumitrescu 	*block_mask |= 1 << LEARNER_ACTIONS_BLOCK;
14944f59d372SCristian Dumitrescu 
14954f59d372SCristian Dumitrescu 	return 0;
14964f59d372SCristian Dumitrescu }
14974f59d372SCristian Dumitrescu 
14984f59d372SCristian Dumitrescu static int
learner_actions_block_parse(struct learner_spec * s,uint32_t * block_mask,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)14994f59d372SCristian Dumitrescu learner_actions_block_parse(struct learner_spec *s,
15004f59d372SCristian Dumitrescu 			    uint32_t *block_mask,
15014f59d372SCristian Dumitrescu 			    char **tokens,
15024f59d372SCristian Dumitrescu 			    uint32_t n_tokens,
15034f59d372SCristian Dumitrescu 			    uint32_t n_lines,
15044f59d372SCristian Dumitrescu 			    uint32_t *err_line,
15054f59d372SCristian Dumitrescu 			    const char **err_msg)
15064f59d372SCristian Dumitrescu {
15074f59d372SCristian Dumitrescu 	const char **new_action_names = NULL;
1508cd79e020SYogesh Jangra 	int *new_action_is_for_table_entries = NULL, *new_action_is_for_default_entry = NULL;
1509cd79e020SYogesh Jangra 	char *name = NULL;
1510cd79e020SYogesh Jangra 	int action_is_for_table_entries = 1, action_is_for_default_entry = 1;
15114f59d372SCristian Dumitrescu 
15124f59d372SCristian Dumitrescu 	/* Handle end of block. */
15134f59d372SCristian Dumitrescu 	if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
15144f59d372SCristian Dumitrescu 		*block_mask &= ~(1 << LEARNER_ACTIONS_BLOCK);
15154f59d372SCristian Dumitrescu 		return 0;
15164f59d372SCristian Dumitrescu 	}
15174f59d372SCristian Dumitrescu 
15184f59d372SCristian Dumitrescu 	/* Check input arguments. */
1519cd79e020SYogesh Jangra 	if ((n_tokens > 2) ||
1520cd79e020SYogesh Jangra 	    ((n_tokens == 2) && strcmp(tokens[1], "@tableonly") &&
1521cd79e020SYogesh Jangra 	      strcmp(tokens[1], "@defaultonly"))) {
15224f59d372SCristian Dumitrescu 		if (err_line)
15234f59d372SCristian Dumitrescu 			*err_line = n_lines;
15244f59d372SCristian Dumitrescu 		if (err_msg)
15254f59d372SCristian Dumitrescu 			*err_msg = "Invalid action name statement.";
15264f59d372SCristian Dumitrescu 		return -EINVAL;
15274f59d372SCristian Dumitrescu 	}
15284f59d372SCristian Dumitrescu 
1529cd79e020SYogesh Jangra 	name = strdup(tokens[0]);
1530cd79e020SYogesh Jangra 
1531cd79e020SYogesh Jangra 	if (n_tokens == 2) {
1532cd79e020SYogesh Jangra 		if (!strcmp(tokens[1], "@tableonly"))
1533cd79e020SYogesh Jangra 			action_is_for_default_entry = 0;
1534cd79e020SYogesh Jangra 
1535cd79e020SYogesh Jangra 		if (!strcmp(tokens[1], "@defaultonly"))
1536cd79e020SYogesh Jangra 			action_is_for_table_entries = 0;
1537cd79e020SYogesh Jangra 	}
15384f59d372SCristian Dumitrescu 
15394f59d372SCristian Dumitrescu 	new_action_names = realloc(s->params.action_names,
15404f59d372SCristian Dumitrescu 				   (s->params.n_actions + 1) * sizeof(char *));
1541cd79e020SYogesh Jangra 	new_action_is_for_table_entries = realloc(s->params.action_is_for_table_entries,
1542cd79e020SYogesh Jangra 						  (s->params.n_actions + 1) * sizeof(int));
1543cd79e020SYogesh Jangra 	new_action_is_for_default_entry = realloc(s->params.action_is_for_default_entry,
1544cd79e020SYogesh Jangra 						  (s->params.n_actions + 1) * sizeof(int));
15454f59d372SCristian Dumitrescu 
1546cd79e020SYogesh Jangra 	if (!name ||
1547cd79e020SYogesh Jangra 	    !new_action_names ||
1548cd79e020SYogesh Jangra 	    !new_action_is_for_table_entries ||
1549cd79e020SYogesh Jangra 	    !new_action_is_for_default_entry) {
1550cd79e020SYogesh Jangra 		free(name);
15514f59d372SCristian Dumitrescu 		free(new_action_names);
1552cd79e020SYogesh Jangra 		free(new_action_is_for_table_entries);
1553cd79e020SYogesh Jangra 		free(new_action_is_for_default_entry);
15544f59d372SCristian Dumitrescu 
15554f59d372SCristian Dumitrescu 		if (err_line)
15564f59d372SCristian Dumitrescu 			*err_line = n_lines;
15574f59d372SCristian Dumitrescu 		if (err_msg)
15584f59d372SCristian Dumitrescu 			*err_msg = "Memory allocation failed.";
15594f59d372SCristian Dumitrescu 		return -ENOMEM;
15604f59d372SCristian Dumitrescu 	}
15614f59d372SCristian Dumitrescu 
15624f59d372SCristian Dumitrescu 	s->params.action_names = new_action_names;
1563cd79e020SYogesh Jangra 	s->params.action_names[s->params.n_actions] = name;
1564cd79e020SYogesh Jangra 
1565cd79e020SYogesh Jangra 	s->params.action_is_for_table_entries = new_action_is_for_table_entries;
1566cd79e020SYogesh Jangra 	s->params.action_is_for_table_entries[s->params.n_actions] = action_is_for_table_entries;
1567cd79e020SYogesh Jangra 
1568cd79e020SYogesh Jangra 	s->params.action_is_for_default_entry = new_action_is_for_default_entry;
1569cd79e020SYogesh Jangra 	s->params.action_is_for_default_entry[s->params.n_actions] = action_is_for_default_entry;
1570cd79e020SYogesh Jangra 
15714f59d372SCristian Dumitrescu 	s->params.n_actions++;
15724f59d372SCristian Dumitrescu 
15734f59d372SCristian Dumitrescu 	return 0;
15744f59d372SCristian Dumitrescu }
15754f59d372SCristian Dumitrescu 
15764f59d372SCristian Dumitrescu static int
learner_default_action_statement_parse(struct learner_spec * s,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)157773d94b00SCristian Dumitrescu learner_default_action_statement_parse(struct learner_spec *s,
157873d94b00SCristian Dumitrescu 				       char **tokens,
157973d94b00SCristian Dumitrescu 				       uint32_t n_tokens,
158073d94b00SCristian Dumitrescu 				       uint32_t n_lines,
158173d94b00SCristian Dumitrescu 				       uint32_t *err_line,
158273d94b00SCristian Dumitrescu 				       const char **err_msg)
158373d94b00SCristian Dumitrescu {
158473d94b00SCristian Dumitrescu 	uint32_t i;
158573d94b00SCristian Dumitrescu 	int status = 0, duplicate = 0;
158673d94b00SCristian Dumitrescu 
158773d94b00SCristian Dumitrescu 	/* Check format. */
158873d94b00SCristian Dumitrescu 	if ((n_tokens < 4) ||
158973d94b00SCristian Dumitrescu 	    strcmp(tokens[2], "args")) {
159073d94b00SCristian Dumitrescu 		status = -EINVAL;
159173d94b00SCristian Dumitrescu 		goto error;
159273d94b00SCristian Dumitrescu 	}
159373d94b00SCristian Dumitrescu 
159473d94b00SCristian Dumitrescu 	if (s->params.default_action_name) {
159573d94b00SCristian Dumitrescu 		duplicate = 1;
159673d94b00SCristian Dumitrescu 		status = -EINVAL;
159773d94b00SCristian Dumitrescu 		goto error;
159873d94b00SCristian Dumitrescu 	}
159973d94b00SCristian Dumitrescu 
160073d94b00SCristian Dumitrescu 	s->params.default_action_name = strdup(tokens[1]);
160173d94b00SCristian Dumitrescu 	if (!s->params.default_action_name) {
160273d94b00SCristian Dumitrescu 		status = -ENOMEM;
160373d94b00SCristian Dumitrescu 		goto error;
160473d94b00SCristian Dumitrescu 	}
160573d94b00SCristian Dumitrescu 
160673d94b00SCristian Dumitrescu 	if (strcmp(tokens[3], "none")) {
160773d94b00SCristian Dumitrescu 		char buffer[MAX_LINE_LENGTH];
160873d94b00SCristian Dumitrescu 		uint32_t n_tokens_args = n_tokens - 3;
160973d94b00SCristian Dumitrescu 
161073d94b00SCristian Dumitrescu 		if (!strcmp(tokens[n_tokens - 1], "const"))
161173d94b00SCristian Dumitrescu 			n_tokens_args--;
161273d94b00SCristian Dumitrescu 
161373d94b00SCristian Dumitrescu 		if (!n_tokens_args) {
161473d94b00SCristian Dumitrescu 			status = -EINVAL;
161573d94b00SCristian Dumitrescu 			goto error;
161673d94b00SCristian Dumitrescu 		}
161773d94b00SCristian Dumitrescu 
161873d94b00SCristian Dumitrescu 		buffer[0] = 0;
161973d94b00SCristian Dumitrescu 		for (i = 0; i < n_tokens_args; i++) {
162073d94b00SCristian Dumitrescu 			if (i)
162173d94b00SCristian Dumitrescu 				strcat(buffer, " ");
162273d94b00SCristian Dumitrescu 
162373d94b00SCristian Dumitrescu 			strcat(buffer, tokens[3 + i]);
162473d94b00SCristian Dumitrescu 		}
162573d94b00SCristian Dumitrescu 
162673d94b00SCristian Dumitrescu 		s->params.default_action_args = strdup(buffer);
162773d94b00SCristian Dumitrescu 		if (!s->params.default_action_args) {
162873d94b00SCristian Dumitrescu 			status = -ENOMEM;
162973d94b00SCristian Dumitrescu 			goto error;
163073d94b00SCristian Dumitrescu 		}
163173d94b00SCristian Dumitrescu 	} else {
163273d94b00SCristian Dumitrescu 		if (((n_tokens != 4) && (n_tokens != 5)) ||
163373d94b00SCristian Dumitrescu 		    ((n_tokens == 5) && (strcmp(tokens[4], "const")))) {
163473d94b00SCristian Dumitrescu 			status = -EINVAL;
163573d94b00SCristian Dumitrescu 			goto error;
163673d94b00SCristian Dumitrescu 		}
163773d94b00SCristian Dumitrescu 	}
163873d94b00SCristian Dumitrescu 
163973d94b00SCristian Dumitrescu 	if (!strcmp(tokens[n_tokens - 1], "const"))
164073d94b00SCristian Dumitrescu 		s->params.default_action_is_const = 1;
164173d94b00SCristian Dumitrescu 
164273d94b00SCristian Dumitrescu 	return 0;
164373d94b00SCristian Dumitrescu 
164473d94b00SCristian Dumitrescu error:
164573d94b00SCristian Dumitrescu 	if (err_line)
164673d94b00SCristian Dumitrescu 		*err_line = n_lines;
164773d94b00SCristian Dumitrescu 
164873d94b00SCristian Dumitrescu 	if (err_msg)
164973d94b00SCristian Dumitrescu 		switch (status) {
165073d94b00SCristian Dumitrescu 		case -ENOMEM:
165173d94b00SCristian Dumitrescu 			*err_msg = "Memory allocation failed.";
165273d94b00SCristian Dumitrescu 			break;
165373d94b00SCristian Dumitrescu 
165473d94b00SCristian Dumitrescu 		default:
165573d94b00SCristian Dumitrescu 			if (duplicate)
165673d94b00SCristian Dumitrescu 				*err_msg = "Duplicate default_action statement.";
165773d94b00SCristian Dumitrescu 
165873d94b00SCristian Dumitrescu 			*err_msg = "Invalid default_action statement.";
165973d94b00SCristian Dumitrescu 		}
166073d94b00SCristian Dumitrescu 
166173d94b00SCristian Dumitrescu 	return status;
166273d94b00SCristian Dumitrescu }
166373d94b00SCristian Dumitrescu 
166473d94b00SCristian Dumitrescu static int
learner_timeout_statement_parse(uint32_t * block_mask,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)1665e2ecc535SCristian Dumitrescu learner_timeout_statement_parse(uint32_t *block_mask,
1666e2ecc535SCristian Dumitrescu 				char **tokens,
1667e2ecc535SCristian Dumitrescu 				uint32_t n_tokens,
1668e2ecc535SCristian Dumitrescu 				uint32_t n_lines,
1669e2ecc535SCristian Dumitrescu 				uint32_t *err_line,
1670e2ecc535SCristian Dumitrescu 				const char **err_msg)
1671e2ecc535SCristian Dumitrescu {
1672e2ecc535SCristian Dumitrescu 	/* Check format. */
1673e2ecc535SCristian Dumitrescu 	if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
1674e2ecc535SCristian Dumitrescu 		if (err_line)
1675e2ecc535SCristian Dumitrescu 			*err_line = n_lines;
1676e2ecc535SCristian Dumitrescu 		if (err_msg)
1677e2ecc535SCristian Dumitrescu 			*err_msg = "Invalid timeout statement.";
1678e2ecc535SCristian Dumitrescu 		return -EINVAL;
1679e2ecc535SCristian Dumitrescu 	}
1680e2ecc535SCristian Dumitrescu 
1681e2ecc535SCristian Dumitrescu 	/* block_mask. */
1682e2ecc535SCristian Dumitrescu 	*block_mask |= 1 << LEARNER_TIMEOUT_BLOCK;
1683e2ecc535SCristian Dumitrescu 
1684e2ecc535SCristian Dumitrescu 	return 0;
1685e2ecc535SCristian Dumitrescu }
1686e2ecc535SCristian Dumitrescu 
1687e2ecc535SCristian Dumitrescu static int
learner_timeout_block_parse(struct learner_spec * s,uint32_t * block_mask,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)1688e2ecc535SCristian Dumitrescu learner_timeout_block_parse(struct learner_spec *s,
1689e2ecc535SCristian Dumitrescu 			    uint32_t *block_mask,
1690e2ecc535SCristian Dumitrescu 			    char **tokens,
1691e2ecc535SCristian Dumitrescu 			    uint32_t n_tokens,
1692e2ecc535SCristian Dumitrescu 			    uint32_t n_lines,
1693e2ecc535SCristian Dumitrescu 			    uint32_t *err_line,
1694e2ecc535SCristian Dumitrescu 			    const char **err_msg)
1695e2ecc535SCristian Dumitrescu {
1696e2ecc535SCristian Dumitrescu 	uint32_t *new_timeout = NULL;
1697e2ecc535SCristian Dumitrescu 	char *str;
1698e2ecc535SCristian Dumitrescu 	uint32_t val;
1699e2ecc535SCristian Dumitrescu 	int status = 0;
1700e2ecc535SCristian Dumitrescu 
1701e2ecc535SCristian Dumitrescu 	/* Handle end of block. */
1702e2ecc535SCristian Dumitrescu 	if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1703e2ecc535SCristian Dumitrescu 		*block_mask &= ~(1 << LEARNER_TIMEOUT_BLOCK);
1704e2ecc535SCristian Dumitrescu 		return 0;
1705e2ecc535SCristian Dumitrescu 	}
1706e2ecc535SCristian Dumitrescu 
1707e2ecc535SCristian Dumitrescu 	/* Check input arguments. */
1708e2ecc535SCristian Dumitrescu 	if (n_tokens != 1) {
1709e2ecc535SCristian Dumitrescu 		status = -EINVAL;
1710e2ecc535SCristian Dumitrescu 		goto error;
1711e2ecc535SCristian Dumitrescu 	}
1712e2ecc535SCristian Dumitrescu 
1713e2ecc535SCristian Dumitrescu 	str = tokens[0];
1714e2ecc535SCristian Dumitrescu 	val = strtoul(str, &str, 0);
1715e2ecc535SCristian Dumitrescu 	if (str[0]) {
1716e2ecc535SCristian Dumitrescu 		status = -EINVAL;
1717e2ecc535SCristian Dumitrescu 		goto error;
1718e2ecc535SCristian Dumitrescu 	}
1719e2ecc535SCristian Dumitrescu 
1720e2ecc535SCristian Dumitrescu 	new_timeout = realloc(s->timeout, (s->n_timeouts + 1) * sizeof(uint32_t));
1721e2ecc535SCristian Dumitrescu 	if (!new_timeout) {
1722e2ecc535SCristian Dumitrescu 		status = -ENOMEM;
1723e2ecc535SCristian Dumitrescu 		goto error;
1724e2ecc535SCristian Dumitrescu 	}
1725e2ecc535SCristian Dumitrescu 
1726e2ecc535SCristian Dumitrescu 	s->timeout = new_timeout;
1727e2ecc535SCristian Dumitrescu 	s->timeout[s->n_timeouts] = val;
1728e2ecc535SCristian Dumitrescu 	s->n_timeouts++;
1729e2ecc535SCristian Dumitrescu 
1730e2ecc535SCristian Dumitrescu 	return 0;
1731e2ecc535SCristian Dumitrescu 
1732e2ecc535SCristian Dumitrescu error:
1733e2ecc535SCristian Dumitrescu 	free(new_timeout);
1734e2ecc535SCristian Dumitrescu 
1735e2ecc535SCristian Dumitrescu 	if (err_line)
1736e2ecc535SCristian Dumitrescu 		*err_line = n_lines;
1737e2ecc535SCristian Dumitrescu 
1738e2ecc535SCristian Dumitrescu 	if (err_msg)
1739e2ecc535SCristian Dumitrescu 		switch (status) {
1740e2ecc535SCristian Dumitrescu 		case -ENOMEM:
1741e2ecc535SCristian Dumitrescu 			*err_msg = "Memory allocation failed.";
1742e2ecc535SCristian Dumitrescu 			break;
1743e2ecc535SCristian Dumitrescu 
1744e2ecc535SCristian Dumitrescu 		default:
1745e2ecc535SCristian Dumitrescu 			*err_msg = "Invalid timeout value statement.";
1746e2ecc535SCristian Dumitrescu 			break;
1747e2ecc535SCristian Dumitrescu 		}
1748e2ecc535SCristian Dumitrescu 
1749e2ecc535SCristian Dumitrescu 	return status;
1750e2ecc535SCristian Dumitrescu }
1751e2ecc535SCristian Dumitrescu 
1752e2ecc535SCristian Dumitrescu 
1753e2ecc535SCristian Dumitrescu static int
learner_statement_parse(struct learner_spec * s,uint32_t * block_mask,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)17544f59d372SCristian Dumitrescu learner_statement_parse(struct learner_spec *s,
17554f59d372SCristian Dumitrescu 		      uint32_t *block_mask,
17564f59d372SCristian Dumitrescu 		      char **tokens,
17574f59d372SCristian Dumitrescu 		      uint32_t n_tokens,
17584f59d372SCristian Dumitrescu 		      uint32_t n_lines,
17594f59d372SCristian Dumitrescu 		      uint32_t *err_line,
17604f59d372SCristian Dumitrescu 		      const char **err_msg)
17614f59d372SCristian Dumitrescu {
17624f59d372SCristian Dumitrescu 	/* Check format. */
17634f59d372SCristian Dumitrescu 	if ((n_tokens != 3) || strcmp(tokens[2], "{")) {
17644f59d372SCristian Dumitrescu 		if (err_line)
17654f59d372SCristian Dumitrescu 			*err_line = n_lines;
17664f59d372SCristian Dumitrescu 		if (err_msg)
17674f59d372SCristian Dumitrescu 			*err_msg = "Invalid learner statement.";
17684f59d372SCristian Dumitrescu 		return -EINVAL;
17694f59d372SCristian Dumitrescu 	}
17704f59d372SCristian Dumitrescu 
17714f59d372SCristian Dumitrescu 	/* spec. */
17724f59d372SCristian Dumitrescu 	s->name = strdup(tokens[1]);
17734f59d372SCristian Dumitrescu 	if (!s->name) {
17744f59d372SCristian Dumitrescu 		if (err_line)
17754f59d372SCristian Dumitrescu 			*err_line = n_lines;
17764f59d372SCristian Dumitrescu 		if (err_msg)
17774f59d372SCristian Dumitrescu 			*err_msg = "Memory allocation failed.";
17784f59d372SCristian Dumitrescu 		return -ENOMEM;
17794f59d372SCristian Dumitrescu 	}
17804f59d372SCristian Dumitrescu 
17814f59d372SCristian Dumitrescu 	/* block_mask. */
17824f59d372SCristian Dumitrescu 	*block_mask |= 1 << LEARNER_BLOCK;
17834f59d372SCristian Dumitrescu 
17844f59d372SCristian Dumitrescu 	return 0;
17854f59d372SCristian Dumitrescu }
17864f59d372SCristian Dumitrescu 
17874f59d372SCristian Dumitrescu static int
learner_block_parse(struct learner_spec * s,uint32_t * block_mask,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)17884f59d372SCristian Dumitrescu learner_block_parse(struct learner_spec *s,
17894f59d372SCristian Dumitrescu 		    uint32_t *block_mask,
17904f59d372SCristian Dumitrescu 		    char **tokens,
17914f59d372SCristian Dumitrescu 		    uint32_t n_tokens,
17924f59d372SCristian Dumitrescu 		    uint32_t n_lines,
17934f59d372SCristian Dumitrescu 		    uint32_t *err_line,
17944f59d372SCristian Dumitrescu 		    const char **err_msg)
17954f59d372SCristian Dumitrescu {
17964f59d372SCristian Dumitrescu 	if (*block_mask & (1 << LEARNER_KEY_BLOCK))
17974f59d372SCristian Dumitrescu 		return learner_key_block_parse(s,
17984f59d372SCristian Dumitrescu 					       block_mask,
17994f59d372SCristian Dumitrescu 					       tokens,
18004f59d372SCristian Dumitrescu 					       n_tokens,
18014f59d372SCristian Dumitrescu 					       n_lines,
18024f59d372SCristian Dumitrescu 					       err_line,
18034f59d372SCristian Dumitrescu 					       err_msg);
18044f59d372SCristian Dumitrescu 
18054f59d372SCristian Dumitrescu 	if (*block_mask & (1 << LEARNER_ACTIONS_BLOCK))
18064f59d372SCristian Dumitrescu 		return learner_actions_block_parse(s,
18074f59d372SCristian Dumitrescu 						   block_mask,
18084f59d372SCristian Dumitrescu 						   tokens,
18094f59d372SCristian Dumitrescu 						   n_tokens,
18104f59d372SCristian Dumitrescu 						   n_lines,
18114f59d372SCristian Dumitrescu 						   err_line,
18124f59d372SCristian Dumitrescu 						   err_msg);
18134f59d372SCristian Dumitrescu 
1814e2ecc535SCristian Dumitrescu 	if (*block_mask & (1 << LEARNER_TIMEOUT_BLOCK))
1815e2ecc535SCristian Dumitrescu 		return learner_timeout_block_parse(s,
1816e2ecc535SCristian Dumitrescu 						   block_mask,
1817e2ecc535SCristian Dumitrescu 						   tokens,
1818e2ecc535SCristian Dumitrescu 						   n_tokens,
1819e2ecc535SCristian Dumitrescu 						   n_lines,
1820e2ecc535SCristian Dumitrescu 						   err_line,
1821e2ecc535SCristian Dumitrescu 						   err_msg);
1822e2ecc535SCristian Dumitrescu 
18234f59d372SCristian Dumitrescu 	/* Handle end of block. */
18244f59d372SCristian Dumitrescu 	if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
18254f59d372SCristian Dumitrescu 		*block_mask &= ~(1 << LEARNER_BLOCK);
18264f59d372SCristian Dumitrescu 		return 0;
18274f59d372SCristian Dumitrescu 	}
18284f59d372SCristian Dumitrescu 
18294f59d372SCristian Dumitrescu 	if (!strcmp(tokens[0], "key"))
18304f59d372SCristian Dumitrescu 		return learner_key_statement_parse(block_mask,
18314f59d372SCristian Dumitrescu 						   tokens,
18324f59d372SCristian Dumitrescu 						   n_tokens,
18334f59d372SCristian Dumitrescu 						   n_lines,
18344f59d372SCristian Dumitrescu 						   err_line,
18354f59d372SCristian Dumitrescu 						   err_msg);
18364f59d372SCristian Dumitrescu 
18374f59d372SCristian Dumitrescu 	if (!strcmp(tokens[0], "actions"))
18384f59d372SCristian Dumitrescu 		return learner_actions_statement_parse(block_mask,
18394f59d372SCristian Dumitrescu 						       tokens,
18404f59d372SCristian Dumitrescu 						       n_tokens,
18414f59d372SCristian Dumitrescu 						       n_lines,
18424f59d372SCristian Dumitrescu 						       err_line,
18434f59d372SCristian Dumitrescu 						       err_msg);
18444f59d372SCristian Dumitrescu 
184573d94b00SCristian Dumitrescu 	if (!strcmp(tokens[0], "default_action"))
184673d94b00SCristian Dumitrescu 		return learner_default_action_statement_parse(s,
184773d94b00SCristian Dumitrescu 							      tokens,
184873d94b00SCristian Dumitrescu 							      n_tokens,
184973d94b00SCristian Dumitrescu 							      n_lines,
185073d94b00SCristian Dumitrescu 							      err_line,
185173d94b00SCristian Dumitrescu 							      err_msg);
18524f59d372SCristian Dumitrescu 
1853fa7723b5SCristian Dumitrescu 	if (!strcmp(tokens[0], "hash")) {
1854fa7723b5SCristian Dumitrescu 		if (n_tokens != 2) {
1855fa7723b5SCristian Dumitrescu 			if (err_line)
1856fa7723b5SCristian Dumitrescu 				*err_line = n_lines;
1857fa7723b5SCristian Dumitrescu 			if (err_msg)
1858fa7723b5SCristian Dumitrescu 				*err_msg = "Invalid hash statement.";
1859fa7723b5SCristian Dumitrescu 			return -EINVAL;
1860fa7723b5SCristian Dumitrescu 		}
1861fa7723b5SCristian Dumitrescu 
1862fa7723b5SCristian Dumitrescu 		if (s->params.hash_func_name) {
1863fa7723b5SCristian Dumitrescu 			if (err_line)
1864fa7723b5SCristian Dumitrescu 				*err_line = n_lines;
1865fa7723b5SCristian Dumitrescu 			if (err_msg)
1866fa7723b5SCristian Dumitrescu 				*err_msg = "Duplicate hash statement.";
1867fa7723b5SCristian Dumitrescu 			return -EINVAL;
1868fa7723b5SCristian Dumitrescu 		}
1869fa7723b5SCristian Dumitrescu 
1870fa7723b5SCristian Dumitrescu 		s->params.hash_func_name = strdup(tokens[1]);
1871fa7723b5SCristian Dumitrescu 		if (!s->params.hash_func_name) {
1872fa7723b5SCristian Dumitrescu 			if (err_line)
1873fa7723b5SCristian Dumitrescu 				*err_line = n_lines;
1874fa7723b5SCristian Dumitrescu 			if (err_msg)
1875fa7723b5SCristian Dumitrescu 				*err_msg = "Memory allocation failed.";
1876fa7723b5SCristian Dumitrescu 			return -ENOMEM;
1877fa7723b5SCristian Dumitrescu 		}
1878fa7723b5SCristian Dumitrescu 
1879fa7723b5SCristian Dumitrescu 		return 0;
1880fa7723b5SCristian Dumitrescu 	}
1881fa7723b5SCristian Dumitrescu 
18824f59d372SCristian Dumitrescu 	if (!strcmp(tokens[0], "size")) {
18834f59d372SCristian Dumitrescu 		char *p = tokens[1];
18844f59d372SCristian Dumitrescu 
18854f59d372SCristian Dumitrescu 		if (n_tokens != 2) {
18864f59d372SCristian Dumitrescu 			if (err_line)
18874f59d372SCristian Dumitrescu 				*err_line = n_lines;
18884f59d372SCristian Dumitrescu 			if (err_msg)
18894f59d372SCristian Dumitrescu 				*err_msg = "Invalid size statement.";
18904f59d372SCristian Dumitrescu 			return -EINVAL;
18914f59d372SCristian Dumitrescu 		}
18924f59d372SCristian Dumitrescu 
18934f59d372SCristian Dumitrescu 		s->size = strtoul(p, &p, 0);
18944f59d372SCristian Dumitrescu 		if (p[0]) {
18954f59d372SCristian Dumitrescu 			if (err_line)
18964f59d372SCristian Dumitrescu 				*err_line = n_lines;
18974f59d372SCristian Dumitrescu 			if (err_msg)
18984f59d372SCristian Dumitrescu 				*err_msg = "Invalid size argument.";
18994f59d372SCristian Dumitrescu 			return -EINVAL;
19004f59d372SCristian Dumitrescu 		}
19014f59d372SCristian Dumitrescu 
19024f59d372SCristian Dumitrescu 		return 0;
19034f59d372SCristian Dumitrescu 	}
19044f59d372SCristian Dumitrescu 
1905e2ecc535SCristian Dumitrescu 	if (!strcmp(tokens[0], "timeout"))
1906e2ecc535SCristian Dumitrescu 		return learner_timeout_statement_parse(block_mask,
1907e2ecc535SCristian Dumitrescu 						       tokens,
1908e2ecc535SCristian Dumitrescu 						       n_tokens,
1909e2ecc535SCristian Dumitrescu 						       n_lines,
1910e2ecc535SCristian Dumitrescu 						       err_line,
1911e2ecc535SCristian Dumitrescu 						       err_msg);
19124f59d372SCristian Dumitrescu 
19134f59d372SCristian Dumitrescu 	/* Anything else. */
19144f59d372SCristian Dumitrescu 	if (err_line)
19154f59d372SCristian Dumitrescu 		*err_line = n_lines;
19164f59d372SCristian Dumitrescu 	if (err_msg)
19174f59d372SCristian Dumitrescu 		*err_msg = "Invalid statement.";
19184f59d372SCristian Dumitrescu 	return -EINVAL;
19194f59d372SCristian Dumitrescu }
19204f59d372SCristian Dumitrescu 
19214f59d372SCristian Dumitrescu /*
192299a2dd95SBruce Richardson  * regarray.
192399a2dd95SBruce Richardson  */
192499a2dd95SBruce Richardson static void
regarray_spec_free(struct regarray_spec * s)192599a2dd95SBruce Richardson regarray_spec_free(struct regarray_spec *s)
192699a2dd95SBruce Richardson {
192799a2dd95SBruce Richardson 	if (!s)
192899a2dd95SBruce Richardson 		return;
192999a2dd95SBruce Richardson 
193099a2dd95SBruce Richardson 	free(s->name);
193199a2dd95SBruce Richardson 	s->name = NULL;
193299a2dd95SBruce Richardson }
193399a2dd95SBruce Richardson 
193499a2dd95SBruce Richardson static int
regarray_statement_parse(struct regarray_spec * s,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)193599a2dd95SBruce Richardson regarray_statement_parse(struct regarray_spec *s,
193699a2dd95SBruce Richardson 			 char **tokens,
193799a2dd95SBruce Richardson 			 uint32_t n_tokens,
193899a2dd95SBruce Richardson 			 uint32_t n_lines,
193999a2dd95SBruce Richardson 			 uint32_t *err_line,
194099a2dd95SBruce Richardson 			 const char **err_msg)
194199a2dd95SBruce Richardson {
194299a2dd95SBruce Richardson 	char *p;
194399a2dd95SBruce Richardson 
194499a2dd95SBruce Richardson 	/* Check format. */
194599a2dd95SBruce Richardson 	if ((n_tokens != 6) ||
194699a2dd95SBruce Richardson 	     strcmp(tokens[2], "size") ||
194799a2dd95SBruce Richardson 	     strcmp(tokens[4], "initval")) {
194899a2dd95SBruce Richardson 		if (err_line)
194999a2dd95SBruce Richardson 			*err_line = n_lines;
195099a2dd95SBruce Richardson 		if (err_msg)
195199a2dd95SBruce Richardson 			*err_msg = "Invalid regarray statement.";
195299a2dd95SBruce Richardson 		return -EINVAL;
195399a2dd95SBruce Richardson 	}
195499a2dd95SBruce Richardson 
195599a2dd95SBruce Richardson 	/* spec. */
195699a2dd95SBruce Richardson 	s->name = strdup(tokens[1]);
195799a2dd95SBruce Richardson 	if (!s->name) {
195899a2dd95SBruce Richardson 		if (err_line)
195999a2dd95SBruce Richardson 			*err_line = n_lines;
196099a2dd95SBruce Richardson 		if (err_msg)
196199a2dd95SBruce Richardson 			*err_msg = "Memory allocation failed.";
196299a2dd95SBruce Richardson 		return -ENOMEM;
196399a2dd95SBruce Richardson 	}
196499a2dd95SBruce Richardson 
196599a2dd95SBruce Richardson 	p = tokens[3];
196699a2dd95SBruce Richardson 	s->size = strtoul(p, &p, 0);
196799a2dd95SBruce Richardson 	if (p[0] || !s->size) {
196899a2dd95SBruce Richardson 		if (err_line)
196999a2dd95SBruce Richardson 			*err_line = n_lines;
197099a2dd95SBruce Richardson 		if (err_msg)
197199a2dd95SBruce Richardson 			*err_msg = "Invalid size argument.";
197299a2dd95SBruce Richardson 		return -EINVAL;
197399a2dd95SBruce Richardson 	}
197499a2dd95SBruce Richardson 
197599a2dd95SBruce Richardson 	p = tokens[5];
197699a2dd95SBruce Richardson 	s->init_val = strtoull(p, &p, 0);
197799a2dd95SBruce Richardson 	if (p[0]) {
197899a2dd95SBruce Richardson 		if (err_line)
197999a2dd95SBruce Richardson 			*err_line = n_lines;
198099a2dd95SBruce Richardson 		if (err_msg)
198199a2dd95SBruce Richardson 			*err_msg = "Invalid initval argument.";
198299a2dd95SBruce Richardson 		return -EINVAL;
198399a2dd95SBruce Richardson 	}
198499a2dd95SBruce Richardson 
198599a2dd95SBruce Richardson 	return 0;
198699a2dd95SBruce Richardson }
198799a2dd95SBruce Richardson 
198899a2dd95SBruce Richardson /*
198999a2dd95SBruce Richardson  * metarray.
199099a2dd95SBruce Richardson  */
199199a2dd95SBruce Richardson static void
metarray_spec_free(struct metarray_spec * s)199299a2dd95SBruce Richardson metarray_spec_free(struct metarray_spec *s)
199399a2dd95SBruce Richardson {
199499a2dd95SBruce Richardson 	if (!s)
199599a2dd95SBruce Richardson 		return;
199699a2dd95SBruce Richardson 
199799a2dd95SBruce Richardson 	free(s->name);
199899a2dd95SBruce Richardson 	s->name = NULL;
199999a2dd95SBruce Richardson }
200099a2dd95SBruce Richardson 
200199a2dd95SBruce Richardson static int
metarray_statement_parse(struct metarray_spec * s,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)200299a2dd95SBruce Richardson metarray_statement_parse(struct metarray_spec *s,
200399a2dd95SBruce Richardson 			 char **tokens,
200499a2dd95SBruce Richardson 			 uint32_t n_tokens,
200599a2dd95SBruce Richardson 			 uint32_t n_lines,
200699a2dd95SBruce Richardson 			 uint32_t *err_line,
200799a2dd95SBruce Richardson 			 const char **err_msg)
200899a2dd95SBruce Richardson {
200999a2dd95SBruce Richardson 	char *p;
201099a2dd95SBruce Richardson 
201199a2dd95SBruce Richardson 	/* Check format. */
201299a2dd95SBruce Richardson 	if ((n_tokens != 4) || strcmp(tokens[2], "size")) {
201399a2dd95SBruce Richardson 		if (err_line)
201499a2dd95SBruce Richardson 			*err_line = n_lines;
201599a2dd95SBruce Richardson 		if (err_msg)
201699a2dd95SBruce Richardson 			*err_msg = "Invalid metarray statement.";
201799a2dd95SBruce Richardson 		return -EINVAL;
201899a2dd95SBruce Richardson 	}
201999a2dd95SBruce Richardson 
202099a2dd95SBruce Richardson 	/* spec. */
202199a2dd95SBruce Richardson 	s->name = strdup(tokens[1]);
202299a2dd95SBruce Richardson 	if (!s->name) {
202399a2dd95SBruce Richardson 		if (err_line)
202499a2dd95SBruce Richardson 			*err_line = n_lines;
202599a2dd95SBruce Richardson 		if (err_msg)
202699a2dd95SBruce Richardson 			*err_msg = "Memory allocation failed.";
202799a2dd95SBruce Richardson 		return -ENOMEM;
202899a2dd95SBruce Richardson 	}
202999a2dd95SBruce Richardson 
203099a2dd95SBruce Richardson 	p = tokens[3];
203199a2dd95SBruce Richardson 	s->size = strtoul(p, &p, 0);
203299a2dd95SBruce Richardson 	if (p[0] || !s->size) {
203399a2dd95SBruce Richardson 		if (err_line)
203499a2dd95SBruce Richardson 			*err_line = n_lines;
203599a2dd95SBruce Richardson 		if (err_msg)
203699a2dd95SBruce Richardson 			*err_msg = "Invalid size argument.";
203799a2dd95SBruce Richardson 		return -EINVAL;
203899a2dd95SBruce Richardson 	}
203999a2dd95SBruce Richardson 
204099a2dd95SBruce Richardson 	return 0;
204199a2dd95SBruce Richardson }
204299a2dd95SBruce Richardson 
204399a2dd95SBruce Richardson /*
20448ba342ceSCristian Dumitrescu  *
20458ba342ceSCristian Dumitrescu  * rss
20468ba342ceSCristian Dumitrescu  */
20478ba342ceSCristian Dumitrescu 
20488ba342ceSCristian Dumitrescu static void
rss_spec_free(struct rss_spec * s)20498ba342ceSCristian Dumitrescu rss_spec_free(struct rss_spec *s)
20508ba342ceSCristian Dumitrescu {
20518ba342ceSCristian Dumitrescu 	if (!s)
20528ba342ceSCristian Dumitrescu 		return;
20538ba342ceSCristian Dumitrescu 
20548ba342ceSCristian Dumitrescu 	free(s->name);
20558ba342ceSCristian Dumitrescu 	s->name = NULL;
20568ba342ceSCristian Dumitrescu }
20578ba342ceSCristian Dumitrescu 
20588ba342ceSCristian Dumitrescu static int
rss_statement_parse(struct rss_spec * s,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)20598ba342ceSCristian Dumitrescu rss_statement_parse(struct rss_spec *s,
20608ba342ceSCristian Dumitrescu 			 char **tokens,
20618ba342ceSCristian Dumitrescu 			 uint32_t n_tokens,
20628ba342ceSCristian Dumitrescu 			 uint32_t n_lines,
20638ba342ceSCristian Dumitrescu 			 uint32_t *err_line,
20648ba342ceSCristian Dumitrescu 			 const char **err_msg)
20658ba342ceSCristian Dumitrescu {
20668ba342ceSCristian Dumitrescu 	/* Check format. */
20678ba342ceSCristian Dumitrescu 	if ((n_tokens != 2)) {
20688ba342ceSCristian Dumitrescu 		if (err_line)
20698ba342ceSCristian Dumitrescu 			*err_line = n_lines;
20708ba342ceSCristian Dumitrescu 		if (err_msg)
20718ba342ceSCristian Dumitrescu 			*err_msg = "Invalid rss statement.";
20728ba342ceSCristian Dumitrescu 		return -EINVAL;
20738ba342ceSCristian Dumitrescu 	}
20748ba342ceSCristian Dumitrescu 
20758ba342ceSCristian Dumitrescu 	/* spec. */
20768ba342ceSCristian Dumitrescu 	s->name = strdup(tokens[1]);
20778ba342ceSCristian Dumitrescu 	if (!s->name) {
20788ba342ceSCristian Dumitrescu 		if (err_line)
20798ba342ceSCristian Dumitrescu 			*err_line = n_lines;
20808ba342ceSCristian Dumitrescu 		if (err_msg)
20818ba342ceSCristian Dumitrescu 			*err_msg = "Memory allocation failed.";
20828ba342ceSCristian Dumitrescu 		return -ENOMEM;
20838ba342ceSCristian Dumitrescu 	}
20848ba342ceSCristian Dumitrescu 
20858ba342ceSCristian Dumitrescu 	return 0;
20868ba342ceSCristian Dumitrescu }
20878ba342ceSCristian Dumitrescu 
20888ba342ceSCristian Dumitrescu /*
208999a2dd95SBruce Richardson  * apply.
209099a2dd95SBruce Richardson  */
209199a2dd95SBruce Richardson static void
apply_spec_free(struct apply_spec * s)209299a2dd95SBruce Richardson apply_spec_free(struct apply_spec *s)
209399a2dd95SBruce Richardson {
209499a2dd95SBruce Richardson 	uint32_t i;
209599a2dd95SBruce Richardson 
209699a2dd95SBruce Richardson 	if (!s)
209799a2dd95SBruce Richardson 		return;
209899a2dd95SBruce Richardson 
209999a2dd95SBruce Richardson 	for (i = 0; i < s->n_instructions; i++) {
210099a2dd95SBruce Richardson 		uintptr_t instr = (uintptr_t)s->instructions[i];
210199a2dd95SBruce Richardson 
210299a2dd95SBruce Richardson 		free((void *)instr);
210399a2dd95SBruce Richardson 	}
210499a2dd95SBruce Richardson 
210599a2dd95SBruce Richardson 	free(s->instructions);
210699a2dd95SBruce Richardson 	s->instructions = NULL;
210799a2dd95SBruce Richardson 
210899a2dd95SBruce Richardson 	s->n_instructions = 0;
210999a2dd95SBruce Richardson }
211099a2dd95SBruce Richardson 
211199a2dd95SBruce Richardson static int
apply_statement_parse(uint32_t * block_mask,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)211299a2dd95SBruce Richardson apply_statement_parse(uint32_t *block_mask,
211399a2dd95SBruce Richardson 		      char **tokens,
211499a2dd95SBruce Richardson 		      uint32_t n_tokens,
211599a2dd95SBruce Richardson 		      uint32_t n_lines,
211699a2dd95SBruce Richardson 		      uint32_t *err_line,
211799a2dd95SBruce Richardson 		      const char **err_msg)
211899a2dd95SBruce Richardson {
211999a2dd95SBruce Richardson 	/* Check format. */
212099a2dd95SBruce Richardson 	if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
212199a2dd95SBruce Richardson 		if (err_line)
212299a2dd95SBruce Richardson 			*err_line = n_lines;
212399a2dd95SBruce Richardson 		if (err_msg)
212499a2dd95SBruce Richardson 			*err_msg = "Invalid apply statement.";
212599a2dd95SBruce Richardson 		return -EINVAL;
212699a2dd95SBruce Richardson 	}
212799a2dd95SBruce Richardson 
212899a2dd95SBruce Richardson 	/* block_mask. */
212999a2dd95SBruce Richardson 	*block_mask |= 1 << APPLY_BLOCK;
213099a2dd95SBruce Richardson 
213199a2dd95SBruce Richardson 	return 0;
213299a2dd95SBruce Richardson }
213399a2dd95SBruce Richardson 
213499a2dd95SBruce Richardson static int
apply_block_parse(struct apply_spec * s,uint32_t * block_mask,char ** tokens,uint32_t n_tokens,uint32_t n_lines,uint32_t * err_line,const char ** err_msg)213599a2dd95SBruce Richardson apply_block_parse(struct apply_spec *s,
213699a2dd95SBruce Richardson 		  uint32_t *block_mask,
213799a2dd95SBruce Richardson 		  char **tokens,
213899a2dd95SBruce Richardson 		  uint32_t n_tokens,
213999a2dd95SBruce Richardson 		  uint32_t n_lines,
214099a2dd95SBruce Richardson 		  uint32_t *err_line,
214199a2dd95SBruce Richardson 		  const char **err_msg)
214299a2dd95SBruce Richardson {
214399a2dd95SBruce Richardson 	char buffer[RTE_SWX_INSTRUCTION_SIZE], *instr;
214499a2dd95SBruce Richardson 	const char **new_instructions;
214599a2dd95SBruce Richardson 	uint32_t i;
214699a2dd95SBruce Richardson 
214799a2dd95SBruce Richardson 	/* Handle end of block. */
214899a2dd95SBruce Richardson 	if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
214999a2dd95SBruce Richardson 		*block_mask &= ~(1 << APPLY_BLOCK);
215099a2dd95SBruce Richardson 		return 0;
215199a2dd95SBruce Richardson 	}
215299a2dd95SBruce Richardson 
215399a2dd95SBruce Richardson 	/* spec. */
215499a2dd95SBruce Richardson 	buffer[0] = 0;
215599a2dd95SBruce Richardson 	for (i = 0; i < n_tokens; i++) {
215699a2dd95SBruce Richardson 		if (i)
215799a2dd95SBruce Richardson 			strcat(buffer, " ");
215899a2dd95SBruce Richardson 		strcat(buffer, tokens[i]);
215999a2dd95SBruce Richardson 	}
216099a2dd95SBruce Richardson 
216199a2dd95SBruce Richardson 	instr = strdup(buffer);
216299a2dd95SBruce Richardson 	if (!instr) {
216399a2dd95SBruce Richardson 		if (err_line)
216499a2dd95SBruce Richardson 			*err_line = n_lines;
216599a2dd95SBruce Richardson 		if (err_msg)
216699a2dd95SBruce Richardson 			*err_msg = "Memory allocation failed.";
216799a2dd95SBruce Richardson 		return -ENOMEM;
216899a2dd95SBruce Richardson 	}
216999a2dd95SBruce Richardson 
217099a2dd95SBruce Richardson 	new_instructions = realloc(s->instructions,
217199a2dd95SBruce Richardson 				   (s->n_instructions + 1) * sizeof(char *));
217299a2dd95SBruce Richardson 	if (!new_instructions) {
217399a2dd95SBruce Richardson 		free(instr);
217499a2dd95SBruce Richardson 
217599a2dd95SBruce Richardson 		if (err_line)
217699a2dd95SBruce Richardson 			*err_line = n_lines;
217799a2dd95SBruce Richardson 		if (err_msg)
217899a2dd95SBruce Richardson 			*err_msg = "Memory allocation failed.";
217999a2dd95SBruce Richardson 		return -ENOMEM;
218099a2dd95SBruce Richardson 	}
218199a2dd95SBruce Richardson 
218299a2dd95SBruce Richardson 	s->instructions = new_instructions;
218399a2dd95SBruce Richardson 	s->instructions[s->n_instructions] = instr;
218499a2dd95SBruce Richardson 	s->n_instructions++;
218599a2dd95SBruce Richardson 
218699a2dd95SBruce Richardson 	return 0;
218799a2dd95SBruce Richardson }
218899a2dd95SBruce Richardson 
218999a2dd95SBruce Richardson /*
219099a2dd95SBruce Richardson  * Pipeline.
219199a2dd95SBruce Richardson  */
21924684aa75SCristian Dumitrescu void
pipeline_spec_free(struct pipeline_spec * s)21934684aa75SCristian Dumitrescu pipeline_spec_free(struct pipeline_spec *s)
21944684aa75SCristian Dumitrescu {
21954684aa75SCristian Dumitrescu 	if (!s)
21964684aa75SCristian Dumitrescu 		return;
21974684aa75SCristian Dumitrescu 
21984684aa75SCristian Dumitrescu 	free(s->extobjs);
21994684aa75SCristian Dumitrescu 	free(s->structs);
22004684aa75SCristian Dumitrescu 	free(s->headers);
22014684aa75SCristian Dumitrescu 	free(s->metadata);
22024684aa75SCristian Dumitrescu 	free(s->actions);
22034684aa75SCristian Dumitrescu 	free(s->tables);
22044684aa75SCristian Dumitrescu 	free(s->selectors);
22054684aa75SCristian Dumitrescu 	free(s->learners);
22064684aa75SCristian Dumitrescu 	free(s->regarrays);
22074684aa75SCristian Dumitrescu 	free(s->metarrays);
22084684aa75SCristian Dumitrescu 	free(s->apply);
22094684aa75SCristian Dumitrescu 
22104684aa75SCristian Dumitrescu 	memset(s, 0, sizeof(struct pipeline_spec));
22114684aa75SCristian Dumitrescu }
22124684aa75SCristian Dumitrescu 
2213894c93e1SCristian Dumitrescu static const char *
match_type_string_get(enum rte_swx_table_match_type match_type)2214894c93e1SCristian Dumitrescu match_type_string_get(enum rte_swx_table_match_type match_type)
2215894c93e1SCristian Dumitrescu {
2216894c93e1SCristian Dumitrescu 	switch (match_type) {
2217894c93e1SCristian Dumitrescu 	case RTE_SWX_TABLE_MATCH_WILDCARD: return "RTE_SWX_TABLE_MATCH_WILDCARD";
2218894c93e1SCristian Dumitrescu 	case RTE_SWX_TABLE_MATCH_LPM: return "RTE_SWX_TABLE_MATCH_LPM";
2219894c93e1SCristian Dumitrescu 	case RTE_SWX_TABLE_MATCH_EXACT: return "RTE_SWX_TABLE_MATCH_EXACT";
2220894c93e1SCristian Dumitrescu 	default: return "RTE_SWX_TABLE_MATCH_UNKNOWN";
2221894c93e1SCristian Dumitrescu 	}
2222894c93e1SCristian Dumitrescu }
2223894c93e1SCristian Dumitrescu 
2224894c93e1SCristian Dumitrescu void
pipeline_spec_codegen(FILE * f,struct pipeline_spec * s)2225894c93e1SCristian Dumitrescu pipeline_spec_codegen(FILE *f,
2226894c93e1SCristian Dumitrescu 		      struct pipeline_spec *s)
2227894c93e1SCristian Dumitrescu {
2228894c93e1SCristian Dumitrescu 	uint32_t i;
2229894c93e1SCristian Dumitrescu 
2230894c93e1SCristian Dumitrescu 	/* Check the input arguments. */
2231894c93e1SCristian Dumitrescu 	if (!f || !s)
2232894c93e1SCristian Dumitrescu 		return;
2233894c93e1SCristian Dumitrescu 
2234894c93e1SCristian Dumitrescu 	/* extobj. */
2235894c93e1SCristian Dumitrescu 	fprintf(f, "static struct extobj_spec extobjs[] = {\n");
2236894c93e1SCristian Dumitrescu 
2237894c93e1SCristian Dumitrescu 	for (i = 0; i < s->n_extobjs; i++) {
2238894c93e1SCristian Dumitrescu 		struct extobj_spec *extobj_spec = &s->extobjs[i];
2239894c93e1SCristian Dumitrescu 
2240894c93e1SCristian Dumitrescu 		fprintf(f, "\t[%d] = {\n", i);
2241894c93e1SCristian Dumitrescu 		fprintf(f, "\t\t.name = \"%s\",\n", extobj_spec->name);
2242894c93e1SCristian Dumitrescu 		fprintf(f, "\t\t.extern_type_name = \"%s\",\n", extobj_spec->extern_type_name);
2243894c93e1SCristian Dumitrescu 		if (extobj_spec->pragma)
2244894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t.pragma = \"%s\",\n", extobj_spec->pragma);
2245894c93e1SCristian Dumitrescu 		else
2246894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t.pragma = NULL,\n");
2247894c93e1SCristian Dumitrescu 		fprintf(f, "\t},\n");
2248894c93e1SCristian Dumitrescu 	}
2249894c93e1SCristian Dumitrescu 
2250894c93e1SCristian Dumitrescu 	fprintf(f, "};\n\n");
2251894c93e1SCristian Dumitrescu 
2252894c93e1SCristian Dumitrescu 	/* regarray. */
2253894c93e1SCristian Dumitrescu 	fprintf(f, "static struct regarray_spec regarrays[] = {\n");
2254894c93e1SCristian Dumitrescu 
2255894c93e1SCristian Dumitrescu 	for (i = 0; i < s->n_regarrays; i++) {
2256894c93e1SCristian Dumitrescu 		struct regarray_spec *regarray_spec = &s->regarrays[i];
2257894c93e1SCristian Dumitrescu 
2258894c93e1SCristian Dumitrescu 		fprintf(f, "\t[%d] = {\n", i);
2259894c93e1SCristian Dumitrescu 		fprintf(f, "\t\t.name = \"%s\",\n", regarray_spec->name);
2260894c93e1SCristian Dumitrescu 		fprintf(f, "\t\t.init_val = %" PRIu64 ",\n", regarray_spec->init_val);
2261894c93e1SCristian Dumitrescu 		fprintf(f, "\t\t.size = %u,\n", regarray_spec->size);
2262894c93e1SCristian Dumitrescu 		fprintf(f, "\t},\n");
2263894c93e1SCristian Dumitrescu 	}
2264894c93e1SCristian Dumitrescu 
2265894c93e1SCristian Dumitrescu 	fprintf(f, "};\n\n");
2266894c93e1SCristian Dumitrescu 
2267894c93e1SCristian Dumitrescu 	/* metarray. */
2268894c93e1SCristian Dumitrescu 	fprintf(f, "static struct metarray_spec metarrays[] = {\n");
2269894c93e1SCristian Dumitrescu 
2270894c93e1SCristian Dumitrescu 	for (i = 0; i < s->n_metarrays; i++) {
2271894c93e1SCristian Dumitrescu 		struct metarray_spec *metarray_spec = &s->metarrays[i];
2272894c93e1SCristian Dumitrescu 
2273894c93e1SCristian Dumitrescu 		fprintf(f, "\t[%d] = {\n", i);
2274894c93e1SCristian Dumitrescu 		fprintf(f, "\t\t.name = \"%s\",\n", metarray_spec->name);
2275894c93e1SCristian Dumitrescu 		fprintf(f, "\t\t.size = %u,\n", metarray_spec->size);
2276894c93e1SCristian Dumitrescu 		fprintf(f, "\t},\n");
2277894c93e1SCristian Dumitrescu 	}
2278894c93e1SCristian Dumitrescu 
2279894c93e1SCristian Dumitrescu 	fprintf(f, "};\n\n");
2280894c93e1SCristian Dumitrescu 
22818ba342ceSCristian Dumitrescu 	/* rss. */
22828ba342ceSCristian Dumitrescu 	fprintf(f, "static struct rss_spec rss[] = {\n");
22838ba342ceSCristian Dumitrescu 
22848ba342ceSCristian Dumitrescu 	for (i = 0; i < s->n_rss; i++) {
22858ba342ceSCristian Dumitrescu 		struct rss_spec *rss_spec = &s->rss[i];
22868ba342ceSCristian Dumitrescu 		fprintf(f, "\t[%d] = {\n", i);
22878ba342ceSCristian Dumitrescu 		fprintf(f, "\t\t.name = \"%s\",\n", rss_spec->name);
22888ba342ceSCristian Dumitrescu 		fprintf(f, "\t},\n");
22898ba342ceSCristian Dumitrescu 	}
22908ba342ceSCristian Dumitrescu 	fprintf(f, "};\n\n");
22918ba342ceSCristian Dumitrescu 
2292894c93e1SCristian Dumitrescu 	/* struct. */
2293894c93e1SCristian Dumitrescu 	for (i = 0; i < s->n_structs; i++) {
2294894c93e1SCristian Dumitrescu 		struct struct_spec *struct_spec = &s->structs[i];
2295894c93e1SCristian Dumitrescu 		uint32_t j;
2296894c93e1SCristian Dumitrescu 
2297894c93e1SCristian Dumitrescu 		fprintf(f, "static struct rte_swx_field_params struct_%s_fields[] = {\n",
2298894c93e1SCristian Dumitrescu 			struct_spec->name);
2299894c93e1SCristian Dumitrescu 
2300894c93e1SCristian Dumitrescu 		for (j = 0; j < struct_spec->n_fields; j++) {
2301894c93e1SCristian Dumitrescu 			struct rte_swx_field_params *field = &struct_spec->fields[j];
2302894c93e1SCristian Dumitrescu 
2303894c93e1SCristian Dumitrescu 			fprintf(f, "\t[%d] = {\n", j);
2304894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t.name = \"%s\",\n", field->name);
2305894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t.n_bits = %u,\n", field->n_bits);
2306894c93e1SCristian Dumitrescu 			fprintf(f, "\t},\n");
2307894c93e1SCristian Dumitrescu 		}
2308894c93e1SCristian Dumitrescu 
2309894c93e1SCristian Dumitrescu 		fprintf(f, "};\n\n");
2310894c93e1SCristian Dumitrescu 	}
2311894c93e1SCristian Dumitrescu 
2312894c93e1SCristian Dumitrescu 	fprintf(f, "static struct struct_spec structs[] = {\n");
2313894c93e1SCristian Dumitrescu 
2314894c93e1SCristian Dumitrescu 	for (i = 0; i < s->n_structs; i++) {
2315894c93e1SCristian Dumitrescu 		struct struct_spec *struct_spec = &s->structs[i];
2316894c93e1SCristian Dumitrescu 
2317894c93e1SCristian Dumitrescu 		fprintf(f, "\t[%d] = {\n", i);
2318894c93e1SCristian Dumitrescu 		fprintf(f, "\t\t.name = \"%s\",\n", struct_spec->name);
2319894c93e1SCristian Dumitrescu 		fprintf(f, "\t\t.fields = struct_%s_fields,\n", struct_spec->name);
2320894c93e1SCristian Dumitrescu 		fprintf(f, "\t\t.n_fields = "
2321894c93e1SCristian Dumitrescu 			"sizeof(struct_%s_fields) / sizeof(struct_%s_fields[0]),\n",
2322894c93e1SCristian Dumitrescu 			struct_spec->name,
2323894c93e1SCristian Dumitrescu 			struct_spec->name);
2324894c93e1SCristian Dumitrescu 		fprintf(f, "\t\t.varbit = %d,\n", struct_spec->varbit);
2325894c93e1SCristian Dumitrescu 		fprintf(f, "\t},\n");
2326894c93e1SCristian Dumitrescu 	}
2327894c93e1SCristian Dumitrescu 
2328894c93e1SCristian Dumitrescu 	fprintf(f, "};\n\n");
2329894c93e1SCristian Dumitrescu 
2330894c93e1SCristian Dumitrescu 	/* header. */
2331894c93e1SCristian Dumitrescu 	fprintf(f, "static struct header_spec headers[] = {\n");
2332894c93e1SCristian Dumitrescu 
2333894c93e1SCristian Dumitrescu 	for (i = 0; i < s->n_headers; i++) {
2334894c93e1SCristian Dumitrescu 		struct header_spec *header_spec = &s->headers[i];
2335894c93e1SCristian Dumitrescu 
2336894c93e1SCristian Dumitrescu 		fprintf(f, "\t[%d] = {\n", i);
2337894c93e1SCristian Dumitrescu 		fprintf(f, "\t\t.name = \"%s\",\n", header_spec->name);
2338894c93e1SCristian Dumitrescu 		fprintf(f, "\t\t.struct_type_name = \"%s\",\n", header_spec->struct_type_name);
2339894c93e1SCristian Dumitrescu 		fprintf(f, "\t},\n");
2340894c93e1SCristian Dumitrescu 	}
2341894c93e1SCristian Dumitrescu 
2342894c93e1SCristian Dumitrescu 	fprintf(f, "};\n\n");
2343894c93e1SCristian Dumitrescu 
2344894c93e1SCristian Dumitrescu 	/* metadata. */
2345894c93e1SCristian Dumitrescu 	fprintf(f, "static struct metadata_spec metadata[] = {\n");
2346894c93e1SCristian Dumitrescu 
2347894c93e1SCristian Dumitrescu 	for (i = 0; i < s->n_metadata; i++) {
2348894c93e1SCristian Dumitrescu 		struct metadata_spec *metadata_spec = &s->metadata[i];
2349894c93e1SCristian Dumitrescu 
2350894c93e1SCristian Dumitrescu 		fprintf(f, "\t[%d] = {\n", i);
2351894c93e1SCristian Dumitrescu 		fprintf(f, "\t\t.struct_type_name = \"%s\",\n", metadata_spec->struct_type_name);
2352894c93e1SCristian Dumitrescu 		fprintf(f, "\t},\n");
2353894c93e1SCristian Dumitrescu 
2354894c93e1SCristian Dumitrescu 	}
2355894c93e1SCristian Dumitrescu 
2356894c93e1SCristian Dumitrescu 	fprintf(f, "};\n\n");
2357894c93e1SCristian Dumitrescu 
2358894c93e1SCristian Dumitrescu 	/* action. */
2359894c93e1SCristian Dumitrescu 	for (i = 0; i < s->n_actions; i++) {
2360894c93e1SCristian Dumitrescu 		struct action_spec *action_spec = &s->actions[i];
2361894c93e1SCristian Dumitrescu 		uint32_t j;
2362894c93e1SCristian Dumitrescu 
2363894c93e1SCristian Dumitrescu 		fprintf(f, "static const char *action_%s_initial_instructions[] = {\n",
2364894c93e1SCristian Dumitrescu 			action_spec->name);
2365894c93e1SCristian Dumitrescu 
2366894c93e1SCristian Dumitrescu 		for (j = 0; j < action_spec->n_instructions; j++) {
2367894c93e1SCristian Dumitrescu 			const char *instr = action_spec->instructions[j];
2368894c93e1SCristian Dumitrescu 
2369894c93e1SCristian Dumitrescu 			fprintf(f, "\t[%d] = \"%s\",\n", j, instr);
2370894c93e1SCristian Dumitrescu 		}
2371894c93e1SCristian Dumitrescu 
2372894c93e1SCristian Dumitrescu 		fprintf(f, "};\n\n");
2373894c93e1SCristian Dumitrescu 	}
2374894c93e1SCristian Dumitrescu 
2375894c93e1SCristian Dumitrescu 	fprintf(f, "static struct action_spec actions[] = {\n");
2376894c93e1SCristian Dumitrescu 
2377894c93e1SCristian Dumitrescu 	for (i = 0; i < s->n_actions; i++) {
2378894c93e1SCristian Dumitrescu 		struct action_spec *action_spec = &s->actions[i];
2379894c93e1SCristian Dumitrescu 
2380894c93e1SCristian Dumitrescu 		fprintf(f, "\t[%d] = {\n", i);
2381894c93e1SCristian Dumitrescu 		fprintf(f, "\t\t.name = \"%s\",\n", action_spec->name);
2382894c93e1SCristian Dumitrescu 
2383894c93e1SCristian Dumitrescu 		if (action_spec->args_struct_type_name)
2384894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t.args_struct_type_name = \"%s\",\n",
2385894c93e1SCristian Dumitrescu 				action_spec->args_struct_type_name);
2386894c93e1SCristian Dumitrescu 		else
2387894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t.args_struct_type_name = NULL,\n");
2388894c93e1SCristian Dumitrescu 
2389894c93e1SCristian Dumitrescu 		fprintf(f, "\t\t.instructions = action_%s_initial_instructions,\n",
2390894c93e1SCristian Dumitrescu 			action_spec->name);
2391894c93e1SCristian Dumitrescu 		fprintf(f, "\t\t.n_instructions = "
2392894c93e1SCristian Dumitrescu 			"sizeof(action_%s_initial_instructions) / "
2393894c93e1SCristian Dumitrescu 			"sizeof(action_%s_initial_instructions[0]),\n",
2394894c93e1SCristian Dumitrescu 			action_spec->name,
2395894c93e1SCristian Dumitrescu 			action_spec->name);
2396894c93e1SCristian Dumitrescu 		fprintf(f, "\t},\n");
2397894c93e1SCristian Dumitrescu 	}
2398894c93e1SCristian Dumitrescu 
2399894c93e1SCristian Dumitrescu 	fprintf(f, "};\n\n");
2400894c93e1SCristian Dumitrescu 
2401894c93e1SCristian Dumitrescu 	/* table. */
2402894c93e1SCristian Dumitrescu 	for (i = 0; i < s->n_tables; i++) {
2403894c93e1SCristian Dumitrescu 		struct table_spec *table_spec = &s->tables[i];
2404894c93e1SCristian Dumitrescu 		uint32_t j;
2405894c93e1SCristian Dumitrescu 
2406894c93e1SCristian Dumitrescu 		/* fields. */
2407894c93e1SCristian Dumitrescu 		if (table_spec->params.fields && table_spec->params.n_fields) {
2408894c93e1SCristian Dumitrescu 			fprintf(f, "static struct rte_swx_match_field_params "
2409894c93e1SCristian Dumitrescu 				"table_%s_fields[] = {\n",
2410894c93e1SCristian Dumitrescu 				table_spec->name);
2411894c93e1SCristian Dumitrescu 
2412894c93e1SCristian Dumitrescu 			for (j = 0; j < table_spec->params.n_fields; j++) {
2413894c93e1SCristian Dumitrescu 				struct rte_swx_match_field_params *field =
2414894c93e1SCristian Dumitrescu 					&table_spec->params.fields[j];
2415894c93e1SCristian Dumitrescu 
2416894c93e1SCristian Dumitrescu 				fprintf(f, "\t[%d] = {\n", j);
2417894c93e1SCristian Dumitrescu 				fprintf(f, "\t\t.name = \"%s\",\n", field->name);
2418894c93e1SCristian Dumitrescu 				fprintf(f, "\t\t.match_type = %s,\n",
2419894c93e1SCristian Dumitrescu 					match_type_string_get(field->match_type));
2420894c93e1SCristian Dumitrescu 				fprintf(f, "\t},\n");
2421894c93e1SCristian Dumitrescu 			}
2422894c93e1SCristian Dumitrescu 
2423894c93e1SCristian Dumitrescu 			fprintf(f, "};\n\n");
2424894c93e1SCristian Dumitrescu 		}
2425894c93e1SCristian Dumitrescu 
2426894c93e1SCristian Dumitrescu 		/* action_names. */
2427894c93e1SCristian Dumitrescu 		if (table_spec->params.action_names && table_spec->params.n_actions) {
2428894c93e1SCristian Dumitrescu 			fprintf(f, "static const char *table_%s_action_names[] = {\n",
2429894c93e1SCristian Dumitrescu 				table_spec->name);
2430894c93e1SCristian Dumitrescu 
2431894c93e1SCristian Dumitrescu 			for (j = 0; j < table_spec->params.n_actions; j++) {
2432894c93e1SCristian Dumitrescu 				const char *action_name = table_spec->params.action_names[j];
2433894c93e1SCristian Dumitrescu 
2434894c93e1SCristian Dumitrescu 				fprintf(f, "\t[%d] = \"%s\",\n", j, action_name);
2435894c93e1SCristian Dumitrescu 			}
2436894c93e1SCristian Dumitrescu 
2437894c93e1SCristian Dumitrescu 			fprintf(f, "};\n\n");
2438894c93e1SCristian Dumitrescu 		}
2439894c93e1SCristian Dumitrescu 
2440894c93e1SCristian Dumitrescu 		/* action_is_for_table_entries. */
2441894c93e1SCristian Dumitrescu 		if (table_spec->params.action_is_for_table_entries &&
2442894c93e1SCristian Dumitrescu 		    table_spec->params.n_actions) {
2443894c93e1SCristian Dumitrescu 			fprintf(f, "static int table_%s_action_is_for_table_entries[] = {\n",
2444894c93e1SCristian Dumitrescu 				table_spec->name);
2445894c93e1SCristian Dumitrescu 
2446894c93e1SCristian Dumitrescu 			for (j = 0; j < table_spec->params.n_actions; j++) {
2447894c93e1SCristian Dumitrescu 				int value = table_spec->params.action_is_for_table_entries[j];
2448894c93e1SCristian Dumitrescu 
2449894c93e1SCristian Dumitrescu 				fprintf(f, "\t[%d] = %d,\n", j, value);
2450894c93e1SCristian Dumitrescu 			}
2451894c93e1SCristian Dumitrescu 
2452894c93e1SCristian Dumitrescu 			fprintf(f, "};\n\n");
2453894c93e1SCristian Dumitrescu 		}
2454894c93e1SCristian Dumitrescu 
2455894c93e1SCristian Dumitrescu 		/* action_is_for_default_entry. */
2456894c93e1SCristian Dumitrescu 		if (table_spec->params.action_is_for_default_entry &&
2457894c93e1SCristian Dumitrescu 		    table_spec->params.n_actions) {
2458894c93e1SCristian Dumitrescu 			fprintf(f, "static int table_%s_action_is_for_default_entry[] = {\n",
2459894c93e1SCristian Dumitrescu 				table_spec->name);
2460894c93e1SCristian Dumitrescu 
2461894c93e1SCristian Dumitrescu 			for (j = 0; j < table_spec->params.n_actions; j++) {
2462894c93e1SCristian Dumitrescu 				int value = table_spec->params.action_is_for_default_entry[j];
2463894c93e1SCristian Dumitrescu 
2464894c93e1SCristian Dumitrescu 				fprintf(f, "\t[%d] = %d,\n", j, value);
2465894c93e1SCristian Dumitrescu 			}
2466894c93e1SCristian Dumitrescu 
2467894c93e1SCristian Dumitrescu 			fprintf(f, "};\n\n");
2468894c93e1SCristian Dumitrescu 		}
2469894c93e1SCristian Dumitrescu 	}
2470894c93e1SCristian Dumitrescu 
2471894c93e1SCristian Dumitrescu 	fprintf(f, "static struct table_spec tables[] = {\n");
2472894c93e1SCristian Dumitrescu 
2473894c93e1SCristian Dumitrescu 	for (i = 0; i < s->n_tables; i++) {
2474894c93e1SCristian Dumitrescu 		struct table_spec *table_spec = &s->tables[i];
2475894c93e1SCristian Dumitrescu 
2476894c93e1SCristian Dumitrescu 		fprintf(f, "\t[%d] = {\n", i);
2477894c93e1SCristian Dumitrescu 		fprintf(f, "\t\t.name = \"%s\",\n", table_spec->name);
2478894c93e1SCristian Dumitrescu 
2479894c93e1SCristian Dumitrescu 		fprintf(f, "\t\t.params = {\n");
2480894c93e1SCristian Dumitrescu 
2481894c93e1SCristian Dumitrescu 		if (table_spec->params.fields && table_spec->params.n_fields) {
2482894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t\t.fields = table_%s_fields,\n", table_spec->name);
2483894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t\t.n_fields = "
2484894c93e1SCristian Dumitrescu 				"sizeof(table_%s_fields) / sizeof(table_%s_fields[0]),\n",
2485894c93e1SCristian Dumitrescu 				table_spec->name,
2486894c93e1SCristian Dumitrescu 				table_spec->name);
2487894c93e1SCristian Dumitrescu 		} else {
2488894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t\t.fields = NULL,\n");
2489894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t\t.n_fields = 0,\n");
2490894c93e1SCristian Dumitrescu 		}
2491894c93e1SCristian Dumitrescu 
2492894c93e1SCristian Dumitrescu 		if (table_spec->params.action_names && table_spec->params.n_actions)
2493894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t\t.action_names = table_%s_action_names,\n",
2494894c93e1SCristian Dumitrescu 				table_spec->name);
2495894c93e1SCristian Dumitrescu 		else
2496894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t\t.action_names = NULL,\n");
2497894c93e1SCristian Dumitrescu 
2498894c93e1SCristian Dumitrescu 		if (table_spec->params.action_is_for_table_entries && table_spec->params.n_actions)
2499894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t\t.action_is_for_table_entries = "
2500894c93e1SCristian Dumitrescu 				"table_%s_action_is_for_table_entries,\n",
2501894c93e1SCristian Dumitrescu 				table_spec->name);
2502894c93e1SCristian Dumitrescu 		else
2503894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t\t.action_is_for_table_entries = NULL,\n");
2504894c93e1SCristian Dumitrescu 
2505894c93e1SCristian Dumitrescu 		if (table_spec->params.action_is_for_default_entry && table_spec->params.n_actions)
2506894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t\t.action_is_for_default_entry = "
2507894c93e1SCristian Dumitrescu 				"table_%s_action_is_for_default_entry,\n",
2508894c93e1SCristian Dumitrescu 				table_spec->name);
2509894c93e1SCristian Dumitrescu 		else
2510894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t\t.action_is_for_default_entry = NULL,\n");
2511894c93e1SCristian Dumitrescu 
2512894c93e1SCristian Dumitrescu 		if (table_spec->params.n_actions)
2513894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t\t.n_actions = sizeof(table_%s_action_names) / "
2514894c93e1SCristian Dumitrescu 				"sizeof(table_%s_action_names[0]),\n",
2515894c93e1SCristian Dumitrescu 				table_spec->name,
2516894c93e1SCristian Dumitrescu 				table_spec->name);
2517894c93e1SCristian Dumitrescu 		else
2518894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t\t.n_actions = 0,\n");
2519894c93e1SCristian Dumitrescu 
2520894c93e1SCristian Dumitrescu 		if (table_spec->params.default_action_name)
2521894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t\t.default_action_name = \"%s\",\n",
2522894c93e1SCristian Dumitrescu 				table_spec->params.default_action_name);
2523894c93e1SCristian Dumitrescu 		else
2524894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t\t.default_action_name = NULL,\n");
2525894c93e1SCristian Dumitrescu 
2526894c93e1SCristian Dumitrescu 		if (table_spec->params.default_action_args)
2527894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t\t.default_action_args = \"%s\",\n",
2528894c93e1SCristian Dumitrescu 				table_spec->params.default_action_args);
2529894c93e1SCristian Dumitrescu 		else
2530894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t\t.default_action_args = NULL,\n");
2531894c93e1SCristian Dumitrescu 
2532894c93e1SCristian Dumitrescu 		fprintf(f, "\t\t\t.default_action_is_const = %d,\n",
2533894c93e1SCristian Dumitrescu 			table_spec->params.default_action_is_const);
25349560a329SCristian Dumitrescu 
25359560a329SCristian Dumitrescu 		if (table_spec->params.hash_func_name)
25369560a329SCristian Dumitrescu 			fprintf(f, "\t\t\t.hash_func_name = \"%s\",\n",
25379560a329SCristian Dumitrescu 				table_spec->params.hash_func_name);
25389560a329SCristian Dumitrescu 		else
25399560a329SCristian Dumitrescu 			fprintf(f, "\t\t\t.hash_func_name = NULL,\n");
25409560a329SCristian Dumitrescu 
2541894c93e1SCristian Dumitrescu 		fprintf(f, "\t\t},\n");
2542894c93e1SCristian Dumitrescu 
2543894c93e1SCristian Dumitrescu 		if (table_spec->recommended_table_type_name)
2544894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t.recommended_table_type_name = \"%s\",\n",
2545894c93e1SCristian Dumitrescu 				table_spec->recommended_table_type_name);
2546894c93e1SCristian Dumitrescu 		else
2547894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t.recommended_table_type_name = NULL,\n");
2548894c93e1SCristian Dumitrescu 
2549894c93e1SCristian Dumitrescu 		if (table_spec->args)
2550894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t.args = \"%s\",\n", table_spec->args);
2551894c93e1SCristian Dumitrescu 		else
2552894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t.args = NULL,\n");
2553894c93e1SCristian Dumitrescu 
2554894c93e1SCristian Dumitrescu 		fprintf(f, "\t\t.size = %u,\n", table_spec->size);
2555894c93e1SCristian Dumitrescu 
2556894c93e1SCristian Dumitrescu 		fprintf(f, "\t},\n");
2557894c93e1SCristian Dumitrescu 	}
2558894c93e1SCristian Dumitrescu 
2559894c93e1SCristian Dumitrescu 	fprintf(f, "};\n\n");
2560894c93e1SCristian Dumitrescu 
2561894c93e1SCristian Dumitrescu 	/* selector. */
2562894c93e1SCristian Dumitrescu 	for (i = 0; i < s->n_selectors; i++) {
2563894c93e1SCristian Dumitrescu 		struct selector_spec *selector_spec = &s->selectors[i];
2564894c93e1SCristian Dumitrescu 		uint32_t j;
2565894c93e1SCristian Dumitrescu 
2566894c93e1SCristian Dumitrescu 		if (selector_spec->params.selector_field_names &&
2567894c93e1SCristian Dumitrescu 		    selector_spec->params.n_selector_fields) {
2568894c93e1SCristian Dumitrescu 			fprintf(f, "static const char *selector_%s_field_names[] = {\n",
2569894c93e1SCristian Dumitrescu 				selector_spec->name);
2570894c93e1SCristian Dumitrescu 
2571894c93e1SCristian Dumitrescu 			for (j = 0; j < selector_spec->params.n_selector_fields; j++) {
2572894c93e1SCristian Dumitrescu 				const char *field_name =
2573894c93e1SCristian Dumitrescu 					selector_spec->params.selector_field_names[j];
2574894c93e1SCristian Dumitrescu 
2575894c93e1SCristian Dumitrescu 				fprintf(f, "\t[%d] = \"%s\",\n", j, field_name);
2576894c93e1SCristian Dumitrescu 			}
2577894c93e1SCristian Dumitrescu 
2578894c93e1SCristian Dumitrescu 			fprintf(f, "};\n\n");
2579894c93e1SCristian Dumitrescu 		}
2580894c93e1SCristian Dumitrescu 	}
2581894c93e1SCristian Dumitrescu 
2582894c93e1SCristian Dumitrescu 	fprintf(f, "static struct selector_spec selectors[] = {\n");
2583894c93e1SCristian Dumitrescu 
2584894c93e1SCristian Dumitrescu 	for (i = 0; i < s->n_selectors; i++) {
2585894c93e1SCristian Dumitrescu 		struct selector_spec *selector_spec = &s->selectors[i];
2586894c93e1SCristian Dumitrescu 
2587894c93e1SCristian Dumitrescu 		fprintf(f, "\t[%d] = {\n", i);
2588894c93e1SCristian Dumitrescu 
2589894c93e1SCristian Dumitrescu 		fprintf(f, "\t\t.name = \"%s\",\n", selector_spec->name);
2590894c93e1SCristian Dumitrescu 		fprintf(f, "\t\t.params = {\n");
2591894c93e1SCristian Dumitrescu 
2592894c93e1SCristian Dumitrescu 		if (selector_spec->params.group_id_field_name)
2593894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t\t.group_id_field_name = \"%s\",\n",
2594894c93e1SCristian Dumitrescu 				selector_spec->params.group_id_field_name);
2595894c93e1SCristian Dumitrescu 		else
2596894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t\t.group_id_field_name = NULL,\n");
2597894c93e1SCristian Dumitrescu 
2598894c93e1SCristian Dumitrescu 		if (selector_spec->params.selector_field_names &&
2599894c93e1SCristian Dumitrescu 		    selector_spec->params.n_selector_fields) {
2600894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t\t.selector_field_names = selector_%s_field_names,\n",
2601894c93e1SCristian Dumitrescu 				selector_spec->name);
2602894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t\t.n_selector_fields = "
2603894c93e1SCristian Dumitrescu 				"sizeof(selector_%s_field_names) / sizeof(selector_%s_field_names[0]),\n",
2604894c93e1SCristian Dumitrescu 				selector_spec->name,
2605894c93e1SCristian Dumitrescu 				selector_spec->name);
2606894c93e1SCristian Dumitrescu 		} else {
2607894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t\t.selector_field_names = NULL,\n");
2608894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t\t.n_selector_fields = 0,\n");
2609894c93e1SCristian Dumitrescu 		}
2610894c93e1SCristian Dumitrescu 
2611894c93e1SCristian Dumitrescu 		if (selector_spec->params.member_id_field_name)
2612894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t\t.member_id_field_name = \"%s\",\n",
2613894c93e1SCristian Dumitrescu 				selector_spec->params.member_id_field_name);
2614894c93e1SCristian Dumitrescu 		else
2615894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t\t.member_id_field_name = NULL,\n");
2616894c93e1SCristian Dumitrescu 
2617894c93e1SCristian Dumitrescu 		fprintf(f, "\t\t\t.n_groups_max = %u,\n", selector_spec->params.n_groups_max);
2618894c93e1SCristian Dumitrescu 
2619894c93e1SCristian Dumitrescu 		fprintf(f, "\t\t\t.n_members_per_group_max = %u,\n",
2620894c93e1SCristian Dumitrescu 			selector_spec->params.n_members_per_group_max);
2621894c93e1SCristian Dumitrescu 
2622894c93e1SCristian Dumitrescu 		fprintf(f, "\t\t},\n");
2623894c93e1SCristian Dumitrescu 		fprintf(f, "\t},\n");
2624894c93e1SCristian Dumitrescu 	}
2625894c93e1SCristian Dumitrescu 
2626894c93e1SCristian Dumitrescu 	fprintf(f, "};\n\n");
2627894c93e1SCristian Dumitrescu 
2628894c93e1SCristian Dumitrescu 	/* learner. */
2629894c93e1SCristian Dumitrescu 	for (i = 0; i < s->n_learners; i++) {
2630894c93e1SCristian Dumitrescu 		struct learner_spec *learner_spec = &s->learners[i];
2631894c93e1SCristian Dumitrescu 		uint32_t j;
2632894c93e1SCristian Dumitrescu 
2633894c93e1SCristian Dumitrescu 		/* field_names. */
2634894c93e1SCristian Dumitrescu 		if (learner_spec->params.field_names && learner_spec->params.n_fields) {
2635894c93e1SCristian Dumitrescu 			fprintf(f, "static const char *learner_%s_field_names[] = {\n",
2636894c93e1SCristian Dumitrescu 				learner_spec->name);
2637894c93e1SCristian Dumitrescu 
2638894c93e1SCristian Dumitrescu 			for (j = 0; j < learner_spec->params.n_fields; j++) {
2639894c93e1SCristian Dumitrescu 				const char *field_name = learner_spec->params.field_names[j];
2640894c93e1SCristian Dumitrescu 
2641894c93e1SCristian Dumitrescu 				fprintf(f, "\t[%d] = \"%s\",\n", j, field_name);
2642894c93e1SCristian Dumitrescu 			}
2643894c93e1SCristian Dumitrescu 
2644894c93e1SCristian Dumitrescu 			fprintf(f, "};\n\n");
2645894c93e1SCristian Dumitrescu 		}
2646894c93e1SCristian Dumitrescu 
2647894c93e1SCristian Dumitrescu 		/* action_names. */
2648894c93e1SCristian Dumitrescu 		if (learner_spec->params.action_names && learner_spec->params.n_actions) {
2649894c93e1SCristian Dumitrescu 			fprintf(f, "static const char *learner_%s_action_names[] = {\n",
2650894c93e1SCristian Dumitrescu 				learner_spec->name);
2651894c93e1SCristian Dumitrescu 
2652894c93e1SCristian Dumitrescu 			for (j = 0; j < learner_spec->params.n_actions; j++) {
2653894c93e1SCristian Dumitrescu 				const char *action_name = learner_spec->params.action_names[j];
2654894c93e1SCristian Dumitrescu 
2655894c93e1SCristian Dumitrescu 				fprintf(f, "\t[%d] = \"%s\",\n", j, action_name);
2656894c93e1SCristian Dumitrescu 			}
2657894c93e1SCristian Dumitrescu 
2658894c93e1SCristian Dumitrescu 			fprintf(f, "};\n\n");
2659894c93e1SCristian Dumitrescu 		}
2660894c93e1SCristian Dumitrescu 
2661894c93e1SCristian Dumitrescu 		/* action_is_for_table_entries. */
2662894c93e1SCristian Dumitrescu 		if (learner_spec->params.action_is_for_table_entries &&
2663894c93e1SCristian Dumitrescu 		    learner_spec->params.n_actions) {
2664894c93e1SCristian Dumitrescu 			fprintf(f, "static int learner_%s_action_is_for_table_entries[] = {\n",
2665894c93e1SCristian Dumitrescu 				learner_spec->name);
2666894c93e1SCristian Dumitrescu 
2667894c93e1SCristian Dumitrescu 			for (j = 0; j < learner_spec->params.n_actions; j++) {
2668894c93e1SCristian Dumitrescu 				int value = learner_spec->params.action_is_for_table_entries[j];
2669894c93e1SCristian Dumitrescu 
2670894c93e1SCristian Dumitrescu 				fprintf(f, "\t[%d] = %d,\n", j, value);
2671894c93e1SCristian Dumitrescu 			}
2672894c93e1SCristian Dumitrescu 
2673894c93e1SCristian Dumitrescu 			fprintf(f, "};\n\n");
2674894c93e1SCristian Dumitrescu 		}
2675894c93e1SCristian Dumitrescu 
2676894c93e1SCristian Dumitrescu 		/* action_is_for_default_entry. */
2677894c93e1SCristian Dumitrescu 		if (learner_spec->params.action_is_for_default_entry &&
2678894c93e1SCristian Dumitrescu 		    learner_spec->params.n_actions) {
2679894c93e1SCristian Dumitrescu 			fprintf(f, "static int learner_%s_action_is_for_default_entry[] = {\n",
2680894c93e1SCristian Dumitrescu 				learner_spec->name);
2681894c93e1SCristian Dumitrescu 
2682894c93e1SCristian Dumitrescu 			for (j = 0; j < learner_spec->params.n_actions; j++) {
2683894c93e1SCristian Dumitrescu 				int value = learner_spec->params.action_is_for_default_entry[j];
2684894c93e1SCristian Dumitrescu 
2685894c93e1SCristian Dumitrescu 				fprintf(f, "\t[%d] = %d,\n", j, value);
2686894c93e1SCristian Dumitrescu 			}
2687894c93e1SCristian Dumitrescu 
2688894c93e1SCristian Dumitrescu 			fprintf(f, "};\n\n");
2689894c93e1SCristian Dumitrescu 		}
2690894c93e1SCristian Dumitrescu 
2691894c93e1SCristian Dumitrescu 		/* timeout. */
2692894c93e1SCristian Dumitrescu 		if (learner_spec->timeout && learner_spec->n_timeouts) {
2693894c93e1SCristian Dumitrescu 			fprintf(f, "static uint32_t learner_%s_timeout[] = {\n",
2694894c93e1SCristian Dumitrescu 				learner_spec->name);
2695894c93e1SCristian Dumitrescu 
2696894c93e1SCristian Dumitrescu 			for (j = 0; j < learner_spec->n_timeouts; j++) {
2697894c93e1SCristian Dumitrescu 				uint32_t value = learner_spec->timeout[j];
2698894c93e1SCristian Dumitrescu 
2699894c93e1SCristian Dumitrescu 				fprintf(f, "\t[%d] = %u,\n", j, value);
2700894c93e1SCristian Dumitrescu 			}
2701894c93e1SCristian Dumitrescu 
2702894c93e1SCristian Dumitrescu 			fprintf(f, "};\n\n");
2703894c93e1SCristian Dumitrescu 		}
2704894c93e1SCristian Dumitrescu 	}
2705894c93e1SCristian Dumitrescu 
2706894c93e1SCristian Dumitrescu 	fprintf(f, "static struct learner_spec learners[] = {\n");
2707894c93e1SCristian Dumitrescu 
2708894c93e1SCristian Dumitrescu 	for (i = 0; i < s->n_learners; i++) {
2709894c93e1SCristian Dumitrescu 		struct learner_spec *learner_spec = &s->learners[i];
2710894c93e1SCristian Dumitrescu 
2711894c93e1SCristian Dumitrescu 		fprintf(f, "\t[%d] = {\n", i);
2712894c93e1SCristian Dumitrescu 		fprintf(f, "\t\t.name = \"%s\",\n", learner_spec->name);
2713894c93e1SCristian Dumitrescu 
2714894c93e1SCristian Dumitrescu 		fprintf(f, "\t\t.params = {\n");
2715894c93e1SCristian Dumitrescu 
2716894c93e1SCristian Dumitrescu 		if (learner_spec->params.field_names && learner_spec->params.n_fields) {
2717894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t\t.field_names = learner_%s_field_names,\n",
2718894c93e1SCristian Dumitrescu 				learner_spec->name);
2719894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t\t.n_fields = "
2720894c93e1SCristian Dumitrescu 				"sizeof(learner_%s_field_names) / "
2721894c93e1SCristian Dumitrescu 				"sizeof(learner_%s_field_names[0]),\n",
2722894c93e1SCristian Dumitrescu 				learner_spec->name,
2723894c93e1SCristian Dumitrescu 				learner_spec->name);
2724894c93e1SCristian Dumitrescu 		} else {
2725894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t\t.field_names = NULL,\n");
2726894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t\t.n_fields = 0,\n");
2727894c93e1SCristian Dumitrescu 		}
2728894c93e1SCristian Dumitrescu 
2729894c93e1SCristian Dumitrescu 		if (learner_spec->params.action_names && learner_spec->params.n_actions)
2730894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t\t.action_names = learner_%s_action_names,\n",
2731894c93e1SCristian Dumitrescu 				learner_spec->name);
2732894c93e1SCristian Dumitrescu 		else
2733894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t\t.action_names = NULL,\n");
2734894c93e1SCristian Dumitrescu 
2735894c93e1SCristian Dumitrescu 		if (learner_spec->params.action_is_for_table_entries &&
2736894c93e1SCristian Dumitrescu 		    learner_spec->params.n_actions)
2737894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t\t.action_is_for_table_entries = "
2738894c93e1SCristian Dumitrescu 				"learner_%s_action_is_for_table_entries,\n",
2739894c93e1SCristian Dumitrescu 				learner_spec->name);
2740894c93e1SCristian Dumitrescu 		else
2741894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t\t.action_is_for_table_entries = NULL,\n");
2742894c93e1SCristian Dumitrescu 
2743894c93e1SCristian Dumitrescu 		if (learner_spec->params.action_is_for_default_entry &&
2744894c93e1SCristian Dumitrescu 		    learner_spec->params.n_actions)
2745894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t\t.action_is_for_default_entry = "
2746894c93e1SCristian Dumitrescu 				"learner_%s_action_is_for_default_entry,\n",
2747894c93e1SCristian Dumitrescu 				learner_spec->name);
2748894c93e1SCristian Dumitrescu 		else
2749894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t\t.action_is_for_default_entry = NULL,\n");
2750894c93e1SCristian Dumitrescu 
2751894c93e1SCristian Dumitrescu 		if (learner_spec->params.action_names && learner_spec->params.n_actions)
2752894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t\t.n_actions = "
2753894c93e1SCristian Dumitrescu 				"sizeof(learner_%s_action_names) / sizeof(learner_%s_action_names[0]),\n",
2754894c93e1SCristian Dumitrescu 				learner_spec->name,
2755894c93e1SCristian Dumitrescu 				learner_spec->name);
2756894c93e1SCristian Dumitrescu 		else
2757894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t\t.n_actions = NULL,\n");
2758894c93e1SCristian Dumitrescu 
2759894c93e1SCristian Dumitrescu 		if (learner_spec->params.default_action_name)
2760894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t\t.default_action_name = \"%s\",\n",
2761894c93e1SCristian Dumitrescu 				learner_spec->params.default_action_name);
2762894c93e1SCristian Dumitrescu 		else
2763894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t\t.default_action_name = NULL,\n");
2764894c93e1SCristian Dumitrescu 
2765894c93e1SCristian Dumitrescu 		if (learner_spec->params.default_action_args)
2766894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t\t.default_action_args = \"%s\",\n",
2767894c93e1SCristian Dumitrescu 				learner_spec->params.default_action_args);
2768894c93e1SCristian Dumitrescu 		else
2769894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t\t.default_action_args = NULL,\n");
2770894c93e1SCristian Dumitrescu 
2771894c93e1SCristian Dumitrescu 		fprintf(f, "\t\t\t.default_action_is_const = %d,\n",
2772894c93e1SCristian Dumitrescu 			learner_spec->params.default_action_is_const);
2773894c93e1SCristian Dumitrescu 
2774fa7723b5SCristian Dumitrescu 		if (learner_spec->params.hash_func_name)
2775fa7723b5SCristian Dumitrescu 			fprintf(f, "\t\t\t.hash_func_name = \"%s\",\n",
2776fa7723b5SCristian Dumitrescu 				learner_spec->params.hash_func_name);
2777fa7723b5SCristian Dumitrescu 		else
2778fa7723b5SCristian Dumitrescu 			fprintf(f, "\t\t\t.hash_func_name = NULL,\n");
2779fa7723b5SCristian Dumitrescu 
2780894c93e1SCristian Dumitrescu 		fprintf(f, "\t\t},\n");
2781894c93e1SCristian Dumitrescu 
2782894c93e1SCristian Dumitrescu 		fprintf(f, "\t\t.size = %u,\n", learner_spec->size);
2783894c93e1SCristian Dumitrescu 
2784894c93e1SCristian Dumitrescu 		if (learner_spec->timeout && learner_spec->n_timeouts) {
2785894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t.timeout = learner_%s_timeout,\n", learner_spec->name);
2786894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t\t.n_timeouts = "
2787894c93e1SCristian Dumitrescu 				"sizeof(learner_%s_timeout) / sizeof(learner_%s_timeout[0]),\n",
2788894c93e1SCristian Dumitrescu 				learner_spec->name,
2789894c93e1SCristian Dumitrescu 				learner_spec->name);
2790894c93e1SCristian Dumitrescu 		} else {
2791894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t.timeout = NULL,\n");
2792894c93e1SCristian Dumitrescu 			fprintf(f, "\t\t\t.n_timeouts = 0,\n");
2793894c93e1SCristian Dumitrescu 		}
2794894c93e1SCristian Dumitrescu 
2795894c93e1SCristian Dumitrescu 		fprintf(f, "\t},\n");
2796894c93e1SCristian Dumitrescu 	}
2797894c93e1SCristian Dumitrescu 
2798894c93e1SCristian Dumitrescu 	fprintf(f, "};\n\n");
2799894c93e1SCristian Dumitrescu 
2800894c93e1SCristian Dumitrescu 	/* apply. */
2801894c93e1SCristian Dumitrescu 	for (i = 0; i < s->n_apply; i++) {
2802894c93e1SCristian Dumitrescu 		struct apply_spec *apply_spec = &s->apply[i];
2803894c93e1SCristian Dumitrescu 		uint32_t j;
2804894c93e1SCristian Dumitrescu 
2805894c93e1SCristian Dumitrescu 		fprintf(f, "static const char *apply%u_initial_instructions[] = {\n", i);
2806894c93e1SCristian Dumitrescu 
2807894c93e1SCristian Dumitrescu 		for (j = 0; j < apply_spec->n_instructions; j++) {
2808894c93e1SCristian Dumitrescu 			const char *instr = apply_spec->instructions[j];
2809894c93e1SCristian Dumitrescu 
2810894c93e1SCristian Dumitrescu 			fprintf(f, "\t[%d] = \"%s\",\n", j, instr);
2811894c93e1SCristian Dumitrescu 		}
2812894c93e1SCristian Dumitrescu 
2813894c93e1SCristian Dumitrescu 		fprintf(f, "};\n\n");
2814894c93e1SCristian Dumitrescu 	}
2815894c93e1SCristian Dumitrescu 
2816894c93e1SCristian Dumitrescu 	fprintf(f, "static struct apply_spec apply[] = {\n");
2817894c93e1SCristian Dumitrescu 
2818894c93e1SCristian Dumitrescu 	for (i = 0; i < s->n_apply; i++) {
2819894c93e1SCristian Dumitrescu 		fprintf(f, "\t[%d] = {\n", i);
2820894c93e1SCristian Dumitrescu 		fprintf(f, "\t.instructions = apply%u_initial_instructions,\n", i);
2821894c93e1SCristian Dumitrescu 		fprintf(f, "\t.n_instructions = "
2822894c93e1SCristian Dumitrescu 			"sizeof(apply%u_initial_instructions) / "
2823894c93e1SCristian Dumitrescu 			"sizeof(apply%u_initial_instructions[0]),\n",
2824894c93e1SCristian Dumitrescu 			i,
2825894c93e1SCristian Dumitrescu 			i);
2826894c93e1SCristian Dumitrescu 		fprintf(f, "\t},\n");
2827894c93e1SCristian Dumitrescu 	}
2828894c93e1SCristian Dumitrescu 
2829894c93e1SCristian Dumitrescu 	fprintf(f, "};\n\n");
2830894c93e1SCristian Dumitrescu 
2831894c93e1SCristian Dumitrescu 	/* pipeline. */
2832894c93e1SCristian Dumitrescu 	fprintf(f, "struct pipeline_spec pipeline_spec = {\n");
2833894c93e1SCristian Dumitrescu 	fprintf(f, "\t.extobjs = extobjs,\n");
2834894c93e1SCristian Dumitrescu 	fprintf(f, "\t.structs = structs,\n");
2835894c93e1SCristian Dumitrescu 	fprintf(f, "\t.headers = headers,\n");
2836894c93e1SCristian Dumitrescu 	fprintf(f, "\t.metadata = metadata,\n");
2837894c93e1SCristian Dumitrescu 	fprintf(f, "\t.actions = actions,\n");
2838894c93e1SCristian Dumitrescu 	fprintf(f, "\t.tables = tables,\n");
2839894c93e1SCristian Dumitrescu 	fprintf(f, "\t.selectors = selectors,\n");
2840894c93e1SCristian Dumitrescu 	fprintf(f, "\t.learners = learners,\n");
2841894c93e1SCristian Dumitrescu 	fprintf(f, "\t.regarrays = regarrays,\n");
2842894c93e1SCristian Dumitrescu 	fprintf(f, "\t.metarrays = metarrays,\n");
28438ba342ceSCristian Dumitrescu 	fprintf(f, "\t.rss = rss,\n");
2844894c93e1SCristian Dumitrescu 	fprintf(f, "\t.apply = apply,\n");
2845894c93e1SCristian Dumitrescu 	fprintf(f, "\t.n_extobjs = sizeof(extobjs) / sizeof(extobjs[0]),\n");
2846894c93e1SCristian Dumitrescu 	fprintf(f, "\t.n_structs = sizeof(structs) / sizeof(structs[0]),\n");
2847894c93e1SCristian Dumitrescu 	fprintf(f, "\t.n_headers = sizeof(headers) / sizeof(headers[0]),\n");
2848894c93e1SCristian Dumitrescu 	fprintf(f, "\t.n_metadata = sizeof(metadata) / sizeof(metadata[0]),\n");
2849894c93e1SCristian Dumitrescu 	fprintf(f, "\t.n_actions = sizeof(actions) / sizeof(actions[0]),\n");
2850894c93e1SCristian Dumitrescu 	fprintf(f, "\t.n_tables = sizeof(tables) / sizeof(tables[0]),\n");
2851894c93e1SCristian Dumitrescu 	fprintf(f, "\t.n_selectors = sizeof(selectors) / sizeof(selectors[0]),\n");
2852894c93e1SCristian Dumitrescu 	fprintf(f, "\t.n_learners = sizeof(learners) / sizeof(learners[0]),\n");
2853894c93e1SCristian Dumitrescu 	fprintf(f, "\t.n_regarrays = sizeof(regarrays) / sizeof(regarrays[0]),\n");
2854894c93e1SCristian Dumitrescu 	fprintf(f, "\t.n_metarrays = sizeof(metarrays) / sizeof(metarrays[0]),\n");
28558ba342ceSCristian Dumitrescu 	fprintf(f, "\t.n_rss = sizeof(rss) / sizeof(rss[0]),\n");
2856894c93e1SCristian Dumitrescu 	fprintf(f, "\t.n_apply = sizeof(apply) / sizeof(apply[0]),\n");
2857894c93e1SCristian Dumitrescu 	fprintf(f, "};\n");
2858894c93e1SCristian Dumitrescu }
2859894c93e1SCristian Dumitrescu 
286030c4abb9SCristian Dumitrescu struct pipeline_spec *
pipeline_spec_parse(FILE * spec,uint32_t * err_line,const char ** err_msg)286130c4abb9SCristian Dumitrescu pipeline_spec_parse(FILE *spec,
286299a2dd95SBruce Richardson 		    uint32_t *err_line,
286399a2dd95SBruce Richardson 		    const char **err_msg)
286499a2dd95SBruce Richardson {
286599a2dd95SBruce Richardson 	struct extobj_spec extobj_spec = {0};
286699a2dd95SBruce Richardson 	struct struct_spec struct_spec = {0};
286799a2dd95SBruce Richardson 	struct header_spec header_spec = {0};
286899a2dd95SBruce Richardson 	struct metadata_spec metadata_spec = {0};
286999a2dd95SBruce Richardson 	struct action_spec action_spec = {0};
287099a2dd95SBruce Richardson 	struct table_spec table_spec = {0};
2871cdaa937dSCristian Dumitrescu 	struct selector_spec selector_spec = {0};
28724f59d372SCristian Dumitrescu 	struct learner_spec learner_spec = {0};
287399a2dd95SBruce Richardson 	struct regarray_spec regarray_spec = {0};
287499a2dd95SBruce Richardson 	struct metarray_spec metarray_spec = {0};
28758ba342ceSCristian Dumitrescu 	struct rss_spec rss_spec = {0};
287699a2dd95SBruce Richardson 	struct apply_spec apply_spec = {0};
287730c4abb9SCristian Dumitrescu 	struct pipeline_spec *s = NULL;
287830c4abb9SCristian Dumitrescu 	uint32_t n_lines = 0;
287999a2dd95SBruce Richardson 	uint32_t block_mask = 0;
288030c4abb9SCristian Dumitrescu 	int status = 0;
288199a2dd95SBruce Richardson 
288299a2dd95SBruce Richardson 	/* Check the input arguments. */
288330c4abb9SCristian Dumitrescu 	if (!spec) {
288499a2dd95SBruce Richardson 		if (err_line)
288530c4abb9SCristian Dumitrescu 			*err_line = n_lines;
288699a2dd95SBruce Richardson 		if (err_msg)
288730c4abb9SCristian Dumitrescu 			*err_msg = "Invalid input argument.";
288899a2dd95SBruce Richardson 		status = -EINVAL;
288999a2dd95SBruce Richardson 		goto error;
289099a2dd95SBruce Richardson 	}
289199a2dd95SBruce Richardson 
289230c4abb9SCristian Dumitrescu 	/* Memory allocation. */
2893*0594ae0cSFerruh Yigit 	s = calloc(1, sizeof(struct pipeline_spec));
289430c4abb9SCristian Dumitrescu 	if (!s) {
289599a2dd95SBruce Richardson 		if (err_line)
289630c4abb9SCristian Dumitrescu 			*err_line = n_lines;
289799a2dd95SBruce Richardson 		if (err_msg)
289830c4abb9SCristian Dumitrescu 			*err_msg = "Memory allocation failed.";
289930c4abb9SCristian Dumitrescu 		status = -ENOMEM;
290099a2dd95SBruce Richardson 		goto error;
290199a2dd95SBruce Richardson 	}
290299a2dd95SBruce Richardson 
290399a2dd95SBruce Richardson 	for (n_lines = 1; ; n_lines++) {
290499a2dd95SBruce Richardson 		char line[MAX_LINE_LENGTH];
290599a2dd95SBruce Richardson 		char *tokens[MAX_TOKENS], *ptr = line;
290699a2dd95SBruce Richardson 		uint32_t n_tokens = 0;
290799a2dd95SBruce Richardson 
290899a2dd95SBruce Richardson 		/* Read next line. */
290999a2dd95SBruce Richardson 		if (!fgets(line, sizeof(line), spec))
291099a2dd95SBruce Richardson 			break;
291199a2dd95SBruce Richardson 
291299a2dd95SBruce Richardson 		/* Parse the line into tokens. */
291399a2dd95SBruce Richardson 		for ( ; ; ) {
291499a2dd95SBruce Richardson 			char *token;
291599a2dd95SBruce Richardson 
291699a2dd95SBruce Richardson 			/* Get token. */
291799a2dd95SBruce Richardson 			token = strtok_r(ptr, " \f\n\r\t\v", &ptr);
291899a2dd95SBruce Richardson 			if (!token)
291999a2dd95SBruce Richardson 				break;
292099a2dd95SBruce Richardson 
292199a2dd95SBruce Richardson 			/* Handle comments. */
292299a2dd95SBruce Richardson 			if ((token[0] == '#') ||
292399a2dd95SBruce Richardson 			    (token[0] == ';') ||
292499a2dd95SBruce Richardson 			    ((token[0] == '/') && (token[1] == '/'))) {
292599a2dd95SBruce Richardson 				break;
292699a2dd95SBruce Richardson 			}
292799a2dd95SBruce Richardson 
292899a2dd95SBruce Richardson 			/* Handle excessively long lines. */
292973d94b00SCristian Dumitrescu 			if (n_tokens >= RTE_DIM(tokens)) {
293099a2dd95SBruce Richardson 				if (err_line)
293199a2dd95SBruce Richardson 					*err_line = n_lines;
293299a2dd95SBruce Richardson 				if (err_msg)
293399a2dd95SBruce Richardson 					*err_msg = "Too many tokens.";
293499a2dd95SBruce Richardson 				status = -EINVAL;
293599a2dd95SBruce Richardson 				goto error;
293699a2dd95SBruce Richardson 			}
293799a2dd95SBruce Richardson 
293899a2dd95SBruce Richardson 			/* Handle excessively long tokens. */
293999a2dd95SBruce Richardson 			if (strnlen(token, RTE_SWX_NAME_SIZE) >=
294099a2dd95SBruce Richardson 			    RTE_SWX_NAME_SIZE) {
294199a2dd95SBruce Richardson 				if (err_line)
294299a2dd95SBruce Richardson 					*err_line = n_lines;
294399a2dd95SBruce Richardson 				if (err_msg)
294499a2dd95SBruce Richardson 					*err_msg = "Token too big.";
294599a2dd95SBruce Richardson 				status = -EINVAL;
294699a2dd95SBruce Richardson 				goto error;
294799a2dd95SBruce Richardson 			}
294899a2dd95SBruce Richardson 
294999a2dd95SBruce Richardson 			/* Save token. */
295099a2dd95SBruce Richardson 			tokens[n_tokens] = token;
295199a2dd95SBruce Richardson 			n_tokens++;
295299a2dd95SBruce Richardson 		}
295399a2dd95SBruce Richardson 
295499a2dd95SBruce Richardson 		/* Handle empty lines. */
295599a2dd95SBruce Richardson 		if (!n_tokens)
295699a2dd95SBruce Richardson 			continue;
295799a2dd95SBruce Richardson 
295899a2dd95SBruce Richardson 		/* struct block. */
295999a2dd95SBruce Richardson 		if (block_mask & (1 << STRUCT_BLOCK)) {
296030c4abb9SCristian Dumitrescu 			struct struct_spec *new_structs;
296130c4abb9SCristian Dumitrescu 
296299a2dd95SBruce Richardson 			status = struct_block_parse(&struct_spec,
296399a2dd95SBruce Richardson 						    &block_mask,
296499a2dd95SBruce Richardson 						    tokens,
296599a2dd95SBruce Richardson 						    n_tokens,
296699a2dd95SBruce Richardson 						    n_lines,
296799a2dd95SBruce Richardson 						    err_line,
296899a2dd95SBruce Richardson 						    err_msg);
296999a2dd95SBruce Richardson 			if (status)
297099a2dd95SBruce Richardson 				goto error;
297199a2dd95SBruce Richardson 
297299a2dd95SBruce Richardson 			if (block_mask & (1 << STRUCT_BLOCK))
297399a2dd95SBruce Richardson 				continue;
297499a2dd95SBruce Richardson 
297599a2dd95SBruce Richardson 			/* End of block. */
297630c4abb9SCristian Dumitrescu 			new_structs = realloc(s->structs,
297730c4abb9SCristian Dumitrescu 					      (s->n_structs + 1) * sizeof(struct struct_spec));
297830c4abb9SCristian Dumitrescu 			if (!new_structs) {
297999a2dd95SBruce Richardson 				if (err_line)
298099a2dd95SBruce Richardson 					*err_line = n_lines;
298199a2dd95SBruce Richardson 				if (err_msg)
298230c4abb9SCristian Dumitrescu 					*err_msg = "Memory allocation failed.";
298330c4abb9SCristian Dumitrescu 				status = -ENOMEM;
298499a2dd95SBruce Richardson 				goto error;
298599a2dd95SBruce Richardson 			}
298699a2dd95SBruce Richardson 
298730c4abb9SCristian Dumitrescu 			s->structs = new_structs;
298830c4abb9SCristian Dumitrescu 			memcpy(&s->structs[s->n_structs], &struct_spec, sizeof(struct struct_spec));
298930c4abb9SCristian Dumitrescu 			s->n_structs++;
299030c4abb9SCristian Dumitrescu 			memset(&struct_spec, 0, sizeof(struct struct_spec));
299199a2dd95SBruce Richardson 
299299a2dd95SBruce Richardson 			continue;
299399a2dd95SBruce Richardson 		}
299499a2dd95SBruce Richardson 
299599a2dd95SBruce Richardson 		/* action block. */
299699a2dd95SBruce Richardson 		if (block_mask & (1 << ACTION_BLOCK)) {
299730c4abb9SCristian Dumitrescu 			struct action_spec *new_actions;
299830c4abb9SCristian Dumitrescu 
299999a2dd95SBruce Richardson 			status = action_block_parse(&action_spec,
300099a2dd95SBruce Richardson 						    &block_mask,
300199a2dd95SBruce Richardson 						    tokens,
300299a2dd95SBruce Richardson 						    n_tokens,
300399a2dd95SBruce Richardson 						    n_lines,
300499a2dd95SBruce Richardson 						    err_line,
300599a2dd95SBruce Richardson 						    err_msg);
300699a2dd95SBruce Richardson 			if (status)
300799a2dd95SBruce Richardson 				goto error;
300899a2dd95SBruce Richardson 
300999a2dd95SBruce Richardson 			if (block_mask & (1 << ACTION_BLOCK))
301099a2dd95SBruce Richardson 				continue;
301199a2dd95SBruce Richardson 
301299a2dd95SBruce Richardson 			/* End of block. */
301330c4abb9SCristian Dumitrescu 			new_actions = realloc(s->actions,
301430c4abb9SCristian Dumitrescu 					      (s->n_actions + 1) * sizeof(struct action_spec));
301530c4abb9SCristian Dumitrescu 			if (!new_actions) {
301699a2dd95SBruce Richardson 				if (err_line)
301799a2dd95SBruce Richardson 					*err_line = n_lines;
301899a2dd95SBruce Richardson 				if (err_msg)
301930c4abb9SCristian Dumitrescu 					*err_msg = "Memory allocation failed.";
302030c4abb9SCristian Dumitrescu 				status = -ENOMEM;
302199a2dd95SBruce Richardson 				goto error;
302299a2dd95SBruce Richardson 			}
302399a2dd95SBruce Richardson 
302430c4abb9SCristian Dumitrescu 			s->actions = new_actions;
302530c4abb9SCristian Dumitrescu 			memcpy(&s->actions[s->n_actions], &action_spec, sizeof(struct action_spec));
302630c4abb9SCristian Dumitrescu 			s->n_actions++;
302730c4abb9SCristian Dumitrescu 			memset(&action_spec, 0, sizeof(struct action_spec));
302899a2dd95SBruce Richardson 
302999a2dd95SBruce Richardson 			continue;
303099a2dd95SBruce Richardson 		}
303199a2dd95SBruce Richardson 
303299a2dd95SBruce Richardson 		/* table block. */
303399a2dd95SBruce Richardson 		if (block_mask & (1 << TABLE_BLOCK)) {
303430c4abb9SCristian Dumitrescu 			struct table_spec *new_tables;
303530c4abb9SCristian Dumitrescu 
303699a2dd95SBruce Richardson 			status = table_block_parse(&table_spec,
303799a2dd95SBruce Richardson 						   &block_mask,
303899a2dd95SBruce Richardson 						   tokens,
303999a2dd95SBruce Richardson 						   n_tokens,
304099a2dd95SBruce Richardson 						   n_lines,
304199a2dd95SBruce Richardson 						   err_line,
304299a2dd95SBruce Richardson 						   err_msg);
304399a2dd95SBruce Richardson 			if (status)
304499a2dd95SBruce Richardson 				goto error;
304599a2dd95SBruce Richardson 
304699a2dd95SBruce Richardson 			if (block_mask & (1 << TABLE_BLOCK))
304799a2dd95SBruce Richardson 				continue;
304899a2dd95SBruce Richardson 
304999a2dd95SBruce Richardson 			/* End of block. */
305030c4abb9SCristian Dumitrescu 			new_tables = realloc(s->tables,
305130c4abb9SCristian Dumitrescu 					     (s->n_tables + 1) * sizeof(struct table_spec));
305230c4abb9SCristian Dumitrescu 			if (!new_tables) {
305399a2dd95SBruce Richardson 				if (err_line)
305499a2dd95SBruce Richardson 					*err_line = n_lines;
305599a2dd95SBruce Richardson 				if (err_msg)
305630c4abb9SCristian Dumitrescu 					*err_msg = "Memory allocation failed.";
305730c4abb9SCristian Dumitrescu 				status = -ENOMEM;
305899a2dd95SBruce Richardson 				goto error;
305999a2dd95SBruce Richardson 			}
306099a2dd95SBruce Richardson 
306130c4abb9SCristian Dumitrescu 			s->tables = new_tables;
306230c4abb9SCristian Dumitrescu 			memcpy(&s->tables[s->n_tables], &table_spec, sizeof(struct table_spec));
306330c4abb9SCristian Dumitrescu 			s->n_tables++;
306430c4abb9SCristian Dumitrescu 			memset(&table_spec, 0, sizeof(struct table_spec));
306599a2dd95SBruce Richardson 
306699a2dd95SBruce Richardson 			continue;
306799a2dd95SBruce Richardson 		}
306899a2dd95SBruce Richardson 
3069cdaa937dSCristian Dumitrescu 		/* selector block. */
3070cdaa937dSCristian Dumitrescu 		if (block_mask & (1 << SELECTOR_BLOCK)) {
307130c4abb9SCristian Dumitrescu 			struct selector_spec *new_selectors;
307230c4abb9SCristian Dumitrescu 
3073cdaa937dSCristian Dumitrescu 			status = selector_block_parse(&selector_spec,
3074cdaa937dSCristian Dumitrescu 						      &block_mask,
3075cdaa937dSCristian Dumitrescu 						      tokens,
3076cdaa937dSCristian Dumitrescu 						      n_tokens,
3077cdaa937dSCristian Dumitrescu 						      n_lines,
3078cdaa937dSCristian Dumitrescu 						      err_line,
3079cdaa937dSCristian Dumitrescu 						      err_msg);
3080cdaa937dSCristian Dumitrescu 			if (status)
3081cdaa937dSCristian Dumitrescu 				goto error;
3082cdaa937dSCristian Dumitrescu 
3083cdaa937dSCristian Dumitrescu 			if (block_mask & (1 << SELECTOR_BLOCK))
3084cdaa937dSCristian Dumitrescu 				continue;
3085cdaa937dSCristian Dumitrescu 
3086cdaa937dSCristian Dumitrescu 			/* End of block. */
308730c4abb9SCristian Dumitrescu 			new_selectors = realloc(s->selectors,
308830c4abb9SCristian Dumitrescu 				(s->n_selectors + 1) * sizeof(struct selector_spec));
308930c4abb9SCristian Dumitrescu 			if (!new_selectors) {
3090cdaa937dSCristian Dumitrescu 				if (err_line)
3091cdaa937dSCristian Dumitrescu 					*err_line = n_lines;
3092cdaa937dSCristian Dumitrescu 				if (err_msg)
309330c4abb9SCristian Dumitrescu 					*err_msg = "Memory allocation failed.";
309430c4abb9SCristian Dumitrescu 				status = -ENOMEM;
3095cdaa937dSCristian Dumitrescu 				goto error;
3096cdaa937dSCristian Dumitrescu 			}
3097cdaa937dSCristian Dumitrescu 
309830c4abb9SCristian Dumitrescu 			s->selectors = new_selectors;
309930c4abb9SCristian Dumitrescu 			memcpy(&s->selectors[s->n_selectors],
310030c4abb9SCristian Dumitrescu 			       &selector_spec,
310130c4abb9SCristian Dumitrescu 			       sizeof(struct selector_spec));
310230c4abb9SCristian Dumitrescu 			s->n_selectors++;
310330c4abb9SCristian Dumitrescu 			memset(&selector_spec, 0, sizeof(struct selector_spec));
3104cdaa937dSCristian Dumitrescu 
3105cdaa937dSCristian Dumitrescu 			continue;
3106cdaa937dSCristian Dumitrescu 		}
3107cdaa937dSCristian Dumitrescu 
31084f59d372SCristian Dumitrescu 		/* learner block. */
31094f59d372SCristian Dumitrescu 		if (block_mask & (1 << LEARNER_BLOCK)) {
311030c4abb9SCristian Dumitrescu 			struct learner_spec *new_learners;
311130c4abb9SCristian Dumitrescu 
31124f59d372SCristian Dumitrescu 			status = learner_block_parse(&learner_spec,
31134f59d372SCristian Dumitrescu 						     &block_mask,
31144f59d372SCristian Dumitrescu 						     tokens,
31154f59d372SCristian Dumitrescu 						     n_tokens,
31164f59d372SCristian Dumitrescu 						     n_lines,
31174f59d372SCristian Dumitrescu 						     err_line,
31184f59d372SCristian Dumitrescu 						     err_msg);
31194f59d372SCristian Dumitrescu 			if (status)
31204f59d372SCristian Dumitrescu 				goto error;
31214f59d372SCristian Dumitrescu 
31224f59d372SCristian Dumitrescu 			if (block_mask & (1 << LEARNER_BLOCK))
31234f59d372SCristian Dumitrescu 				continue;
31244f59d372SCristian Dumitrescu 
31254f59d372SCristian Dumitrescu 			/* End of block. */
312630c4abb9SCristian Dumitrescu 			new_learners = realloc(s->learners,
312730c4abb9SCristian Dumitrescu 					       (s->n_learners + 1) * sizeof(struct learner_spec));
312830c4abb9SCristian Dumitrescu 			if (!new_learners) {
31294f59d372SCristian Dumitrescu 				if (err_line)
31304f59d372SCristian Dumitrescu 					*err_line = n_lines;
31314f59d372SCristian Dumitrescu 				if (err_msg)
313230c4abb9SCristian Dumitrescu 					*err_msg = "Memory allocation failed.";
313330c4abb9SCristian Dumitrescu 				status = -ENOMEM;
31344f59d372SCristian Dumitrescu 				goto error;
31354f59d372SCristian Dumitrescu 			}
31364f59d372SCristian Dumitrescu 
313730c4abb9SCristian Dumitrescu 			s->learners = new_learners;
313830c4abb9SCristian Dumitrescu 			memcpy(&s->learners[s->n_learners],
313930c4abb9SCristian Dumitrescu 			       &learner_spec,
314030c4abb9SCristian Dumitrescu 			       sizeof(struct learner_spec));
314130c4abb9SCristian Dumitrescu 			s->n_learners++;
314230c4abb9SCristian Dumitrescu 			memset(&learner_spec, 0, sizeof(struct learner_spec));
31434f59d372SCristian Dumitrescu 
31444f59d372SCristian Dumitrescu 			continue;
31454f59d372SCristian Dumitrescu 		}
31464f59d372SCristian Dumitrescu 
314799a2dd95SBruce Richardson 		/* apply block. */
314899a2dd95SBruce Richardson 		if (block_mask & (1 << APPLY_BLOCK)) {
314930c4abb9SCristian Dumitrescu 			struct apply_spec *new_apply;
315030c4abb9SCristian Dumitrescu 
315199a2dd95SBruce Richardson 			status = apply_block_parse(&apply_spec,
315299a2dd95SBruce Richardson 						   &block_mask,
315399a2dd95SBruce Richardson 						   tokens,
315499a2dd95SBruce Richardson 						   n_tokens,
315599a2dd95SBruce Richardson 						   n_lines,
315699a2dd95SBruce Richardson 						   err_line,
315799a2dd95SBruce Richardson 						   err_msg);
315899a2dd95SBruce Richardson 			if (status)
315999a2dd95SBruce Richardson 				goto error;
316099a2dd95SBruce Richardson 
316199a2dd95SBruce Richardson 			if (block_mask & (1 << APPLY_BLOCK))
316299a2dd95SBruce Richardson 				continue;
316399a2dd95SBruce Richardson 
316499a2dd95SBruce Richardson 			/* End of block. */
316530c4abb9SCristian Dumitrescu 			new_apply = realloc(s->apply, (s->n_apply + 1) * sizeof(struct apply_spec));
316630c4abb9SCristian Dumitrescu 			if (!new_apply) {
316799a2dd95SBruce Richardson 				if (err_line)
316899a2dd95SBruce Richardson 					*err_line = n_lines;
316999a2dd95SBruce Richardson 				if (err_msg)
317030c4abb9SCristian Dumitrescu 					*err_msg = "Memory allocation failed.";
317130c4abb9SCristian Dumitrescu 				status = -ENOMEM;
317299a2dd95SBruce Richardson 				goto error;
317399a2dd95SBruce Richardson 			}
317499a2dd95SBruce Richardson 
317530c4abb9SCristian Dumitrescu 			s->apply = new_apply;
317630c4abb9SCristian Dumitrescu 			memcpy(&s->apply[s->n_apply], &apply_spec, sizeof(struct apply_spec));
317730c4abb9SCristian Dumitrescu 			s->n_apply++;
317830c4abb9SCristian Dumitrescu 			memset(&apply_spec, 0, sizeof(struct apply_spec));
317999a2dd95SBruce Richardson 
318099a2dd95SBruce Richardson 			continue;
318199a2dd95SBruce Richardson 		}
318299a2dd95SBruce Richardson 
318399a2dd95SBruce Richardson 		/* extobj. */
318499a2dd95SBruce Richardson 		if (!strcmp(tokens[0], "extobj")) {
318530c4abb9SCristian Dumitrescu 			struct extobj_spec *new_extobjs;
318630c4abb9SCristian Dumitrescu 
318799a2dd95SBruce Richardson 			status = extobj_statement_parse(&extobj_spec,
318899a2dd95SBruce Richardson 							tokens,
318999a2dd95SBruce Richardson 							n_tokens,
319099a2dd95SBruce Richardson 							n_lines,
319199a2dd95SBruce Richardson 							err_line,
319299a2dd95SBruce Richardson 							err_msg);
319399a2dd95SBruce Richardson 			if (status)
319499a2dd95SBruce Richardson 				goto error;
319599a2dd95SBruce Richardson 
319630c4abb9SCristian Dumitrescu 			new_extobjs = realloc(s->extobjs,
319730c4abb9SCristian Dumitrescu 					      (s->n_extobjs + 1) * sizeof(struct extobj_spec));
319830c4abb9SCristian Dumitrescu 			if (!new_extobjs) {
319999a2dd95SBruce Richardson 				if (err_line)
320099a2dd95SBruce Richardson 					*err_line = n_lines;
320199a2dd95SBruce Richardson 				if (err_msg)
320230c4abb9SCristian Dumitrescu 					*err_msg = "Memory allocation failed.";
320330c4abb9SCristian Dumitrescu 				status = -ENOMEM;
320499a2dd95SBruce Richardson 				goto error;
320599a2dd95SBruce Richardson 			}
320699a2dd95SBruce Richardson 
320730c4abb9SCristian Dumitrescu 			s->extobjs = new_extobjs;
320830c4abb9SCristian Dumitrescu 			memcpy(&s->extobjs[s->n_extobjs], &extobj_spec, sizeof(struct extobj_spec));
320930c4abb9SCristian Dumitrescu 			s->n_extobjs++;
321030c4abb9SCristian Dumitrescu 			memset(&extobj_spec, 0, sizeof(struct extobj_spec));
321199a2dd95SBruce Richardson 
321299a2dd95SBruce Richardson 			continue;
321399a2dd95SBruce Richardson 		}
321499a2dd95SBruce Richardson 
321599a2dd95SBruce Richardson 		/* struct. */
321699a2dd95SBruce Richardson 		if (!strcmp(tokens[0], "struct")) {
321799a2dd95SBruce Richardson 			status = struct_statement_parse(&struct_spec,
321899a2dd95SBruce Richardson 							&block_mask,
321999a2dd95SBruce Richardson 							tokens,
322099a2dd95SBruce Richardson 							n_tokens,
322199a2dd95SBruce Richardson 							n_lines,
322299a2dd95SBruce Richardson 							err_line,
322399a2dd95SBruce Richardson 							err_msg);
322499a2dd95SBruce Richardson 			if (status)
322599a2dd95SBruce Richardson 				goto error;
322699a2dd95SBruce Richardson 
322799a2dd95SBruce Richardson 			continue;
322899a2dd95SBruce Richardson 		}
322999a2dd95SBruce Richardson 
323099a2dd95SBruce Richardson 		/* header. */
323199a2dd95SBruce Richardson 		if (!strcmp(tokens[0], "header")) {
323230c4abb9SCristian Dumitrescu 			struct header_spec *new_headers;
323330c4abb9SCristian Dumitrescu 
323499a2dd95SBruce Richardson 			status = header_statement_parse(&header_spec,
323599a2dd95SBruce Richardson 							tokens,
323699a2dd95SBruce Richardson 							n_tokens,
323799a2dd95SBruce Richardson 							n_lines,
323899a2dd95SBruce Richardson 							err_line,
323999a2dd95SBruce Richardson 							err_msg);
324099a2dd95SBruce Richardson 			if (status)
324199a2dd95SBruce Richardson 				goto error;
324299a2dd95SBruce Richardson 
324330c4abb9SCristian Dumitrescu 			new_headers = realloc(s->headers,
324430c4abb9SCristian Dumitrescu 					      (s->n_headers + 1) * sizeof(struct header_spec));
324530c4abb9SCristian Dumitrescu 			if (!new_headers) {
324699a2dd95SBruce Richardson 				if (err_line)
324799a2dd95SBruce Richardson 					*err_line = n_lines;
324899a2dd95SBruce Richardson 				if (err_msg)
324930c4abb9SCristian Dumitrescu 					*err_msg = "Memory allocation failed.";
325030c4abb9SCristian Dumitrescu 				status = -ENOMEM;
325199a2dd95SBruce Richardson 				goto error;
325299a2dd95SBruce Richardson 			}
325399a2dd95SBruce Richardson 
325430c4abb9SCristian Dumitrescu 			s->headers = new_headers;
325530c4abb9SCristian Dumitrescu 			memcpy(&s->headers[s->n_headers], &header_spec, sizeof(struct header_spec));
325630c4abb9SCristian Dumitrescu 			s->n_headers++;
325730c4abb9SCristian Dumitrescu 			memset(&header_spec, 0, sizeof(struct header_spec));
325899a2dd95SBruce Richardson 
325999a2dd95SBruce Richardson 			continue;
326099a2dd95SBruce Richardson 		}
326199a2dd95SBruce Richardson 
326299a2dd95SBruce Richardson 		/* metadata. */
326399a2dd95SBruce Richardson 		if (!strcmp(tokens[0], "metadata")) {
326430c4abb9SCristian Dumitrescu 			struct metadata_spec *new_metadata;
326530c4abb9SCristian Dumitrescu 
326699a2dd95SBruce Richardson 			status = metadata_statement_parse(&metadata_spec,
326799a2dd95SBruce Richardson 							  tokens,
326899a2dd95SBruce Richardson 							  n_tokens,
326999a2dd95SBruce Richardson 							  n_lines,
327099a2dd95SBruce Richardson 							  err_line,
327199a2dd95SBruce Richardson 							  err_msg);
327299a2dd95SBruce Richardson 			if (status)
327399a2dd95SBruce Richardson 				goto error;
327499a2dd95SBruce Richardson 
327530c4abb9SCristian Dumitrescu 			new_metadata = realloc(s->metadata,
327630c4abb9SCristian Dumitrescu 					       (s->n_metadata + 1) * sizeof(struct metadata_spec));
327730c4abb9SCristian Dumitrescu 			if (!new_metadata) {
327899a2dd95SBruce Richardson 				if (err_line)
327999a2dd95SBruce Richardson 					*err_line = n_lines;
328099a2dd95SBruce Richardson 				if (err_msg)
328130c4abb9SCristian Dumitrescu 					*err_msg = "Memory allocation failed.";
328230c4abb9SCristian Dumitrescu 				status = -ENOMEM;
328399a2dd95SBruce Richardson 				goto error;
328499a2dd95SBruce Richardson 			}
328599a2dd95SBruce Richardson 
328630c4abb9SCristian Dumitrescu 			s->metadata = new_metadata;
328730c4abb9SCristian Dumitrescu 			memcpy(&s->metadata[s->n_metadata],
328830c4abb9SCristian Dumitrescu 			       &metadata_spec,
328930c4abb9SCristian Dumitrescu 			       sizeof(struct metadata_spec));
329030c4abb9SCristian Dumitrescu 			s->n_metadata++;
329130c4abb9SCristian Dumitrescu 			memset(&metadata_spec, 0, sizeof(struct metadata_spec));
329299a2dd95SBruce Richardson 
329399a2dd95SBruce Richardson 			continue;
329499a2dd95SBruce Richardson 		}
329599a2dd95SBruce Richardson 
329699a2dd95SBruce Richardson 		/* action. */
329799a2dd95SBruce Richardson 		if (!strcmp(tokens[0], "action")) {
329899a2dd95SBruce Richardson 			status = action_statement_parse(&action_spec,
329999a2dd95SBruce Richardson 							&block_mask,
330099a2dd95SBruce Richardson 							tokens,
330199a2dd95SBruce Richardson 							n_tokens,
330299a2dd95SBruce Richardson 							n_lines,
330399a2dd95SBruce Richardson 							err_line,
330499a2dd95SBruce Richardson 							err_msg);
330599a2dd95SBruce Richardson 			if (status)
330699a2dd95SBruce Richardson 				goto error;
330799a2dd95SBruce Richardson 
330899a2dd95SBruce Richardson 			continue;
330999a2dd95SBruce Richardson 		}
331099a2dd95SBruce Richardson 
331199a2dd95SBruce Richardson 		/* table. */
331299a2dd95SBruce Richardson 		if (!strcmp(tokens[0], "table")) {
331399a2dd95SBruce Richardson 			status = table_statement_parse(&table_spec,
331499a2dd95SBruce Richardson 						       &block_mask,
331599a2dd95SBruce Richardson 						       tokens,
331699a2dd95SBruce Richardson 						       n_tokens,
331799a2dd95SBruce Richardson 						       n_lines,
331899a2dd95SBruce Richardson 						       err_line,
331999a2dd95SBruce Richardson 						       err_msg);
332099a2dd95SBruce Richardson 			if (status)
332199a2dd95SBruce Richardson 				goto error;
332299a2dd95SBruce Richardson 
332399a2dd95SBruce Richardson 			continue;
332499a2dd95SBruce Richardson 		}
332599a2dd95SBruce Richardson 
3326cdaa937dSCristian Dumitrescu 		/* selector. */
3327cdaa937dSCristian Dumitrescu 		if (!strcmp(tokens[0], "selector")) {
3328cdaa937dSCristian Dumitrescu 			status = selector_statement_parse(&selector_spec,
3329cdaa937dSCristian Dumitrescu 							  &block_mask,
3330cdaa937dSCristian Dumitrescu 							  tokens,
3331cdaa937dSCristian Dumitrescu 							  n_tokens,
3332cdaa937dSCristian Dumitrescu 							  n_lines,
3333cdaa937dSCristian Dumitrescu 							  err_line,
3334cdaa937dSCristian Dumitrescu 							  err_msg);
3335cdaa937dSCristian Dumitrescu 			if (status)
3336cdaa937dSCristian Dumitrescu 				goto error;
3337cdaa937dSCristian Dumitrescu 
3338cdaa937dSCristian Dumitrescu 			continue;
3339cdaa937dSCristian Dumitrescu 		}
3340cdaa937dSCristian Dumitrescu 
33414f59d372SCristian Dumitrescu 		/* learner. */
33424f59d372SCristian Dumitrescu 		if (!strcmp(tokens[0], "learner")) {
33434f59d372SCristian Dumitrescu 			status = learner_statement_parse(&learner_spec,
33444f59d372SCristian Dumitrescu 							 &block_mask,
33454f59d372SCristian Dumitrescu 							 tokens,
33464f59d372SCristian Dumitrescu 							 n_tokens,
33474f59d372SCristian Dumitrescu 							 n_lines,
33484f59d372SCristian Dumitrescu 							 err_line,
33494f59d372SCristian Dumitrescu 							 err_msg);
33504f59d372SCristian Dumitrescu 			if (status)
33514f59d372SCristian Dumitrescu 				goto error;
33524f59d372SCristian Dumitrescu 
33534f59d372SCristian Dumitrescu 			continue;
33544f59d372SCristian Dumitrescu 		}
33554f59d372SCristian Dumitrescu 
335699a2dd95SBruce Richardson 		/* regarray. */
335799a2dd95SBruce Richardson 		if (!strcmp(tokens[0], "regarray")) {
335830c4abb9SCristian Dumitrescu 			struct regarray_spec *new_regarrays;
335930c4abb9SCristian Dumitrescu 
336099a2dd95SBruce Richardson 			status = regarray_statement_parse(&regarray_spec,
336199a2dd95SBruce Richardson 							  tokens,
336299a2dd95SBruce Richardson 							  n_tokens,
336399a2dd95SBruce Richardson 							  n_lines,
336499a2dd95SBruce Richardson 							  err_line,
336599a2dd95SBruce Richardson 							  err_msg);
336699a2dd95SBruce Richardson 			if (status)
336799a2dd95SBruce Richardson 				goto error;
336899a2dd95SBruce Richardson 
336930c4abb9SCristian Dumitrescu 			new_regarrays = realloc(s->regarrays,
337030c4abb9SCristian Dumitrescu 				(s->n_regarrays + 1) * sizeof(struct regarray_spec));
337130c4abb9SCristian Dumitrescu 			if (!new_regarrays) {
337299a2dd95SBruce Richardson 				if (err_line)
337399a2dd95SBruce Richardson 					*err_line = n_lines;
337499a2dd95SBruce Richardson 				if (err_msg)
337530c4abb9SCristian Dumitrescu 					*err_msg = "Memory allocation failed.";
337630c4abb9SCristian Dumitrescu 				status = -ENOMEM;
337799a2dd95SBruce Richardson 				goto error;
337899a2dd95SBruce Richardson 			}
337999a2dd95SBruce Richardson 
338030c4abb9SCristian Dumitrescu 			s->regarrays = new_regarrays;
338130c4abb9SCristian Dumitrescu 			memcpy(&s->regarrays[s->n_regarrays],
338230c4abb9SCristian Dumitrescu 			       &regarray_spec,
338330c4abb9SCristian Dumitrescu 			       sizeof(struct regarray_spec));
338430c4abb9SCristian Dumitrescu 			s->n_regarrays++;
338530c4abb9SCristian Dumitrescu 			memset(&regarray_spec, 0, sizeof(struct regarray_spec));
338699a2dd95SBruce Richardson 
338799a2dd95SBruce Richardson 			continue;
338899a2dd95SBruce Richardson 		}
338999a2dd95SBruce Richardson 
339099a2dd95SBruce Richardson 		/* metarray. */
339199a2dd95SBruce Richardson 		if (!strcmp(tokens[0], "metarray")) {
339230c4abb9SCristian Dumitrescu 			struct metarray_spec *new_metarrays;
339330c4abb9SCristian Dumitrescu 
339499a2dd95SBruce Richardson 			status = metarray_statement_parse(&metarray_spec,
339599a2dd95SBruce Richardson 							  tokens,
339699a2dd95SBruce Richardson 							  n_tokens,
339799a2dd95SBruce Richardson 							  n_lines,
339899a2dd95SBruce Richardson 							  err_line,
339999a2dd95SBruce Richardson 							  err_msg);
340099a2dd95SBruce Richardson 			if (status)
340199a2dd95SBruce Richardson 				goto error;
340299a2dd95SBruce Richardson 
340330c4abb9SCristian Dumitrescu 			new_metarrays = realloc(s->metarrays,
340430c4abb9SCristian Dumitrescu 				(s->n_metarrays + 1) * sizeof(struct metarray_spec));
340530c4abb9SCristian Dumitrescu 			if (!new_metarrays) {
340699a2dd95SBruce Richardson 				if (err_line)
340799a2dd95SBruce Richardson 					*err_line = n_lines;
340899a2dd95SBruce Richardson 				if (err_msg)
340930c4abb9SCristian Dumitrescu 					*err_msg = "Memory allocation failed.";
341030c4abb9SCristian Dumitrescu 				status = -ENOMEM;
341199a2dd95SBruce Richardson 				goto error;
341299a2dd95SBruce Richardson 			}
341399a2dd95SBruce Richardson 
341430c4abb9SCristian Dumitrescu 			s->metarrays = new_metarrays;
341530c4abb9SCristian Dumitrescu 			memcpy(&s->metarrays[s->n_metarrays],
341630c4abb9SCristian Dumitrescu 			       &metarray_spec,
341730c4abb9SCristian Dumitrescu 			       sizeof(struct metarray_spec));
341830c4abb9SCristian Dumitrescu 			s->n_metarrays++;
341930c4abb9SCristian Dumitrescu 			memset(&metarray_spec, 0, sizeof(struct metarray_spec));
342099a2dd95SBruce Richardson 
342199a2dd95SBruce Richardson 			continue;
342299a2dd95SBruce Richardson 		}
342399a2dd95SBruce Richardson 
34248ba342ceSCristian Dumitrescu 		/* rss object configuration */
34258ba342ceSCristian Dumitrescu 		if (!strcmp(tokens[0], "rss")) {
34268ba342ceSCristian Dumitrescu 			struct rss_spec *new_rss;
34278ba342ceSCristian Dumitrescu 
34288ba342ceSCristian Dumitrescu 			status = rss_statement_parse(&rss_spec,
34298ba342ceSCristian Dumitrescu 						     tokens,
34308ba342ceSCristian Dumitrescu 						     n_tokens,
34318ba342ceSCristian Dumitrescu 						     n_lines,
34328ba342ceSCristian Dumitrescu 						     err_line,
34338ba342ceSCristian Dumitrescu 						     err_msg);
34348ba342ceSCristian Dumitrescu 			if (status)
34358ba342ceSCristian Dumitrescu 				goto error;
34368ba342ceSCristian Dumitrescu 
34378ba342ceSCristian Dumitrescu 			new_rss = realloc(s->rss,
34388ba342ceSCristian Dumitrescu 				(s->n_rss + 1) * sizeof(struct rss_spec));
34398ba342ceSCristian Dumitrescu 			if (!new_rss) {
34408ba342ceSCristian Dumitrescu 				if (err_line)
34418ba342ceSCristian Dumitrescu 					*err_line = n_lines;
34428ba342ceSCristian Dumitrescu 				if (err_msg)
34438ba342ceSCristian Dumitrescu 					*err_msg = "Memory allocation failed.";
34448ba342ceSCristian Dumitrescu 				status = -ENOMEM;
34458ba342ceSCristian Dumitrescu 				goto error;
34468ba342ceSCristian Dumitrescu 			}
34478ba342ceSCristian Dumitrescu 
34488ba342ceSCristian Dumitrescu 			s->rss = new_rss;
34498ba342ceSCristian Dumitrescu 			memcpy(&s->rss[s->n_rss],
34508ba342ceSCristian Dumitrescu 			       &rss_spec,
34518ba342ceSCristian Dumitrescu 			       sizeof(struct rss_spec));
34528ba342ceSCristian Dumitrescu 			s->n_rss++;
34538ba342ceSCristian Dumitrescu 			memset(&rss_spec, 0, sizeof(struct rss_spec));
34548ba342ceSCristian Dumitrescu 
34558ba342ceSCristian Dumitrescu 			continue;
34568ba342ceSCristian Dumitrescu 		}
34578ba342ceSCristian Dumitrescu 
345899a2dd95SBruce Richardson 		/* apply. */
345999a2dd95SBruce Richardson 		if (!strcmp(tokens[0], "apply")) {
346099a2dd95SBruce Richardson 			status = apply_statement_parse(&block_mask,
346199a2dd95SBruce Richardson 						       tokens,
346299a2dd95SBruce Richardson 						       n_tokens,
346399a2dd95SBruce Richardson 						       n_lines,
346499a2dd95SBruce Richardson 						       err_line,
346599a2dd95SBruce Richardson 						       err_msg);
346699a2dd95SBruce Richardson 			if (status)
346799a2dd95SBruce Richardson 				goto error;
346899a2dd95SBruce Richardson 
346999a2dd95SBruce Richardson 			continue;
347099a2dd95SBruce Richardson 		}
347199a2dd95SBruce Richardson 
347299a2dd95SBruce Richardson 		/* Anything else. */
347399a2dd95SBruce Richardson 		if (err_line)
347499a2dd95SBruce Richardson 			*err_line = n_lines;
347599a2dd95SBruce Richardson 		if (err_msg)
347699a2dd95SBruce Richardson 			*err_msg = "Unknown statement.";
347799a2dd95SBruce Richardson 		status = -EINVAL;
347899a2dd95SBruce Richardson 		goto error;
347999a2dd95SBruce Richardson 	}
348099a2dd95SBruce Richardson 
348199a2dd95SBruce Richardson 	/* Handle unfinished block. */
348299a2dd95SBruce Richardson 	if (block_mask) {
348399a2dd95SBruce Richardson 		if (err_line)
348499a2dd95SBruce Richardson 			*err_line = n_lines;
348599a2dd95SBruce Richardson 		if (err_msg)
348699a2dd95SBruce Richardson 			*err_msg = "Missing }.";
348799a2dd95SBruce Richardson 		status = -EINVAL;
348899a2dd95SBruce Richardson 		goto error;
348999a2dd95SBruce Richardson 	}
349099a2dd95SBruce Richardson 
349130c4abb9SCristian Dumitrescu 	return s;
349299a2dd95SBruce Richardson 
349399a2dd95SBruce Richardson error:
349499a2dd95SBruce Richardson 	extobj_spec_free(&extobj_spec);
349599a2dd95SBruce Richardson 	struct_spec_free(&struct_spec);
349699a2dd95SBruce Richardson 	header_spec_free(&header_spec);
349799a2dd95SBruce Richardson 	metadata_spec_free(&metadata_spec);
349899a2dd95SBruce Richardson 	action_spec_free(&action_spec);
349999a2dd95SBruce Richardson 	table_spec_free(&table_spec);
3500cdaa937dSCristian Dumitrescu 	selector_spec_free(&selector_spec);
35014f59d372SCristian Dumitrescu 	learner_spec_free(&learner_spec);
350299a2dd95SBruce Richardson 	regarray_spec_free(&regarray_spec);
350399a2dd95SBruce Richardson 	metarray_spec_free(&metarray_spec);
35048ba342ceSCristian Dumitrescu 	rss_spec_free(&rss_spec);
350599a2dd95SBruce Richardson 	apply_spec_free(&apply_spec);
350630c4abb9SCristian Dumitrescu 	pipeline_spec_free(s);
350730c4abb9SCristian Dumitrescu 
350830c4abb9SCristian Dumitrescu 	return NULL;
350930c4abb9SCristian Dumitrescu }
351030c4abb9SCristian Dumitrescu 
351130c4abb9SCristian Dumitrescu int
pipeline_spec_configure(struct rte_swx_pipeline * p,struct pipeline_spec * s,const char ** err_msg)351230c4abb9SCristian Dumitrescu pipeline_spec_configure(struct rte_swx_pipeline *p,
351330c4abb9SCristian Dumitrescu 			struct pipeline_spec *s,
351430c4abb9SCristian Dumitrescu 			const char **err_msg)
351530c4abb9SCristian Dumitrescu {
351630c4abb9SCristian Dumitrescu 	uint32_t i;
351730c4abb9SCristian Dumitrescu 	int status = 0;
351830c4abb9SCristian Dumitrescu 
351930c4abb9SCristian Dumitrescu 	/* extobj. */
352030c4abb9SCristian Dumitrescu 	for (i = 0; i < s->n_extobjs; i++) {
352130c4abb9SCristian Dumitrescu 		struct extobj_spec *extobj_spec = &s->extobjs[i];
352230c4abb9SCristian Dumitrescu 
352330c4abb9SCristian Dumitrescu 		status = rte_swx_pipeline_extern_object_config(p,
352430c4abb9SCristian Dumitrescu 			extobj_spec->name,
352530c4abb9SCristian Dumitrescu 			extobj_spec->extern_type_name,
352630c4abb9SCristian Dumitrescu 			extobj_spec->pragma);
352730c4abb9SCristian Dumitrescu 		if (status) {
352830c4abb9SCristian Dumitrescu 			if (err_msg)
352930c4abb9SCristian Dumitrescu 				*err_msg = "Extern object configuration error.";
353030c4abb9SCristian Dumitrescu 			return status;
353130c4abb9SCristian Dumitrescu 		}
353230c4abb9SCristian Dumitrescu 	}
353330c4abb9SCristian Dumitrescu 
353430c4abb9SCristian Dumitrescu 	/* regarray. */
353530c4abb9SCristian Dumitrescu 	for (i = 0; i < s->n_regarrays; i++) {
353630c4abb9SCristian Dumitrescu 		struct regarray_spec *regarray_spec = &s->regarrays[i];
353730c4abb9SCristian Dumitrescu 
353830c4abb9SCristian Dumitrescu 		status = rte_swx_pipeline_regarray_config(p,
353930c4abb9SCristian Dumitrescu 			regarray_spec->name,
354030c4abb9SCristian Dumitrescu 			regarray_spec->size,
354130c4abb9SCristian Dumitrescu 			regarray_spec->init_val);
354230c4abb9SCristian Dumitrescu 		if (status) {
354330c4abb9SCristian Dumitrescu 			if (err_msg)
354430c4abb9SCristian Dumitrescu 				*err_msg = "Register array configuration error.";
354530c4abb9SCristian Dumitrescu 			return status;
354630c4abb9SCristian Dumitrescu 		}
354730c4abb9SCristian Dumitrescu 	}
354830c4abb9SCristian Dumitrescu 
35492cd7722aSYogesh Jangra 	/* rss. */
35502cd7722aSYogesh Jangra 	for (i = 0; i < s->n_rss; i++) {
35512cd7722aSYogesh Jangra 		struct rss_spec *rss_spec = &s->rss[i];
35522cd7722aSYogesh Jangra 
35532cd7722aSYogesh Jangra 		status = rte_swx_pipeline_rss_config(p, rss_spec->name);
35542cd7722aSYogesh Jangra 		if (status) {
35552cd7722aSYogesh Jangra 			if (err_msg)
35562cd7722aSYogesh Jangra 				*err_msg = "rss object configuration error.";
35572cd7722aSYogesh Jangra 			return status;
35582cd7722aSYogesh Jangra 		}
35592cd7722aSYogesh Jangra 	}
35602cd7722aSYogesh Jangra 
356130c4abb9SCristian Dumitrescu 	/* metarray. */
356230c4abb9SCristian Dumitrescu 	for (i = 0; i < s->n_metarrays; i++) {
356330c4abb9SCristian Dumitrescu 		struct metarray_spec *metarray_spec = &s->metarrays[i];
356430c4abb9SCristian Dumitrescu 
356530c4abb9SCristian Dumitrescu 		status = rte_swx_pipeline_metarray_config(p,
356630c4abb9SCristian Dumitrescu 			metarray_spec->name,
356730c4abb9SCristian Dumitrescu 			metarray_spec->size);
356830c4abb9SCristian Dumitrescu 		if (status) {
356930c4abb9SCristian Dumitrescu 			if (err_msg)
357030c4abb9SCristian Dumitrescu 				*err_msg = "Meter array configuration error.";
357130c4abb9SCristian Dumitrescu 			return status;
357230c4abb9SCristian Dumitrescu 		}
357330c4abb9SCristian Dumitrescu 	}
357430c4abb9SCristian Dumitrescu 
357530c4abb9SCristian Dumitrescu 	/* struct. */
357630c4abb9SCristian Dumitrescu 	for (i = 0; i < s->n_structs; i++) {
357730c4abb9SCristian Dumitrescu 		struct struct_spec *struct_spec = &s->structs[i];
357830c4abb9SCristian Dumitrescu 
357930c4abb9SCristian Dumitrescu 		status = rte_swx_pipeline_struct_type_register(p,
358030c4abb9SCristian Dumitrescu 			struct_spec->name,
358130c4abb9SCristian Dumitrescu 			struct_spec->fields,
358230c4abb9SCristian Dumitrescu 			struct_spec->n_fields,
358330c4abb9SCristian Dumitrescu 			struct_spec->varbit);
358430c4abb9SCristian Dumitrescu 		if (status) {
358530c4abb9SCristian Dumitrescu 			if (err_msg)
358630c4abb9SCristian Dumitrescu 				*err_msg = "Struct type registration error.";
358730c4abb9SCristian Dumitrescu 			return status;
358830c4abb9SCristian Dumitrescu 		}
358930c4abb9SCristian Dumitrescu 	}
359030c4abb9SCristian Dumitrescu 
359130c4abb9SCristian Dumitrescu 	/* header. */
359230c4abb9SCristian Dumitrescu 	for (i = 0; i < s->n_headers; i++) {
359330c4abb9SCristian Dumitrescu 		struct header_spec *header_spec = &s->headers[i];
359430c4abb9SCristian Dumitrescu 
359530c4abb9SCristian Dumitrescu 		status = rte_swx_pipeline_packet_header_register(p,
359630c4abb9SCristian Dumitrescu 			header_spec->name,
359730c4abb9SCristian Dumitrescu 			header_spec->struct_type_name);
359830c4abb9SCristian Dumitrescu 		if (status) {
359930c4abb9SCristian Dumitrescu 			if (err_msg)
360030c4abb9SCristian Dumitrescu 				*err_msg = "Header configuration error.";
360130c4abb9SCristian Dumitrescu 			return status;
360230c4abb9SCristian Dumitrescu 		}
360330c4abb9SCristian Dumitrescu 	}
360430c4abb9SCristian Dumitrescu 
360530c4abb9SCristian Dumitrescu 	/* metadata. */
360630c4abb9SCristian Dumitrescu 	for (i = 0; i < s->n_metadata; i++) {
360730c4abb9SCristian Dumitrescu 		struct metadata_spec *metadata_spec = &s->metadata[i];
360830c4abb9SCristian Dumitrescu 
360930c4abb9SCristian Dumitrescu 		status = rte_swx_pipeline_packet_metadata_register(p,
361030c4abb9SCristian Dumitrescu 			metadata_spec->struct_type_name);
361130c4abb9SCristian Dumitrescu 		if (status) {
361230c4abb9SCristian Dumitrescu 			if (err_msg)
361330c4abb9SCristian Dumitrescu 				*err_msg = "Meta-data registration error.";
361430c4abb9SCristian Dumitrescu 			return status;
361530c4abb9SCristian Dumitrescu 		}
361630c4abb9SCristian Dumitrescu 	}
361730c4abb9SCristian Dumitrescu 
361830c4abb9SCristian Dumitrescu 	/* action. */
361930c4abb9SCristian Dumitrescu 	for (i = 0; i < s->n_actions; i++) {
362030c4abb9SCristian Dumitrescu 		struct action_spec *action_spec = &s->actions[i];
362130c4abb9SCristian Dumitrescu 
362230c4abb9SCristian Dumitrescu 		status = rte_swx_pipeline_action_config(p,
362330c4abb9SCristian Dumitrescu 			action_spec->name,
362430c4abb9SCristian Dumitrescu 			action_spec->args_struct_type_name,
362530c4abb9SCristian Dumitrescu 			action_spec->instructions,
362630c4abb9SCristian Dumitrescu 			action_spec->n_instructions);
362730c4abb9SCristian Dumitrescu 		if (status) {
362830c4abb9SCristian Dumitrescu 			if (err_msg)
362930c4abb9SCristian Dumitrescu 				*err_msg = "Action configuration error.";
363030c4abb9SCristian Dumitrescu 			return status;
363130c4abb9SCristian Dumitrescu 		}
363230c4abb9SCristian Dumitrescu 	}
363330c4abb9SCristian Dumitrescu 
363430c4abb9SCristian Dumitrescu 	/* table. */
363530c4abb9SCristian Dumitrescu 	for (i = 0; i < s->n_tables; i++) {
363630c4abb9SCristian Dumitrescu 		struct table_spec *table_spec = &s->tables[i];
363730c4abb9SCristian Dumitrescu 
363830c4abb9SCristian Dumitrescu 		status = rte_swx_pipeline_table_config(p,
363930c4abb9SCristian Dumitrescu 			table_spec->name,
364030c4abb9SCristian Dumitrescu 			&table_spec->params,
364130c4abb9SCristian Dumitrescu 			table_spec->recommended_table_type_name,
364230c4abb9SCristian Dumitrescu 			table_spec->args,
364330c4abb9SCristian Dumitrescu 			table_spec->size);
364430c4abb9SCristian Dumitrescu 		if (status) {
364530c4abb9SCristian Dumitrescu 			if (err_msg)
364630c4abb9SCristian Dumitrescu 				*err_msg = "Table configuration error.";
364730c4abb9SCristian Dumitrescu 			return status;
364830c4abb9SCristian Dumitrescu 		}
364930c4abb9SCristian Dumitrescu 	}
365030c4abb9SCristian Dumitrescu 
365130c4abb9SCristian Dumitrescu 	/* selector. */
365230c4abb9SCristian Dumitrescu 	for (i = 0; i < s->n_selectors; i++) {
365330c4abb9SCristian Dumitrescu 		struct selector_spec *selector_spec = &s->selectors[i];
365430c4abb9SCristian Dumitrescu 
365530c4abb9SCristian Dumitrescu 		status = rte_swx_pipeline_selector_config(p,
365630c4abb9SCristian Dumitrescu 			selector_spec->name,
365730c4abb9SCristian Dumitrescu 			&selector_spec->params);
365830c4abb9SCristian Dumitrescu 		if (status) {
365930c4abb9SCristian Dumitrescu 			if (err_msg)
366030c4abb9SCristian Dumitrescu 				*err_msg = "Selector table configuration error.";
366130c4abb9SCristian Dumitrescu 			return status;
366230c4abb9SCristian Dumitrescu 		}
366330c4abb9SCristian Dumitrescu 	}
366430c4abb9SCristian Dumitrescu 
366530c4abb9SCristian Dumitrescu 	/* learner. */
366630c4abb9SCristian Dumitrescu 	for (i = 0; i < s->n_learners; i++) {
366730c4abb9SCristian Dumitrescu 		struct learner_spec *learner_spec = &s->learners[i];
366830c4abb9SCristian Dumitrescu 
366930c4abb9SCristian Dumitrescu 		status = rte_swx_pipeline_learner_config(p,
367030c4abb9SCristian Dumitrescu 			learner_spec->name,
367130c4abb9SCristian Dumitrescu 			&learner_spec->params,
367230c4abb9SCristian Dumitrescu 			learner_spec->size,
367330c4abb9SCristian Dumitrescu 			learner_spec->timeout,
367430c4abb9SCristian Dumitrescu 			learner_spec->n_timeouts);
367530c4abb9SCristian Dumitrescu 		if (status) {
367630c4abb9SCristian Dumitrescu 			if (err_msg)
367730c4abb9SCristian Dumitrescu 				*err_msg = "Learner table configuration error.";
367830c4abb9SCristian Dumitrescu 			return status;
367930c4abb9SCristian Dumitrescu 		}
368030c4abb9SCristian Dumitrescu 	}
368130c4abb9SCristian Dumitrescu 
368230c4abb9SCristian Dumitrescu 	/* apply. */
368330c4abb9SCristian Dumitrescu 	for (i = 0; i < s->n_apply; i++) {
368430c4abb9SCristian Dumitrescu 		struct apply_spec *apply_spec = &s->apply[i];
368530c4abb9SCristian Dumitrescu 
368630c4abb9SCristian Dumitrescu 		status = rte_swx_pipeline_instructions_config(p,
368730c4abb9SCristian Dumitrescu 			apply_spec->instructions,
368830c4abb9SCristian Dumitrescu 			apply_spec->n_instructions);
368930c4abb9SCristian Dumitrescu 		if (status) {
369030c4abb9SCristian Dumitrescu 			if (err_msg)
369130c4abb9SCristian Dumitrescu 				*err_msg = "Pipeline instructions configuration error.";
369230c4abb9SCristian Dumitrescu 			return status;
369330c4abb9SCristian Dumitrescu 		}
369430c4abb9SCristian Dumitrescu 	}
369530c4abb9SCristian Dumitrescu 
369630c4abb9SCristian Dumitrescu 	return 0;
369730c4abb9SCristian Dumitrescu }
369830c4abb9SCristian Dumitrescu 
369954cae37eSCristian Dumitrescu static void
port_in_params_free(void * params,const char * port_type)370054cae37eSCristian Dumitrescu port_in_params_free(void *params, const char *port_type)
370154cae37eSCristian Dumitrescu {
370254cae37eSCristian Dumitrescu 	uintptr_t dev_name;
370354cae37eSCristian Dumitrescu 
370454cae37eSCristian Dumitrescu 	if (!params || !port_type)
370554cae37eSCristian Dumitrescu 		return;
370654cae37eSCristian Dumitrescu 
370754cae37eSCristian Dumitrescu 	if (!strcmp(port_type, "ethdev")) {
370854cae37eSCristian Dumitrescu 		struct rte_swx_port_ethdev_reader_params *p = params;
370954cae37eSCristian Dumitrescu 
371054cae37eSCristian Dumitrescu 		dev_name = (uintptr_t)p->dev_name;
371154cae37eSCristian Dumitrescu 	} else if (!strcmp(port_type, "ring")) {
371254cae37eSCristian Dumitrescu 		struct rte_swx_port_ring_reader_params *p = params;
371354cae37eSCristian Dumitrescu 
371454cae37eSCristian Dumitrescu 		dev_name = (uintptr_t)p->name;
371554cae37eSCristian Dumitrescu 	} else if (!strcmp(port_type, "source")) {
371654cae37eSCristian Dumitrescu 		struct rte_swx_port_source_params *p = params;
371754cae37eSCristian Dumitrescu 
371854cae37eSCristian Dumitrescu 		dev_name = (uintptr_t)p->file_name;
371954cae37eSCristian Dumitrescu 	} else
372054cae37eSCristian Dumitrescu 		dev_name = (uintptr_t)NULL;
372154cae37eSCristian Dumitrescu 
372254cae37eSCristian Dumitrescu 	free((void *)dev_name);
372354cae37eSCristian Dumitrescu 	free(params);
372454cae37eSCristian Dumitrescu }
372554cae37eSCristian Dumitrescu 
372654cae37eSCristian Dumitrescu static void
port_out_params_free(void * params,const char * port_type)372754cae37eSCristian Dumitrescu port_out_params_free(void *params, const char *port_type)
372854cae37eSCristian Dumitrescu {
372954cae37eSCristian Dumitrescu 	uintptr_t dev_name;
373054cae37eSCristian Dumitrescu 
373154cae37eSCristian Dumitrescu 	if (!params || !port_type)
373254cae37eSCristian Dumitrescu 		return;
373354cae37eSCristian Dumitrescu 
373454cae37eSCristian Dumitrescu 	if (!strcmp(port_type, "ethdev")) {
373554cae37eSCristian Dumitrescu 		struct rte_swx_port_ethdev_writer_params *p = params;
373654cae37eSCristian Dumitrescu 
373754cae37eSCristian Dumitrescu 		dev_name = (uintptr_t)p->dev_name;
373854cae37eSCristian Dumitrescu 	} else if (!strcmp(port_type, "ring")) {
373954cae37eSCristian Dumitrescu 		struct rte_swx_port_ring_writer_params *p = params;
374054cae37eSCristian Dumitrescu 
374154cae37eSCristian Dumitrescu 		dev_name = (uintptr_t)p->name;
374254cae37eSCristian Dumitrescu 	} else if (!strcmp(port_type, "sink")) {
374354cae37eSCristian Dumitrescu 		struct rte_swx_port_sink_params *p = params;
374454cae37eSCristian Dumitrescu 
374554cae37eSCristian Dumitrescu 		dev_name = (uintptr_t)p->file_name;
374654cae37eSCristian Dumitrescu 	} else
374754cae37eSCristian Dumitrescu 		dev_name = (uintptr_t)NULL;
374854cae37eSCristian Dumitrescu 
374954cae37eSCristian Dumitrescu 	free((void *)dev_name);
375054cae37eSCristian Dumitrescu 	free(params);
375154cae37eSCristian Dumitrescu }
375254cae37eSCristian Dumitrescu 
375354cae37eSCristian Dumitrescu void
pipeline_iospec_free(struct pipeline_iospec * s)375454cae37eSCristian Dumitrescu pipeline_iospec_free(struct pipeline_iospec *s)
375554cae37eSCristian Dumitrescu {
375654cae37eSCristian Dumitrescu 	uint32_t i;
375754cae37eSCristian Dumitrescu 
375854cae37eSCristian Dumitrescu 	if (!s)
375954cae37eSCristian Dumitrescu 		return;
376054cae37eSCristian Dumitrescu 
376154cae37eSCristian Dumitrescu 	/* Input ports. */
376254cae37eSCristian Dumitrescu 	for (i = 0; i < s->n_ports_in; i++) {
376354cae37eSCristian Dumitrescu 		uintptr_t name = (uintptr_t)s->port_in_type[i];
376454cae37eSCristian Dumitrescu 
376554cae37eSCristian Dumitrescu 		port_in_params_free(s->port_in_params[i], s->port_in_type[i]);
376654cae37eSCristian Dumitrescu 		free((void *)name);
376754cae37eSCristian Dumitrescu 	}
376854cae37eSCristian Dumitrescu 
376954cae37eSCristian Dumitrescu 	free(s->port_in_type);
377054cae37eSCristian Dumitrescu 	free(s->port_in_params);
377154cae37eSCristian Dumitrescu 
377254cae37eSCristian Dumitrescu 	/* Output ports. */
377354cae37eSCristian Dumitrescu 	for (i = 0; i < s->n_ports_out; i++) {
377454cae37eSCristian Dumitrescu 		uintptr_t name = (uintptr_t)s->port_out_type[i];
377554cae37eSCristian Dumitrescu 
377654cae37eSCristian Dumitrescu 		port_out_params_free(s->port_out_params[i], s->port_out_type[i]);
377754cae37eSCristian Dumitrescu 		free((void *)name);
377854cae37eSCristian Dumitrescu 	}
377954cae37eSCristian Dumitrescu 
378054cae37eSCristian Dumitrescu 	free(s->port_out_type);
378154cae37eSCristian Dumitrescu 	free(s->port_out_params);
378254cae37eSCristian Dumitrescu 
378354cae37eSCristian Dumitrescu 	free(s);
378454cae37eSCristian Dumitrescu }
378554cae37eSCristian Dumitrescu 
378654cae37eSCristian Dumitrescu static int
mirroring_parse(struct rte_swx_pipeline_mirroring_params * p,char ** tokens,uint32_t n_tokens,const char ** err_msg)378754cae37eSCristian Dumitrescu mirroring_parse(struct rte_swx_pipeline_mirroring_params *p,
378854cae37eSCristian Dumitrescu 		char **tokens,
378954cae37eSCristian Dumitrescu 		uint32_t n_tokens,
379054cae37eSCristian Dumitrescu 		const char **err_msg)
379154cae37eSCristian Dumitrescu {
379254cae37eSCristian Dumitrescu 	char *token;
379354cae37eSCristian Dumitrescu 
379454cae37eSCristian Dumitrescu 	if ((n_tokens != 4) || strcmp(tokens[0], "slots") || strcmp(tokens[2], "sessions")) {
379554cae37eSCristian Dumitrescu 		if (err_msg)
379654cae37eSCristian Dumitrescu 			*err_msg = "Invalid statement.";
379754cae37eSCristian Dumitrescu 		return -EINVAL;
379854cae37eSCristian Dumitrescu 	}
379954cae37eSCristian Dumitrescu 
380054cae37eSCristian Dumitrescu 	/* <n_slots>. */
380154cae37eSCristian Dumitrescu 	token = tokens[1];
380254cae37eSCristian Dumitrescu 	p->n_slots = strtoul(token, &token, 0);
380354cae37eSCristian Dumitrescu 	if (token[0]) {
380454cae37eSCristian Dumitrescu 		if (err_msg)
380554cae37eSCristian Dumitrescu 			*err_msg = "Invalid <n_slots> parameter.";
380654cae37eSCristian Dumitrescu 		return -EINVAL;
380754cae37eSCristian Dumitrescu 	}
380854cae37eSCristian Dumitrescu 
380954cae37eSCristian Dumitrescu 	/* <n_sessions>. */
381054cae37eSCristian Dumitrescu 	token = tokens[3];
381154cae37eSCristian Dumitrescu 	p->n_sessions = strtoul(token, &token, 0);
381254cae37eSCristian Dumitrescu 	if (token[0]) {
381354cae37eSCristian Dumitrescu 		if (err_msg)
381454cae37eSCristian Dumitrescu 			*err_msg = "Invalid <n_sessions> parameter.";
381554cae37eSCristian Dumitrescu 		return -EINVAL;
381654cae37eSCristian Dumitrescu 	}
381754cae37eSCristian Dumitrescu 
381854cae37eSCristian Dumitrescu 	return 0;
381954cae37eSCristian Dumitrescu }
382054cae37eSCristian Dumitrescu 
382154cae37eSCristian Dumitrescu static void *
port_in_ethdev_parse(char ** tokens,uint32_t n_tokens,const char ** err_msg)382254cae37eSCristian Dumitrescu port_in_ethdev_parse(char **tokens, uint32_t n_tokens, const char **err_msg)
382354cae37eSCristian Dumitrescu {
382454cae37eSCristian Dumitrescu 	struct rte_swx_port_ethdev_reader_params *p = NULL;
382554cae37eSCristian Dumitrescu 	char *token, *dev_name = NULL;
382654cae37eSCristian Dumitrescu 	uint32_t queue_id, burst_size;
382754cae37eSCristian Dumitrescu 
382854cae37eSCristian Dumitrescu 	if ((n_tokens != 5) || strcmp(tokens[1], "rxq") || strcmp(tokens[3], "bsz")) {
382954cae37eSCristian Dumitrescu 		if (err_msg)
383054cae37eSCristian Dumitrescu 			*err_msg = "Invalid statement.";
383154cae37eSCristian Dumitrescu 		return NULL;
383254cae37eSCristian Dumitrescu 	}
383354cae37eSCristian Dumitrescu 
383454cae37eSCristian Dumitrescu 	/* <queue_id>. */
383554cae37eSCristian Dumitrescu 	token = tokens[2];
383654cae37eSCristian Dumitrescu 	queue_id = strtoul(token, &token, 0);
383754cae37eSCristian Dumitrescu 	if (token[0]) {
383854cae37eSCristian Dumitrescu 		if (err_msg)
383954cae37eSCristian Dumitrescu 			*err_msg = "Invalid <queue_id> parameter.";
384054cae37eSCristian Dumitrescu 		return NULL;
384154cae37eSCristian Dumitrescu 	}
384254cae37eSCristian Dumitrescu 
384354cae37eSCristian Dumitrescu 	/* <burst_size>. */
384454cae37eSCristian Dumitrescu 	token = tokens[4];
384554cae37eSCristian Dumitrescu 	burst_size = strtoul(token, &token, 0);
384654cae37eSCristian Dumitrescu 	if (token[0]) {
384754cae37eSCristian Dumitrescu 		if (err_msg)
384854cae37eSCristian Dumitrescu 			*err_msg = "Invalid <burst_size> parameter.";
384954cae37eSCristian Dumitrescu 		return NULL;
385054cae37eSCristian Dumitrescu 	}
385154cae37eSCristian Dumitrescu 
385254cae37eSCristian Dumitrescu 	/* Memory allocation. */
385354cae37eSCristian Dumitrescu 	dev_name = strdup(tokens[0]);
385454cae37eSCristian Dumitrescu 	p = malloc(sizeof(struct rte_swx_port_ethdev_reader_params));
385554cae37eSCristian Dumitrescu 	if (!dev_name || !p) {
385654cae37eSCristian Dumitrescu 		free(dev_name);
385754cae37eSCristian Dumitrescu 		free(p);
385854cae37eSCristian Dumitrescu 
385954cae37eSCristian Dumitrescu 		if (err_msg)
386054cae37eSCristian Dumitrescu 			*err_msg = "Memory allocation failed.";
386154cae37eSCristian Dumitrescu 		return NULL;
386254cae37eSCristian Dumitrescu 	}
386354cae37eSCristian Dumitrescu 
386454cae37eSCristian Dumitrescu 	/* Initialization. */
386554cae37eSCristian Dumitrescu 	p->dev_name = dev_name;
386654cae37eSCristian Dumitrescu 	p->queue_id = queue_id;
386754cae37eSCristian Dumitrescu 	p->burst_size = burst_size;
386854cae37eSCristian Dumitrescu 
386954cae37eSCristian Dumitrescu 	return p;
387054cae37eSCristian Dumitrescu }
387154cae37eSCristian Dumitrescu 
387254cae37eSCristian Dumitrescu static void *
port_in_ring_parse(char ** tokens,uint32_t n_tokens,const char ** err_msg)387354cae37eSCristian Dumitrescu port_in_ring_parse(char **tokens, uint32_t n_tokens, const char **err_msg)
387454cae37eSCristian Dumitrescu {
387554cae37eSCristian Dumitrescu 	struct rte_swx_port_ring_reader_params *p = NULL;
387654cae37eSCristian Dumitrescu 	char *token, *name = NULL;
387754cae37eSCristian Dumitrescu 	uint32_t burst_size;
387854cae37eSCristian Dumitrescu 
387954cae37eSCristian Dumitrescu 	if ((n_tokens != 3) || strcmp(tokens[1], "bsz")) {
388054cae37eSCristian Dumitrescu 		if (err_msg)
388154cae37eSCristian Dumitrescu 			*err_msg = "Invalid statement.";
388254cae37eSCristian Dumitrescu 		return NULL;
388354cae37eSCristian Dumitrescu 	}
388454cae37eSCristian Dumitrescu 
388554cae37eSCristian Dumitrescu 	/* <burst_size>. */
388654cae37eSCristian Dumitrescu 	token = tokens[2];
388754cae37eSCristian Dumitrescu 	burst_size = strtoul(token, &token, 0);
388854cae37eSCristian Dumitrescu 	if (token[0]) {
388954cae37eSCristian Dumitrescu 		if (err_msg)
389054cae37eSCristian Dumitrescu 			*err_msg = "Invalid <burst_size> parameter.";
389154cae37eSCristian Dumitrescu 		return NULL;
389254cae37eSCristian Dumitrescu 	}
389354cae37eSCristian Dumitrescu 
389454cae37eSCristian Dumitrescu 	/* Memory allocation. */
389554cae37eSCristian Dumitrescu 	name = strdup(tokens[0]);
389654cae37eSCristian Dumitrescu 	p = malloc(sizeof(struct rte_swx_port_ring_reader_params));
389754cae37eSCristian Dumitrescu 	if (!name || !p) {
389854cae37eSCristian Dumitrescu 		free(name);
389954cae37eSCristian Dumitrescu 		free(p);
390054cae37eSCristian Dumitrescu 
390154cae37eSCristian Dumitrescu 		if (err_msg)
390254cae37eSCristian Dumitrescu 			*err_msg = "Memory allocation failed.";
390354cae37eSCristian Dumitrescu 		return NULL;
390454cae37eSCristian Dumitrescu 	}
390554cae37eSCristian Dumitrescu 
390654cae37eSCristian Dumitrescu 	/* Initialization. */
390754cae37eSCristian Dumitrescu 	p->name = name;
390854cae37eSCristian Dumitrescu 	p->burst_size = burst_size;
390954cae37eSCristian Dumitrescu 
391054cae37eSCristian Dumitrescu 	return p;
391154cae37eSCristian Dumitrescu }
391254cae37eSCristian Dumitrescu 
391354cae37eSCristian Dumitrescu static void *
port_in_source_parse(char ** tokens,uint32_t n_tokens,const char ** err_msg)391454cae37eSCristian Dumitrescu port_in_source_parse(char **tokens, uint32_t n_tokens, const char **err_msg)
391554cae37eSCristian Dumitrescu {
391654cae37eSCristian Dumitrescu 	struct rte_swx_port_source_params *p = NULL;
391754cae37eSCristian Dumitrescu 	struct rte_mempool *pool = NULL;
391854cae37eSCristian Dumitrescu 	char *token, *file_name = NULL;
391954cae37eSCristian Dumitrescu 	uint32_t n_loops, n_pkts_max;
392054cae37eSCristian Dumitrescu 
392154cae37eSCristian Dumitrescu 	if ((n_tokens != 8) ||
392254cae37eSCristian Dumitrescu 	    strcmp(tokens[0], "mempool") ||
392354cae37eSCristian Dumitrescu 	    strcmp(tokens[2], "file") ||
392454cae37eSCristian Dumitrescu 	    strcmp(tokens[4], "loop") ||
392554cae37eSCristian Dumitrescu 	    strcmp(tokens[6], "packets")) {
392654cae37eSCristian Dumitrescu 		if (err_msg)
392754cae37eSCristian Dumitrescu 			*err_msg = "Invalid statement.";
392854cae37eSCristian Dumitrescu 		return NULL;
392954cae37eSCristian Dumitrescu 	}
393054cae37eSCristian Dumitrescu 
393154cae37eSCristian Dumitrescu 	/* <mempool_name>. */
393254cae37eSCristian Dumitrescu 	pool = rte_mempool_lookup(tokens[1]);
393354cae37eSCristian Dumitrescu 	if (!pool) {
393454cae37eSCristian Dumitrescu 		if (err_msg)
393554cae37eSCristian Dumitrescu 			*err_msg = "Invalid <mempool_name> parameter.";
393654cae37eSCristian Dumitrescu 		return NULL;
393754cae37eSCristian Dumitrescu 	}
393854cae37eSCristian Dumitrescu 
393954cae37eSCristian Dumitrescu 	/* <n_loops>. */
394054cae37eSCristian Dumitrescu 	token = tokens[5];
394154cae37eSCristian Dumitrescu 	n_loops = strtoul(token, &token, 0);
394254cae37eSCristian Dumitrescu 	if (token[0]) {
394354cae37eSCristian Dumitrescu 		if (err_msg)
394454cae37eSCristian Dumitrescu 			*err_msg = "Invalid <n_loops> parameter.";
394554cae37eSCristian Dumitrescu 		return NULL;
394654cae37eSCristian Dumitrescu 	}
394754cae37eSCristian Dumitrescu 
394854cae37eSCristian Dumitrescu 	/* <n_pkts_max>. */
394954cae37eSCristian Dumitrescu 	token = tokens[7];
395054cae37eSCristian Dumitrescu 	n_pkts_max = strtoul(token, &token, 0);
395154cae37eSCristian Dumitrescu 	if (token[0]) {
395254cae37eSCristian Dumitrescu 		if (err_msg)
395354cae37eSCristian Dumitrescu 			*err_msg = "Invalid <n_pkts_max> parameter.";
395454cae37eSCristian Dumitrescu 		return NULL;
395554cae37eSCristian Dumitrescu 	}
395654cae37eSCristian Dumitrescu 
395754cae37eSCristian Dumitrescu 	/* Memory allocation. */
395854cae37eSCristian Dumitrescu 	file_name = strdup(tokens[3]);
395954cae37eSCristian Dumitrescu 	p = malloc(sizeof(struct rte_swx_port_source_params));
396054cae37eSCristian Dumitrescu 	if (!file_name || !p) {
396154cae37eSCristian Dumitrescu 		free(file_name);
396254cae37eSCristian Dumitrescu 		free(p);
396354cae37eSCristian Dumitrescu 
396454cae37eSCristian Dumitrescu 		if (err_msg)
396554cae37eSCristian Dumitrescu 			*err_msg = "Memory allocation failed.";
396654cae37eSCristian Dumitrescu 		return NULL;
396754cae37eSCristian Dumitrescu 	}
396854cae37eSCristian Dumitrescu 
396954cae37eSCristian Dumitrescu 	/* Initialization. */
397054cae37eSCristian Dumitrescu 	p->pool = pool;
397154cae37eSCristian Dumitrescu 	p->file_name = file_name;
397254cae37eSCristian Dumitrescu 	p->n_loops = n_loops;
397354cae37eSCristian Dumitrescu 	p->n_pkts_max = n_pkts_max;
397454cae37eSCristian Dumitrescu 
397554cae37eSCristian Dumitrescu 	return p;
397654cae37eSCristian Dumitrescu }
397754cae37eSCristian Dumitrescu 
397854cae37eSCristian Dumitrescu static void *
port_in_fd_parse(char ** tokens,uint32_t n_tokens,const char ** err_msg)397954cae37eSCristian Dumitrescu port_in_fd_parse(char **tokens,
398054cae37eSCristian Dumitrescu 		 uint32_t n_tokens,
398154cae37eSCristian Dumitrescu 		 const char **err_msg)
398254cae37eSCristian Dumitrescu {
398354cae37eSCristian Dumitrescu 	struct rte_swx_port_fd_reader_params *p = NULL;
398454cae37eSCristian Dumitrescu 	struct rte_mempool *mempool = NULL;
398554cae37eSCristian Dumitrescu 	char *token;
398654cae37eSCristian Dumitrescu 	uint32_t mtu, burst_size;
398754cae37eSCristian Dumitrescu 	int fd;
398854cae37eSCristian Dumitrescu 
398954cae37eSCristian Dumitrescu 	if ((n_tokens != 7) ||
399054cae37eSCristian Dumitrescu 	    strcmp(tokens[1], "mtu") ||
399154cae37eSCristian Dumitrescu 	    strcmp(tokens[3], "mempool") ||
399254cae37eSCristian Dumitrescu 	    strcmp(tokens[5], "bsz")) {
399354cae37eSCristian Dumitrescu 		if (err_msg)
399454cae37eSCristian Dumitrescu 			*err_msg = "Invalid statement.";
399554cae37eSCristian Dumitrescu 		return NULL;
399654cae37eSCristian Dumitrescu 	}
399754cae37eSCristian Dumitrescu 
399854cae37eSCristian Dumitrescu 	/* <file_descriptor>. */
399954cae37eSCristian Dumitrescu 	token = tokens[0];
400054cae37eSCristian Dumitrescu 	fd = strtol(token, &token, 0);
400154cae37eSCristian Dumitrescu 	if (token[0]) {
400254cae37eSCristian Dumitrescu 		if (err_msg)
400354cae37eSCristian Dumitrescu 			*err_msg = "Invalid <file_descriptor> parameter.";
400454cae37eSCristian Dumitrescu 		return NULL;
400554cae37eSCristian Dumitrescu 	}
400654cae37eSCristian Dumitrescu 
400754cae37eSCristian Dumitrescu 	/* <mtu>. */
400854cae37eSCristian Dumitrescu 	token = tokens[2];
400954cae37eSCristian Dumitrescu 	mtu = strtoul(token, &token, 0);
401054cae37eSCristian Dumitrescu 	if (token[0]) {
401154cae37eSCristian Dumitrescu 		if (err_msg)
401254cae37eSCristian Dumitrescu 			*err_msg = "Invalid <mtu> parameter.";
401354cae37eSCristian Dumitrescu 		return NULL;
401454cae37eSCristian Dumitrescu 	}
401554cae37eSCristian Dumitrescu 
401654cae37eSCristian Dumitrescu 	/* <mempool_name>. */
401754cae37eSCristian Dumitrescu 	mempool = rte_mempool_lookup(tokens[4]);
401854cae37eSCristian Dumitrescu 	if (!mempool) {
401954cae37eSCristian Dumitrescu 		if (err_msg)
402054cae37eSCristian Dumitrescu 			*err_msg = "Invalid <mempool_name> parameter.";
402154cae37eSCristian Dumitrescu 		return NULL;
402254cae37eSCristian Dumitrescu 	}
402354cae37eSCristian Dumitrescu 
402454cae37eSCristian Dumitrescu 	/* <burst_size>. */
402554cae37eSCristian Dumitrescu 	token = tokens[6];
402654cae37eSCristian Dumitrescu 	burst_size = strtoul(token, &token, 0);
402754cae37eSCristian Dumitrescu 	if (token[0]) {
402854cae37eSCristian Dumitrescu 		if (err_msg)
402954cae37eSCristian Dumitrescu 			*err_msg = "Invalid <burst_size> parameter.";
403054cae37eSCristian Dumitrescu 		return NULL;
403154cae37eSCristian Dumitrescu 	}
403254cae37eSCristian Dumitrescu 
403354cae37eSCristian Dumitrescu 	/* Memory allocation. */
403454cae37eSCristian Dumitrescu 	p = malloc(sizeof(struct rte_swx_port_fd_reader_params));
403554cae37eSCristian Dumitrescu 	if (!p) {
403654cae37eSCristian Dumitrescu 		if (err_msg)
403754cae37eSCristian Dumitrescu 			*err_msg = "Memory allocation failed.";
403854cae37eSCristian Dumitrescu 		return NULL;
403954cae37eSCristian Dumitrescu 	}
404054cae37eSCristian Dumitrescu 
404154cae37eSCristian Dumitrescu 	/* Initialization. */
404254cae37eSCristian Dumitrescu 	p->fd = fd;
404354cae37eSCristian Dumitrescu 	p->mtu = mtu;
404454cae37eSCristian Dumitrescu 	p->mempool = mempool;
404554cae37eSCristian Dumitrescu 	p->burst_size = burst_size;
404654cae37eSCristian Dumitrescu 
404754cae37eSCristian Dumitrescu 	return p;
404854cae37eSCristian Dumitrescu }
404954cae37eSCristian Dumitrescu 
405054cae37eSCristian Dumitrescu static void *
port_out_ethdev_parse(char ** tokens,uint32_t n_tokens,const char ** err_msg)405154cae37eSCristian Dumitrescu port_out_ethdev_parse(char **tokens, uint32_t n_tokens, const char **err_msg)
405254cae37eSCristian Dumitrescu {
405354cae37eSCristian Dumitrescu 	struct rte_swx_port_ethdev_writer_params *p = NULL;
405454cae37eSCristian Dumitrescu 	char *token, *dev_name = NULL;
405554cae37eSCristian Dumitrescu 	uint32_t queue_id, burst_size;
405654cae37eSCristian Dumitrescu 
405754cae37eSCristian Dumitrescu 	if ((n_tokens != 5) || strcmp(tokens[1], "txq") || strcmp(tokens[3], "bsz")) {
405854cae37eSCristian Dumitrescu 		if (err_msg)
405954cae37eSCristian Dumitrescu 			*err_msg = "Invalid statement.";
406054cae37eSCristian Dumitrescu 		return NULL;
406154cae37eSCristian Dumitrescu 	}
406254cae37eSCristian Dumitrescu 
406354cae37eSCristian Dumitrescu 	/* <queue_id>. */
406454cae37eSCristian Dumitrescu 	token = tokens[2];
406554cae37eSCristian Dumitrescu 	queue_id = strtoul(token, &token, 0);
406654cae37eSCristian Dumitrescu 	if (token[0]) {
406754cae37eSCristian Dumitrescu 		if (err_msg)
406854cae37eSCristian Dumitrescu 			*err_msg = "Invalid <queue_id> parameter.";
406954cae37eSCristian Dumitrescu 		return NULL;
407054cae37eSCristian Dumitrescu 	}
407154cae37eSCristian Dumitrescu 
407254cae37eSCristian Dumitrescu 	/* <burst_size>. */
407354cae37eSCristian Dumitrescu 	token = tokens[4];
407454cae37eSCristian Dumitrescu 	burst_size = strtoul(token, &token, 0);
407554cae37eSCristian Dumitrescu 	if (token[0]) {
407654cae37eSCristian Dumitrescu 		if (err_msg)
407754cae37eSCristian Dumitrescu 			*err_msg = "Invalid <burst_size> parameter.";
407854cae37eSCristian Dumitrescu 		return NULL;
407954cae37eSCristian Dumitrescu 	}
408054cae37eSCristian Dumitrescu 
408154cae37eSCristian Dumitrescu 	/* Memory allocation. */
408254cae37eSCristian Dumitrescu 	dev_name = strdup(tokens[0]);
408354cae37eSCristian Dumitrescu 	p = malloc(sizeof(struct rte_swx_port_ethdev_writer_params));
408454cae37eSCristian Dumitrescu 	if (!dev_name || !p) {
408554cae37eSCristian Dumitrescu 		free(dev_name);
408654cae37eSCristian Dumitrescu 		free(p);
408754cae37eSCristian Dumitrescu 
408854cae37eSCristian Dumitrescu 		if (err_msg)
408954cae37eSCristian Dumitrescu 			*err_msg = "Memory allocation failed.";
409054cae37eSCristian Dumitrescu 		return NULL;
409154cae37eSCristian Dumitrescu 	}
409254cae37eSCristian Dumitrescu 
409354cae37eSCristian Dumitrescu 	/* Initialization. */
409454cae37eSCristian Dumitrescu 	p->dev_name = dev_name;
409554cae37eSCristian Dumitrescu 	p->queue_id = queue_id;
409654cae37eSCristian Dumitrescu 	p->burst_size = burst_size;
409754cae37eSCristian Dumitrescu 
409854cae37eSCristian Dumitrescu 	return p;
409954cae37eSCristian Dumitrescu }
410054cae37eSCristian Dumitrescu 
410154cae37eSCristian Dumitrescu static void *
port_out_ring_parse(char ** tokens,uint32_t n_tokens,const char ** err_msg)410254cae37eSCristian Dumitrescu port_out_ring_parse(char **tokens, uint32_t n_tokens, const char **err_msg)
410354cae37eSCristian Dumitrescu {
410454cae37eSCristian Dumitrescu 	struct rte_swx_port_ring_writer_params *p = NULL;
410554cae37eSCristian Dumitrescu 	char *token, *name = NULL;
410654cae37eSCristian Dumitrescu 	uint32_t burst_size;
410754cae37eSCristian Dumitrescu 
410854cae37eSCristian Dumitrescu 	if ((n_tokens != 3) || strcmp(tokens[1], "bsz")) {
410954cae37eSCristian Dumitrescu 		if (err_msg)
411054cae37eSCristian Dumitrescu 			*err_msg = "Invalid statement.";
411154cae37eSCristian Dumitrescu 		return NULL;
411254cae37eSCristian Dumitrescu 	}
411354cae37eSCristian Dumitrescu 
411454cae37eSCristian Dumitrescu 	/* <burst_size>. */
411554cae37eSCristian Dumitrescu 	token = tokens[2];
411654cae37eSCristian Dumitrescu 	burst_size = strtoul(token, &token, 0);
411754cae37eSCristian Dumitrescu 	if (token[0]) {
411854cae37eSCristian Dumitrescu 		if (err_msg)
411954cae37eSCristian Dumitrescu 			*err_msg = "Invalid <burst_size> parameter.";
412054cae37eSCristian Dumitrescu 		return NULL;
412154cae37eSCristian Dumitrescu 	}
412254cae37eSCristian Dumitrescu 
412354cae37eSCristian Dumitrescu 	/* Memory allocation. */
412454cae37eSCristian Dumitrescu 	name = strdup(tokens[0]);
412554cae37eSCristian Dumitrescu 	p = malloc(sizeof(struct rte_swx_port_ring_writer_params));
412654cae37eSCristian Dumitrescu 	if (!name || !p) {
412754cae37eSCristian Dumitrescu 		free(name);
412854cae37eSCristian Dumitrescu 		free(p);
412954cae37eSCristian Dumitrescu 
413054cae37eSCristian Dumitrescu 		if (err_msg)
413154cae37eSCristian Dumitrescu 			*err_msg = "Memory allocation failed.";
413254cae37eSCristian Dumitrescu 		return NULL;
413354cae37eSCristian Dumitrescu 	}
413454cae37eSCristian Dumitrescu 
413554cae37eSCristian Dumitrescu 	/* Initialization. */
413654cae37eSCristian Dumitrescu 	p->name = name;
413754cae37eSCristian Dumitrescu 	p->burst_size = burst_size;
413854cae37eSCristian Dumitrescu 
413954cae37eSCristian Dumitrescu 	return p;
414054cae37eSCristian Dumitrescu }
414154cae37eSCristian Dumitrescu 
414254cae37eSCristian Dumitrescu static void *
port_out_sink_parse(char ** tokens,uint32_t n_tokens,const char ** err_msg)414354cae37eSCristian Dumitrescu port_out_sink_parse(char **tokens, uint32_t n_tokens, const char **err_msg)
414454cae37eSCristian Dumitrescu {
414554cae37eSCristian Dumitrescu 	struct rte_swx_port_sink_params *p = NULL;
414654cae37eSCristian Dumitrescu 	char *file_name = NULL;
414754cae37eSCristian Dumitrescu 	int file_name_valid = 0;
414854cae37eSCristian Dumitrescu 
414954cae37eSCristian Dumitrescu 	if ((n_tokens != 2) || strcmp(tokens[0], "file")) {
415054cae37eSCristian Dumitrescu 		if (err_msg)
415154cae37eSCristian Dumitrescu 			*err_msg = "Invalid statement.";
415254cae37eSCristian Dumitrescu 		return NULL;
415354cae37eSCristian Dumitrescu 	}
415454cae37eSCristian Dumitrescu 
415554cae37eSCristian Dumitrescu 	/* Memory allocation. */
415654cae37eSCristian Dumitrescu 	if (strcmp(tokens[1], "none")) {
415754cae37eSCristian Dumitrescu 		file_name_valid = 1;
415854cae37eSCristian Dumitrescu 		file_name = strdup(tokens[1]);
415954cae37eSCristian Dumitrescu 	}
416054cae37eSCristian Dumitrescu 
416154cae37eSCristian Dumitrescu 	p = malloc(sizeof(struct rte_swx_port_ring_writer_params));
416254cae37eSCristian Dumitrescu 	if ((file_name_valid && !file_name) || !p) {
416354cae37eSCristian Dumitrescu 		free(file_name);
416454cae37eSCristian Dumitrescu 		free(p);
416554cae37eSCristian Dumitrescu 
416654cae37eSCristian Dumitrescu 		if (err_msg)
416754cae37eSCristian Dumitrescu 			*err_msg = "Memory allocation failed.";
416854cae37eSCristian Dumitrescu 		return NULL;
416954cae37eSCristian Dumitrescu 	}
417054cae37eSCristian Dumitrescu 
417154cae37eSCristian Dumitrescu 	/* Initialization. */
417254cae37eSCristian Dumitrescu 	p->file_name = file_name;
417354cae37eSCristian Dumitrescu 
417454cae37eSCristian Dumitrescu 	return p;
417554cae37eSCristian Dumitrescu }
417654cae37eSCristian Dumitrescu 
417754cae37eSCristian Dumitrescu static void *
port_out_fd_parse(char ** tokens,uint32_t n_tokens,const char ** err_msg)417854cae37eSCristian Dumitrescu port_out_fd_parse(char **tokens,
417954cae37eSCristian Dumitrescu 		  uint32_t n_tokens,
418054cae37eSCristian Dumitrescu 		  const char **err_msg)
418154cae37eSCristian Dumitrescu {
418254cae37eSCristian Dumitrescu 	struct rte_swx_port_fd_writer_params *p = NULL;
418354cae37eSCristian Dumitrescu 	char *token;
418454cae37eSCristian Dumitrescu 	uint32_t burst_size;
418554cae37eSCristian Dumitrescu 	int fd;
418654cae37eSCristian Dumitrescu 
418754cae37eSCristian Dumitrescu 	if ((n_tokens != 3) || strcmp(tokens[1], "bsz")) {
418854cae37eSCristian Dumitrescu 		if (err_msg)
418954cae37eSCristian Dumitrescu 			*err_msg = "Invalid statement.";
419054cae37eSCristian Dumitrescu 		return NULL;
419154cae37eSCristian Dumitrescu 	}
419254cae37eSCristian Dumitrescu 
419354cae37eSCristian Dumitrescu 	/* <file_descriptor>. */
419454cae37eSCristian Dumitrescu 	token = tokens[0];
419554cae37eSCristian Dumitrescu 	fd = strtol(token, &token, 0);
419654cae37eSCristian Dumitrescu 	if (token[0]) {
419754cae37eSCristian Dumitrescu 		if (err_msg)
419854cae37eSCristian Dumitrescu 			*err_msg = "Invalid <file_descriptor> parameter.";
419954cae37eSCristian Dumitrescu 		return NULL;
420054cae37eSCristian Dumitrescu 	}
420154cae37eSCristian Dumitrescu 
420254cae37eSCristian Dumitrescu 	/* <burst_size>. */
420354cae37eSCristian Dumitrescu 	token = tokens[2];
420454cae37eSCristian Dumitrescu 	burst_size = strtoul(token, &token, 0);
420554cae37eSCristian Dumitrescu 	if (token[0]) {
420654cae37eSCristian Dumitrescu 		if (err_msg)
420754cae37eSCristian Dumitrescu 			*err_msg = "Invalid <burst_size> parameter.";
420854cae37eSCristian Dumitrescu 		return NULL;
420954cae37eSCristian Dumitrescu 	}
421054cae37eSCristian Dumitrescu 
421154cae37eSCristian Dumitrescu 	/* Memory allocation. */
421254cae37eSCristian Dumitrescu 	p = malloc(sizeof(struct rte_swx_port_fd_writer_params));
421354cae37eSCristian Dumitrescu 	if (!p) {
421454cae37eSCristian Dumitrescu 		if (err_msg)
421554cae37eSCristian Dumitrescu 			*err_msg = "Memory allocation failed.";
421654cae37eSCristian Dumitrescu 		return NULL;
421754cae37eSCristian Dumitrescu 	}
421854cae37eSCristian Dumitrescu 
421954cae37eSCristian Dumitrescu 	/* Initialization. */
422054cae37eSCristian Dumitrescu 	p->fd = fd;
422154cae37eSCristian Dumitrescu 	p->burst_size = burst_size;
422254cae37eSCristian Dumitrescu 
422354cae37eSCristian Dumitrescu 	return p;
422454cae37eSCristian Dumitrescu }
422554cae37eSCristian Dumitrescu 
422654cae37eSCristian Dumitrescu struct pipeline_iospec *
pipeline_iospec_parse(FILE * spec,uint32_t * err_line,const char ** err_msg)422754cae37eSCristian Dumitrescu pipeline_iospec_parse(FILE *spec,
422854cae37eSCristian Dumitrescu 		      uint32_t *err_line,
422954cae37eSCristian Dumitrescu 		      const char **err_msg)
423054cae37eSCristian Dumitrescu {
423154cae37eSCristian Dumitrescu 	struct pipeline_iospec *s = NULL;
423254cae37eSCristian Dumitrescu 	uint32_t n_lines = 0;
423354cae37eSCristian Dumitrescu 
423454cae37eSCristian Dumitrescu 	/* Check the input arguments. */
423554cae37eSCristian Dumitrescu 	if (!spec) {
423654cae37eSCristian Dumitrescu 		if (err_line)
423754cae37eSCristian Dumitrescu 			*err_line = n_lines;
423854cae37eSCristian Dumitrescu 		if (err_msg)
423954cae37eSCristian Dumitrescu 			*err_msg = "Invalid input argument.";
424054cae37eSCristian Dumitrescu 		goto error;
424154cae37eSCristian Dumitrescu 	}
424254cae37eSCristian Dumitrescu 
424354cae37eSCristian Dumitrescu 	/* Memory allocation. */
4244*0594ae0cSFerruh Yigit 	s = calloc(1, sizeof(struct pipeline_iospec));
424554cae37eSCristian Dumitrescu 	if (!s) {
424654cae37eSCristian Dumitrescu 		if (err_line)
424754cae37eSCristian Dumitrescu 			*err_line = n_lines;
424854cae37eSCristian Dumitrescu 		if (err_msg)
424954cae37eSCristian Dumitrescu 			*err_msg = "Memory allocation failed.";
425054cae37eSCristian Dumitrescu 		goto error;
425154cae37eSCristian Dumitrescu 	}
425254cae37eSCristian Dumitrescu 
425354cae37eSCristian Dumitrescu 	/* Initialize with the default values. */
425454cae37eSCristian Dumitrescu 	s->mirroring_params.n_slots = RTE_SWX_PACKET_MIRRORING_SLOTS_DEFAULT;
425554cae37eSCristian Dumitrescu 	s->mirroring_params.n_sessions = RTE_SWX_PACKET_MIRRORING_SESSIONS_DEFAULT;
425654cae37eSCristian Dumitrescu 
425754cae37eSCristian Dumitrescu 	for (n_lines = 1; ; n_lines++) {
425854cae37eSCristian Dumitrescu 		char line[MAX_LINE_LENGTH];
425954cae37eSCristian Dumitrescu 		char *tokens[MAX_TOKENS], *ptr = line;
426054cae37eSCristian Dumitrescu 		uint32_t n_tokens = 0;
426154cae37eSCristian Dumitrescu 
426254cae37eSCristian Dumitrescu 		/* Read next line. */
426354cae37eSCristian Dumitrescu 		if (!fgets(line, sizeof(line), spec))
426454cae37eSCristian Dumitrescu 			break;
426554cae37eSCristian Dumitrescu 
426654cae37eSCristian Dumitrescu 		/* Parse the line into tokens. */
426754cae37eSCristian Dumitrescu 		for ( ; ; ) {
426854cae37eSCristian Dumitrescu 			char *token;
426954cae37eSCristian Dumitrescu 
427054cae37eSCristian Dumitrescu 			/* Get token. */
427154cae37eSCristian Dumitrescu 			token = strtok_r(ptr, " \f\n\r\t\v", &ptr);
427254cae37eSCristian Dumitrescu 			if (!token)
427354cae37eSCristian Dumitrescu 				break;
427454cae37eSCristian Dumitrescu 
427554cae37eSCristian Dumitrescu 			/* Handle comments. */
427654cae37eSCristian Dumitrescu 			if ((token[0] == '#') ||
427754cae37eSCristian Dumitrescu 			    (token[0] == ';') ||
427854cae37eSCristian Dumitrescu 			    ((token[0] == '/') && (token[1] == '/'))) {
427954cae37eSCristian Dumitrescu 				break;
428054cae37eSCristian Dumitrescu 			}
428154cae37eSCristian Dumitrescu 
428254cae37eSCristian Dumitrescu 			/* Handle excessively long lines. */
428354cae37eSCristian Dumitrescu 			if (n_tokens >= RTE_DIM(tokens)) {
428454cae37eSCristian Dumitrescu 				if (err_line)
428554cae37eSCristian Dumitrescu 					*err_line = n_lines;
428654cae37eSCristian Dumitrescu 				if (err_msg)
428754cae37eSCristian Dumitrescu 					*err_msg = "Too many tokens.";
428854cae37eSCristian Dumitrescu 				goto error;
428954cae37eSCristian Dumitrescu 			}
429054cae37eSCristian Dumitrescu 
429154cae37eSCristian Dumitrescu 			/* Handle excessively long tokens. */
429254cae37eSCristian Dumitrescu 			if (strnlen(token, RTE_SWX_NAME_SIZE) >=
429354cae37eSCristian Dumitrescu 			    RTE_SWX_NAME_SIZE) {
429454cae37eSCristian Dumitrescu 				if (err_line)
429554cae37eSCristian Dumitrescu 					*err_line = n_lines;
429654cae37eSCristian Dumitrescu 				if (err_msg)
429754cae37eSCristian Dumitrescu 					*err_msg = "Token too big.";
429854cae37eSCristian Dumitrescu 				goto error;
429954cae37eSCristian Dumitrescu 			}
430054cae37eSCristian Dumitrescu 
430154cae37eSCristian Dumitrescu 			/* Save token. */
430254cae37eSCristian Dumitrescu 			tokens[n_tokens] = token;
430354cae37eSCristian Dumitrescu 			n_tokens++;
430454cae37eSCristian Dumitrescu 		}
430554cae37eSCristian Dumitrescu 
430654cae37eSCristian Dumitrescu 		/* Handle empty lines. */
430754cae37eSCristian Dumitrescu 		if (!n_tokens)
430854cae37eSCristian Dumitrescu 			continue;
430954cae37eSCristian Dumitrescu 
431054cae37eSCristian Dumitrescu 		/* mirroring. */
431154cae37eSCristian Dumitrescu 		if ((n_tokens >= 1) && !strcmp(tokens[0], "mirroring")) {
431254cae37eSCristian Dumitrescu 			int status = 0;
431354cae37eSCristian Dumitrescu 
431454cae37eSCristian Dumitrescu 			status = mirroring_parse(&s->mirroring_params,
431554cae37eSCristian Dumitrescu 						 &tokens[1],
431654cae37eSCristian Dumitrescu 						 n_tokens - 1,
431754cae37eSCristian Dumitrescu 						 err_msg);
431854cae37eSCristian Dumitrescu 			if (status) {
431954cae37eSCristian Dumitrescu 				if (err_line)
432054cae37eSCristian Dumitrescu 					*err_line = n_lines;
432154cae37eSCristian Dumitrescu 				goto error;
432254cae37eSCristian Dumitrescu 			}
432354cae37eSCristian Dumitrescu 
432454cae37eSCristian Dumitrescu 			continue;
432554cae37eSCristian Dumitrescu 		}
432654cae37eSCristian Dumitrescu 
432754cae37eSCristian Dumitrescu 		/* port in. */
432854cae37eSCristian Dumitrescu 		if ((n_tokens >= 4) && !strcmp(tokens[0], "port") && !strcmp(tokens[1], "in")) {
432954cae37eSCristian Dumitrescu 			char *token = tokens[2];
433054cae37eSCristian Dumitrescu 			uint32_t *new_id = NULL;
433154cae37eSCristian Dumitrescu 			const char **new_type = NULL, *port_type = NULL;
433254cae37eSCristian Dumitrescu 			void **new_params = NULL, *p = NULL;
433354cae37eSCristian Dumitrescu 			uint32_t port_id;
433454cae37eSCristian Dumitrescu 
433554cae37eSCristian Dumitrescu 			/* <port_id>. */
433654cae37eSCristian Dumitrescu 			port_id = strtoul(token, &token, 0);
433754cae37eSCristian Dumitrescu 			if (token[0]) {
433854cae37eSCristian Dumitrescu 				if (err_line)
433954cae37eSCristian Dumitrescu 					*err_line = n_lines;
434054cae37eSCristian Dumitrescu 				if (err_msg)
434154cae37eSCristian Dumitrescu 					*err_msg = "Invalid port ID.";
434254cae37eSCristian Dumitrescu 				goto error;
434354cae37eSCristian Dumitrescu 			}
434454cae37eSCristian Dumitrescu 
434554cae37eSCristian Dumitrescu 			/* <port_type>. */
434654cae37eSCristian Dumitrescu 			if (!strcmp(tokens[3], "ethdev"))
434754cae37eSCristian Dumitrescu 				p = port_in_ethdev_parse(&tokens[4], n_tokens - 4, err_msg);
434854cae37eSCristian Dumitrescu 			else if (!strcmp(tokens[3], "ring"))
434954cae37eSCristian Dumitrescu 				p = port_in_ring_parse(&tokens[4], n_tokens - 4, err_msg);
435054cae37eSCristian Dumitrescu 			else if (!strcmp(tokens[3], "source"))
435154cae37eSCristian Dumitrescu 				p = port_in_source_parse(&tokens[4], n_tokens - 4, err_msg);
435254cae37eSCristian Dumitrescu 			else if (!strcmp(tokens[3], "fd"))
435354cae37eSCristian Dumitrescu 				p = port_in_fd_parse(&tokens[4], n_tokens - 4, err_msg);
435454cae37eSCristian Dumitrescu 			else {
435554cae37eSCristian Dumitrescu 				p = NULL;
435654cae37eSCristian Dumitrescu 				if (err_msg)
435754cae37eSCristian Dumitrescu 					*err_msg = "Invalid port type.";
435854cae37eSCristian Dumitrescu 			}
435954cae37eSCristian Dumitrescu 
436054cae37eSCristian Dumitrescu 			if (!p) {
436154cae37eSCristian Dumitrescu 				if (err_line)
436254cae37eSCristian Dumitrescu 					*err_line = n_lines;
436354cae37eSCristian Dumitrescu 				goto error;
436454cae37eSCristian Dumitrescu 			}
436554cae37eSCristian Dumitrescu 
436654cae37eSCristian Dumitrescu 			/* New port. */
436754cae37eSCristian Dumitrescu 			port_type = strdup(tokens[3]);
436854cae37eSCristian Dumitrescu 			new_id = realloc(s->port_in_id,
436954cae37eSCristian Dumitrescu 					 (s->n_ports_in + 1) * sizeof(uint32_t));
437054cae37eSCristian Dumitrescu 			new_type = realloc(s->port_in_type,
437154cae37eSCristian Dumitrescu 					   (s->n_ports_in + 1) * sizeof(char *));
437254cae37eSCristian Dumitrescu 			new_params = realloc(s->port_in_params,
437354cae37eSCristian Dumitrescu 					     (s->n_ports_in + 1) * sizeof(void *));
437454cae37eSCristian Dumitrescu 			if (!port_type || !new_id || !new_type || !new_params) {
437554cae37eSCristian Dumitrescu 				uintptr_t pt = (uintptr_t)port_type;
437654cae37eSCristian Dumitrescu 
437754cae37eSCristian Dumitrescu 				port_in_params_free(p, tokens[3]);
437854cae37eSCristian Dumitrescu 				free((void *)pt);
437954cae37eSCristian Dumitrescu 				free(new_id);
438054cae37eSCristian Dumitrescu 				free(new_type);
438154cae37eSCristian Dumitrescu 				free(new_params);
438254cae37eSCristian Dumitrescu 
438354cae37eSCristian Dumitrescu 				if (err_line)
438454cae37eSCristian Dumitrescu 					*err_line = n_lines;
438554cae37eSCristian Dumitrescu 				if (err_msg)
438654cae37eSCristian Dumitrescu 					*err_msg = "Memory allocation failed.";
438754cae37eSCristian Dumitrescu 				goto error;
438854cae37eSCristian Dumitrescu 			}
438954cae37eSCristian Dumitrescu 
439054cae37eSCristian Dumitrescu 			s->port_in_id = new_id;
439154cae37eSCristian Dumitrescu 			s->port_in_type = new_type;
439254cae37eSCristian Dumitrescu 			s->port_in_params = new_params;
439354cae37eSCristian Dumitrescu 
439454cae37eSCristian Dumitrescu 			s->port_in_id[s->n_ports_in] = port_id;
439554cae37eSCristian Dumitrescu 			s->port_in_type[s->n_ports_in] = port_type;
439654cae37eSCristian Dumitrescu 			s->port_in_params[s->n_ports_in] = p;
439754cae37eSCristian Dumitrescu 			s->n_ports_in++;
439854cae37eSCristian Dumitrescu 
439954cae37eSCristian Dumitrescu 			continue;
440054cae37eSCristian Dumitrescu 		}
440154cae37eSCristian Dumitrescu 
440254cae37eSCristian Dumitrescu 		/* port out. */
440354cae37eSCristian Dumitrescu 		if ((n_tokens >= 4) && !strcmp(tokens[0], "port") && !strcmp(tokens[1], "out")) {
440454cae37eSCristian Dumitrescu 			char *token = tokens[2];
440554cae37eSCristian Dumitrescu 			uint32_t *new_id = NULL;
440654cae37eSCristian Dumitrescu 			const char **new_type = NULL, *port_type = NULL;
440754cae37eSCristian Dumitrescu 			void **new_params = NULL, *p = NULL;
440854cae37eSCristian Dumitrescu 			uint32_t port_id;
440954cae37eSCristian Dumitrescu 
441054cae37eSCristian Dumitrescu 			/* <port_id>. */
441154cae37eSCristian Dumitrescu 			port_id = strtoul(token, &token, 0);
441254cae37eSCristian Dumitrescu 			if (token[0]) {
441354cae37eSCristian Dumitrescu 				if (err_line)
441454cae37eSCristian Dumitrescu 					*err_line = n_lines;
441554cae37eSCristian Dumitrescu 				if (err_msg)
441654cae37eSCristian Dumitrescu 					*err_msg = "Invalid port ID.";
441754cae37eSCristian Dumitrescu 				goto error;
441854cae37eSCristian Dumitrescu 			}
441954cae37eSCristian Dumitrescu 
442054cae37eSCristian Dumitrescu 			/* <port_type>. */
442154cae37eSCristian Dumitrescu 			if (!strcmp(tokens[3], "ethdev"))
442254cae37eSCristian Dumitrescu 				p = port_out_ethdev_parse(&tokens[4], n_tokens - 4, err_msg);
442354cae37eSCristian Dumitrescu 			else if (!strcmp(tokens[3], "ring"))
442454cae37eSCristian Dumitrescu 				p = port_out_ring_parse(&tokens[4], n_tokens - 4, err_msg);
442554cae37eSCristian Dumitrescu 			else if (!strcmp(tokens[3], "sink"))
442654cae37eSCristian Dumitrescu 				p = port_out_sink_parse(&tokens[4], n_tokens - 4, err_msg);
442754cae37eSCristian Dumitrescu 			else if (!strcmp(tokens[3], "fd"))
442854cae37eSCristian Dumitrescu 				p = port_out_fd_parse(&tokens[4], n_tokens - 4, err_msg);
442954cae37eSCristian Dumitrescu 			else {
443054cae37eSCristian Dumitrescu 				p = NULL;
443154cae37eSCristian Dumitrescu 				if (err_msg)
443254cae37eSCristian Dumitrescu 					*err_msg = "Invalid port type.";
443354cae37eSCristian Dumitrescu 			}
443454cae37eSCristian Dumitrescu 
443554cae37eSCristian Dumitrescu 			if (!p) {
443654cae37eSCristian Dumitrescu 				if (err_line)
443754cae37eSCristian Dumitrescu 					*err_line = n_lines;
443854cae37eSCristian Dumitrescu 				goto error;
443954cae37eSCristian Dumitrescu 			}
444054cae37eSCristian Dumitrescu 
444154cae37eSCristian Dumitrescu 			/* New port. */
444254cae37eSCristian Dumitrescu 			port_type = strdup(tokens[3]);
444354cae37eSCristian Dumitrescu 			new_id = realloc(s->port_out_id,
444454cae37eSCristian Dumitrescu 					 (s->n_ports_out + 1) * sizeof(uint32_t));
444554cae37eSCristian Dumitrescu 			new_type = realloc(s->port_out_type,
444654cae37eSCristian Dumitrescu 					   (s->n_ports_out + 1) * sizeof(char *));
444754cae37eSCristian Dumitrescu 			new_params = realloc(s->port_out_params,
444854cae37eSCristian Dumitrescu 					     (s->n_ports_out + 1) * sizeof(void *));
444954cae37eSCristian Dumitrescu 			if (!port_type || !new_id || !new_type || !new_params) {
445054cae37eSCristian Dumitrescu 				uintptr_t pt = (uintptr_t)port_type;
445154cae37eSCristian Dumitrescu 
445254cae37eSCristian Dumitrescu 				port_out_params_free(p, tokens[3]);
445354cae37eSCristian Dumitrescu 				free((void *)pt);
445454cae37eSCristian Dumitrescu 				free(new_id);
445554cae37eSCristian Dumitrescu 				free(new_type);
445654cae37eSCristian Dumitrescu 				free(new_params);
445754cae37eSCristian Dumitrescu 
445854cae37eSCristian Dumitrescu 				if (err_line)
445954cae37eSCristian Dumitrescu 					*err_line = n_lines;
446054cae37eSCristian Dumitrescu 				if (err_msg)
446154cae37eSCristian Dumitrescu 					*err_msg = "Memory allocation failed.";
446254cae37eSCristian Dumitrescu 				goto error;
446354cae37eSCristian Dumitrescu 			}
446454cae37eSCristian Dumitrescu 
446554cae37eSCristian Dumitrescu 			s->port_out_id = new_id;
446654cae37eSCristian Dumitrescu 			s->port_out_type = new_type;
446754cae37eSCristian Dumitrescu 			s->port_out_params = new_params;
446854cae37eSCristian Dumitrescu 
446954cae37eSCristian Dumitrescu 			s->port_out_id[s->n_ports_out] = port_id;
447054cae37eSCristian Dumitrescu 			s->port_out_type[s->n_ports_out] = port_type;
447154cae37eSCristian Dumitrescu 			s->port_out_params[s->n_ports_out] = p;
447254cae37eSCristian Dumitrescu 			s->n_ports_out++;
447354cae37eSCristian Dumitrescu 
447454cae37eSCristian Dumitrescu 			continue;
447554cae37eSCristian Dumitrescu 		}
447654cae37eSCristian Dumitrescu 
447754cae37eSCristian Dumitrescu 		/* Anything else. */
447854cae37eSCristian Dumitrescu 		if (err_line)
447954cae37eSCristian Dumitrescu 			*err_line = n_lines;
448054cae37eSCristian Dumitrescu 		if (err_msg)
448154cae37eSCristian Dumitrescu 			*err_msg = "Unknown I/O statement.";
448254cae37eSCristian Dumitrescu 		goto error;
448354cae37eSCristian Dumitrescu 	}
448454cae37eSCristian Dumitrescu 
448554cae37eSCristian Dumitrescu 	return s;
448654cae37eSCristian Dumitrescu 
448754cae37eSCristian Dumitrescu error:
448854cae37eSCristian Dumitrescu 	pipeline_iospec_free(s);
448954cae37eSCristian Dumitrescu 
449054cae37eSCristian Dumitrescu 	return NULL;
449154cae37eSCristian Dumitrescu }
449254cae37eSCristian Dumitrescu 
449354cae37eSCristian Dumitrescu int
pipeline_iospec_configure(struct rte_swx_pipeline * p,struct pipeline_iospec * s,const char ** err_msg)449454cae37eSCristian Dumitrescu pipeline_iospec_configure(struct rte_swx_pipeline *p,
449554cae37eSCristian Dumitrescu 			  struct pipeline_iospec *s,
449654cae37eSCristian Dumitrescu 			  const char **err_msg)
449754cae37eSCristian Dumitrescu {
449854cae37eSCristian Dumitrescu 	uint32_t i;
449954cae37eSCristian Dumitrescu 	int status = 0;
450054cae37eSCristian Dumitrescu 
450154cae37eSCristian Dumitrescu 	/* Check input arguments. */
450254cae37eSCristian Dumitrescu 	if (!p || !s) {
450354cae37eSCristian Dumitrescu 		if (err_msg)
450454cae37eSCristian Dumitrescu 			*err_msg = "Invalid input argument";
450554cae37eSCristian Dumitrescu 		return -EINVAL;
450654cae37eSCristian Dumitrescu 	}
450754cae37eSCristian Dumitrescu 
450854cae37eSCristian Dumitrescu 	/* Mirroring. */
450954cae37eSCristian Dumitrescu 	status = rte_swx_pipeline_mirroring_config(p, &s->mirroring_params);
451054cae37eSCristian Dumitrescu 	if (status) {
451154cae37eSCristian Dumitrescu 		if (err_msg)
451254cae37eSCristian Dumitrescu 			*err_msg = "Pipeline mirroring configuration error.";
451354cae37eSCristian Dumitrescu 		return status;
451454cae37eSCristian Dumitrescu 	}
451554cae37eSCristian Dumitrescu 
451654cae37eSCristian Dumitrescu 	/* Input ports. */
451754cae37eSCristian Dumitrescu 	for (i = 0; i < s->n_ports_in; i++) {
451854cae37eSCristian Dumitrescu 		status = rte_swx_pipeline_port_in_config(p,
451954cae37eSCristian Dumitrescu 							 i,
452054cae37eSCristian Dumitrescu 							 s->port_in_type[i],
452154cae37eSCristian Dumitrescu 							 s->port_in_params[i]);
452254cae37eSCristian Dumitrescu 		if (status) {
452354cae37eSCristian Dumitrescu 			if (err_msg)
452454cae37eSCristian Dumitrescu 				*err_msg = "Pipeline input port configuration error.";
452554cae37eSCristian Dumitrescu 			return status;
452654cae37eSCristian Dumitrescu 		}
452754cae37eSCristian Dumitrescu 	}
452854cae37eSCristian Dumitrescu 
452954cae37eSCristian Dumitrescu 	/* Output ports. */
453054cae37eSCristian Dumitrescu 	for (i = 0; i < s->n_ports_out; i++) {
453154cae37eSCristian Dumitrescu 		status = rte_swx_pipeline_port_out_config(p,
453254cae37eSCristian Dumitrescu 							  i,
453354cae37eSCristian Dumitrescu 							  s->port_out_type[i],
453454cae37eSCristian Dumitrescu 							  s->port_out_params[i]);
453554cae37eSCristian Dumitrescu 		if (status) {
453654cae37eSCristian Dumitrescu 			if (err_msg)
453754cae37eSCristian Dumitrescu 				*err_msg = "Pipeline output port configuration error.";
453854cae37eSCristian Dumitrescu 			return status;
453954cae37eSCristian Dumitrescu 		}
454054cae37eSCristian Dumitrescu 	}
454154cae37eSCristian Dumitrescu 
454254cae37eSCristian Dumitrescu 	return 0;
454354cae37eSCristian Dumitrescu }
4544