Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2020 Intel Corporation
3 : : */
4 : : #include <stdint.h>
5 : : #include <inttypes.h>
6 : : #include <stdlib.h>
7 : : #include <stdio.h>
8 : : #include <string.h>
9 : : #include <errno.h>
10 : :
11 : : #include <rte_common.h>
12 : : #include <rte_mempool.h>
13 : :
14 : : #include <rte_swx_port_ethdev.h>
15 : : #include <rte_swx_port_ring.h>
16 : : #include <rte_swx_port_source_sink.h>
17 : : #include <rte_swx_port_fd.h>
18 : :
19 : : #include "rte_swx_pipeline_spec.h"
20 : :
21 : : #ifndef MAX_LINE_LENGTH
22 : : #define MAX_LINE_LENGTH 2048
23 : : #endif
24 : :
25 : : #ifndef MAX_TOKENS
26 : : #define MAX_TOKENS 256
27 : : #endif
28 : :
29 : : #define STRUCT_BLOCK 0
30 : : #define ACTION_BLOCK 1
31 : : #define TABLE_BLOCK 2
32 : : #define TABLE_KEY_BLOCK 3
33 : : #define TABLE_ACTIONS_BLOCK 4
34 : : #define SELECTOR_BLOCK 5
35 : : #define SELECTOR_SELECTOR_BLOCK 6
36 : : #define LEARNER_BLOCK 7
37 : : #define LEARNER_KEY_BLOCK 8
38 : : #define LEARNER_ACTIONS_BLOCK 9
39 : : #define LEARNER_TIMEOUT_BLOCK 10
40 : : #define APPLY_BLOCK 11
41 : :
42 : : /*
43 : : * extobj.
44 : : */
45 : : static void
46 : 0 : extobj_spec_free(struct extobj_spec *s)
47 : : {
48 [ # # ]: 0 : if (!s)
49 : : return;
50 : :
51 : 0 : free(s->name);
52 : 0 : s->name = NULL;
53 : :
54 : 0 : free(s->extern_type_name);
55 : 0 : s->extern_type_name = NULL;
56 : :
57 : 0 : free(s->pragma);
58 : 0 : s->pragma = NULL;
59 : : }
60 : :
61 : : static int
62 : 0 : extobj_statement_parse(struct extobj_spec *s,
63 : : char **tokens,
64 : : uint32_t n_tokens,
65 : : uint32_t n_lines,
66 : : uint32_t *err_line,
67 : : const char **err_msg)
68 : : {
69 : : /* Check format. */
70 [ # # # # ]: 0 : if (((n_tokens != 4) && (n_tokens != 6)) ||
71 [ # # # # ]: 0 : ((n_tokens == 4) && strcmp(tokens[2], "instanceof")) ||
72 [ # # ]: 0 : ((n_tokens == 6) && (strcmp(tokens[2], "instanceof") ||
73 [ # # ]: 0 : strcmp(tokens[4], "pragma")))) {
74 [ # # ]: 0 : if (err_line)
75 : 0 : *err_line = n_lines;
76 [ # # ]: 0 : if (err_msg)
77 : 0 : *err_msg = "Invalid extobj statement.";
78 : 0 : return -EINVAL;
79 : : }
80 : :
81 : : /* spec. */
82 : 0 : s->name = strdup(tokens[1]);
83 : 0 : s->extern_type_name = strdup(tokens[3]);
84 [ # # ]: 0 : s->pragma = (n_tokens == 6) ? strdup(tokens[5]) : NULL;
85 : :
86 [ # # ]: 0 : if (!s->name ||
87 [ # # # # ]: 0 : !s->extern_type_name ||
88 [ # # ]: 0 : ((n_tokens == 6) && !s->pragma)) {
89 : 0 : free(s->name);
90 : 0 : free(s->extern_type_name);
91 : 0 : free(s->pragma);
92 : :
93 [ # # ]: 0 : if (err_line)
94 : 0 : *err_line = n_lines;
95 [ # # ]: 0 : if (err_msg)
96 : 0 : *err_msg = "Memory allocation failed.";
97 : 0 : return -ENOMEM;
98 : : }
99 : :
100 : : return 0;
101 : : }
102 : :
103 : : /*
104 : : * struct.
105 : : */
106 : : static void
107 : 0 : struct_spec_free(struct struct_spec *s)
108 : : {
109 : : uint32_t i;
110 : :
111 [ # # ]: 0 : if (!s)
112 : : return;
113 : :
114 : 0 : free(s->name);
115 : 0 : s->name = NULL;
116 : :
117 [ # # ]: 0 : for (i = 0; i < s->n_fields; i++) {
118 : 0 : uintptr_t name = (uintptr_t)s->fields[i].name;
119 : :
120 : 0 : free((void *)name);
121 : : }
122 : :
123 : 0 : free(s->fields);
124 : 0 : s->fields = NULL;
125 : :
126 : 0 : s->n_fields = 0;
127 : :
128 : 0 : s->varbit = 0;
129 : : }
130 : :
131 : : static int
132 : 0 : struct_statement_parse(struct struct_spec *s,
133 : : uint32_t *block_mask,
134 : : char **tokens,
135 : : uint32_t n_tokens,
136 : : uint32_t n_lines,
137 : : uint32_t *err_line,
138 : : const char **err_msg)
139 : : {
140 : : /* Check format. */
141 [ # # # # ]: 0 : if ((n_tokens != 3) || strcmp(tokens[2], "{")) {
142 [ # # ]: 0 : if (err_line)
143 : 0 : *err_line = n_lines;
144 [ # # ]: 0 : if (err_msg)
145 : 0 : *err_msg = "Invalid struct statement.";
146 : 0 : return -EINVAL;
147 : : }
148 : :
149 : : /* spec. */
150 : 0 : s->name = strdup(tokens[1]);
151 [ # # ]: 0 : if (!s->name) {
152 [ # # ]: 0 : if (err_line)
153 : 0 : *err_line = n_lines;
154 [ # # ]: 0 : if (err_msg)
155 : 0 : *err_msg = "Memory allocation failed.";
156 : 0 : return -ENOMEM;
157 : : }
158 : :
159 : : /* block_mask. */
160 : 0 : *block_mask |= 1 << STRUCT_BLOCK;
161 : :
162 : 0 : return 0;
163 : : }
164 : :
165 : : static int
166 : 0 : struct_block_parse(struct struct_spec *s,
167 : : uint32_t *block_mask,
168 : : char **tokens,
169 : : uint32_t n_tokens,
170 : : uint32_t n_lines,
171 : : uint32_t *err_line,
172 : : const char **err_msg)
173 : : {
174 : : struct rte_swx_field_params *new_fields;
175 : 0 : char *p = tokens[0], *name = NULL;
176 : : uint32_t n_bits;
177 : : int varbit = 0, error = 0, error_size_invalid = 0, error_varbit_not_last = 0;
178 : :
179 : : /* Handle end of block. */
180 [ # # # # ]: 0 : if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
181 : 0 : *block_mask &= ~(1 << STRUCT_BLOCK);
182 : 0 : return 0;
183 : : }
184 : :
185 : : /* Check format. */
186 [ # # ]: 0 : if (n_tokens != 2) {
187 : : error = -EINVAL;
188 : 0 : goto error;
189 : : }
190 : :
191 [ # # ]: 0 : if (s->varbit) {
192 : : error = -EINVAL;
193 : : error_varbit_not_last = 1;
194 : 0 : goto error;
195 : : }
196 : :
197 [ # # ]: 0 : if (!strncmp(p, "bit<", strlen("bit<"))) {
198 : 0 : size_t len = strlen(p);
199 : :
200 [ # # # # ]: 0 : if ((len < strlen("bit< >")) || (p[len - 1] != '>')) {
201 : : error = -EINVAL;
202 : 0 : goto error;
203 : : }
204 : :
205 : : /* Remove the "bit<" and ">". */
206 : 0 : p[strlen(p) - 1] = 0;
207 : 0 : p += strlen("bit<");
208 [ # # ]: 0 : } else if (!strncmp(p, "varbit<", strlen("varbit<"))) {
209 : 0 : size_t len = strlen(p);
210 : :
211 [ # # # # ]: 0 : if ((len < strlen("varbit< >")) || (p[len - 1] != '>')) {
212 : : error = -EINVAL;
213 : 0 : goto error;
214 : : }
215 : :
216 : : /* Remove the "varbit<" and ">". */
217 : 0 : p[strlen(p) - 1] = 0;
218 : 0 : p += strlen("varbit<");
219 : :
220 : : /* Set the varbit flag. */
221 : : varbit = 1;
222 : : } else {
223 : : error = -EINVAL;
224 : 0 : goto error;
225 : : }
226 : :
227 : 0 : n_bits = strtoul(p, &p, 0);
228 [ # # # # ]: 0 : if ((p[0]) ||
229 : 0 : !n_bits ||
230 [ # # ]: 0 : (n_bits % 8)) {
231 : : error = -EINVAL;
232 : : error_size_invalid = 1;
233 : 0 : goto error;
234 : : }
235 : :
236 : : /* spec. */
237 : 0 : name = strdup(tokens[1]);
238 [ # # ]: 0 : if (!name) {
239 : : error = -ENOMEM;
240 : 0 : goto error;
241 : : }
242 : :
243 : 0 : new_fields = realloc(s->fields, (s->n_fields + 1) * sizeof(struct rte_swx_field_params));
244 [ # # ]: 0 : if (!new_fields) {
245 : : error = -ENOMEM;
246 : 0 : goto error;
247 : : }
248 : :
249 : 0 : s->fields = new_fields;
250 : 0 : s->fields[s->n_fields].name = name;
251 : 0 : s->fields[s->n_fields].n_bits = n_bits;
252 : 0 : s->n_fields++;
253 : 0 : s->varbit = varbit;
254 : :
255 : 0 : return 0;
256 : :
257 : 0 : error:
258 : 0 : free(name);
259 : :
260 [ # # ]: 0 : if (err_line)
261 : 0 : *err_line = n_lines;
262 : :
263 [ # # ]: 0 : if (err_msg) {
264 : 0 : *err_msg = "Invalid struct field statement.";
265 : :
266 [ # # ]: 0 : if ((error == -EINVAL) && error_varbit_not_last)
267 : 0 : *err_msg = "Varbit field is not the last struct field.";
268 : :
269 [ # # ]: 0 : if ((error == -EINVAL) && error_size_invalid)
270 : 0 : *err_msg = "Invalid struct field size.";
271 : :
272 [ # # ]: 0 : if (error == -ENOMEM)
273 : 0 : *err_msg = "Memory allocation failed.";
274 : : }
275 : :
276 : : return error;
277 : : }
278 : :
279 : : /*
280 : : * header.
281 : : */
282 : : static void
283 : : header_spec_free(struct header_spec *s)
284 : : {
285 : : if (!s)
286 : : return;
287 : :
288 : 0 : free(s->name);
289 : : s->name = NULL;
290 : :
291 : 0 : free(s->struct_type_name);
292 : : s->struct_type_name = NULL;
293 : : }
294 : :
295 : : static int
296 : 0 : header_statement_parse(struct header_spec *s,
297 : : char **tokens,
298 : : uint32_t n_tokens,
299 : : uint32_t n_lines,
300 : : uint32_t *err_line,
301 : : const char **err_msg)
302 : : {
303 : : /* Check format. */
304 [ # # # # ]: 0 : if ((n_tokens != 4) || strcmp(tokens[2], "instanceof")) {
305 [ # # ]: 0 : if (err_line)
306 : 0 : *err_line = n_lines;
307 [ # # ]: 0 : if (err_msg)
308 : 0 : *err_msg = "Invalid header statement.";
309 : 0 : return -EINVAL;
310 : : }
311 : :
312 : : /* spec. */
313 : 0 : s->name = strdup(tokens[1]);
314 : 0 : s->struct_type_name = strdup(tokens[3]);
315 : :
316 [ # # # # ]: 0 : if (!s->name || !s->struct_type_name) {
317 : 0 : free(s->name);
318 : 0 : free(s->struct_type_name);
319 : :
320 [ # # ]: 0 : if (err_line)
321 : 0 : *err_line = n_lines;
322 [ # # ]: 0 : if (err_msg)
323 : 0 : *err_msg = "Memory allocation failed.";
324 : 0 : return -ENOMEM;
325 : : }
326 : :
327 : : return 0;
328 : : }
329 : :
330 : : /*
331 : : * metadata.
332 : : */
333 : : static void
334 : : metadata_spec_free(struct metadata_spec *s)
335 : : {
336 : : if (!s)
337 : : return;
338 : :
339 : 0 : free(s->struct_type_name);
340 : : s->struct_type_name = NULL;
341 : : }
342 : :
343 : : static int
344 : 0 : metadata_statement_parse(struct metadata_spec *s,
345 : : char **tokens,
346 : : uint32_t n_tokens,
347 : : uint32_t n_lines,
348 : : uint32_t *err_line,
349 : : const char **err_msg)
350 : : {
351 : : /* Check format. */
352 [ # # # # ]: 0 : if ((n_tokens != 3) || strcmp(tokens[1], "instanceof")) {
353 [ # # ]: 0 : if (err_line)
354 : 0 : *err_line = n_lines;
355 [ # # ]: 0 : if (err_msg)
356 : 0 : *err_msg = "Invalid metadata statement.";
357 : 0 : return -EINVAL;
358 : : }
359 : :
360 : : /* spec. */
361 : 0 : s->struct_type_name = strdup(tokens[2]);
362 [ # # ]: 0 : if (!s->struct_type_name) {
363 [ # # ]: 0 : if (err_line)
364 : 0 : *err_line = n_lines;
365 [ # # ]: 0 : if (err_msg)
366 : 0 : *err_msg = "Memory allocation failed.";
367 : 0 : return -ENOMEM;
368 : : }
369 : :
370 : : return 0;
371 : : }
372 : :
373 : : /*
374 : : * action.
375 : : */
376 : : static void
377 : 0 : action_spec_free(struct action_spec *s)
378 : : {
379 : : uint32_t i;
380 : :
381 [ # # ]: 0 : if (!s)
382 : : return;
383 : :
384 : 0 : free(s->name);
385 : 0 : s->name = NULL;
386 : :
387 : 0 : free(s->args_struct_type_name);
388 : 0 : s->args_struct_type_name = NULL;
389 : :
390 [ # # ]: 0 : for (i = 0; i < s->n_instructions; i++) {
391 : 0 : uintptr_t instr = (uintptr_t)s->instructions[i];
392 : :
393 : 0 : free((void *)instr);
394 : : }
395 : :
396 : 0 : free(s->instructions);
397 : 0 : s->instructions = NULL;
398 : :
399 : 0 : s->n_instructions = 0;
400 : : }
401 : :
402 : : static int
403 : 0 : action_statement_parse(struct action_spec *s,
404 : : uint32_t *block_mask,
405 : : char **tokens,
406 : : uint32_t n_tokens,
407 : : uint32_t n_lines,
408 : : uint32_t *err_line,
409 : : const char **err_msg)
410 : : {
411 : : /* Check format. */
412 [ # # # # ]: 0 : if (((n_tokens != 5) && (n_tokens != 6)) ||
413 : 0 : ((n_tokens == 5) &&
414 [ # # ]: 0 : (strcmp(tokens[2], "args") ||
415 [ # # ]: 0 : strcmp(tokens[3], "none") ||
416 [ # # # # ]: 0 : strcmp(tokens[4], "{"))) ||
417 : 0 : ((n_tokens == 6) &&
418 [ # # ]: 0 : (strcmp(tokens[2], "args") ||
419 [ # # ]: 0 : strcmp(tokens[3], "instanceof") ||
420 [ # # ]: 0 : strcmp(tokens[5], "{")))) {
421 [ # # ]: 0 : if (err_line)
422 : 0 : *err_line = n_lines;
423 [ # # ]: 0 : if (err_msg)
424 : 0 : *err_msg = "Invalid action statement.";
425 : 0 : return -EINVAL;
426 : : }
427 : :
428 : : /* spec. */
429 : 0 : s->name = strdup(tokens[1]);
430 [ # # ]: 0 : s->args_struct_type_name = (n_tokens == 6) ? strdup(tokens[4]) : NULL;
431 : :
432 [ # # # # : 0 : if ((!s->name) || ((n_tokens == 6) && !s->args_struct_type_name)) {
# # ]
433 [ # # ]: 0 : if (err_line)
434 : 0 : *err_line = n_lines;
435 [ # # ]: 0 : if (err_msg)
436 : 0 : *err_msg = "Memory allocation failed.";
437 : 0 : return -ENOMEM;
438 : : }
439 : :
440 : : /* block_mask. */
441 : 0 : *block_mask |= 1 << ACTION_BLOCK;
442 : :
443 : 0 : return 0;
444 : : }
445 : :
446 : : static int
447 : 0 : action_block_parse(struct action_spec *s,
448 : : uint32_t *block_mask,
449 : : char **tokens,
450 : : uint32_t n_tokens,
451 : : uint32_t n_lines,
452 : : uint32_t *err_line,
453 : : const char **err_msg)
454 : : {
455 : : char buffer[RTE_SWX_INSTRUCTION_SIZE], *instr;
456 : : const char **new_instructions;
457 : : uint32_t i;
458 : :
459 : : /* Handle end of block. */
460 [ # # # # ]: 0 : if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
461 : 0 : *block_mask &= ~(1 << ACTION_BLOCK);
462 : 0 : return 0;
463 : : }
464 : :
465 : : /* spec. */
466 : 0 : buffer[0] = 0;
467 [ # # ]: 0 : for (i = 0; i < n_tokens; i++) {
468 [ # # ]: 0 : if (i)
469 : : strcat(buffer, " ");
470 : 0 : strcat(buffer, tokens[i]);
471 : : }
472 : :
473 : 0 : instr = strdup(buffer);
474 [ # # ]: 0 : if (!instr) {
475 [ # # ]: 0 : if (err_line)
476 : 0 : *err_line = n_lines;
477 [ # # ]: 0 : if (err_msg)
478 : 0 : *err_msg = "Memory allocation failed.";
479 : 0 : return -ENOMEM;
480 : : }
481 : :
482 : 0 : new_instructions = realloc(s->instructions,
483 : 0 : (s->n_instructions + 1) * sizeof(char *));
484 [ # # ]: 0 : if (!new_instructions) {
485 : 0 : free(instr);
486 : :
487 [ # # ]: 0 : if (err_line)
488 : 0 : *err_line = n_lines;
489 [ # # ]: 0 : if (err_msg)
490 : 0 : *err_msg = "Memory allocation failed.";
491 : 0 : return -ENOMEM;
492 : : }
493 : :
494 : 0 : s->instructions = new_instructions;
495 : 0 : s->instructions[s->n_instructions] = instr;
496 : 0 : s->n_instructions++;
497 : :
498 : 0 : return 0;
499 : : }
500 : :
501 : : /*
502 : : * table.
503 : : */
504 : : static void
505 : 0 : table_spec_free(struct table_spec *s)
506 : : {
507 : : uintptr_t default_action_name, default_action_args, hash_func_name;
508 : : uint32_t i;
509 : :
510 [ # # ]: 0 : if (!s)
511 : : return;
512 : :
513 : 0 : free(s->name);
514 : 0 : s->name = NULL;
515 : :
516 [ # # ]: 0 : for (i = 0; i < s->params.n_fields; i++) {
517 : 0 : uintptr_t name = (uintptr_t)s->params.fields[i].name;
518 : :
519 : 0 : free((void *)name);
520 : : }
521 : :
522 : 0 : free(s->params.fields);
523 : 0 : s->params.fields = NULL;
524 : :
525 : 0 : s->params.n_fields = 0;
526 : :
527 [ # # ]: 0 : for (i = 0; i < s->params.n_actions; i++) {
528 : 0 : uintptr_t name = (uintptr_t)s->params.action_names[i];
529 : :
530 : 0 : free((void *)name);
531 : : }
532 : :
533 : 0 : free(s->params.action_names);
534 : 0 : s->params.action_names = NULL;
535 : :
536 : 0 : s->params.n_actions = 0;
537 : :
538 : 0 : default_action_name = (uintptr_t)s->params.default_action_name;
539 : 0 : free((void *)default_action_name);
540 : 0 : s->params.default_action_name = NULL;
541 : :
542 : 0 : default_action_args = (uintptr_t)s->params.default_action_args;
543 : 0 : free((void *)default_action_args);
544 : 0 : s->params.default_action_args = NULL;
545 : :
546 : 0 : free(s->params.action_is_for_table_entries);
547 : 0 : s->params.action_is_for_table_entries = NULL;
548 : :
549 : 0 : free(s->params.action_is_for_default_entry);
550 : 0 : s->params.action_is_for_default_entry = NULL;
551 : :
552 : 0 : s->params.default_action_is_const = 0;
553 : :
554 : 0 : hash_func_name = (uintptr_t)s->params.hash_func_name;
555 : 0 : free((void *)hash_func_name);
556 : 0 : s->params.hash_func_name = NULL;
557 : :
558 : 0 : free(s->recommended_table_type_name);
559 : 0 : s->recommended_table_type_name = NULL;
560 : :
561 : 0 : free(s->args);
562 : 0 : s->args = NULL;
563 : :
564 : 0 : s->size = 0;
565 : : }
566 : :
567 : : static int
568 : 0 : table_key_statement_parse(uint32_t *block_mask,
569 : : char **tokens,
570 : : uint32_t n_tokens,
571 : : uint32_t n_lines,
572 : : uint32_t *err_line,
573 : : const char **err_msg)
574 : : {
575 : : /* Check format. */
576 [ # # # # ]: 0 : if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
577 [ # # ]: 0 : if (err_line)
578 : 0 : *err_line = n_lines;
579 [ # # ]: 0 : if (err_msg)
580 : 0 : *err_msg = "Invalid key statement.";
581 : 0 : return -EINVAL;
582 : : }
583 : :
584 : : /* block_mask. */
585 : 0 : *block_mask |= 1 << TABLE_KEY_BLOCK;
586 : :
587 : 0 : return 0;
588 : : }
589 : :
590 : : static int
591 : 0 : table_key_block_parse(struct table_spec *s,
592 : : uint32_t *block_mask,
593 : : char **tokens,
594 : : uint32_t n_tokens,
595 : : uint32_t n_lines,
596 : : uint32_t *err_line,
597 : : const char **err_msg)
598 : : {
599 : : struct rte_swx_match_field_params *new_fields;
600 : : enum rte_swx_table_match_type match_type = RTE_SWX_TABLE_MATCH_WILDCARD;
601 : : char *name;
602 : :
603 : : /* Handle end of block. */
604 [ # # # # ]: 0 : if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
605 : 0 : *block_mask &= ~(1 << TABLE_KEY_BLOCK);
606 : 0 : return 0;
607 : : }
608 : :
609 : : /* Check input arguments. */
610 [ # # ]: 0 : if ((n_tokens != 2) ||
611 [ # # ]: 0 : (strcmp(tokens[1], "exact") &&
612 [ # # ]: 0 : strcmp(tokens[1], "wildcard") &&
613 [ # # ]: 0 : strcmp(tokens[1], "lpm"))) {
614 [ # # ]: 0 : if (err_line)
615 : 0 : *err_line = n_lines;
616 [ # # ]: 0 : if (err_msg)
617 : 0 : *err_msg = "Invalid match field statement.";
618 : 0 : return -EINVAL;
619 : : }
620 : :
621 : : if (!strcmp(tokens[1], "wildcard"))
622 : : match_type = RTE_SWX_TABLE_MATCH_WILDCARD;
623 [ # # ]: 0 : if (!strcmp(tokens[1], "lpm"))
624 : : match_type = RTE_SWX_TABLE_MATCH_LPM;
625 [ # # ]: 0 : if (!strcmp(tokens[1], "exact"))
626 : : match_type = RTE_SWX_TABLE_MATCH_EXACT;
627 : :
628 : 0 : name = strdup(tokens[0]);
629 [ # # ]: 0 : if (!name) {
630 [ # # ]: 0 : if (err_line)
631 : 0 : *err_line = n_lines;
632 [ # # ]: 0 : if (err_msg)
633 : 0 : *err_msg = "Memory allocation failed.";
634 : 0 : return -ENOMEM;
635 : : }
636 : :
637 : 0 : new_fields = realloc(s->params.fields,
638 : 0 : (s->params.n_fields + 1) * sizeof(struct rte_swx_match_field_params));
639 [ # # ]: 0 : if (!new_fields) {
640 : 0 : free(name);
641 : :
642 [ # # ]: 0 : if (err_line)
643 : 0 : *err_line = n_lines;
644 [ # # ]: 0 : if (err_msg)
645 : 0 : *err_msg = "Memory allocation failed.";
646 : 0 : return -ENOMEM;
647 : : }
648 : :
649 : 0 : s->params.fields = new_fields;
650 : 0 : s->params.fields[s->params.n_fields].name = name;
651 : 0 : s->params.fields[s->params.n_fields].match_type = match_type;
652 : 0 : s->params.n_fields++;
653 : :
654 : 0 : return 0;
655 : : }
656 : :
657 : : static int
658 : 0 : table_actions_statement_parse(uint32_t *block_mask,
659 : : char **tokens,
660 : : uint32_t n_tokens,
661 : : uint32_t n_lines,
662 : : uint32_t *err_line,
663 : : const char **err_msg)
664 : : {
665 : : /* Check format. */
666 [ # # # # ]: 0 : if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
667 [ # # ]: 0 : if (err_line)
668 : 0 : *err_line = n_lines;
669 [ # # ]: 0 : if (err_msg)
670 : 0 : *err_msg = "Invalid actions statement.";
671 : 0 : return -EINVAL;
672 : : }
673 : :
674 : : /* block_mask. */
675 : 0 : *block_mask |= 1 << TABLE_ACTIONS_BLOCK;
676 : :
677 : 0 : return 0;
678 : : }
679 : :
680 : : static int
681 : 0 : table_actions_block_parse(struct table_spec *s,
682 : : uint32_t *block_mask,
683 : : char **tokens,
684 : : uint32_t n_tokens,
685 : : uint32_t n_lines,
686 : : uint32_t *err_line,
687 : : const char **err_msg)
688 : : {
689 : : const char **new_action_names = NULL;
690 : : int *new_action_is_for_table_entries = NULL, *new_action_is_for_default_entry = NULL;
691 : : char *name = NULL;
692 : : int action_is_for_table_entries = 1, action_is_for_default_entry = 1;
693 : :
694 : : /* Handle end of block. */
695 [ # # # # ]: 0 : if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
696 : 0 : *block_mask &= ~(1 << TABLE_ACTIONS_BLOCK);
697 : 0 : return 0;
698 : : }
699 : :
700 : : /* Check input arguments. */
701 [ # # # # ]: 0 : if ((n_tokens > 2) ||
702 [ # # ]: 0 : ((n_tokens == 2) && strcmp(tokens[1], "@tableonly") &&
703 [ # # ]: 0 : strcmp(tokens[1], "@defaultonly"))) {
704 [ # # ]: 0 : if (err_line)
705 : 0 : *err_line = n_lines;
706 [ # # ]: 0 : if (err_msg)
707 : 0 : *err_msg = "Invalid action name statement.";
708 : 0 : return -EINVAL;
709 : : }
710 : :
711 : 0 : name = strdup(tokens[0]);
712 : :
713 [ # # ]: 0 : if (n_tokens == 2) {
714 [ # # ]: 0 : if (!strcmp(tokens[1], "@tableonly"))
715 : : action_is_for_default_entry = 0;
716 : :
717 [ # # ]: 0 : if (!strcmp(tokens[1], "@defaultonly"))
718 : : action_is_for_table_entries = 0;
719 : : }
720 : :
721 : 0 : new_action_names = realloc(s->params.action_names,
722 : 0 : (s->params.n_actions + 1) * sizeof(char *));
723 : 0 : new_action_is_for_table_entries = realloc(s->params.action_is_for_table_entries,
724 : 0 : (s->params.n_actions + 1) * sizeof(int));
725 : 0 : new_action_is_for_default_entry = realloc(s->params.action_is_for_default_entry,
726 : 0 : (s->params.n_actions + 1) * sizeof(int));
727 : :
728 : 0 : if (!name ||
729 [ # # ]: 0 : !new_action_names ||
730 : 0 : !new_action_is_for_table_entries ||
731 [ # # ]: 0 : !new_action_is_for_default_entry) {
732 : 0 : free(name);
733 : 0 : free(new_action_names);
734 : 0 : free(new_action_is_for_table_entries);
735 : 0 : free(new_action_is_for_default_entry);
736 : :
737 [ # # ]: 0 : if (err_line)
738 : 0 : *err_line = n_lines;
739 [ # # ]: 0 : if (err_msg)
740 : 0 : *err_msg = "Memory allocation failed.";
741 : 0 : return -ENOMEM;
742 : : }
743 : :
744 : 0 : s->params.action_names = new_action_names;
745 : 0 : s->params.action_names[s->params.n_actions] = name;
746 : :
747 : 0 : s->params.action_is_for_table_entries = new_action_is_for_table_entries;
748 : 0 : s->params.action_is_for_table_entries[s->params.n_actions] = action_is_for_table_entries;
749 : :
750 : 0 : s->params.action_is_for_default_entry = new_action_is_for_default_entry;
751 : 0 : s->params.action_is_for_default_entry[s->params.n_actions] = action_is_for_default_entry;
752 : :
753 : 0 : s->params.n_actions++;
754 : :
755 : 0 : return 0;
756 : : }
757 : :
758 : : static int
759 : 0 : table_default_action_statement_parse(struct table_spec *s,
760 : : char **tokens,
761 : : uint32_t n_tokens,
762 : : uint32_t n_lines,
763 : : uint32_t *err_line,
764 : : const char **err_msg)
765 : : {
766 : : uint32_t i;
767 : : int status = 0, duplicate = 0;
768 : :
769 : : /* Check format. */
770 [ # # ]: 0 : if ((n_tokens < 4) ||
771 [ # # ]: 0 : strcmp(tokens[2], "args")) {
772 : : status = -EINVAL;
773 : 0 : goto error;
774 : : }
775 : :
776 [ # # ]: 0 : if (s->params.default_action_name) {
777 : : duplicate = 1;
778 : : status = -EINVAL;
779 : 0 : goto error;
780 : : }
781 : :
782 : 0 : s->params.default_action_name = strdup(tokens[1]);
783 [ # # ]: 0 : if (!s->params.default_action_name) {
784 : : status = -ENOMEM;
785 : 0 : goto error;
786 : : }
787 : :
788 [ # # ]: 0 : if (strcmp(tokens[3], "none")) {
789 : : char buffer[MAX_LINE_LENGTH];
790 : 0 : uint32_t n_tokens_args = n_tokens - 3;
791 : :
792 [ # # ]: 0 : if (!strcmp(tokens[n_tokens - 1], "const"))
793 : 0 : n_tokens_args--;
794 : :
795 [ # # ]: 0 : if (!n_tokens_args) {
796 : : status = -EINVAL;
797 : 0 : goto error;
798 : : }
799 : :
800 : 0 : buffer[0] = 0;
801 [ # # ]: 0 : for (i = 0; i < n_tokens_args; i++) {
802 [ # # ]: 0 : if (i)
803 : : strcat(buffer, " ");
804 : :
805 : 0 : strcat(buffer, tokens[3 + i]);
806 : : }
807 : :
808 : 0 : s->params.default_action_args = strdup(buffer);
809 [ # # ]: 0 : if (!s->params.default_action_args) {
810 : : status = -ENOMEM;
811 : 0 : goto error;
812 : : }
813 : : } else {
814 [ # # # # ]: 0 : if (((n_tokens != 4) && (n_tokens != 5)) ||
815 [ # # ]: 0 : ((n_tokens == 5) && (strcmp(tokens[4], "const")))) {
816 : : status = -EINVAL;
817 : 0 : goto error;
818 : : }
819 : : }
820 : :
821 [ # # ]: 0 : if (!strcmp(tokens[n_tokens - 1], "const"))
822 : 0 : s->params.default_action_is_const = 1;
823 : :
824 : : return 0;
825 : :
826 : 0 : error:
827 [ # # ]: 0 : if (err_line)
828 : 0 : *err_line = n_lines;
829 : :
830 [ # # ]: 0 : if (err_msg)
831 [ # # ]: 0 : switch (status) {
832 : 0 : case -ENOMEM:
833 : 0 : *err_msg = "Memory allocation failed.";
834 : 0 : break;
835 : :
836 : : default:
837 : : if (duplicate)
838 : : *err_msg = "Duplicate default_action statement.";
839 : :
840 : 0 : *err_msg = "Invalid default_action statement.";
841 : : }
842 : :
843 : : return status;
844 : : }
845 : :
846 : : static int
847 : 0 : table_statement_parse(struct table_spec *s,
848 : : uint32_t *block_mask,
849 : : char **tokens,
850 : : uint32_t n_tokens,
851 : : uint32_t n_lines,
852 : : uint32_t *err_line,
853 : : const char **err_msg)
854 : : {
855 : : /* Check format. */
856 [ # # # # ]: 0 : if ((n_tokens != 3) || strcmp(tokens[2], "{")) {
857 [ # # ]: 0 : if (err_line)
858 : 0 : *err_line = n_lines;
859 [ # # ]: 0 : if (err_msg)
860 : 0 : *err_msg = "Invalid table statement.";
861 : 0 : return -EINVAL;
862 : : }
863 : :
864 : : /* spec. */
865 : 0 : s->name = strdup(tokens[1]);
866 [ # # ]: 0 : if (!s->name) {
867 [ # # ]: 0 : if (err_line)
868 : 0 : *err_line = n_lines;
869 [ # # ]: 0 : if (err_msg)
870 : 0 : *err_msg = "Memory allocation failed.";
871 : 0 : return -ENOMEM;
872 : : }
873 : :
874 : : /* block_mask. */
875 : 0 : *block_mask |= 1 << TABLE_BLOCK;
876 : :
877 : 0 : return 0;
878 : : }
879 : :
880 : : static int
881 : 0 : table_block_parse(struct table_spec *s,
882 : : uint32_t *block_mask,
883 : : char **tokens,
884 : : uint32_t n_tokens,
885 : : uint32_t n_lines,
886 : : uint32_t *err_line,
887 : : const char **err_msg)
888 : : {
889 [ # # ]: 0 : if (*block_mask & (1 << TABLE_KEY_BLOCK))
890 : 0 : return table_key_block_parse(s,
891 : : block_mask,
892 : : tokens,
893 : : n_tokens,
894 : : n_lines,
895 : : err_line,
896 : : err_msg);
897 : :
898 [ # # ]: 0 : if (*block_mask & (1 << TABLE_ACTIONS_BLOCK))
899 : 0 : return table_actions_block_parse(s,
900 : : block_mask,
901 : : tokens,
902 : : n_tokens,
903 : : n_lines,
904 : : err_line,
905 : : err_msg);
906 : :
907 : : /* Handle end of block. */
908 [ # # # # ]: 0 : if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
909 : 0 : *block_mask &= ~(1 << TABLE_BLOCK);
910 : 0 : return 0;
911 : : }
912 : :
913 [ # # ]: 0 : if (!strcmp(tokens[0], "key"))
914 : 0 : return table_key_statement_parse(block_mask,
915 : : tokens,
916 : : n_tokens,
917 : : n_lines,
918 : : err_line,
919 : : err_msg);
920 : :
921 [ # # ]: 0 : if (!strcmp(tokens[0], "actions"))
922 : 0 : return table_actions_statement_parse(block_mask,
923 : : tokens,
924 : : n_tokens,
925 : : n_lines,
926 : : err_line,
927 : : err_msg);
928 : :
929 [ # # ]: 0 : if (!strcmp(tokens[0], "default_action"))
930 : 0 : return table_default_action_statement_parse(s,
931 : : tokens,
932 : : n_tokens,
933 : : n_lines,
934 : : err_line,
935 : : err_msg);
936 : :
937 [ # # ]: 0 : if (!strcmp(tokens[0], "hash")) {
938 [ # # ]: 0 : if (n_tokens != 2) {
939 [ # # ]: 0 : if (err_line)
940 : 0 : *err_line = n_lines;
941 [ # # ]: 0 : if (err_msg)
942 : 0 : *err_msg = "Invalid hash statement.";
943 : 0 : return -EINVAL;
944 : : }
945 : :
946 [ # # ]: 0 : if (s->params.hash_func_name) {
947 [ # # ]: 0 : if (err_line)
948 : 0 : *err_line = n_lines;
949 [ # # ]: 0 : if (err_msg)
950 : 0 : *err_msg = "Duplicate hash statement.";
951 : 0 : return -EINVAL;
952 : : }
953 : :
954 : 0 : s->params.hash_func_name = strdup(tokens[1]);
955 [ # # ]: 0 : if (!s->params.hash_func_name) {
956 [ # # ]: 0 : if (err_line)
957 : 0 : *err_line = n_lines;
958 [ # # ]: 0 : if (err_msg)
959 : 0 : *err_msg = "Memory allocation failed.";
960 : 0 : return -ENOMEM;
961 : : }
962 : :
963 : : return 0;
964 : : }
965 : :
966 [ # # ]: 0 : if (!strcmp(tokens[0], "instanceof")) {
967 [ # # ]: 0 : if (n_tokens != 2) {
968 [ # # ]: 0 : if (err_line)
969 : 0 : *err_line = n_lines;
970 [ # # ]: 0 : if (err_msg)
971 : 0 : *err_msg = "Invalid instanceof statement.";
972 : 0 : return -EINVAL;
973 : : }
974 : :
975 [ # # ]: 0 : if (s->recommended_table_type_name) {
976 [ # # ]: 0 : if (err_line)
977 : 0 : *err_line = n_lines;
978 [ # # ]: 0 : if (err_msg)
979 : 0 : *err_msg = "Duplicate instanceof statement.";
980 : 0 : return -EINVAL;
981 : : }
982 : :
983 : 0 : s->recommended_table_type_name = strdup(tokens[1]);
984 [ # # ]: 0 : if (!s->recommended_table_type_name) {
985 [ # # ]: 0 : if (err_line)
986 : 0 : *err_line = n_lines;
987 [ # # ]: 0 : if (err_msg)
988 : 0 : *err_msg = "Memory allocation failed.";
989 : 0 : return -ENOMEM;
990 : : }
991 : :
992 : : return 0;
993 : : }
994 : :
995 [ # # ]: 0 : if (!strcmp(tokens[0], "pragma")) {
996 [ # # ]: 0 : if (n_tokens != 2) {
997 [ # # ]: 0 : if (err_line)
998 : 0 : *err_line = n_lines;
999 [ # # ]: 0 : if (err_msg)
1000 : 0 : *err_msg = "Invalid pragma statement.";
1001 : 0 : return -EINVAL;
1002 : : }
1003 : :
1004 [ # # ]: 0 : if (s->args) {
1005 [ # # ]: 0 : if (err_line)
1006 : 0 : *err_line = n_lines;
1007 [ # # ]: 0 : if (err_msg)
1008 : 0 : *err_msg = "Duplicate pragma statement.";
1009 : 0 : return -EINVAL;
1010 : : }
1011 : :
1012 : 0 : s->args = strdup(tokens[1]);
1013 [ # # ]: 0 : if (!s->args) {
1014 [ # # ]: 0 : if (err_line)
1015 : 0 : *err_line = n_lines;
1016 [ # # ]: 0 : if (err_msg)
1017 : 0 : *err_msg = "Memory allocation failed.";
1018 : 0 : return -ENOMEM;
1019 : : }
1020 : :
1021 : : return 0;
1022 : : }
1023 : :
1024 [ # # ]: 0 : if (!strcmp(tokens[0], "size")) {
1025 : 0 : char *p = tokens[1];
1026 : :
1027 [ # # ]: 0 : if (n_tokens != 2) {
1028 [ # # ]: 0 : if (err_line)
1029 : 0 : *err_line = n_lines;
1030 [ # # ]: 0 : if (err_msg)
1031 : 0 : *err_msg = "Invalid pragma statement.";
1032 : 0 : return -EINVAL;
1033 : : }
1034 : :
1035 : 0 : s->size = strtoul(p, &p, 0);
1036 [ # # ]: 0 : if (p[0]) {
1037 [ # # ]: 0 : if (err_line)
1038 : 0 : *err_line = n_lines;
1039 [ # # ]: 0 : if (err_msg)
1040 : 0 : *err_msg = "Invalid size argument.";
1041 : 0 : return -EINVAL;
1042 : : }
1043 : :
1044 : : return 0;
1045 : : }
1046 : :
1047 : : /* Anything else. */
1048 [ # # ]: 0 : if (err_line)
1049 : 0 : *err_line = n_lines;
1050 [ # # ]: 0 : if (err_msg)
1051 : 0 : *err_msg = "Invalid statement.";
1052 : : return -EINVAL;
1053 : : }
1054 : :
1055 : : /*
1056 : : * selector.
1057 : : */
1058 : : static void
1059 : 0 : selector_spec_free(struct selector_spec *s)
1060 : : {
1061 : : uintptr_t field_name;
1062 : : uint32_t i;
1063 : :
1064 [ # # ]: 0 : if (!s)
1065 : : return;
1066 : :
1067 : : /* name. */
1068 : 0 : free(s->name);
1069 : 0 : s->name = NULL;
1070 : :
1071 : : /* params->group_id_field_name. */
1072 : 0 : field_name = (uintptr_t)s->params.group_id_field_name;
1073 : 0 : free((void *)field_name);
1074 : 0 : s->params.group_id_field_name = NULL;
1075 : :
1076 : : /* params->selector_field_names. */
1077 [ # # ]: 0 : for (i = 0; i < s->params.n_selector_fields; i++) {
1078 : 0 : field_name = (uintptr_t)s->params.selector_field_names[i];
1079 : :
1080 : 0 : free((void *)field_name);
1081 : : }
1082 : :
1083 : 0 : free(s->params.selector_field_names);
1084 : 0 : s->params.selector_field_names = NULL;
1085 : :
1086 : 0 : s->params.n_selector_fields = 0;
1087 : :
1088 : : /* params->member_id_field_name. */
1089 : 0 : field_name = (uintptr_t)s->params.member_id_field_name;
1090 : 0 : free((void *)field_name);
1091 : 0 : s->params.member_id_field_name = NULL;
1092 : :
1093 : : /* params->n_groups_max. */
1094 : 0 : s->params.n_groups_max = 0;
1095 : :
1096 : : /* params->n_members_per_group_max. */
1097 : 0 : s->params.n_members_per_group_max = 0;
1098 : : }
1099 : :
1100 : : static int
1101 : 0 : selector_statement_parse(struct selector_spec *s,
1102 : : uint32_t *block_mask,
1103 : : char **tokens,
1104 : : uint32_t n_tokens,
1105 : : uint32_t n_lines,
1106 : : uint32_t *err_line,
1107 : : const char **err_msg)
1108 : : {
1109 : : /* Check format. */
1110 [ # # # # ]: 0 : if ((n_tokens != 3) || strcmp(tokens[2], "{")) {
1111 [ # # ]: 0 : if (err_line)
1112 : 0 : *err_line = n_lines;
1113 [ # # ]: 0 : if (err_msg)
1114 : 0 : *err_msg = "Invalid selector statement.";
1115 : 0 : return -EINVAL;
1116 : : }
1117 : :
1118 : : /* spec. */
1119 : 0 : s->name = strdup(tokens[1]);
1120 [ # # ]: 0 : if (!s->name) {
1121 [ # # ]: 0 : if (err_line)
1122 : 0 : *err_line = n_lines;
1123 [ # # ]: 0 : if (err_msg)
1124 : 0 : *err_msg = "Memory allocation failed.";
1125 : 0 : return -ENOMEM;
1126 : : }
1127 : :
1128 : : /* block_mask. */
1129 : 0 : *block_mask |= 1 << SELECTOR_BLOCK;
1130 : :
1131 : 0 : return 0;
1132 : : }
1133 : :
1134 : : static int
1135 : 0 : selector_selector_statement_parse(uint32_t *block_mask,
1136 : : char **tokens,
1137 : : uint32_t n_tokens,
1138 : : uint32_t n_lines,
1139 : : uint32_t *err_line,
1140 : : const char **err_msg)
1141 : : {
1142 : : /* Check format. */
1143 [ # # # # ]: 0 : if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
1144 [ # # ]: 0 : if (err_line)
1145 : 0 : *err_line = n_lines;
1146 [ # # ]: 0 : if (err_msg)
1147 : 0 : *err_msg = "Invalid selector statement.";
1148 : 0 : return -EINVAL;
1149 : : }
1150 : :
1151 : : /* block_mask. */
1152 : 0 : *block_mask |= 1 << SELECTOR_SELECTOR_BLOCK;
1153 : :
1154 : 0 : return 0;
1155 : : }
1156 : :
1157 : : static int
1158 : 0 : selector_selector_block_parse(struct selector_spec *s,
1159 : : uint32_t *block_mask,
1160 : : char **tokens,
1161 : : uint32_t n_tokens,
1162 : : uint32_t n_lines,
1163 : : uint32_t *err_line,
1164 : : const char **err_msg)
1165 : : {
1166 : : const char **new_fields;
1167 : : char *name;
1168 : :
1169 : : /* Handle end of block. */
1170 [ # # # # ]: 0 : if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1171 : 0 : *block_mask &= ~(1 << SELECTOR_SELECTOR_BLOCK);
1172 : 0 : return 0;
1173 : : }
1174 : :
1175 : : /* Check input arguments. */
1176 [ # # ]: 0 : if (n_tokens != 1) {
1177 [ # # ]: 0 : if (err_line)
1178 : 0 : *err_line = n_lines;
1179 [ # # ]: 0 : if (err_msg)
1180 : 0 : *err_msg = "Invalid selector field statement.";
1181 : 0 : return -EINVAL;
1182 : : }
1183 : :
1184 : 0 : name = strdup(tokens[0]);
1185 [ # # ]: 0 : if (!name) {
1186 [ # # ]: 0 : if (err_line)
1187 : 0 : *err_line = n_lines;
1188 [ # # ]: 0 : if (err_msg)
1189 : 0 : *err_msg = "Memory allocation failed.";
1190 : 0 : return -ENOMEM;
1191 : : }
1192 : :
1193 : 0 : new_fields = realloc(s->params.selector_field_names,
1194 : 0 : (s->params.n_selector_fields + 1) * sizeof(char *));
1195 [ # # ]: 0 : if (!new_fields) {
1196 : 0 : free(name);
1197 : :
1198 [ # # ]: 0 : if (err_line)
1199 : 0 : *err_line = n_lines;
1200 [ # # ]: 0 : if (err_msg)
1201 : 0 : *err_msg = "Memory allocation failed.";
1202 : 0 : return -ENOMEM;
1203 : : }
1204 : :
1205 : 0 : s->params.selector_field_names = new_fields;
1206 : 0 : s->params.selector_field_names[s->params.n_selector_fields] = name;
1207 : 0 : s->params.n_selector_fields++;
1208 : :
1209 : 0 : return 0;
1210 : : }
1211 : :
1212 : : static int
1213 : 0 : selector_block_parse(struct selector_spec *s,
1214 : : uint32_t *block_mask,
1215 : : char **tokens,
1216 : : uint32_t n_tokens,
1217 : : uint32_t n_lines,
1218 : : uint32_t *err_line,
1219 : : const char **err_msg)
1220 : : {
1221 [ # # ]: 0 : if (*block_mask & (1 << SELECTOR_SELECTOR_BLOCK))
1222 : 0 : return selector_selector_block_parse(s,
1223 : : block_mask,
1224 : : tokens,
1225 : : n_tokens,
1226 : : n_lines,
1227 : : err_line,
1228 : : err_msg);
1229 : :
1230 : : /* Handle end of block. */
1231 [ # # # # ]: 0 : if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1232 : 0 : *block_mask &= ~(1 << SELECTOR_BLOCK);
1233 : 0 : return 0;
1234 : : }
1235 : :
1236 [ # # ]: 0 : if (!strcmp(tokens[0], "group_id")) {
1237 [ # # ]: 0 : if (n_tokens != 2) {
1238 [ # # ]: 0 : if (err_line)
1239 : 0 : *err_line = n_lines;
1240 [ # # ]: 0 : if (err_msg)
1241 : 0 : *err_msg = "Invalid group_id statement.";
1242 : 0 : return -EINVAL;
1243 : : }
1244 : :
1245 : 0 : s->params.group_id_field_name = strdup(tokens[1]);
1246 [ # # ]: 0 : if (!s->params.group_id_field_name) {
1247 [ # # ]: 0 : if (err_line)
1248 : 0 : *err_line = n_lines;
1249 [ # # ]: 0 : if (err_msg)
1250 : 0 : *err_msg = "Memory allocation failed.";
1251 : 0 : return -ENOMEM;
1252 : : }
1253 : :
1254 : : return 0;
1255 : : }
1256 : :
1257 [ # # ]: 0 : if (!strcmp(tokens[0], "selector"))
1258 : 0 : return selector_selector_statement_parse(block_mask,
1259 : : tokens,
1260 : : n_tokens,
1261 : : n_lines,
1262 : : err_line,
1263 : : err_msg);
1264 : :
1265 [ # # ]: 0 : if (!strcmp(tokens[0], "member_id")) {
1266 [ # # ]: 0 : if (n_tokens != 2) {
1267 [ # # ]: 0 : if (err_line)
1268 : 0 : *err_line = n_lines;
1269 [ # # ]: 0 : if (err_msg)
1270 : 0 : *err_msg = "Invalid member_id statement.";
1271 : 0 : return -EINVAL;
1272 : : }
1273 : :
1274 : 0 : s->params.member_id_field_name = strdup(tokens[1]);
1275 [ # # ]: 0 : if (!s->params.member_id_field_name) {
1276 [ # # ]: 0 : if (err_line)
1277 : 0 : *err_line = n_lines;
1278 [ # # ]: 0 : if (err_msg)
1279 : 0 : *err_msg = "Memory allocation failed.";
1280 : 0 : return -ENOMEM;
1281 : : }
1282 : :
1283 : : return 0;
1284 : : }
1285 : :
1286 [ # # ]: 0 : if (!strcmp(tokens[0], "n_groups_max")) {
1287 : 0 : char *p = tokens[1];
1288 : :
1289 [ # # ]: 0 : if (n_tokens != 2) {
1290 [ # # ]: 0 : if (err_line)
1291 : 0 : *err_line = n_lines;
1292 [ # # ]: 0 : if (err_msg)
1293 : 0 : *err_msg = "Invalid n_groups statement.";
1294 : 0 : return -EINVAL;
1295 : : }
1296 : :
1297 : 0 : s->params.n_groups_max = strtoul(p, &p, 0);
1298 [ # # ]: 0 : if (p[0]) {
1299 [ # # ]: 0 : if (err_line)
1300 : 0 : *err_line = n_lines;
1301 [ # # ]: 0 : if (err_msg)
1302 : 0 : *err_msg = "Invalid n_groups argument.";
1303 : 0 : return -EINVAL;
1304 : : }
1305 : :
1306 : : return 0;
1307 : : }
1308 : :
1309 [ # # ]: 0 : if (!strcmp(tokens[0], "n_members_per_group_max")) {
1310 : 0 : char *p = tokens[1];
1311 : :
1312 [ # # ]: 0 : if (n_tokens != 2) {
1313 [ # # ]: 0 : if (err_line)
1314 : 0 : *err_line = n_lines;
1315 [ # # ]: 0 : if (err_msg)
1316 : 0 : *err_msg = "Invalid n_members_per_group statement.";
1317 : 0 : return -EINVAL;
1318 : : }
1319 : :
1320 : 0 : s->params.n_members_per_group_max = strtoul(p, &p, 0);
1321 [ # # ]: 0 : if (p[0]) {
1322 [ # # ]: 0 : if (err_line)
1323 : 0 : *err_line = n_lines;
1324 [ # # ]: 0 : if (err_msg)
1325 : 0 : *err_msg = "Invalid n_members_per_group argument.";
1326 : 0 : return -EINVAL;
1327 : : }
1328 : :
1329 : : return 0;
1330 : : }
1331 : :
1332 : : /* Anything else. */
1333 [ # # ]: 0 : if (err_line)
1334 : 0 : *err_line = n_lines;
1335 [ # # ]: 0 : if (err_msg)
1336 : 0 : *err_msg = "Invalid statement.";
1337 : : return -EINVAL;
1338 : : }
1339 : :
1340 : : /*
1341 : : * learner.
1342 : : */
1343 : : static void
1344 : 0 : learner_spec_free(struct learner_spec *s)
1345 : : {
1346 : : uintptr_t default_action_name, default_action_args, hash_func_name;
1347 : : uint32_t i;
1348 : :
1349 [ # # ]: 0 : if (!s)
1350 : : return;
1351 : :
1352 : 0 : free(s->name);
1353 : 0 : s->name = NULL;
1354 : :
1355 [ # # ]: 0 : for (i = 0; i < s->params.n_fields; i++) {
1356 : 0 : uintptr_t name = (uintptr_t)s->params.field_names[i];
1357 : :
1358 : 0 : free((void *)name);
1359 : : }
1360 : :
1361 : 0 : free(s->params.field_names);
1362 : 0 : s->params.field_names = NULL;
1363 : :
1364 : 0 : s->params.n_fields = 0;
1365 : :
1366 [ # # ]: 0 : for (i = 0; i < s->params.n_actions; i++) {
1367 : 0 : uintptr_t name = (uintptr_t)s->params.action_names[i];
1368 : :
1369 : 0 : free((void *)name);
1370 : : }
1371 : :
1372 : 0 : free(s->params.action_names);
1373 : 0 : s->params.action_names = NULL;
1374 : :
1375 : 0 : s->params.n_actions = 0;
1376 : :
1377 : 0 : default_action_name = (uintptr_t)s->params.default_action_name;
1378 : 0 : free((void *)default_action_name);
1379 : 0 : s->params.default_action_name = NULL;
1380 : :
1381 : 0 : default_action_args = (uintptr_t)s->params.default_action_args;
1382 : 0 : free((void *)default_action_args);
1383 : 0 : s->params.default_action_args = NULL;
1384 : :
1385 : 0 : free(s->params.action_is_for_table_entries);
1386 : 0 : s->params.action_is_for_table_entries = NULL;
1387 : :
1388 : 0 : free(s->params.action_is_for_default_entry);
1389 : 0 : s->params.action_is_for_default_entry = NULL;
1390 : :
1391 : 0 : s->params.default_action_is_const = 0;
1392 : :
1393 : 0 : hash_func_name = (uintptr_t)s->params.hash_func_name;
1394 : 0 : free((void *)hash_func_name);
1395 : 0 : s->params.hash_func_name = NULL;
1396 : :
1397 : 0 : s->size = 0;
1398 : :
1399 : 0 : free(s->timeout);
1400 : 0 : s->timeout = NULL;
1401 : :
1402 : 0 : s->n_timeouts = 0;
1403 : : }
1404 : :
1405 : : static int
1406 : 0 : learner_key_statement_parse(uint32_t *block_mask,
1407 : : char **tokens,
1408 : : uint32_t n_tokens,
1409 : : uint32_t n_lines,
1410 : : uint32_t *err_line,
1411 : : const char **err_msg)
1412 : : {
1413 : : /* Check format. */
1414 [ # # # # ]: 0 : if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
1415 [ # # ]: 0 : if (err_line)
1416 : 0 : *err_line = n_lines;
1417 [ # # ]: 0 : if (err_msg)
1418 : 0 : *err_msg = "Invalid key statement.";
1419 : 0 : return -EINVAL;
1420 : : }
1421 : :
1422 : : /* block_mask. */
1423 : 0 : *block_mask |= 1 << LEARNER_KEY_BLOCK;
1424 : :
1425 : 0 : return 0;
1426 : : }
1427 : :
1428 : : static int
1429 : 0 : learner_key_block_parse(struct learner_spec *s,
1430 : : uint32_t *block_mask,
1431 : : char **tokens,
1432 : : uint32_t n_tokens,
1433 : : uint32_t n_lines,
1434 : : uint32_t *err_line,
1435 : : const char **err_msg)
1436 : : {
1437 : : const char **new_field_names = NULL;
1438 : : char *field_name = NULL;
1439 : :
1440 : : /* Handle end of block. */
1441 [ # # # # ]: 0 : if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1442 : 0 : *block_mask &= ~(1 << LEARNER_KEY_BLOCK);
1443 : 0 : return 0;
1444 : : }
1445 : :
1446 : : /* Check input arguments. */
1447 [ # # ]: 0 : if (n_tokens != 1) {
1448 [ # # ]: 0 : if (err_line)
1449 : 0 : *err_line = n_lines;
1450 [ # # ]: 0 : if (err_msg)
1451 : 0 : *err_msg = "Invalid match field statement.";
1452 : 0 : return -EINVAL;
1453 : : }
1454 : :
1455 : 0 : field_name = strdup(tokens[0]);
1456 : 0 : new_field_names = realloc(s->params.field_names, (s->params.n_fields + 1) * sizeof(char *));
1457 [ # # ]: 0 : if (!field_name || !new_field_names) {
1458 : 0 : free(field_name);
1459 : 0 : free(new_field_names);
1460 : :
1461 [ # # ]: 0 : if (err_line)
1462 : 0 : *err_line = n_lines;
1463 [ # # ]: 0 : if (err_msg)
1464 : 0 : *err_msg = "Memory allocation failed.";
1465 : 0 : return -ENOMEM;
1466 : : }
1467 : :
1468 : 0 : s->params.field_names = new_field_names;
1469 : 0 : s->params.field_names[s->params.n_fields] = field_name;
1470 : 0 : s->params.n_fields++;
1471 : :
1472 : 0 : return 0;
1473 : : }
1474 : :
1475 : : static int
1476 : 0 : learner_actions_statement_parse(uint32_t *block_mask,
1477 : : char **tokens,
1478 : : uint32_t n_tokens,
1479 : : uint32_t n_lines,
1480 : : uint32_t *err_line,
1481 : : const char **err_msg)
1482 : : {
1483 : : /* Check format. */
1484 [ # # # # ]: 0 : if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
1485 [ # # ]: 0 : if (err_line)
1486 : 0 : *err_line = n_lines;
1487 [ # # ]: 0 : if (err_msg)
1488 : 0 : *err_msg = "Invalid actions statement.";
1489 : 0 : return -EINVAL;
1490 : : }
1491 : :
1492 : : /* block_mask. */
1493 : 0 : *block_mask |= 1 << LEARNER_ACTIONS_BLOCK;
1494 : :
1495 : 0 : return 0;
1496 : : }
1497 : :
1498 : : static int
1499 : 0 : learner_actions_block_parse(struct learner_spec *s,
1500 : : uint32_t *block_mask,
1501 : : char **tokens,
1502 : : uint32_t n_tokens,
1503 : : uint32_t n_lines,
1504 : : uint32_t *err_line,
1505 : : const char **err_msg)
1506 : : {
1507 : : const char **new_action_names = NULL;
1508 : : int *new_action_is_for_table_entries = NULL, *new_action_is_for_default_entry = NULL;
1509 : : char *name = NULL;
1510 : : int action_is_for_table_entries = 1, action_is_for_default_entry = 1;
1511 : :
1512 : : /* Handle end of block. */
1513 [ # # # # ]: 0 : if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1514 : 0 : *block_mask &= ~(1 << LEARNER_ACTIONS_BLOCK);
1515 : 0 : return 0;
1516 : : }
1517 : :
1518 : : /* Check input arguments. */
1519 [ # # # # ]: 0 : if ((n_tokens > 2) ||
1520 [ # # ]: 0 : ((n_tokens == 2) && strcmp(tokens[1], "@tableonly") &&
1521 [ # # ]: 0 : strcmp(tokens[1], "@defaultonly"))) {
1522 [ # # ]: 0 : if (err_line)
1523 : 0 : *err_line = n_lines;
1524 [ # # ]: 0 : if (err_msg)
1525 : 0 : *err_msg = "Invalid action name statement.";
1526 : 0 : return -EINVAL;
1527 : : }
1528 : :
1529 : 0 : name = strdup(tokens[0]);
1530 : :
1531 [ # # ]: 0 : if (n_tokens == 2) {
1532 [ # # ]: 0 : if (!strcmp(tokens[1], "@tableonly"))
1533 : : action_is_for_default_entry = 0;
1534 : :
1535 [ # # ]: 0 : if (!strcmp(tokens[1], "@defaultonly"))
1536 : : action_is_for_table_entries = 0;
1537 : : }
1538 : :
1539 : 0 : new_action_names = realloc(s->params.action_names,
1540 : 0 : (s->params.n_actions + 1) * sizeof(char *));
1541 : 0 : new_action_is_for_table_entries = realloc(s->params.action_is_for_table_entries,
1542 : 0 : (s->params.n_actions + 1) * sizeof(int));
1543 : 0 : new_action_is_for_default_entry = realloc(s->params.action_is_for_default_entry,
1544 : 0 : (s->params.n_actions + 1) * sizeof(int));
1545 : :
1546 : 0 : if (!name ||
1547 [ # # ]: 0 : !new_action_names ||
1548 : 0 : !new_action_is_for_table_entries ||
1549 [ # # ]: 0 : !new_action_is_for_default_entry) {
1550 : 0 : free(name);
1551 : 0 : free(new_action_names);
1552 : 0 : free(new_action_is_for_table_entries);
1553 : 0 : free(new_action_is_for_default_entry);
1554 : :
1555 [ # # ]: 0 : if (err_line)
1556 : 0 : *err_line = n_lines;
1557 [ # # ]: 0 : if (err_msg)
1558 : 0 : *err_msg = "Memory allocation failed.";
1559 : 0 : return -ENOMEM;
1560 : : }
1561 : :
1562 : 0 : s->params.action_names = new_action_names;
1563 : 0 : s->params.action_names[s->params.n_actions] = name;
1564 : :
1565 : 0 : s->params.action_is_for_table_entries = new_action_is_for_table_entries;
1566 : 0 : s->params.action_is_for_table_entries[s->params.n_actions] = action_is_for_table_entries;
1567 : :
1568 : 0 : s->params.action_is_for_default_entry = new_action_is_for_default_entry;
1569 : 0 : s->params.action_is_for_default_entry[s->params.n_actions] = action_is_for_default_entry;
1570 : :
1571 : 0 : s->params.n_actions++;
1572 : :
1573 : 0 : return 0;
1574 : : }
1575 : :
1576 : : static int
1577 : 0 : learner_default_action_statement_parse(struct learner_spec *s,
1578 : : char **tokens,
1579 : : uint32_t n_tokens,
1580 : : uint32_t n_lines,
1581 : : uint32_t *err_line,
1582 : : const char **err_msg)
1583 : : {
1584 : : uint32_t i;
1585 : : int status = 0, duplicate = 0;
1586 : :
1587 : : /* Check format. */
1588 [ # # ]: 0 : if ((n_tokens < 4) ||
1589 [ # # ]: 0 : strcmp(tokens[2], "args")) {
1590 : : status = -EINVAL;
1591 : 0 : goto error;
1592 : : }
1593 : :
1594 [ # # ]: 0 : if (s->params.default_action_name) {
1595 : : duplicate = 1;
1596 : : status = -EINVAL;
1597 : 0 : goto error;
1598 : : }
1599 : :
1600 : 0 : s->params.default_action_name = strdup(tokens[1]);
1601 [ # # ]: 0 : if (!s->params.default_action_name) {
1602 : : status = -ENOMEM;
1603 : 0 : goto error;
1604 : : }
1605 : :
1606 [ # # ]: 0 : if (strcmp(tokens[3], "none")) {
1607 : : char buffer[MAX_LINE_LENGTH];
1608 : 0 : uint32_t n_tokens_args = n_tokens - 3;
1609 : :
1610 [ # # ]: 0 : if (!strcmp(tokens[n_tokens - 1], "const"))
1611 : 0 : n_tokens_args--;
1612 : :
1613 [ # # ]: 0 : if (!n_tokens_args) {
1614 : : status = -EINVAL;
1615 : 0 : goto error;
1616 : : }
1617 : :
1618 : 0 : buffer[0] = 0;
1619 [ # # ]: 0 : for (i = 0; i < n_tokens_args; i++) {
1620 [ # # ]: 0 : if (i)
1621 : : strcat(buffer, " ");
1622 : :
1623 : 0 : strcat(buffer, tokens[3 + i]);
1624 : : }
1625 : :
1626 : 0 : s->params.default_action_args = strdup(buffer);
1627 [ # # ]: 0 : if (!s->params.default_action_args) {
1628 : : status = -ENOMEM;
1629 : 0 : goto error;
1630 : : }
1631 : : } else {
1632 [ # # # # ]: 0 : if (((n_tokens != 4) && (n_tokens != 5)) ||
1633 [ # # ]: 0 : ((n_tokens == 5) && (strcmp(tokens[4], "const")))) {
1634 : : status = -EINVAL;
1635 : 0 : goto error;
1636 : : }
1637 : : }
1638 : :
1639 [ # # ]: 0 : if (!strcmp(tokens[n_tokens - 1], "const"))
1640 : 0 : s->params.default_action_is_const = 1;
1641 : :
1642 : : return 0;
1643 : :
1644 : 0 : error:
1645 [ # # ]: 0 : if (err_line)
1646 : 0 : *err_line = n_lines;
1647 : :
1648 [ # # ]: 0 : if (err_msg)
1649 [ # # ]: 0 : switch (status) {
1650 : 0 : case -ENOMEM:
1651 : 0 : *err_msg = "Memory allocation failed.";
1652 : 0 : break;
1653 : :
1654 : : default:
1655 : : if (duplicate)
1656 : : *err_msg = "Duplicate default_action statement.";
1657 : :
1658 : 0 : *err_msg = "Invalid default_action statement.";
1659 : : }
1660 : :
1661 : : return status;
1662 : : }
1663 : :
1664 : : static int
1665 : 0 : learner_timeout_statement_parse(uint32_t *block_mask,
1666 : : char **tokens,
1667 : : uint32_t n_tokens,
1668 : : uint32_t n_lines,
1669 : : uint32_t *err_line,
1670 : : const char **err_msg)
1671 : : {
1672 : : /* Check format. */
1673 [ # # # # ]: 0 : if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
1674 [ # # ]: 0 : if (err_line)
1675 : 0 : *err_line = n_lines;
1676 [ # # ]: 0 : if (err_msg)
1677 : 0 : *err_msg = "Invalid timeout statement.";
1678 : 0 : return -EINVAL;
1679 : : }
1680 : :
1681 : : /* block_mask. */
1682 : 0 : *block_mask |= 1 << LEARNER_TIMEOUT_BLOCK;
1683 : :
1684 : 0 : return 0;
1685 : : }
1686 : :
1687 : : static int
1688 : 0 : learner_timeout_block_parse(struct learner_spec *s,
1689 : : uint32_t *block_mask,
1690 : : char **tokens,
1691 : : uint32_t n_tokens,
1692 : : uint32_t n_lines,
1693 : : uint32_t *err_line,
1694 : : const char **err_msg)
1695 : : {
1696 : : uint32_t *new_timeout = NULL;
1697 : : char *str;
1698 : : uint32_t val;
1699 : : int status = 0;
1700 : :
1701 : : /* Handle end of block. */
1702 [ # # # # ]: 0 : if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1703 : 0 : *block_mask &= ~(1 << LEARNER_TIMEOUT_BLOCK);
1704 : 0 : return 0;
1705 : : }
1706 : :
1707 : : /* Check input arguments. */
1708 [ # # ]: 0 : if (n_tokens != 1) {
1709 : : status = -EINVAL;
1710 : 0 : goto error;
1711 : : }
1712 : :
1713 : 0 : str = tokens[0];
1714 : 0 : val = strtoul(str, &str, 0);
1715 [ # # ]: 0 : if (str[0]) {
1716 : : status = -EINVAL;
1717 : 0 : goto error;
1718 : : }
1719 : :
1720 : 0 : new_timeout = realloc(s->timeout, (s->n_timeouts + 1) * sizeof(uint32_t));
1721 [ # # ]: 0 : if (!new_timeout) {
1722 : : status = -ENOMEM;
1723 : 0 : goto error;
1724 : : }
1725 : :
1726 : 0 : s->timeout = new_timeout;
1727 : 0 : s->timeout[s->n_timeouts] = val;
1728 : 0 : s->n_timeouts++;
1729 : :
1730 : 0 : return 0;
1731 : :
1732 : 0 : error:
1733 : : free(new_timeout);
1734 : :
1735 [ # # ]: 0 : if (err_line)
1736 : 0 : *err_line = n_lines;
1737 : :
1738 [ # # ]: 0 : if (err_msg)
1739 [ # # ]: 0 : switch (status) {
1740 : 0 : case -ENOMEM:
1741 : 0 : *err_msg = "Memory allocation failed.";
1742 : 0 : break;
1743 : :
1744 : 0 : default:
1745 : 0 : *err_msg = "Invalid timeout value statement.";
1746 : 0 : break;
1747 : : }
1748 : :
1749 : : return status;
1750 : : }
1751 : :
1752 : :
1753 : : static int
1754 : 0 : learner_statement_parse(struct learner_spec *s,
1755 : : uint32_t *block_mask,
1756 : : char **tokens,
1757 : : uint32_t n_tokens,
1758 : : uint32_t n_lines,
1759 : : uint32_t *err_line,
1760 : : const char **err_msg)
1761 : : {
1762 : : /* Check format. */
1763 [ # # # # ]: 0 : if ((n_tokens != 3) || strcmp(tokens[2], "{")) {
1764 [ # # ]: 0 : if (err_line)
1765 : 0 : *err_line = n_lines;
1766 [ # # ]: 0 : if (err_msg)
1767 : 0 : *err_msg = "Invalid learner statement.";
1768 : 0 : return -EINVAL;
1769 : : }
1770 : :
1771 : : /* spec. */
1772 : 0 : s->name = strdup(tokens[1]);
1773 [ # # ]: 0 : if (!s->name) {
1774 [ # # ]: 0 : if (err_line)
1775 : 0 : *err_line = n_lines;
1776 [ # # ]: 0 : if (err_msg)
1777 : 0 : *err_msg = "Memory allocation failed.";
1778 : 0 : return -ENOMEM;
1779 : : }
1780 : :
1781 : : /* block_mask. */
1782 : 0 : *block_mask |= 1 << LEARNER_BLOCK;
1783 : :
1784 : 0 : return 0;
1785 : : }
1786 : :
1787 : : static int
1788 : 0 : learner_block_parse(struct learner_spec *s,
1789 : : uint32_t *block_mask,
1790 : : char **tokens,
1791 : : uint32_t n_tokens,
1792 : : uint32_t n_lines,
1793 : : uint32_t *err_line,
1794 : : const char **err_msg)
1795 : : {
1796 [ # # ]: 0 : if (*block_mask & (1 << LEARNER_KEY_BLOCK))
1797 : 0 : return learner_key_block_parse(s,
1798 : : block_mask,
1799 : : tokens,
1800 : : n_tokens,
1801 : : n_lines,
1802 : : err_line,
1803 : : err_msg);
1804 : :
1805 [ # # ]: 0 : if (*block_mask & (1 << LEARNER_ACTIONS_BLOCK))
1806 : 0 : return learner_actions_block_parse(s,
1807 : : block_mask,
1808 : : tokens,
1809 : : n_tokens,
1810 : : n_lines,
1811 : : err_line,
1812 : : err_msg);
1813 : :
1814 [ # # ]: 0 : if (*block_mask & (1 << LEARNER_TIMEOUT_BLOCK))
1815 : 0 : return learner_timeout_block_parse(s,
1816 : : block_mask,
1817 : : tokens,
1818 : : n_tokens,
1819 : : n_lines,
1820 : : err_line,
1821 : : err_msg);
1822 : :
1823 : : /* Handle end of block. */
1824 [ # # # # ]: 0 : if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1825 : 0 : *block_mask &= ~(1 << LEARNER_BLOCK);
1826 : 0 : return 0;
1827 : : }
1828 : :
1829 [ # # ]: 0 : if (!strcmp(tokens[0], "key"))
1830 : 0 : return learner_key_statement_parse(block_mask,
1831 : : tokens,
1832 : : n_tokens,
1833 : : n_lines,
1834 : : err_line,
1835 : : err_msg);
1836 : :
1837 [ # # ]: 0 : if (!strcmp(tokens[0], "actions"))
1838 : 0 : return learner_actions_statement_parse(block_mask,
1839 : : tokens,
1840 : : n_tokens,
1841 : : n_lines,
1842 : : err_line,
1843 : : err_msg);
1844 : :
1845 [ # # ]: 0 : if (!strcmp(tokens[0], "default_action"))
1846 : 0 : return learner_default_action_statement_parse(s,
1847 : : tokens,
1848 : : n_tokens,
1849 : : n_lines,
1850 : : err_line,
1851 : : err_msg);
1852 : :
1853 [ # # ]: 0 : if (!strcmp(tokens[0], "hash")) {
1854 [ # # ]: 0 : if (n_tokens != 2) {
1855 [ # # ]: 0 : if (err_line)
1856 : 0 : *err_line = n_lines;
1857 [ # # ]: 0 : if (err_msg)
1858 : 0 : *err_msg = "Invalid hash statement.";
1859 : 0 : return -EINVAL;
1860 : : }
1861 : :
1862 [ # # ]: 0 : if (s->params.hash_func_name) {
1863 [ # # ]: 0 : if (err_line)
1864 : 0 : *err_line = n_lines;
1865 [ # # ]: 0 : if (err_msg)
1866 : 0 : *err_msg = "Duplicate hash statement.";
1867 : 0 : return -EINVAL;
1868 : : }
1869 : :
1870 : 0 : s->params.hash_func_name = strdup(tokens[1]);
1871 [ # # ]: 0 : if (!s->params.hash_func_name) {
1872 [ # # ]: 0 : if (err_line)
1873 : 0 : *err_line = n_lines;
1874 [ # # ]: 0 : if (err_msg)
1875 : 0 : *err_msg = "Memory allocation failed.";
1876 : 0 : return -ENOMEM;
1877 : : }
1878 : :
1879 : : return 0;
1880 : : }
1881 : :
1882 [ # # ]: 0 : if (!strcmp(tokens[0], "size")) {
1883 : 0 : char *p = tokens[1];
1884 : :
1885 [ # # ]: 0 : if (n_tokens != 2) {
1886 [ # # ]: 0 : if (err_line)
1887 : 0 : *err_line = n_lines;
1888 [ # # ]: 0 : if (err_msg)
1889 : 0 : *err_msg = "Invalid size statement.";
1890 : 0 : return -EINVAL;
1891 : : }
1892 : :
1893 : 0 : s->size = strtoul(p, &p, 0);
1894 [ # # ]: 0 : if (p[0]) {
1895 [ # # ]: 0 : if (err_line)
1896 : 0 : *err_line = n_lines;
1897 [ # # ]: 0 : if (err_msg)
1898 : 0 : *err_msg = "Invalid size argument.";
1899 : 0 : return -EINVAL;
1900 : : }
1901 : :
1902 : : return 0;
1903 : : }
1904 : :
1905 [ # # ]: 0 : if (!strcmp(tokens[0], "timeout"))
1906 : 0 : return learner_timeout_statement_parse(block_mask,
1907 : : tokens,
1908 : : n_tokens,
1909 : : n_lines,
1910 : : err_line,
1911 : : err_msg);
1912 : :
1913 : : /* Anything else. */
1914 [ # # ]: 0 : if (err_line)
1915 : 0 : *err_line = n_lines;
1916 [ # # ]: 0 : if (err_msg)
1917 : 0 : *err_msg = "Invalid statement.";
1918 : : return -EINVAL;
1919 : : }
1920 : :
1921 : : /*
1922 : : * regarray.
1923 : : */
1924 : : static void
1925 : : regarray_spec_free(struct regarray_spec *s)
1926 : : {
1927 : : if (!s)
1928 : : return;
1929 : :
1930 : 0 : free(s->name);
1931 : : s->name = NULL;
1932 : : }
1933 : :
1934 : : static int
1935 : 0 : regarray_statement_parse(struct regarray_spec *s,
1936 : : char **tokens,
1937 : : uint32_t n_tokens,
1938 : : uint32_t n_lines,
1939 : : uint32_t *err_line,
1940 : : const char **err_msg)
1941 : : {
1942 : : char *p;
1943 : :
1944 : : /* Check format. */
1945 [ # # ]: 0 : if ((n_tokens != 6) ||
1946 [ # # ]: 0 : strcmp(tokens[2], "size") ||
1947 [ # # ]: 0 : strcmp(tokens[4], "initval")) {
1948 [ # # ]: 0 : if (err_line)
1949 : 0 : *err_line = n_lines;
1950 [ # # ]: 0 : if (err_msg)
1951 : 0 : *err_msg = "Invalid regarray statement.";
1952 : 0 : return -EINVAL;
1953 : : }
1954 : :
1955 : : /* spec. */
1956 : 0 : s->name = strdup(tokens[1]);
1957 [ # # ]: 0 : if (!s->name) {
1958 [ # # ]: 0 : if (err_line)
1959 : 0 : *err_line = n_lines;
1960 [ # # ]: 0 : if (err_msg)
1961 : 0 : *err_msg = "Memory allocation failed.";
1962 : 0 : return -ENOMEM;
1963 : : }
1964 : :
1965 : 0 : p = tokens[3];
1966 : 0 : s->size = strtoul(p, &p, 0);
1967 [ # # # # ]: 0 : if (p[0] || !s->size) {
1968 [ # # ]: 0 : if (err_line)
1969 : 0 : *err_line = n_lines;
1970 [ # # ]: 0 : if (err_msg)
1971 : 0 : *err_msg = "Invalid size argument.";
1972 : 0 : return -EINVAL;
1973 : : }
1974 : :
1975 : 0 : p = tokens[5];
1976 : 0 : s->init_val = strtoull(p, &p, 0);
1977 [ # # ]: 0 : if (p[0]) {
1978 [ # # ]: 0 : if (err_line)
1979 : 0 : *err_line = n_lines;
1980 [ # # ]: 0 : if (err_msg)
1981 : 0 : *err_msg = "Invalid initval argument.";
1982 : 0 : return -EINVAL;
1983 : : }
1984 : :
1985 : : return 0;
1986 : : }
1987 : :
1988 : : /*
1989 : : * metarray.
1990 : : */
1991 : : static void
1992 : : metarray_spec_free(struct metarray_spec *s)
1993 : : {
1994 : : if (!s)
1995 : : return;
1996 : :
1997 : 0 : free(s->name);
1998 : : s->name = NULL;
1999 : : }
2000 : :
2001 : : static int
2002 : 0 : metarray_statement_parse(struct metarray_spec *s,
2003 : : char **tokens,
2004 : : uint32_t n_tokens,
2005 : : uint32_t n_lines,
2006 : : uint32_t *err_line,
2007 : : const char **err_msg)
2008 : : {
2009 : : char *p;
2010 : :
2011 : : /* Check format. */
2012 [ # # # # ]: 0 : if ((n_tokens != 4) || strcmp(tokens[2], "size")) {
2013 [ # # ]: 0 : if (err_line)
2014 : 0 : *err_line = n_lines;
2015 [ # # ]: 0 : if (err_msg)
2016 : 0 : *err_msg = "Invalid metarray statement.";
2017 : 0 : return -EINVAL;
2018 : : }
2019 : :
2020 : : /* spec. */
2021 : 0 : s->name = strdup(tokens[1]);
2022 [ # # ]: 0 : if (!s->name) {
2023 [ # # ]: 0 : if (err_line)
2024 : 0 : *err_line = n_lines;
2025 [ # # ]: 0 : if (err_msg)
2026 : 0 : *err_msg = "Memory allocation failed.";
2027 : 0 : return -ENOMEM;
2028 : : }
2029 : :
2030 : 0 : p = tokens[3];
2031 : 0 : s->size = strtoul(p, &p, 0);
2032 [ # # # # ]: 0 : if (p[0] || !s->size) {
2033 [ # # ]: 0 : if (err_line)
2034 : 0 : *err_line = n_lines;
2035 [ # # ]: 0 : if (err_msg)
2036 : 0 : *err_msg = "Invalid size argument.";
2037 : 0 : return -EINVAL;
2038 : : }
2039 : :
2040 : : return 0;
2041 : : }
2042 : :
2043 : : /*
2044 : : *
2045 : : * rss
2046 : : */
2047 : :
2048 : : static void
2049 : : rss_spec_free(struct rss_spec *s)
2050 : : {
2051 : : if (!s)
2052 : : return;
2053 : :
2054 : 0 : free(s->name);
2055 : : s->name = NULL;
2056 : : }
2057 : :
2058 : : static int
2059 : 0 : rss_statement_parse(struct rss_spec *s,
2060 : : char **tokens,
2061 : : uint32_t n_tokens,
2062 : : uint32_t n_lines,
2063 : : uint32_t *err_line,
2064 : : const char **err_msg)
2065 : : {
2066 : : /* Check format. */
2067 [ # # ]: 0 : if ((n_tokens != 2)) {
2068 [ # # ]: 0 : if (err_line)
2069 : 0 : *err_line = n_lines;
2070 [ # # ]: 0 : if (err_msg)
2071 : 0 : *err_msg = "Invalid rss statement.";
2072 : 0 : return -EINVAL;
2073 : : }
2074 : :
2075 : : /* spec. */
2076 : 0 : s->name = strdup(tokens[1]);
2077 [ # # ]: 0 : if (!s->name) {
2078 [ # # ]: 0 : if (err_line)
2079 : 0 : *err_line = n_lines;
2080 [ # # ]: 0 : if (err_msg)
2081 : 0 : *err_msg = "Memory allocation failed.";
2082 : 0 : return -ENOMEM;
2083 : : }
2084 : :
2085 : : return 0;
2086 : : }
2087 : :
2088 : : /*
2089 : : * apply.
2090 : : */
2091 : : static void
2092 : 0 : apply_spec_free(struct apply_spec *s)
2093 : : {
2094 : : uint32_t i;
2095 : :
2096 [ # # ]: 0 : if (!s)
2097 : : return;
2098 : :
2099 [ # # ]: 0 : for (i = 0; i < s->n_instructions; i++) {
2100 : 0 : uintptr_t instr = (uintptr_t)s->instructions[i];
2101 : :
2102 : 0 : free((void *)instr);
2103 : : }
2104 : :
2105 : 0 : free(s->instructions);
2106 : 0 : s->instructions = NULL;
2107 : :
2108 : 0 : s->n_instructions = 0;
2109 : : }
2110 : :
2111 : : static int
2112 : 0 : apply_statement_parse(uint32_t *block_mask,
2113 : : char **tokens,
2114 : : uint32_t n_tokens,
2115 : : uint32_t n_lines,
2116 : : uint32_t *err_line,
2117 : : const char **err_msg)
2118 : : {
2119 : : /* Check format. */
2120 [ # # # # ]: 0 : if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
2121 [ # # ]: 0 : if (err_line)
2122 : 0 : *err_line = n_lines;
2123 [ # # ]: 0 : if (err_msg)
2124 : 0 : *err_msg = "Invalid apply statement.";
2125 : 0 : return -EINVAL;
2126 : : }
2127 : :
2128 : : /* block_mask. */
2129 : 0 : *block_mask |= 1 << APPLY_BLOCK;
2130 : :
2131 : 0 : return 0;
2132 : : }
2133 : :
2134 : : static int
2135 : 0 : apply_block_parse(struct apply_spec *s,
2136 : : uint32_t *block_mask,
2137 : : char **tokens,
2138 : : uint32_t n_tokens,
2139 : : uint32_t n_lines,
2140 : : uint32_t *err_line,
2141 : : const char **err_msg)
2142 : : {
2143 : : char buffer[RTE_SWX_INSTRUCTION_SIZE], *instr;
2144 : : const char **new_instructions;
2145 : : uint32_t i;
2146 : :
2147 : : /* Handle end of block. */
2148 [ # # # # ]: 0 : if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
2149 : 0 : *block_mask &= ~(1 << APPLY_BLOCK);
2150 : 0 : return 0;
2151 : : }
2152 : :
2153 : : /* spec. */
2154 : 0 : buffer[0] = 0;
2155 [ # # ]: 0 : for (i = 0; i < n_tokens; i++) {
2156 [ # # ]: 0 : if (i)
2157 : : strcat(buffer, " ");
2158 : 0 : strcat(buffer, tokens[i]);
2159 : : }
2160 : :
2161 : 0 : instr = strdup(buffer);
2162 [ # # ]: 0 : if (!instr) {
2163 [ # # ]: 0 : if (err_line)
2164 : 0 : *err_line = n_lines;
2165 [ # # ]: 0 : if (err_msg)
2166 : 0 : *err_msg = "Memory allocation failed.";
2167 : 0 : return -ENOMEM;
2168 : : }
2169 : :
2170 : 0 : new_instructions = realloc(s->instructions,
2171 : 0 : (s->n_instructions + 1) * sizeof(char *));
2172 [ # # ]: 0 : if (!new_instructions) {
2173 : 0 : free(instr);
2174 : :
2175 [ # # ]: 0 : if (err_line)
2176 : 0 : *err_line = n_lines;
2177 [ # # ]: 0 : if (err_msg)
2178 : 0 : *err_msg = "Memory allocation failed.";
2179 : 0 : return -ENOMEM;
2180 : : }
2181 : :
2182 : 0 : s->instructions = new_instructions;
2183 : 0 : s->instructions[s->n_instructions] = instr;
2184 : 0 : s->n_instructions++;
2185 : :
2186 : 0 : return 0;
2187 : : }
2188 : :
2189 : : /*
2190 : : * Pipeline.
2191 : : */
2192 : : void
2193 : 0 : pipeline_spec_free(struct pipeline_spec *s)
2194 : : {
2195 [ # # ]: 0 : if (!s)
2196 : : return;
2197 : :
2198 : 0 : free(s->extobjs);
2199 : 0 : free(s->structs);
2200 : 0 : free(s->headers);
2201 : 0 : free(s->metadata);
2202 : 0 : free(s->actions);
2203 : 0 : free(s->tables);
2204 : 0 : free(s->selectors);
2205 : 0 : free(s->learners);
2206 : 0 : free(s->regarrays);
2207 : 0 : free(s->metarrays);
2208 : 0 : free(s->apply);
2209 : :
2210 : : memset(s, 0, sizeof(struct pipeline_spec));
2211 : : }
2212 : :
2213 : : static const char *
2214 : : match_type_string_get(enum rte_swx_table_match_type match_type)
2215 : : {
2216 : 0 : switch (match_type) {
2217 : : case RTE_SWX_TABLE_MATCH_WILDCARD: return "RTE_SWX_TABLE_MATCH_WILDCARD";
2218 : 0 : case RTE_SWX_TABLE_MATCH_LPM: return "RTE_SWX_TABLE_MATCH_LPM";
2219 : 0 : case RTE_SWX_TABLE_MATCH_EXACT: return "RTE_SWX_TABLE_MATCH_EXACT";
2220 : 0 : default: return "RTE_SWX_TABLE_MATCH_UNKNOWN";
2221 : : }
2222 : : }
2223 : :
2224 : : void
2225 : 0 : pipeline_spec_codegen(FILE *f,
2226 : : struct pipeline_spec *s)
2227 : : {
2228 : : uint32_t i;
2229 : :
2230 : : /* Check the input arguments. */
2231 [ # # ]: 0 : if (!f || !s)
2232 : : return;
2233 : :
2234 : : /* extobj. */
2235 : : fprintf(f, "static struct extobj_spec extobjs[] = {\n");
2236 : :
2237 [ # # ]: 0 : for (i = 0; i < s->n_extobjs; i++) {
2238 : 0 : struct extobj_spec *extobj_spec = &s->extobjs[i];
2239 : :
2240 : : fprintf(f, "\t[%d] = {\n", i);
2241 : 0 : fprintf(f, "\t\t.name = \"%s\",\n", extobj_spec->name);
2242 : 0 : fprintf(f, "\t\t.extern_type_name = \"%s\",\n", extobj_spec->extern_type_name);
2243 [ # # ]: 0 : if (extobj_spec->pragma)
2244 : : fprintf(f, "\t\t.pragma = \"%s\",\n", extobj_spec->pragma);
2245 : : else
2246 : : fprintf(f, "\t\t.pragma = NULL,\n");
2247 : : fprintf(f, "\t},\n");
2248 : : }
2249 : :
2250 : : fprintf(f, "};\n\n");
2251 : :
2252 : : /* regarray. */
2253 : : fprintf(f, "static struct regarray_spec regarrays[] = {\n");
2254 : :
2255 [ # # ]: 0 : for (i = 0; i < s->n_regarrays; i++) {
2256 : 0 : struct regarray_spec *regarray_spec = &s->regarrays[i];
2257 : :
2258 : : fprintf(f, "\t[%d] = {\n", i);
2259 : 0 : fprintf(f, "\t\t.name = \"%s\",\n", regarray_spec->name);
2260 : 0 : fprintf(f, "\t\t.init_val = %" PRIu64 ",\n", regarray_spec->init_val);
2261 : 0 : fprintf(f, "\t\t.size = %u,\n", regarray_spec->size);
2262 : : fprintf(f, "\t},\n");
2263 : : }
2264 : :
2265 : : fprintf(f, "};\n\n");
2266 : :
2267 : : /* metarray. */
2268 : : fprintf(f, "static struct metarray_spec metarrays[] = {\n");
2269 : :
2270 [ # # ]: 0 : for (i = 0; i < s->n_metarrays; i++) {
2271 : 0 : struct metarray_spec *metarray_spec = &s->metarrays[i];
2272 : :
2273 : : fprintf(f, "\t[%d] = {\n", i);
2274 : 0 : fprintf(f, "\t\t.name = \"%s\",\n", metarray_spec->name);
2275 : 0 : fprintf(f, "\t\t.size = %u,\n", metarray_spec->size);
2276 : : fprintf(f, "\t},\n");
2277 : : }
2278 : :
2279 : : fprintf(f, "};\n\n");
2280 : :
2281 : : /* rss. */
2282 : : fprintf(f, "static struct rss_spec rss[] = {\n");
2283 : :
2284 [ # # ]: 0 : for (i = 0; i < s->n_rss; i++) {
2285 : 0 : struct rss_spec *rss_spec = &s->rss[i];
2286 : : fprintf(f, "\t[%d] = {\n", i);
2287 : 0 : fprintf(f, "\t\t.name = \"%s\",\n", rss_spec->name);
2288 : : fprintf(f, "\t},\n");
2289 : : }
2290 : : fprintf(f, "};\n\n");
2291 : :
2292 : : /* struct. */
2293 [ # # ]: 0 : for (i = 0; i < s->n_structs; i++) {
2294 : 0 : struct struct_spec *struct_spec = &s->structs[i];
2295 : : uint32_t j;
2296 : :
2297 : 0 : fprintf(f, "static struct rte_swx_field_params struct_%s_fields[] = {\n",
2298 : : struct_spec->name);
2299 : :
2300 [ # # ]: 0 : for (j = 0; j < struct_spec->n_fields; j++) {
2301 : 0 : struct rte_swx_field_params *field = &struct_spec->fields[j];
2302 : :
2303 : : fprintf(f, "\t[%d] = {\n", j);
2304 : 0 : fprintf(f, "\t\t.name = \"%s\",\n", field->name);
2305 : 0 : fprintf(f, "\t\t.n_bits = %u,\n", field->n_bits);
2306 : : fprintf(f, "\t},\n");
2307 : : }
2308 : :
2309 : : fprintf(f, "};\n\n");
2310 : : }
2311 : :
2312 : : fprintf(f, "static struct struct_spec structs[] = {\n");
2313 : :
2314 [ # # ]: 0 : for (i = 0; i < s->n_structs; i++) {
2315 : 0 : struct struct_spec *struct_spec = &s->structs[i];
2316 : :
2317 : : fprintf(f, "\t[%d] = {\n", i);
2318 : 0 : fprintf(f, "\t\t.name = \"%s\",\n", struct_spec->name);
2319 : 0 : fprintf(f, "\t\t.fields = struct_%s_fields,\n", struct_spec->name);
2320 : 0 : fprintf(f, "\t\t.n_fields = "
2321 : : "sizeof(struct_%s_fields) / sizeof(struct_%s_fields[0]),\n",
2322 : : struct_spec->name,
2323 : : struct_spec->name);
2324 : 0 : fprintf(f, "\t\t.varbit = %d,\n", struct_spec->varbit);
2325 : : fprintf(f, "\t},\n");
2326 : : }
2327 : :
2328 : : fprintf(f, "};\n\n");
2329 : :
2330 : : /* header. */
2331 : : fprintf(f, "static struct header_spec headers[] = {\n");
2332 : :
2333 [ # # ]: 0 : for (i = 0; i < s->n_headers; i++) {
2334 : 0 : struct header_spec *header_spec = &s->headers[i];
2335 : :
2336 : : fprintf(f, "\t[%d] = {\n", i);
2337 : 0 : fprintf(f, "\t\t.name = \"%s\",\n", header_spec->name);
2338 : 0 : fprintf(f, "\t\t.struct_type_name = \"%s\",\n", header_spec->struct_type_name);
2339 : : fprintf(f, "\t},\n");
2340 : : }
2341 : :
2342 : : fprintf(f, "};\n\n");
2343 : :
2344 : : /* metadata. */
2345 : : fprintf(f, "static struct metadata_spec metadata[] = {\n");
2346 : :
2347 [ # # ]: 0 : for (i = 0; i < s->n_metadata; i++) {
2348 : 0 : struct metadata_spec *metadata_spec = &s->metadata[i];
2349 : :
2350 : : fprintf(f, "\t[%d] = {\n", i);
2351 : 0 : fprintf(f, "\t\t.struct_type_name = \"%s\",\n", metadata_spec->struct_type_name);
2352 : : fprintf(f, "\t},\n");
2353 : :
2354 : : }
2355 : :
2356 : : fprintf(f, "};\n\n");
2357 : :
2358 : : /* action. */
2359 [ # # ]: 0 : for (i = 0; i < s->n_actions; i++) {
2360 : 0 : struct action_spec *action_spec = &s->actions[i];
2361 : : uint32_t j;
2362 : :
2363 : 0 : fprintf(f, "static const char *action_%s_initial_instructions[] = {\n",
2364 : : action_spec->name);
2365 : :
2366 [ # # ]: 0 : for (j = 0; j < action_spec->n_instructions; j++) {
2367 : 0 : const char *instr = action_spec->instructions[j];
2368 : :
2369 : : fprintf(f, "\t[%d] = \"%s\",\n", j, instr);
2370 : : }
2371 : :
2372 : : fprintf(f, "};\n\n");
2373 : : }
2374 : :
2375 : : fprintf(f, "static struct action_spec actions[] = {\n");
2376 : :
2377 [ # # ]: 0 : for (i = 0; i < s->n_actions; i++) {
2378 : 0 : struct action_spec *action_spec = &s->actions[i];
2379 : :
2380 : : fprintf(f, "\t[%d] = {\n", i);
2381 : 0 : fprintf(f, "\t\t.name = \"%s\",\n", action_spec->name);
2382 : :
2383 [ # # ]: 0 : if (action_spec->args_struct_type_name)
2384 : : fprintf(f, "\t\t.args_struct_type_name = \"%s\",\n",
2385 : : action_spec->args_struct_type_name);
2386 : : else
2387 : : fprintf(f, "\t\t.args_struct_type_name = NULL,\n");
2388 : :
2389 : 0 : fprintf(f, "\t\t.instructions = action_%s_initial_instructions,\n",
2390 : : action_spec->name);
2391 : 0 : fprintf(f, "\t\t.n_instructions = "
2392 : : "sizeof(action_%s_initial_instructions) / "
2393 : : "sizeof(action_%s_initial_instructions[0]),\n",
2394 : : action_spec->name,
2395 : : action_spec->name);
2396 : : fprintf(f, "\t},\n");
2397 : : }
2398 : :
2399 : : fprintf(f, "};\n\n");
2400 : :
2401 : : /* table. */
2402 [ # # ]: 0 : for (i = 0; i < s->n_tables; i++) {
2403 : 0 : struct table_spec *table_spec = &s->tables[i];
2404 : : uint32_t j;
2405 : :
2406 : : /* fields. */
2407 [ # # # # ]: 0 : if (table_spec->params.fields && table_spec->params.n_fields) {
2408 : 0 : fprintf(f, "static struct rte_swx_match_field_params "
2409 : : "table_%s_fields[] = {\n",
2410 : : table_spec->name);
2411 : :
2412 [ # # ]: 0 : for (j = 0; j < table_spec->params.n_fields; j++) {
2413 : 0 : struct rte_swx_match_field_params *field =
2414 : 0 : &table_spec->params.fields[j];
2415 : :
2416 : : fprintf(f, "\t[%d] = {\n", j);
2417 : 0 : fprintf(f, "\t\t.name = \"%s\",\n", field->name);
2418 [ # # # # ]: 0 : fprintf(f, "\t\t.match_type = %s,\n",
2419 : : match_type_string_get(field->match_type));
2420 : : fprintf(f, "\t},\n");
2421 : : }
2422 : :
2423 : : fprintf(f, "};\n\n");
2424 : : }
2425 : :
2426 : : /* action_names. */
2427 [ # # # # ]: 0 : if (table_spec->params.action_names && table_spec->params.n_actions) {
2428 : 0 : fprintf(f, "static const char *table_%s_action_names[] = {\n",
2429 : : table_spec->name);
2430 : :
2431 [ # # ]: 0 : for (j = 0; j < table_spec->params.n_actions; j++) {
2432 : 0 : const char *action_name = table_spec->params.action_names[j];
2433 : :
2434 : : fprintf(f, "\t[%d] = \"%s\",\n", j, action_name);
2435 : : }
2436 : :
2437 : : fprintf(f, "};\n\n");
2438 : : }
2439 : :
2440 : : /* action_is_for_table_entries. */
2441 [ # # ]: 0 : if (table_spec->params.action_is_for_table_entries &&
2442 [ # # ]: 0 : table_spec->params.n_actions) {
2443 : 0 : fprintf(f, "static int table_%s_action_is_for_table_entries[] = {\n",
2444 : : table_spec->name);
2445 : :
2446 [ # # ]: 0 : for (j = 0; j < table_spec->params.n_actions; j++) {
2447 : 0 : int value = table_spec->params.action_is_for_table_entries[j];
2448 : :
2449 : : fprintf(f, "\t[%d] = %d,\n", j, value);
2450 : : }
2451 : :
2452 : : fprintf(f, "};\n\n");
2453 : : }
2454 : :
2455 : : /* action_is_for_default_entry. */
2456 [ # # ]: 0 : if (table_spec->params.action_is_for_default_entry &&
2457 [ # # ]: 0 : table_spec->params.n_actions) {
2458 : 0 : fprintf(f, "static int table_%s_action_is_for_default_entry[] = {\n",
2459 : : table_spec->name);
2460 : :
2461 [ # # ]: 0 : for (j = 0; j < table_spec->params.n_actions; j++) {
2462 : 0 : int value = table_spec->params.action_is_for_default_entry[j];
2463 : :
2464 : : fprintf(f, "\t[%d] = %d,\n", j, value);
2465 : : }
2466 : :
2467 : : fprintf(f, "};\n\n");
2468 : : }
2469 : : }
2470 : :
2471 : : fprintf(f, "static struct table_spec tables[] = {\n");
2472 : :
2473 [ # # ]: 0 : for (i = 0; i < s->n_tables; i++) {
2474 : 0 : struct table_spec *table_spec = &s->tables[i];
2475 : :
2476 : : fprintf(f, "\t[%d] = {\n", i);
2477 : 0 : fprintf(f, "\t\t.name = \"%s\",\n", table_spec->name);
2478 : :
2479 : : fprintf(f, "\t\t.params = {\n");
2480 : :
2481 [ # # # # ]: 0 : if (table_spec->params.fields && table_spec->params.n_fields) {
2482 : 0 : fprintf(f, "\t\t\t.fields = table_%s_fields,\n", table_spec->name);
2483 : 0 : fprintf(f, "\t\t\t.n_fields = "
2484 : : "sizeof(table_%s_fields) / sizeof(table_%s_fields[0]),\n",
2485 : : table_spec->name,
2486 : : table_spec->name);
2487 : : } else {
2488 : : fprintf(f, "\t\t\t.fields = NULL,\n");
2489 : : fprintf(f, "\t\t\t.n_fields = 0,\n");
2490 : : }
2491 : :
2492 [ # # # # ]: 0 : if (table_spec->params.action_names && table_spec->params.n_actions)
2493 : 0 : fprintf(f, "\t\t\t.action_names = table_%s_action_names,\n",
2494 : : table_spec->name);
2495 : : else
2496 : : fprintf(f, "\t\t\t.action_names = NULL,\n");
2497 : :
2498 [ # # # # ]: 0 : if (table_spec->params.action_is_for_table_entries && table_spec->params.n_actions)
2499 : 0 : fprintf(f, "\t\t\t.action_is_for_table_entries = "
2500 : : "table_%s_action_is_for_table_entries,\n",
2501 : : table_spec->name);
2502 : : else
2503 : : fprintf(f, "\t\t\t.action_is_for_table_entries = NULL,\n");
2504 : :
2505 [ # # # # ]: 0 : if (table_spec->params.action_is_for_default_entry && table_spec->params.n_actions)
2506 : 0 : fprintf(f, "\t\t\t.action_is_for_default_entry = "
2507 : : "table_%s_action_is_for_default_entry,\n",
2508 : : table_spec->name);
2509 : : else
2510 : : fprintf(f, "\t\t\t.action_is_for_default_entry = NULL,\n");
2511 : :
2512 [ # # ]: 0 : if (table_spec->params.n_actions)
2513 : 0 : fprintf(f, "\t\t\t.n_actions = sizeof(table_%s_action_names) / "
2514 : : "sizeof(table_%s_action_names[0]),\n",
2515 : : table_spec->name,
2516 : : table_spec->name);
2517 : : else
2518 : : fprintf(f, "\t\t\t.n_actions = 0,\n");
2519 : :
2520 [ # # ]: 0 : if (table_spec->params.default_action_name)
2521 : : fprintf(f, "\t\t\t.default_action_name = \"%s\",\n",
2522 : : table_spec->params.default_action_name);
2523 : : else
2524 : : fprintf(f, "\t\t\t.default_action_name = NULL,\n");
2525 : :
2526 [ # # ]: 0 : if (table_spec->params.default_action_args)
2527 : : fprintf(f, "\t\t\t.default_action_args = \"%s\",\n",
2528 : : table_spec->params.default_action_args);
2529 : : else
2530 : : fprintf(f, "\t\t\t.default_action_args = NULL,\n");
2531 : :
2532 : 0 : fprintf(f, "\t\t\t.default_action_is_const = %d,\n",
2533 : : table_spec->params.default_action_is_const);
2534 : :
2535 [ # # ]: 0 : if (table_spec->params.hash_func_name)
2536 : : fprintf(f, "\t\t\t.hash_func_name = \"%s\",\n",
2537 : : table_spec->params.hash_func_name);
2538 : : else
2539 : : fprintf(f, "\t\t\t.hash_func_name = NULL,\n");
2540 : :
2541 : : fprintf(f, "\t\t},\n");
2542 : :
2543 [ # # ]: 0 : if (table_spec->recommended_table_type_name)
2544 : : fprintf(f, "\t\t.recommended_table_type_name = \"%s\",\n",
2545 : : table_spec->recommended_table_type_name);
2546 : : else
2547 : : fprintf(f, "\t\t.recommended_table_type_name = NULL,\n");
2548 : :
2549 [ # # ]: 0 : if (table_spec->args)
2550 : : fprintf(f, "\t\t.args = \"%s\",\n", table_spec->args);
2551 : : else
2552 : : fprintf(f, "\t\t.args = NULL,\n");
2553 : :
2554 : 0 : fprintf(f, "\t\t.size = %u,\n", table_spec->size);
2555 : :
2556 : : fprintf(f, "\t},\n");
2557 : : }
2558 : :
2559 : : fprintf(f, "};\n\n");
2560 : :
2561 : : /* selector. */
2562 [ # # ]: 0 : for (i = 0; i < s->n_selectors; i++) {
2563 : 0 : struct selector_spec *selector_spec = &s->selectors[i];
2564 : : uint32_t j;
2565 : :
2566 [ # # ]: 0 : if (selector_spec->params.selector_field_names &&
2567 [ # # ]: 0 : selector_spec->params.n_selector_fields) {
2568 : 0 : fprintf(f, "static const char *selector_%s_field_names[] = {\n",
2569 : : selector_spec->name);
2570 : :
2571 [ # # ]: 0 : for (j = 0; j < selector_spec->params.n_selector_fields; j++) {
2572 : 0 : const char *field_name =
2573 : 0 : selector_spec->params.selector_field_names[j];
2574 : :
2575 : : fprintf(f, "\t[%d] = \"%s\",\n", j, field_name);
2576 : : }
2577 : :
2578 : : fprintf(f, "};\n\n");
2579 : : }
2580 : : }
2581 : :
2582 : : fprintf(f, "static struct selector_spec selectors[] = {\n");
2583 : :
2584 [ # # ]: 0 : for (i = 0; i < s->n_selectors; i++) {
2585 : 0 : struct selector_spec *selector_spec = &s->selectors[i];
2586 : :
2587 : : fprintf(f, "\t[%d] = {\n", i);
2588 : :
2589 : 0 : fprintf(f, "\t\t.name = \"%s\",\n", selector_spec->name);
2590 : : fprintf(f, "\t\t.params = {\n");
2591 : :
2592 [ # # ]: 0 : if (selector_spec->params.group_id_field_name)
2593 : : fprintf(f, "\t\t\t.group_id_field_name = \"%s\",\n",
2594 : : selector_spec->params.group_id_field_name);
2595 : : else
2596 : : fprintf(f, "\t\t\t.group_id_field_name = NULL,\n");
2597 : :
2598 [ # # ]: 0 : if (selector_spec->params.selector_field_names &&
2599 [ # # ]: 0 : selector_spec->params.n_selector_fields) {
2600 : 0 : fprintf(f, "\t\t\t.selector_field_names = selector_%s_field_names,\n",
2601 : : selector_spec->name);
2602 : 0 : fprintf(f, "\t\t\t.n_selector_fields = "
2603 : : "sizeof(selector_%s_field_names) / sizeof(selector_%s_field_names[0]),\n",
2604 : : selector_spec->name,
2605 : : selector_spec->name);
2606 : : } else {
2607 : : fprintf(f, "\t\t\t.selector_field_names = NULL,\n");
2608 : : fprintf(f, "\t\t\t.n_selector_fields = 0,\n");
2609 : : }
2610 : :
2611 [ # # ]: 0 : if (selector_spec->params.member_id_field_name)
2612 : : fprintf(f, "\t\t\t.member_id_field_name = \"%s\",\n",
2613 : : selector_spec->params.member_id_field_name);
2614 : : else
2615 : : fprintf(f, "\t\t\t.member_id_field_name = NULL,\n");
2616 : :
2617 : 0 : fprintf(f, "\t\t\t.n_groups_max = %u,\n", selector_spec->params.n_groups_max);
2618 : :
2619 : 0 : fprintf(f, "\t\t\t.n_members_per_group_max = %u,\n",
2620 : : selector_spec->params.n_members_per_group_max);
2621 : :
2622 : : fprintf(f, "\t\t},\n");
2623 : : fprintf(f, "\t},\n");
2624 : : }
2625 : :
2626 : : fprintf(f, "};\n\n");
2627 : :
2628 : : /* learner. */
2629 [ # # ]: 0 : for (i = 0; i < s->n_learners; i++) {
2630 : 0 : struct learner_spec *learner_spec = &s->learners[i];
2631 : : uint32_t j;
2632 : :
2633 : : /* field_names. */
2634 [ # # # # ]: 0 : if (learner_spec->params.field_names && learner_spec->params.n_fields) {
2635 : 0 : fprintf(f, "static const char *learner_%s_field_names[] = {\n",
2636 : : learner_spec->name);
2637 : :
2638 [ # # ]: 0 : for (j = 0; j < learner_spec->params.n_fields; j++) {
2639 : 0 : const char *field_name = learner_spec->params.field_names[j];
2640 : :
2641 : : fprintf(f, "\t[%d] = \"%s\",\n", j, field_name);
2642 : : }
2643 : :
2644 : : fprintf(f, "};\n\n");
2645 : : }
2646 : :
2647 : : /* action_names. */
2648 [ # # # # ]: 0 : if (learner_spec->params.action_names && learner_spec->params.n_actions) {
2649 : 0 : fprintf(f, "static const char *learner_%s_action_names[] = {\n",
2650 : : learner_spec->name);
2651 : :
2652 [ # # ]: 0 : for (j = 0; j < learner_spec->params.n_actions; j++) {
2653 : 0 : const char *action_name = learner_spec->params.action_names[j];
2654 : :
2655 : : fprintf(f, "\t[%d] = \"%s\",\n", j, action_name);
2656 : : }
2657 : :
2658 : : fprintf(f, "};\n\n");
2659 : : }
2660 : :
2661 : : /* action_is_for_table_entries. */
2662 [ # # ]: 0 : if (learner_spec->params.action_is_for_table_entries &&
2663 [ # # ]: 0 : learner_spec->params.n_actions) {
2664 : 0 : fprintf(f, "static int learner_%s_action_is_for_table_entries[] = {\n",
2665 : : learner_spec->name);
2666 : :
2667 [ # # ]: 0 : for (j = 0; j < learner_spec->params.n_actions; j++) {
2668 : 0 : int value = learner_spec->params.action_is_for_table_entries[j];
2669 : :
2670 : : fprintf(f, "\t[%d] = %d,\n", j, value);
2671 : : }
2672 : :
2673 : : fprintf(f, "};\n\n");
2674 : : }
2675 : :
2676 : : /* action_is_for_default_entry. */
2677 [ # # ]: 0 : if (learner_spec->params.action_is_for_default_entry &&
2678 [ # # ]: 0 : learner_spec->params.n_actions) {
2679 : 0 : fprintf(f, "static int learner_%s_action_is_for_default_entry[] = {\n",
2680 : : learner_spec->name);
2681 : :
2682 [ # # ]: 0 : for (j = 0; j < learner_spec->params.n_actions; j++) {
2683 : 0 : int value = learner_spec->params.action_is_for_default_entry[j];
2684 : :
2685 : : fprintf(f, "\t[%d] = %d,\n", j, value);
2686 : : }
2687 : :
2688 : : fprintf(f, "};\n\n");
2689 : : }
2690 : :
2691 : : /* timeout. */
2692 [ # # # # ]: 0 : if (learner_spec->timeout && learner_spec->n_timeouts) {
2693 : 0 : fprintf(f, "static uint32_t learner_%s_timeout[] = {\n",
2694 : : learner_spec->name);
2695 : :
2696 [ # # ]: 0 : for (j = 0; j < learner_spec->n_timeouts; j++) {
2697 : 0 : uint32_t value = learner_spec->timeout[j];
2698 : :
2699 : : fprintf(f, "\t[%d] = %u,\n", j, value);
2700 : : }
2701 : :
2702 : : fprintf(f, "};\n\n");
2703 : : }
2704 : : }
2705 : :
2706 : : fprintf(f, "static struct learner_spec learners[] = {\n");
2707 : :
2708 [ # # ]: 0 : for (i = 0; i < s->n_learners; i++) {
2709 : 0 : struct learner_spec *learner_spec = &s->learners[i];
2710 : :
2711 : : fprintf(f, "\t[%d] = {\n", i);
2712 : 0 : fprintf(f, "\t\t.name = \"%s\",\n", learner_spec->name);
2713 : :
2714 : : fprintf(f, "\t\t.params = {\n");
2715 : :
2716 [ # # # # ]: 0 : if (learner_spec->params.field_names && learner_spec->params.n_fields) {
2717 : 0 : fprintf(f, "\t\t\t.field_names = learner_%s_field_names,\n",
2718 : : learner_spec->name);
2719 : 0 : fprintf(f, "\t\t\t.n_fields = "
2720 : : "sizeof(learner_%s_field_names) / "
2721 : : "sizeof(learner_%s_field_names[0]),\n",
2722 : : learner_spec->name,
2723 : : learner_spec->name);
2724 : : } else {
2725 : : fprintf(f, "\t\t\t.field_names = NULL,\n");
2726 : : fprintf(f, "\t\t\t.n_fields = 0,\n");
2727 : : }
2728 : :
2729 [ # # # # ]: 0 : if (learner_spec->params.action_names && learner_spec->params.n_actions)
2730 : 0 : fprintf(f, "\t\t\t.action_names = learner_%s_action_names,\n",
2731 : : learner_spec->name);
2732 : : else
2733 : : fprintf(f, "\t\t\t.action_names = NULL,\n");
2734 : :
2735 [ # # ]: 0 : if (learner_spec->params.action_is_for_table_entries &&
2736 [ # # ]: 0 : learner_spec->params.n_actions)
2737 : 0 : fprintf(f, "\t\t\t.action_is_for_table_entries = "
2738 : : "learner_%s_action_is_for_table_entries,\n",
2739 : : learner_spec->name);
2740 : : else
2741 : : fprintf(f, "\t\t\t.action_is_for_table_entries = NULL,\n");
2742 : :
2743 [ # # ]: 0 : if (learner_spec->params.action_is_for_default_entry &&
2744 [ # # ]: 0 : learner_spec->params.n_actions)
2745 : 0 : fprintf(f, "\t\t\t.action_is_for_default_entry = "
2746 : : "learner_%s_action_is_for_default_entry,\n",
2747 : : learner_spec->name);
2748 : : else
2749 : : fprintf(f, "\t\t\t.action_is_for_default_entry = NULL,\n");
2750 : :
2751 [ # # # # ]: 0 : if (learner_spec->params.action_names && learner_spec->params.n_actions)
2752 : 0 : fprintf(f, "\t\t\t.n_actions = "
2753 : : "sizeof(learner_%s_action_names) / sizeof(learner_%s_action_names[0]),\n",
2754 : : learner_spec->name,
2755 : : learner_spec->name);
2756 : : else
2757 : : fprintf(f, "\t\t\t.n_actions = NULL,\n");
2758 : :
2759 [ # # ]: 0 : if (learner_spec->params.default_action_name)
2760 : : fprintf(f, "\t\t\t.default_action_name = \"%s\",\n",
2761 : : learner_spec->params.default_action_name);
2762 : : else
2763 : : fprintf(f, "\t\t\t.default_action_name = NULL,\n");
2764 : :
2765 [ # # ]: 0 : if (learner_spec->params.default_action_args)
2766 : : fprintf(f, "\t\t\t.default_action_args = \"%s\",\n",
2767 : : learner_spec->params.default_action_args);
2768 : : else
2769 : : fprintf(f, "\t\t\t.default_action_args = NULL,\n");
2770 : :
2771 : 0 : fprintf(f, "\t\t\t.default_action_is_const = %d,\n",
2772 : : learner_spec->params.default_action_is_const);
2773 : :
2774 [ # # ]: 0 : if (learner_spec->params.hash_func_name)
2775 : : fprintf(f, "\t\t\t.hash_func_name = \"%s\",\n",
2776 : : learner_spec->params.hash_func_name);
2777 : : else
2778 : : fprintf(f, "\t\t\t.hash_func_name = NULL,\n");
2779 : :
2780 : : fprintf(f, "\t\t},\n");
2781 : :
2782 : 0 : fprintf(f, "\t\t.size = %u,\n", learner_spec->size);
2783 : :
2784 [ # # # # ]: 0 : if (learner_spec->timeout && learner_spec->n_timeouts) {
2785 : 0 : fprintf(f, "\t\t.timeout = learner_%s_timeout,\n", learner_spec->name);
2786 : 0 : fprintf(f, "\t\t\t.n_timeouts = "
2787 : : "sizeof(learner_%s_timeout) / sizeof(learner_%s_timeout[0]),\n",
2788 : : learner_spec->name,
2789 : : learner_spec->name);
2790 : : } else {
2791 : : fprintf(f, "\t\t.timeout = NULL,\n");
2792 : : fprintf(f, "\t\t\t.n_timeouts = 0,\n");
2793 : : }
2794 : :
2795 : : fprintf(f, "\t},\n");
2796 : : }
2797 : :
2798 : : fprintf(f, "};\n\n");
2799 : :
2800 : : /* apply. */
2801 [ # # ]: 0 : for (i = 0; i < s->n_apply; i++) {
2802 : 0 : struct apply_spec *apply_spec = &s->apply[i];
2803 : : uint32_t j;
2804 : :
2805 : : fprintf(f, "static const char *apply%u_initial_instructions[] = {\n", i);
2806 : :
2807 [ # # ]: 0 : for (j = 0; j < apply_spec->n_instructions; j++) {
2808 : 0 : const char *instr = apply_spec->instructions[j];
2809 : :
2810 : : fprintf(f, "\t[%d] = \"%s\",\n", j, instr);
2811 : : }
2812 : :
2813 : : fprintf(f, "};\n\n");
2814 : : }
2815 : :
2816 : : fprintf(f, "static struct apply_spec apply[] = {\n");
2817 : :
2818 [ # # ]: 0 : for (i = 0; i < s->n_apply; i++) {
2819 : : fprintf(f, "\t[%d] = {\n", i);
2820 : : fprintf(f, "\t.instructions = apply%u_initial_instructions,\n", i);
2821 : : fprintf(f, "\t.n_instructions = "
2822 : : "sizeof(apply%u_initial_instructions) / "
2823 : : "sizeof(apply%u_initial_instructions[0]),\n",
2824 : : i,
2825 : : i);
2826 : : fprintf(f, "\t},\n");
2827 : : }
2828 : :
2829 : : fprintf(f, "};\n\n");
2830 : :
2831 : : /* pipeline. */
2832 : : fprintf(f, "struct pipeline_spec pipeline_spec = {\n");
2833 : : fprintf(f, "\t.extobjs = extobjs,\n");
2834 : : fprintf(f, "\t.structs = structs,\n");
2835 : : fprintf(f, "\t.headers = headers,\n");
2836 : : fprintf(f, "\t.metadata = metadata,\n");
2837 : : fprintf(f, "\t.actions = actions,\n");
2838 : : fprintf(f, "\t.tables = tables,\n");
2839 : : fprintf(f, "\t.selectors = selectors,\n");
2840 : : fprintf(f, "\t.learners = learners,\n");
2841 : : fprintf(f, "\t.regarrays = regarrays,\n");
2842 : : fprintf(f, "\t.metarrays = metarrays,\n");
2843 : : fprintf(f, "\t.rss = rss,\n");
2844 : : fprintf(f, "\t.apply = apply,\n");
2845 : : fprintf(f, "\t.n_extobjs = sizeof(extobjs) / sizeof(extobjs[0]),\n");
2846 : : fprintf(f, "\t.n_structs = sizeof(structs) / sizeof(structs[0]),\n");
2847 : : fprintf(f, "\t.n_headers = sizeof(headers) / sizeof(headers[0]),\n");
2848 : : fprintf(f, "\t.n_metadata = sizeof(metadata) / sizeof(metadata[0]),\n");
2849 : : fprintf(f, "\t.n_actions = sizeof(actions) / sizeof(actions[0]),\n");
2850 : : fprintf(f, "\t.n_tables = sizeof(tables) / sizeof(tables[0]),\n");
2851 : : fprintf(f, "\t.n_selectors = sizeof(selectors) / sizeof(selectors[0]),\n");
2852 : : fprintf(f, "\t.n_learners = sizeof(learners) / sizeof(learners[0]),\n");
2853 : : fprintf(f, "\t.n_regarrays = sizeof(regarrays) / sizeof(regarrays[0]),\n");
2854 : : fprintf(f, "\t.n_metarrays = sizeof(metarrays) / sizeof(metarrays[0]),\n");
2855 : : fprintf(f, "\t.n_rss = sizeof(rss) / sizeof(rss[0]),\n");
2856 : : fprintf(f, "\t.n_apply = sizeof(apply) / sizeof(apply[0]),\n");
2857 : : fprintf(f, "};\n");
2858 : : }
2859 : :
2860 : : struct pipeline_spec *
2861 : 0 : pipeline_spec_parse(FILE *spec,
2862 : : uint32_t *err_line,
2863 : : const char **err_msg)
2864 : : {
2865 : 0 : struct extobj_spec extobj_spec = {0};
2866 : 0 : struct struct_spec struct_spec = {0};
2867 : 0 : struct header_spec header_spec = {0};
2868 : 0 : struct metadata_spec metadata_spec = {0};
2869 : 0 : struct action_spec action_spec = {0};
2870 : 0 : struct table_spec table_spec = {0};
2871 : 0 : struct selector_spec selector_spec = {0};
2872 : 0 : struct learner_spec learner_spec = {0};
2873 : 0 : struct regarray_spec regarray_spec = {0};
2874 : 0 : struct metarray_spec metarray_spec = {0};
2875 : 0 : struct rss_spec rss_spec = {0};
2876 : 0 : struct apply_spec apply_spec = {0};
2877 : : struct pipeline_spec *s = NULL;
2878 : : uint32_t n_lines = 0;
2879 : 0 : uint32_t block_mask = 0;
2880 : : int status = 0;
2881 : :
2882 : : /* Check the input arguments. */
2883 [ # # ]: 0 : if (!spec) {
2884 [ # # ]: 0 : if (err_line)
2885 : 0 : *err_line = n_lines;
2886 [ # # ]: 0 : if (err_msg)
2887 : 0 : *err_msg = "Invalid input argument.";
2888 : : status = -EINVAL;
2889 : 0 : goto error;
2890 : : }
2891 : :
2892 : : /* Memory allocation. */
2893 : 0 : s = calloc(1, sizeof(struct pipeline_spec));
2894 [ # # ]: 0 : if (!s) {
2895 [ # # ]: 0 : if (err_line)
2896 : 0 : *err_line = n_lines;
2897 [ # # ]: 0 : if (err_msg)
2898 : 0 : *err_msg = "Memory allocation failed.";
2899 : : status = -ENOMEM;
2900 : 0 : goto error;
2901 : : }
2902 : :
2903 : 0 : for (n_lines = 1; ; n_lines++) {
2904 : : char line[MAX_LINE_LENGTH];
2905 : 0 : char *tokens[MAX_TOKENS], *ptr = line;
2906 : : uint32_t n_tokens = 0;
2907 : :
2908 : : /* Read next line. */
2909 [ # # ]: 0 : if (!fgets(line, sizeof(line), spec))
2910 : : break;
2911 : :
2912 : : /* Parse the line into tokens. */
2913 : 0 : for ( ; ; ) {
2914 : : char *token;
2915 : :
2916 : : /* Get token. */
2917 : 0 : token = strtok_r(ptr, " \f\n\r\t\v", &ptr);
2918 [ # # ]: 0 : if (!token)
2919 : : break;
2920 : :
2921 : : /* Handle comments. */
2922 [ # # ]: 0 : if ((token[0] == '#') ||
2923 [ # # ]: 0 : (token[0] == ';') ||
2924 [ # # ]: 0 : ((token[0] == '/') && (token[1] == '/'))) {
2925 : : break;
2926 : : }
2927 : :
2928 : : /* Handle excessively long lines. */
2929 [ # # ]: 0 : if (n_tokens >= RTE_DIM(tokens)) {
2930 [ # # ]: 0 : if (err_line)
2931 : 0 : *err_line = n_lines;
2932 [ # # ]: 0 : if (err_msg)
2933 : 0 : *err_msg = "Too many tokens.";
2934 : : status = -EINVAL;
2935 : 0 : goto error;
2936 : : }
2937 : :
2938 : : /* Handle excessively long tokens. */
2939 [ # # ]: 0 : if (strnlen(token, RTE_SWX_NAME_SIZE) >=
2940 : : RTE_SWX_NAME_SIZE) {
2941 [ # # ]: 0 : if (err_line)
2942 : 0 : *err_line = n_lines;
2943 [ # # ]: 0 : if (err_msg)
2944 : 0 : *err_msg = "Token too big.";
2945 : : status = -EINVAL;
2946 : 0 : goto error;
2947 : : }
2948 : :
2949 : : /* Save token. */
2950 : 0 : tokens[n_tokens] = token;
2951 : 0 : n_tokens++;
2952 : : }
2953 : :
2954 : : /* Handle empty lines. */
2955 [ # # ]: 0 : if (!n_tokens)
2956 : 0 : continue;
2957 : :
2958 : : /* struct block. */
2959 [ # # ]: 0 : if (block_mask & (1 << STRUCT_BLOCK)) {
2960 : : struct struct_spec *new_structs;
2961 : :
2962 : 0 : status = struct_block_parse(&struct_spec,
2963 : : &block_mask,
2964 : : tokens,
2965 : : n_tokens,
2966 : : n_lines,
2967 : : err_line,
2968 : : err_msg);
2969 [ # # ]: 0 : if (status)
2970 : 0 : goto error;
2971 : :
2972 [ # # ]: 0 : if (block_mask & (1 << STRUCT_BLOCK))
2973 : 0 : continue;
2974 : :
2975 : : /* End of block. */
2976 : 0 : new_structs = realloc(s->structs,
2977 : 0 : (s->n_structs + 1) * sizeof(struct struct_spec));
2978 [ # # ]: 0 : if (!new_structs) {
2979 [ # # ]: 0 : if (err_line)
2980 : 0 : *err_line = n_lines;
2981 [ # # ]: 0 : if (err_msg)
2982 : 0 : *err_msg = "Memory allocation failed.";
2983 : : status = -ENOMEM;
2984 : 0 : goto error;
2985 : : }
2986 : :
2987 : 0 : s->structs = new_structs;
2988 : 0 : memcpy(&s->structs[s->n_structs], &struct_spec, sizeof(struct struct_spec));
2989 : 0 : s->n_structs++;
2990 : : memset(&struct_spec, 0, sizeof(struct struct_spec));
2991 : :
2992 : 0 : continue;
2993 : : }
2994 : :
2995 : : /* action block. */
2996 [ # # ]: 0 : if (block_mask & (1 << ACTION_BLOCK)) {
2997 : : struct action_spec *new_actions;
2998 : :
2999 : 0 : status = action_block_parse(&action_spec,
3000 : : &block_mask,
3001 : : tokens,
3002 : : n_tokens,
3003 : : n_lines,
3004 : : err_line,
3005 : : err_msg);
3006 [ # # ]: 0 : if (status)
3007 : 0 : goto error;
3008 : :
3009 [ # # ]: 0 : if (block_mask & (1 << ACTION_BLOCK))
3010 : 0 : continue;
3011 : :
3012 : : /* End of block. */
3013 : 0 : new_actions = realloc(s->actions,
3014 : 0 : (s->n_actions + 1) * sizeof(struct action_spec));
3015 [ # # ]: 0 : if (!new_actions) {
3016 [ # # ]: 0 : if (err_line)
3017 : 0 : *err_line = n_lines;
3018 [ # # ]: 0 : if (err_msg)
3019 : 0 : *err_msg = "Memory allocation failed.";
3020 : : status = -ENOMEM;
3021 : 0 : goto error;
3022 : : }
3023 : :
3024 : 0 : s->actions = new_actions;
3025 : 0 : memcpy(&s->actions[s->n_actions], &action_spec, sizeof(struct action_spec));
3026 : 0 : s->n_actions++;
3027 : : memset(&action_spec, 0, sizeof(struct action_spec));
3028 : :
3029 : 0 : continue;
3030 : : }
3031 : :
3032 : : /* table block. */
3033 [ # # ]: 0 : if (block_mask & (1 << TABLE_BLOCK)) {
3034 : : struct table_spec *new_tables;
3035 : :
3036 : 0 : status = table_block_parse(&table_spec,
3037 : : &block_mask,
3038 : : tokens,
3039 : : n_tokens,
3040 : : n_lines,
3041 : : err_line,
3042 : : err_msg);
3043 [ # # ]: 0 : if (status)
3044 : 0 : goto error;
3045 : :
3046 [ # # ]: 0 : if (block_mask & (1 << TABLE_BLOCK))
3047 : 0 : continue;
3048 : :
3049 : : /* End of block. */
3050 : 0 : new_tables = realloc(s->tables,
3051 : 0 : (s->n_tables + 1) * sizeof(struct table_spec));
3052 [ # # ]: 0 : if (!new_tables) {
3053 [ # # ]: 0 : if (err_line)
3054 : 0 : *err_line = n_lines;
3055 [ # # ]: 0 : if (err_msg)
3056 : 0 : *err_msg = "Memory allocation failed.";
3057 : : status = -ENOMEM;
3058 : 0 : goto error;
3059 : : }
3060 : :
3061 : 0 : s->tables = new_tables;
3062 : 0 : memcpy(&s->tables[s->n_tables], &table_spec, sizeof(struct table_spec));
3063 : 0 : s->n_tables++;
3064 : : memset(&table_spec, 0, sizeof(struct table_spec));
3065 : :
3066 : 0 : continue;
3067 : : }
3068 : :
3069 : : /* selector block. */
3070 [ # # ]: 0 : if (block_mask & (1 << SELECTOR_BLOCK)) {
3071 : : struct selector_spec *new_selectors;
3072 : :
3073 : 0 : status = selector_block_parse(&selector_spec,
3074 : : &block_mask,
3075 : : tokens,
3076 : : n_tokens,
3077 : : n_lines,
3078 : : err_line,
3079 : : err_msg);
3080 [ # # ]: 0 : if (status)
3081 : 0 : goto error;
3082 : :
3083 [ # # ]: 0 : if (block_mask & (1 << SELECTOR_BLOCK))
3084 : 0 : continue;
3085 : :
3086 : : /* End of block. */
3087 : 0 : new_selectors = realloc(s->selectors,
3088 : 0 : (s->n_selectors + 1) * sizeof(struct selector_spec));
3089 [ # # ]: 0 : if (!new_selectors) {
3090 [ # # ]: 0 : if (err_line)
3091 : 0 : *err_line = n_lines;
3092 [ # # ]: 0 : if (err_msg)
3093 : 0 : *err_msg = "Memory allocation failed.";
3094 : : status = -ENOMEM;
3095 : 0 : goto error;
3096 : : }
3097 : :
3098 : 0 : s->selectors = new_selectors;
3099 : 0 : memcpy(&s->selectors[s->n_selectors],
3100 : : &selector_spec,
3101 : : sizeof(struct selector_spec));
3102 : 0 : s->n_selectors++;
3103 : : memset(&selector_spec, 0, sizeof(struct selector_spec));
3104 : :
3105 : 0 : continue;
3106 : : }
3107 : :
3108 : : /* learner block. */
3109 [ # # ]: 0 : if (block_mask & (1 << LEARNER_BLOCK)) {
3110 : : struct learner_spec *new_learners;
3111 : :
3112 : 0 : status = learner_block_parse(&learner_spec,
3113 : : &block_mask,
3114 : : tokens,
3115 : : n_tokens,
3116 : : n_lines,
3117 : : err_line,
3118 : : err_msg);
3119 [ # # ]: 0 : if (status)
3120 : 0 : goto error;
3121 : :
3122 [ # # ]: 0 : if (block_mask & (1 << LEARNER_BLOCK))
3123 : 0 : continue;
3124 : :
3125 : : /* End of block. */
3126 : 0 : new_learners = realloc(s->learners,
3127 : 0 : (s->n_learners + 1) * sizeof(struct learner_spec));
3128 [ # # ]: 0 : if (!new_learners) {
3129 [ # # ]: 0 : if (err_line)
3130 : 0 : *err_line = n_lines;
3131 [ # # ]: 0 : if (err_msg)
3132 : 0 : *err_msg = "Memory allocation failed.";
3133 : : status = -ENOMEM;
3134 : 0 : goto error;
3135 : : }
3136 : :
3137 : 0 : s->learners = new_learners;
3138 : 0 : memcpy(&s->learners[s->n_learners],
3139 : : &learner_spec,
3140 : : sizeof(struct learner_spec));
3141 : 0 : s->n_learners++;
3142 : : memset(&learner_spec, 0, sizeof(struct learner_spec));
3143 : :
3144 : 0 : continue;
3145 : : }
3146 : :
3147 : : /* apply block. */
3148 [ # # ]: 0 : if (block_mask & (1 << APPLY_BLOCK)) {
3149 : : struct apply_spec *new_apply;
3150 : :
3151 : 0 : status = apply_block_parse(&apply_spec,
3152 : : &block_mask,
3153 : : tokens,
3154 : : n_tokens,
3155 : : n_lines,
3156 : : err_line,
3157 : : err_msg);
3158 [ # # ]: 0 : if (status)
3159 : 0 : goto error;
3160 : :
3161 [ # # ]: 0 : if (block_mask & (1 << APPLY_BLOCK))
3162 : 0 : continue;
3163 : :
3164 : : /* End of block. */
3165 : 0 : new_apply = realloc(s->apply, (s->n_apply + 1) * sizeof(struct apply_spec));
3166 [ # # ]: 0 : if (!new_apply) {
3167 [ # # ]: 0 : if (err_line)
3168 : 0 : *err_line = n_lines;
3169 [ # # ]: 0 : if (err_msg)
3170 : 0 : *err_msg = "Memory allocation failed.";
3171 : : status = -ENOMEM;
3172 : 0 : goto error;
3173 : : }
3174 : :
3175 : 0 : s->apply = new_apply;
3176 : 0 : memcpy(&s->apply[s->n_apply], &apply_spec, sizeof(struct apply_spec));
3177 : 0 : s->n_apply++;
3178 : : memset(&apply_spec, 0, sizeof(struct apply_spec));
3179 : :
3180 : 0 : continue;
3181 : : }
3182 : :
3183 : : /* extobj. */
3184 [ # # ]: 0 : if (!strcmp(tokens[0], "extobj")) {
3185 : : struct extobj_spec *new_extobjs;
3186 : :
3187 : 0 : status = extobj_statement_parse(&extobj_spec,
3188 : : tokens,
3189 : : n_tokens,
3190 : : n_lines,
3191 : : err_line,
3192 : : err_msg);
3193 [ # # ]: 0 : if (status)
3194 : 0 : goto error;
3195 : :
3196 : 0 : new_extobjs = realloc(s->extobjs,
3197 : 0 : (s->n_extobjs + 1) * sizeof(struct extobj_spec));
3198 [ # # ]: 0 : if (!new_extobjs) {
3199 [ # # ]: 0 : if (err_line)
3200 : 0 : *err_line = n_lines;
3201 [ # # ]: 0 : if (err_msg)
3202 : 0 : *err_msg = "Memory allocation failed.";
3203 : : status = -ENOMEM;
3204 : 0 : goto error;
3205 : : }
3206 : :
3207 : 0 : s->extobjs = new_extobjs;
3208 : 0 : memcpy(&s->extobjs[s->n_extobjs], &extobj_spec, sizeof(struct extobj_spec));
3209 : 0 : s->n_extobjs++;
3210 : : memset(&extobj_spec, 0, sizeof(struct extobj_spec));
3211 : :
3212 : 0 : continue;
3213 : : }
3214 : :
3215 : : /* struct. */
3216 [ # # ]: 0 : if (!strcmp(tokens[0], "struct")) {
3217 : 0 : status = struct_statement_parse(&struct_spec,
3218 : : &block_mask,
3219 : : tokens,
3220 : : n_tokens,
3221 : : n_lines,
3222 : : err_line,
3223 : : err_msg);
3224 [ # # ]: 0 : if (status)
3225 : 0 : goto error;
3226 : :
3227 : 0 : continue;
3228 : : }
3229 : :
3230 : : /* header. */
3231 [ # # ]: 0 : if (!strcmp(tokens[0], "header")) {
3232 : : struct header_spec *new_headers;
3233 : :
3234 : 0 : status = header_statement_parse(&header_spec,
3235 : : tokens,
3236 : : n_tokens,
3237 : : n_lines,
3238 : : err_line,
3239 : : err_msg);
3240 [ # # ]: 0 : if (status)
3241 : 0 : goto error;
3242 : :
3243 : 0 : new_headers = realloc(s->headers,
3244 : 0 : (s->n_headers + 1) * sizeof(struct header_spec));
3245 [ # # ]: 0 : if (!new_headers) {
3246 [ # # ]: 0 : if (err_line)
3247 : 0 : *err_line = n_lines;
3248 [ # # ]: 0 : if (err_msg)
3249 : 0 : *err_msg = "Memory allocation failed.";
3250 : : status = -ENOMEM;
3251 : 0 : goto error;
3252 : : }
3253 : :
3254 : 0 : s->headers = new_headers;
3255 : 0 : memcpy(&s->headers[s->n_headers], &header_spec, sizeof(struct header_spec));
3256 : 0 : s->n_headers++;
3257 : : memset(&header_spec, 0, sizeof(struct header_spec));
3258 : :
3259 : 0 : continue;
3260 : : }
3261 : :
3262 : : /* metadata. */
3263 [ # # ]: 0 : if (!strcmp(tokens[0], "metadata")) {
3264 : : struct metadata_spec *new_metadata;
3265 : :
3266 : 0 : status = metadata_statement_parse(&metadata_spec,
3267 : : tokens,
3268 : : n_tokens,
3269 : : n_lines,
3270 : : err_line,
3271 : : err_msg);
3272 [ # # ]: 0 : if (status)
3273 : 0 : goto error;
3274 : :
3275 : 0 : new_metadata = realloc(s->metadata,
3276 : 0 : (s->n_metadata + 1) * sizeof(struct metadata_spec));
3277 [ # # ]: 0 : if (!new_metadata) {
3278 [ # # ]: 0 : if (err_line)
3279 : 0 : *err_line = n_lines;
3280 [ # # ]: 0 : if (err_msg)
3281 : 0 : *err_msg = "Memory allocation failed.";
3282 : : status = -ENOMEM;
3283 : 0 : goto error;
3284 : : }
3285 : :
3286 : 0 : s->metadata = new_metadata;
3287 : 0 : memcpy(&s->metadata[s->n_metadata],
3288 : : &metadata_spec,
3289 : : sizeof(struct metadata_spec));
3290 : 0 : s->n_metadata++;
3291 : : memset(&metadata_spec, 0, sizeof(struct metadata_spec));
3292 : :
3293 : 0 : continue;
3294 : : }
3295 : :
3296 : : /* action. */
3297 [ # # ]: 0 : if (!strcmp(tokens[0], "action")) {
3298 : 0 : status = action_statement_parse(&action_spec,
3299 : : &block_mask,
3300 : : tokens,
3301 : : n_tokens,
3302 : : n_lines,
3303 : : err_line,
3304 : : err_msg);
3305 [ # # ]: 0 : if (status)
3306 : 0 : goto error;
3307 : :
3308 : 0 : continue;
3309 : : }
3310 : :
3311 : : /* table. */
3312 [ # # ]: 0 : if (!strcmp(tokens[0], "table")) {
3313 : 0 : status = table_statement_parse(&table_spec,
3314 : : &block_mask,
3315 : : tokens,
3316 : : n_tokens,
3317 : : n_lines,
3318 : : err_line,
3319 : : err_msg);
3320 [ # # ]: 0 : if (status)
3321 : 0 : goto error;
3322 : :
3323 : 0 : continue;
3324 : : }
3325 : :
3326 : : /* selector. */
3327 [ # # ]: 0 : if (!strcmp(tokens[0], "selector")) {
3328 : 0 : status = selector_statement_parse(&selector_spec,
3329 : : &block_mask,
3330 : : tokens,
3331 : : n_tokens,
3332 : : n_lines,
3333 : : err_line,
3334 : : err_msg);
3335 [ # # ]: 0 : if (status)
3336 : 0 : goto error;
3337 : :
3338 : 0 : continue;
3339 : : }
3340 : :
3341 : : /* learner. */
3342 [ # # ]: 0 : if (!strcmp(tokens[0], "learner")) {
3343 : 0 : status = learner_statement_parse(&learner_spec,
3344 : : &block_mask,
3345 : : tokens,
3346 : : n_tokens,
3347 : : n_lines,
3348 : : err_line,
3349 : : err_msg);
3350 [ # # ]: 0 : if (status)
3351 : 0 : goto error;
3352 : :
3353 : 0 : continue;
3354 : : }
3355 : :
3356 : : /* regarray. */
3357 [ # # ]: 0 : if (!strcmp(tokens[0], "regarray")) {
3358 : : struct regarray_spec *new_regarrays;
3359 : :
3360 : 0 : status = regarray_statement_parse(®array_spec,
3361 : : tokens,
3362 : : n_tokens,
3363 : : n_lines,
3364 : : err_line,
3365 : : err_msg);
3366 [ # # ]: 0 : if (status)
3367 : 0 : goto error;
3368 : :
3369 : 0 : new_regarrays = realloc(s->regarrays,
3370 : 0 : (s->n_regarrays + 1) * sizeof(struct regarray_spec));
3371 [ # # ]: 0 : if (!new_regarrays) {
3372 [ # # ]: 0 : if (err_line)
3373 : 0 : *err_line = n_lines;
3374 [ # # ]: 0 : if (err_msg)
3375 : 0 : *err_msg = "Memory allocation failed.";
3376 : : status = -ENOMEM;
3377 : 0 : goto error;
3378 : : }
3379 : :
3380 : 0 : s->regarrays = new_regarrays;
3381 : 0 : memcpy(&s->regarrays[s->n_regarrays],
3382 : : ®array_spec,
3383 : : sizeof(struct regarray_spec));
3384 : 0 : s->n_regarrays++;
3385 : : memset(®array_spec, 0, sizeof(struct regarray_spec));
3386 : :
3387 : 0 : continue;
3388 : : }
3389 : :
3390 : : /* metarray. */
3391 [ # # ]: 0 : if (!strcmp(tokens[0], "metarray")) {
3392 : : struct metarray_spec *new_metarrays;
3393 : :
3394 : 0 : status = metarray_statement_parse(&metarray_spec,
3395 : : tokens,
3396 : : n_tokens,
3397 : : n_lines,
3398 : : err_line,
3399 : : err_msg);
3400 [ # # ]: 0 : if (status)
3401 : 0 : goto error;
3402 : :
3403 : 0 : new_metarrays = realloc(s->metarrays,
3404 : 0 : (s->n_metarrays + 1) * sizeof(struct metarray_spec));
3405 [ # # ]: 0 : if (!new_metarrays) {
3406 [ # # ]: 0 : if (err_line)
3407 : 0 : *err_line = n_lines;
3408 [ # # ]: 0 : if (err_msg)
3409 : 0 : *err_msg = "Memory allocation failed.";
3410 : : status = -ENOMEM;
3411 : 0 : goto error;
3412 : : }
3413 : :
3414 : 0 : s->metarrays = new_metarrays;
3415 : 0 : memcpy(&s->metarrays[s->n_metarrays],
3416 : : &metarray_spec,
3417 : : sizeof(struct metarray_spec));
3418 : 0 : s->n_metarrays++;
3419 : : memset(&metarray_spec, 0, sizeof(struct metarray_spec));
3420 : :
3421 : 0 : continue;
3422 : : }
3423 : :
3424 : : /* rss object configuration */
3425 [ # # ]: 0 : if (!strcmp(tokens[0], "rss")) {
3426 : : struct rss_spec *new_rss;
3427 : :
3428 : 0 : status = rss_statement_parse(&rss_spec,
3429 : : tokens,
3430 : : n_tokens,
3431 : : n_lines,
3432 : : err_line,
3433 : : err_msg);
3434 [ # # ]: 0 : if (status)
3435 : 0 : goto error;
3436 : :
3437 : 0 : new_rss = realloc(s->rss,
3438 : 0 : (s->n_rss + 1) * sizeof(struct rss_spec));
3439 [ # # ]: 0 : if (!new_rss) {
3440 [ # # ]: 0 : if (err_line)
3441 : 0 : *err_line = n_lines;
3442 [ # # ]: 0 : if (err_msg)
3443 : 0 : *err_msg = "Memory allocation failed.";
3444 : : status = -ENOMEM;
3445 : 0 : goto error;
3446 : : }
3447 : :
3448 : 0 : s->rss = new_rss;
3449 : 0 : memcpy(&s->rss[s->n_rss],
3450 : : &rss_spec,
3451 : : sizeof(struct rss_spec));
3452 : 0 : s->n_rss++;
3453 : : memset(&rss_spec, 0, sizeof(struct rss_spec));
3454 : :
3455 : 0 : continue;
3456 : : }
3457 : :
3458 : : /* apply. */
3459 [ # # ]: 0 : if (!strcmp(tokens[0], "apply")) {
3460 : 0 : status = apply_statement_parse(&block_mask,
3461 : : tokens,
3462 : : n_tokens,
3463 : : n_lines,
3464 : : err_line,
3465 : : err_msg);
3466 [ # # ]: 0 : if (status)
3467 : 0 : goto error;
3468 : :
3469 : 0 : continue;
3470 : : }
3471 : :
3472 : : /* Anything else. */
3473 [ # # ]: 0 : if (err_line)
3474 : 0 : *err_line = n_lines;
3475 [ # # ]: 0 : if (err_msg)
3476 : 0 : *err_msg = "Unknown statement.";
3477 : : status = -EINVAL;
3478 : 0 : goto error;
3479 : : }
3480 : :
3481 : : /* Handle unfinished block. */
3482 [ # # ]: 0 : if (block_mask) {
3483 [ # # ]: 0 : if (err_line)
3484 : 0 : *err_line = n_lines;
3485 [ # # ]: 0 : if (err_msg)
3486 : 0 : *err_msg = "Missing }.";
3487 : : status = -EINVAL;
3488 : 0 : goto error;
3489 : : }
3490 : :
3491 : : return s;
3492 : :
3493 : 0 : error:
3494 : 0 : extobj_spec_free(&extobj_spec);
3495 : 0 : struct_spec_free(&struct_spec);
3496 : : header_spec_free(&header_spec);
3497 : : metadata_spec_free(&metadata_spec);
3498 : 0 : action_spec_free(&action_spec);
3499 : 0 : table_spec_free(&table_spec);
3500 : 0 : selector_spec_free(&selector_spec);
3501 : 0 : learner_spec_free(&learner_spec);
3502 : : regarray_spec_free(®array_spec);
3503 : : metarray_spec_free(&metarray_spec);
3504 : : rss_spec_free(&rss_spec);
3505 : 0 : apply_spec_free(&apply_spec);
3506 : 0 : pipeline_spec_free(s);
3507 : :
3508 : 0 : return NULL;
3509 : : }
3510 : :
3511 : : int
3512 : 0 : pipeline_spec_configure(struct rte_swx_pipeline *p,
3513 : : struct pipeline_spec *s,
3514 : : const char **err_msg)
3515 : : {
3516 : : uint32_t i;
3517 : : int status = 0;
3518 : :
3519 : : /* extobj. */
3520 [ # # ]: 0 : for (i = 0; i < s->n_extobjs; i++) {
3521 : 0 : struct extobj_spec *extobj_spec = &s->extobjs[i];
3522 : :
3523 : 0 : status = rte_swx_pipeline_extern_object_config(p,
3524 : 0 : extobj_spec->name,
3525 : 0 : extobj_spec->extern_type_name,
3526 : 0 : extobj_spec->pragma);
3527 [ # # ]: 0 : if (status) {
3528 [ # # ]: 0 : if (err_msg)
3529 : 0 : *err_msg = "Extern object configuration error.";
3530 : 0 : return status;
3531 : : }
3532 : : }
3533 : :
3534 : : /* regarray. */
3535 [ # # ]: 0 : for (i = 0; i < s->n_regarrays; i++) {
3536 : 0 : struct regarray_spec *regarray_spec = &s->regarrays[i];
3537 : :
3538 : 0 : status = rte_swx_pipeline_regarray_config(p,
3539 : 0 : regarray_spec->name,
3540 : : regarray_spec->size,
3541 : : regarray_spec->init_val);
3542 [ # # ]: 0 : if (status) {
3543 [ # # ]: 0 : if (err_msg)
3544 : 0 : *err_msg = "Register array configuration error.";
3545 : 0 : return status;
3546 : : }
3547 : : }
3548 : :
3549 : : /* rss. */
3550 [ # # ]: 0 : for (i = 0; i < s->n_rss; i++) {
3551 : 0 : struct rss_spec *rss_spec = &s->rss[i];
3552 : :
3553 : 0 : status = rte_swx_pipeline_rss_config(p, rss_spec->name);
3554 [ # # ]: 0 : if (status) {
3555 [ # # ]: 0 : if (err_msg)
3556 : 0 : *err_msg = "rss object configuration error.";
3557 : 0 : return status;
3558 : : }
3559 : : }
3560 : :
3561 : : /* metarray. */
3562 [ # # ]: 0 : for (i = 0; i < s->n_metarrays; i++) {
3563 : 0 : struct metarray_spec *metarray_spec = &s->metarrays[i];
3564 : :
3565 : 0 : status = rte_swx_pipeline_metarray_config(p,
3566 : 0 : metarray_spec->name,
3567 : : metarray_spec->size);
3568 [ # # ]: 0 : if (status) {
3569 [ # # ]: 0 : if (err_msg)
3570 : 0 : *err_msg = "Meter array configuration error.";
3571 : 0 : return status;
3572 : : }
3573 : : }
3574 : :
3575 : : /* struct. */
3576 [ # # ]: 0 : for (i = 0; i < s->n_structs; i++) {
3577 : 0 : struct struct_spec *struct_spec = &s->structs[i];
3578 : :
3579 : 0 : status = rte_swx_pipeline_struct_type_register(p,
3580 : 0 : struct_spec->name,
3581 : : struct_spec->fields,
3582 : : struct_spec->n_fields,
3583 : : struct_spec->varbit);
3584 [ # # ]: 0 : if (status) {
3585 [ # # ]: 0 : if (err_msg)
3586 : 0 : *err_msg = "Struct type registration error.";
3587 : 0 : return status;
3588 : : }
3589 : : }
3590 : :
3591 : : /* header. */
3592 [ # # ]: 0 : for (i = 0; i < s->n_headers; i++) {
3593 : 0 : struct header_spec *header_spec = &s->headers[i];
3594 : :
3595 : 0 : status = rte_swx_pipeline_packet_header_register(p,
3596 : 0 : header_spec->name,
3597 : 0 : header_spec->struct_type_name);
3598 [ # # ]: 0 : if (status) {
3599 [ # # ]: 0 : if (err_msg)
3600 : 0 : *err_msg = "Header configuration error.";
3601 : 0 : return status;
3602 : : }
3603 : : }
3604 : :
3605 : : /* metadata. */
3606 [ # # ]: 0 : for (i = 0; i < s->n_metadata; i++) {
3607 : 0 : struct metadata_spec *metadata_spec = &s->metadata[i];
3608 : :
3609 : 0 : status = rte_swx_pipeline_packet_metadata_register(p,
3610 : 0 : metadata_spec->struct_type_name);
3611 [ # # ]: 0 : if (status) {
3612 [ # # ]: 0 : if (err_msg)
3613 : 0 : *err_msg = "Meta-data registration error.";
3614 : 0 : return status;
3615 : : }
3616 : : }
3617 : :
3618 : : /* action. */
3619 [ # # ]: 0 : for (i = 0; i < s->n_actions; i++) {
3620 : 0 : struct action_spec *action_spec = &s->actions[i];
3621 : :
3622 : 0 : status = rte_swx_pipeline_action_config(p,
3623 : 0 : action_spec->name,
3624 : 0 : action_spec->args_struct_type_name,
3625 : : action_spec->instructions,
3626 : : action_spec->n_instructions);
3627 [ # # ]: 0 : if (status) {
3628 [ # # ]: 0 : if (err_msg)
3629 : 0 : *err_msg = "Action configuration error.";
3630 : 0 : return status;
3631 : : }
3632 : : }
3633 : :
3634 : : /* table. */
3635 [ # # ]: 0 : for (i = 0; i < s->n_tables; i++) {
3636 : 0 : struct table_spec *table_spec = &s->tables[i];
3637 : :
3638 : 0 : status = rte_swx_pipeline_table_config(p,
3639 : 0 : table_spec->name,
3640 : : &table_spec->params,
3641 : 0 : table_spec->recommended_table_type_name,
3642 : 0 : table_spec->args,
3643 : : table_spec->size);
3644 [ # # ]: 0 : if (status) {
3645 [ # # ]: 0 : if (err_msg)
3646 : 0 : *err_msg = "Table configuration error.";
3647 : 0 : return status;
3648 : : }
3649 : : }
3650 : :
3651 : : /* selector. */
3652 [ # # ]: 0 : for (i = 0; i < s->n_selectors; i++) {
3653 : 0 : struct selector_spec *selector_spec = &s->selectors[i];
3654 : :
3655 : 0 : status = rte_swx_pipeline_selector_config(p,
3656 : 0 : selector_spec->name,
3657 : : &selector_spec->params);
3658 [ # # ]: 0 : if (status) {
3659 [ # # ]: 0 : if (err_msg)
3660 : 0 : *err_msg = "Selector table configuration error.";
3661 : 0 : return status;
3662 : : }
3663 : : }
3664 : :
3665 : : /* learner. */
3666 [ # # ]: 0 : for (i = 0; i < s->n_learners; i++) {
3667 : 0 : struct learner_spec *learner_spec = &s->learners[i];
3668 : :
3669 : 0 : status = rte_swx_pipeline_learner_config(p,
3670 : 0 : learner_spec->name,
3671 : : &learner_spec->params,
3672 : : learner_spec->size,
3673 : : learner_spec->timeout,
3674 : : learner_spec->n_timeouts);
3675 [ # # ]: 0 : if (status) {
3676 [ # # ]: 0 : if (err_msg)
3677 : 0 : *err_msg = "Learner table configuration error.";
3678 : 0 : return status;
3679 : : }
3680 : : }
3681 : :
3682 : : /* apply. */
3683 [ # # ]: 0 : for (i = 0; i < s->n_apply; i++) {
3684 : 0 : struct apply_spec *apply_spec = &s->apply[i];
3685 : :
3686 : 0 : status = rte_swx_pipeline_instructions_config(p,
3687 : : apply_spec->instructions,
3688 : : apply_spec->n_instructions);
3689 [ # # ]: 0 : if (status) {
3690 [ # # ]: 0 : if (err_msg)
3691 : 0 : *err_msg = "Pipeline instructions configuration error.";
3692 : 0 : return status;
3693 : : }
3694 : : }
3695 : :
3696 : : return 0;
3697 : : }
3698 : :
3699 : : static void
3700 : 0 : port_in_params_free(void *params, const char *port_type)
3701 : : {
3702 : : uintptr_t dev_name;
3703 : :
3704 [ # # ]: 0 : if (!params || !port_type)
3705 : : return;
3706 : :
3707 [ # # ]: 0 : if (!strcmp(port_type, "ethdev")) {
3708 : : struct rte_swx_port_ethdev_reader_params *p = params;
3709 : :
3710 : 0 : dev_name = (uintptr_t)p->dev_name;
3711 [ # # ]: 0 : } else if (!strcmp(port_type, "ring")) {
3712 : : struct rte_swx_port_ring_reader_params *p = params;
3713 : :
3714 : 0 : dev_name = (uintptr_t)p->name;
3715 [ # # ]: 0 : } else if (!strcmp(port_type, "source")) {
3716 : : struct rte_swx_port_source_params *p = params;
3717 : :
3718 : 0 : dev_name = (uintptr_t)p->file_name;
3719 : : } else
3720 : : dev_name = (uintptr_t)NULL;
3721 : :
3722 : 0 : free((void *)dev_name);
3723 : 0 : free(params);
3724 : : }
3725 : :
3726 : : static void
3727 : 0 : port_out_params_free(void *params, const char *port_type)
3728 : : {
3729 : : uintptr_t dev_name;
3730 : :
3731 [ # # ]: 0 : if (!params || !port_type)
3732 : : return;
3733 : :
3734 [ # # ]: 0 : if (!strcmp(port_type, "ethdev")) {
3735 : : struct rte_swx_port_ethdev_writer_params *p = params;
3736 : :
3737 : 0 : dev_name = (uintptr_t)p->dev_name;
3738 [ # # ]: 0 : } else if (!strcmp(port_type, "ring")) {
3739 : : struct rte_swx_port_ring_writer_params *p = params;
3740 : :
3741 : 0 : dev_name = (uintptr_t)p->name;
3742 [ # # ]: 0 : } else if (!strcmp(port_type, "sink")) {
3743 : : struct rte_swx_port_sink_params *p = params;
3744 : :
3745 : 0 : dev_name = (uintptr_t)p->file_name;
3746 : : } else
3747 : : dev_name = (uintptr_t)NULL;
3748 : :
3749 : 0 : free((void *)dev_name);
3750 : 0 : free(params);
3751 : : }
3752 : :
3753 : : void
3754 : 0 : pipeline_iospec_free(struct pipeline_iospec *s)
3755 : : {
3756 : : uint32_t i;
3757 : :
3758 [ # # ]: 0 : if (!s)
3759 : : return;
3760 : :
3761 : : /* Input ports. */
3762 [ # # ]: 0 : for (i = 0; i < s->n_ports_in; i++) {
3763 : 0 : uintptr_t name = (uintptr_t)s->port_in_type[i];
3764 : :
3765 : 0 : port_in_params_free(s->port_in_params[i], s->port_in_type[i]);
3766 : 0 : free((void *)name);
3767 : : }
3768 : :
3769 : 0 : free(s->port_in_type);
3770 : 0 : free(s->port_in_params);
3771 : :
3772 : : /* Output ports. */
3773 [ # # ]: 0 : for (i = 0; i < s->n_ports_out; i++) {
3774 : 0 : uintptr_t name = (uintptr_t)s->port_out_type[i];
3775 : :
3776 : 0 : port_out_params_free(s->port_out_params[i], s->port_out_type[i]);
3777 : 0 : free((void *)name);
3778 : : }
3779 : :
3780 : 0 : free(s->port_out_type);
3781 : 0 : free(s->port_out_params);
3782 : :
3783 : 0 : free(s);
3784 : : }
3785 : :
3786 : : static int
3787 : 0 : mirroring_parse(struct rte_swx_pipeline_mirroring_params *p,
3788 : : char **tokens,
3789 : : uint32_t n_tokens,
3790 : : const char **err_msg)
3791 : : {
3792 : : char *token;
3793 : :
3794 [ # # # # : 0 : if ((n_tokens != 4) || strcmp(tokens[0], "slots") || strcmp(tokens[2], "sessions")) {
# # ]
3795 [ # # ]: 0 : if (err_msg)
3796 : 0 : *err_msg = "Invalid statement.";
3797 : 0 : return -EINVAL;
3798 : : }
3799 : :
3800 : : /* <n_slots>. */
3801 : 0 : token = tokens[1];
3802 : 0 : p->n_slots = strtoul(token, &token, 0);
3803 [ # # ]: 0 : if (token[0]) {
3804 [ # # ]: 0 : if (err_msg)
3805 : 0 : *err_msg = "Invalid <n_slots> parameter.";
3806 : 0 : return -EINVAL;
3807 : : }
3808 : :
3809 : : /* <n_sessions>. */
3810 : 0 : token = tokens[3];
3811 : 0 : p->n_sessions = strtoul(token, &token, 0);
3812 [ # # ]: 0 : if (token[0]) {
3813 [ # # ]: 0 : if (err_msg)
3814 : 0 : *err_msg = "Invalid <n_sessions> parameter.";
3815 : 0 : return -EINVAL;
3816 : : }
3817 : :
3818 : : return 0;
3819 : : }
3820 : :
3821 : : static void *
3822 : 0 : port_in_ethdev_parse(char **tokens, uint32_t n_tokens, const char **err_msg)
3823 : : {
3824 : : struct rte_swx_port_ethdev_reader_params *p = NULL;
3825 : : char *token, *dev_name = NULL;
3826 : : uint32_t queue_id, burst_size;
3827 : :
3828 [ # # # # : 0 : if ((n_tokens != 5) || strcmp(tokens[1], "rxq") || strcmp(tokens[3], "bsz")) {
# # ]
3829 [ # # ]: 0 : if (err_msg)
3830 : 0 : *err_msg = "Invalid statement.";
3831 : 0 : return NULL;
3832 : : }
3833 : :
3834 : : /* <queue_id>. */
3835 : 0 : token = tokens[2];
3836 : 0 : queue_id = strtoul(token, &token, 0);
3837 [ # # ]: 0 : if (token[0]) {
3838 [ # # ]: 0 : if (err_msg)
3839 : 0 : *err_msg = "Invalid <queue_id> parameter.";
3840 : 0 : return NULL;
3841 : : }
3842 : :
3843 : : /* <burst_size>. */
3844 : 0 : token = tokens[4];
3845 : 0 : burst_size = strtoul(token, &token, 0);
3846 [ # # ]: 0 : if (token[0]) {
3847 [ # # ]: 0 : if (err_msg)
3848 : 0 : *err_msg = "Invalid <burst_size> parameter.";
3849 : 0 : return NULL;
3850 : : }
3851 : :
3852 : : /* Memory allocation. */
3853 : 0 : dev_name = strdup(tokens[0]);
3854 : 0 : p = malloc(sizeof(struct rte_swx_port_ethdev_reader_params));
3855 [ # # ]: 0 : if (!dev_name || !p) {
3856 : 0 : free(dev_name);
3857 : 0 : free(p);
3858 : :
3859 [ # # ]: 0 : if (err_msg)
3860 : 0 : *err_msg = "Memory allocation failed.";
3861 : 0 : return NULL;
3862 : : }
3863 : :
3864 : : /* Initialization. */
3865 : 0 : p->dev_name = dev_name;
3866 : 0 : p->queue_id = queue_id;
3867 : 0 : p->burst_size = burst_size;
3868 : :
3869 : 0 : return p;
3870 : : }
3871 : :
3872 : : static void *
3873 : 0 : port_in_ring_parse(char **tokens, uint32_t n_tokens, const char **err_msg)
3874 : : {
3875 : : struct rte_swx_port_ring_reader_params *p = NULL;
3876 : : char *token, *name = NULL;
3877 : : uint32_t burst_size;
3878 : :
3879 [ # # # # ]: 0 : if ((n_tokens != 3) || strcmp(tokens[1], "bsz")) {
3880 [ # # ]: 0 : if (err_msg)
3881 : 0 : *err_msg = "Invalid statement.";
3882 : 0 : return NULL;
3883 : : }
3884 : :
3885 : : /* <burst_size>. */
3886 : 0 : token = tokens[2];
3887 : 0 : burst_size = strtoul(token, &token, 0);
3888 [ # # ]: 0 : if (token[0]) {
3889 [ # # ]: 0 : if (err_msg)
3890 : 0 : *err_msg = "Invalid <burst_size> parameter.";
3891 : 0 : return NULL;
3892 : : }
3893 : :
3894 : : /* Memory allocation. */
3895 : 0 : name = strdup(tokens[0]);
3896 : 0 : p = malloc(sizeof(struct rte_swx_port_ring_reader_params));
3897 [ # # ]: 0 : if (!name || !p) {
3898 : 0 : free(name);
3899 : 0 : free(p);
3900 : :
3901 [ # # ]: 0 : if (err_msg)
3902 : 0 : *err_msg = "Memory allocation failed.";
3903 : 0 : return NULL;
3904 : : }
3905 : :
3906 : : /* Initialization. */
3907 : 0 : p->name = name;
3908 : 0 : p->burst_size = burst_size;
3909 : :
3910 : 0 : return p;
3911 : : }
3912 : :
3913 : : static void *
3914 : 0 : port_in_source_parse(char **tokens, uint32_t n_tokens, const char **err_msg)
3915 : : {
3916 : : struct rte_swx_port_source_params *p = NULL;
3917 : : struct rte_mempool *pool = NULL;
3918 : : char *token, *file_name = NULL;
3919 : : uint32_t n_loops, n_pkts_max;
3920 : :
3921 [ # # ]: 0 : if ((n_tokens != 8) ||
3922 [ # # ]: 0 : strcmp(tokens[0], "mempool") ||
3923 [ # # ]: 0 : strcmp(tokens[2], "file") ||
3924 [ # # ]: 0 : strcmp(tokens[4], "loop") ||
3925 [ # # ]: 0 : strcmp(tokens[6], "packets")) {
3926 [ # # ]: 0 : if (err_msg)
3927 : 0 : *err_msg = "Invalid statement.";
3928 : 0 : return NULL;
3929 : : }
3930 : :
3931 : : /* <mempool_name>. */
3932 : 0 : pool = rte_mempool_lookup(tokens[1]);
3933 [ # # ]: 0 : if (!pool) {
3934 [ # # ]: 0 : if (err_msg)
3935 : 0 : *err_msg = "Invalid <mempool_name> parameter.";
3936 : 0 : return NULL;
3937 : : }
3938 : :
3939 : : /* <n_loops>. */
3940 : 0 : token = tokens[5];
3941 : 0 : n_loops = strtoul(token, &token, 0);
3942 [ # # ]: 0 : if (token[0]) {
3943 [ # # ]: 0 : if (err_msg)
3944 : 0 : *err_msg = "Invalid <n_loops> parameter.";
3945 : 0 : return NULL;
3946 : : }
3947 : :
3948 : : /* <n_pkts_max>. */
3949 : 0 : token = tokens[7];
3950 : 0 : n_pkts_max = strtoul(token, &token, 0);
3951 [ # # ]: 0 : if (token[0]) {
3952 [ # # ]: 0 : if (err_msg)
3953 : 0 : *err_msg = "Invalid <n_pkts_max> parameter.";
3954 : 0 : return NULL;
3955 : : }
3956 : :
3957 : : /* Memory allocation. */
3958 : 0 : file_name = strdup(tokens[3]);
3959 : 0 : p = malloc(sizeof(struct rte_swx_port_source_params));
3960 [ # # ]: 0 : if (!file_name || !p) {
3961 : 0 : free(file_name);
3962 : 0 : free(p);
3963 : :
3964 [ # # ]: 0 : if (err_msg)
3965 : 0 : *err_msg = "Memory allocation failed.";
3966 : 0 : return NULL;
3967 : : }
3968 : :
3969 : : /* Initialization. */
3970 : 0 : p->pool = pool;
3971 : 0 : p->file_name = file_name;
3972 : 0 : p->n_loops = n_loops;
3973 : 0 : p->n_pkts_max = n_pkts_max;
3974 : :
3975 : 0 : return p;
3976 : : }
3977 : :
3978 : : static void *
3979 : 0 : port_in_fd_parse(char **tokens,
3980 : : uint32_t n_tokens,
3981 : : const char **err_msg)
3982 : : {
3983 : : struct rte_swx_port_fd_reader_params *p = NULL;
3984 : : struct rte_mempool *mempool = NULL;
3985 : : char *token;
3986 : : uint32_t mtu, burst_size;
3987 : : int fd;
3988 : :
3989 [ # # ]: 0 : if ((n_tokens != 7) ||
3990 [ # # ]: 0 : strcmp(tokens[1], "mtu") ||
3991 [ # # ]: 0 : strcmp(tokens[3], "mempool") ||
3992 [ # # ]: 0 : strcmp(tokens[5], "bsz")) {
3993 [ # # ]: 0 : if (err_msg)
3994 : 0 : *err_msg = "Invalid statement.";
3995 : 0 : return NULL;
3996 : : }
3997 : :
3998 : : /* <file_descriptor>. */
3999 : 0 : token = tokens[0];
4000 : 0 : fd = strtol(token, &token, 0);
4001 [ # # ]: 0 : if (token[0]) {
4002 [ # # ]: 0 : if (err_msg)
4003 : 0 : *err_msg = "Invalid <file_descriptor> parameter.";
4004 : 0 : return NULL;
4005 : : }
4006 : :
4007 : : /* <mtu>. */
4008 : 0 : token = tokens[2];
4009 : 0 : mtu = strtoul(token, &token, 0);
4010 [ # # ]: 0 : if (token[0]) {
4011 [ # # ]: 0 : if (err_msg)
4012 : 0 : *err_msg = "Invalid <mtu> parameter.";
4013 : 0 : return NULL;
4014 : : }
4015 : :
4016 : : /* <mempool_name>. */
4017 : 0 : mempool = rte_mempool_lookup(tokens[4]);
4018 [ # # ]: 0 : if (!mempool) {
4019 [ # # ]: 0 : if (err_msg)
4020 : 0 : *err_msg = "Invalid <mempool_name> parameter.";
4021 : 0 : return NULL;
4022 : : }
4023 : :
4024 : : /* <burst_size>. */
4025 : 0 : token = tokens[6];
4026 : 0 : burst_size = strtoul(token, &token, 0);
4027 [ # # ]: 0 : if (token[0]) {
4028 [ # # ]: 0 : if (err_msg)
4029 : 0 : *err_msg = "Invalid <burst_size> parameter.";
4030 : 0 : return NULL;
4031 : : }
4032 : :
4033 : : /* Memory allocation. */
4034 : 0 : p = malloc(sizeof(struct rte_swx_port_fd_reader_params));
4035 [ # # ]: 0 : if (!p) {
4036 [ # # ]: 0 : if (err_msg)
4037 : 0 : *err_msg = "Memory allocation failed.";
4038 : 0 : return NULL;
4039 : : }
4040 : :
4041 : : /* Initialization. */
4042 : 0 : p->fd = fd;
4043 : 0 : p->mtu = mtu;
4044 : 0 : p->mempool = mempool;
4045 : 0 : p->burst_size = burst_size;
4046 : :
4047 : 0 : return p;
4048 : : }
4049 : :
4050 : : static void *
4051 : 0 : port_out_ethdev_parse(char **tokens, uint32_t n_tokens, const char **err_msg)
4052 : : {
4053 : : struct rte_swx_port_ethdev_writer_params *p = NULL;
4054 : : char *token, *dev_name = NULL;
4055 : : uint32_t queue_id, burst_size;
4056 : :
4057 [ # # # # : 0 : if ((n_tokens != 5) || strcmp(tokens[1], "txq") || strcmp(tokens[3], "bsz")) {
# # ]
4058 [ # # ]: 0 : if (err_msg)
4059 : 0 : *err_msg = "Invalid statement.";
4060 : 0 : return NULL;
4061 : : }
4062 : :
4063 : : /* <queue_id>. */
4064 : 0 : token = tokens[2];
4065 : 0 : queue_id = strtoul(token, &token, 0);
4066 [ # # ]: 0 : if (token[0]) {
4067 [ # # ]: 0 : if (err_msg)
4068 : 0 : *err_msg = "Invalid <queue_id> parameter.";
4069 : 0 : return NULL;
4070 : : }
4071 : :
4072 : : /* <burst_size>. */
4073 : 0 : token = tokens[4];
4074 : 0 : burst_size = strtoul(token, &token, 0);
4075 [ # # ]: 0 : if (token[0]) {
4076 [ # # ]: 0 : if (err_msg)
4077 : 0 : *err_msg = "Invalid <burst_size> parameter.";
4078 : 0 : return NULL;
4079 : : }
4080 : :
4081 : : /* Memory allocation. */
4082 : 0 : dev_name = strdup(tokens[0]);
4083 : 0 : p = malloc(sizeof(struct rte_swx_port_ethdev_writer_params));
4084 [ # # ]: 0 : if (!dev_name || !p) {
4085 : 0 : free(dev_name);
4086 : 0 : free(p);
4087 : :
4088 [ # # ]: 0 : if (err_msg)
4089 : 0 : *err_msg = "Memory allocation failed.";
4090 : 0 : return NULL;
4091 : : }
4092 : :
4093 : : /* Initialization. */
4094 : 0 : p->dev_name = dev_name;
4095 : 0 : p->queue_id = queue_id;
4096 : 0 : p->burst_size = burst_size;
4097 : :
4098 : 0 : return p;
4099 : : }
4100 : :
4101 : : static void *
4102 : 0 : port_out_ring_parse(char **tokens, uint32_t n_tokens, const char **err_msg)
4103 : : {
4104 : : struct rte_swx_port_ring_writer_params *p = NULL;
4105 : : char *token, *name = NULL;
4106 : : uint32_t burst_size;
4107 : :
4108 [ # # # # ]: 0 : if ((n_tokens != 3) || strcmp(tokens[1], "bsz")) {
4109 [ # # ]: 0 : if (err_msg)
4110 : 0 : *err_msg = "Invalid statement.";
4111 : 0 : return NULL;
4112 : : }
4113 : :
4114 : : /* <burst_size>. */
4115 : 0 : token = tokens[2];
4116 : 0 : burst_size = strtoul(token, &token, 0);
4117 [ # # ]: 0 : if (token[0]) {
4118 [ # # ]: 0 : if (err_msg)
4119 : 0 : *err_msg = "Invalid <burst_size> parameter.";
4120 : 0 : return NULL;
4121 : : }
4122 : :
4123 : : /* Memory allocation. */
4124 : 0 : name = strdup(tokens[0]);
4125 : 0 : p = malloc(sizeof(struct rte_swx_port_ring_writer_params));
4126 [ # # ]: 0 : if (!name || !p) {
4127 : 0 : free(name);
4128 : 0 : free(p);
4129 : :
4130 [ # # ]: 0 : if (err_msg)
4131 : 0 : *err_msg = "Memory allocation failed.";
4132 : 0 : return NULL;
4133 : : }
4134 : :
4135 : : /* Initialization. */
4136 : 0 : p->name = name;
4137 : 0 : p->burst_size = burst_size;
4138 : :
4139 : 0 : return p;
4140 : : }
4141 : :
4142 : : static void *
4143 : 0 : port_out_sink_parse(char **tokens, uint32_t n_tokens, const char **err_msg)
4144 : : {
4145 : : struct rte_swx_port_sink_params *p = NULL;
4146 : : char *file_name = NULL;
4147 : : int file_name_valid = 0;
4148 : :
4149 [ # # # # ]: 0 : if ((n_tokens != 2) || strcmp(tokens[0], "file")) {
4150 [ # # ]: 0 : if (err_msg)
4151 : 0 : *err_msg = "Invalid statement.";
4152 : 0 : return NULL;
4153 : : }
4154 : :
4155 : : /* Memory allocation. */
4156 [ # # ]: 0 : if (strcmp(tokens[1], "none")) {
4157 : : file_name_valid = 1;
4158 : 0 : file_name = strdup(tokens[1]);
4159 : : }
4160 : :
4161 : 0 : p = malloc(sizeof(struct rte_swx_port_ring_writer_params));
4162 [ # # # # ]: 0 : if ((file_name_valid && !file_name) || !p) {
4163 : 0 : free(file_name);
4164 : 0 : free(p);
4165 : :
4166 [ # # ]: 0 : if (err_msg)
4167 : 0 : *err_msg = "Memory allocation failed.";
4168 : 0 : return NULL;
4169 : : }
4170 : :
4171 : : /* Initialization. */
4172 : 0 : p->file_name = file_name;
4173 : :
4174 : 0 : return p;
4175 : : }
4176 : :
4177 : : static void *
4178 : 0 : port_out_fd_parse(char **tokens,
4179 : : uint32_t n_tokens,
4180 : : const char **err_msg)
4181 : : {
4182 : : struct rte_swx_port_fd_writer_params *p = NULL;
4183 : : char *token;
4184 : : uint32_t burst_size;
4185 : : int fd;
4186 : :
4187 [ # # # # ]: 0 : if ((n_tokens != 3) || strcmp(tokens[1], "bsz")) {
4188 [ # # ]: 0 : if (err_msg)
4189 : 0 : *err_msg = "Invalid statement.";
4190 : 0 : return NULL;
4191 : : }
4192 : :
4193 : : /* <file_descriptor>. */
4194 : 0 : token = tokens[0];
4195 : 0 : fd = strtol(token, &token, 0);
4196 [ # # ]: 0 : if (token[0]) {
4197 [ # # ]: 0 : if (err_msg)
4198 : 0 : *err_msg = "Invalid <file_descriptor> parameter.";
4199 : 0 : return NULL;
4200 : : }
4201 : :
4202 : : /* <burst_size>. */
4203 : 0 : token = tokens[2];
4204 : 0 : burst_size = strtoul(token, &token, 0);
4205 [ # # ]: 0 : if (token[0]) {
4206 [ # # ]: 0 : if (err_msg)
4207 : 0 : *err_msg = "Invalid <burst_size> parameter.";
4208 : 0 : return NULL;
4209 : : }
4210 : :
4211 : : /* Memory allocation. */
4212 : 0 : p = malloc(sizeof(struct rte_swx_port_fd_writer_params));
4213 [ # # ]: 0 : if (!p) {
4214 [ # # ]: 0 : if (err_msg)
4215 : 0 : *err_msg = "Memory allocation failed.";
4216 : 0 : return NULL;
4217 : : }
4218 : :
4219 : : /* Initialization. */
4220 : 0 : p->fd = fd;
4221 : 0 : p->burst_size = burst_size;
4222 : :
4223 : 0 : return p;
4224 : : }
4225 : :
4226 : : struct pipeline_iospec *
4227 : 0 : pipeline_iospec_parse(FILE *spec,
4228 : : uint32_t *err_line,
4229 : : const char **err_msg)
4230 : : {
4231 : : struct pipeline_iospec *s = NULL;
4232 : : uint32_t n_lines = 0;
4233 : :
4234 : : /* Check the input arguments. */
4235 [ # # ]: 0 : if (!spec) {
4236 [ # # ]: 0 : if (err_line)
4237 : 0 : *err_line = n_lines;
4238 [ # # ]: 0 : if (err_msg)
4239 : 0 : *err_msg = "Invalid input argument.";
4240 : 0 : goto error;
4241 : : }
4242 : :
4243 : : /* Memory allocation. */
4244 : 0 : s = calloc(1, sizeof(struct pipeline_iospec));
4245 [ # # ]: 0 : if (!s) {
4246 [ # # ]: 0 : if (err_line)
4247 : 0 : *err_line = n_lines;
4248 [ # # ]: 0 : if (err_msg)
4249 : 0 : *err_msg = "Memory allocation failed.";
4250 : 0 : goto error;
4251 : : }
4252 : :
4253 : : /* Initialize with the default values. */
4254 : 0 : s->mirroring_params.n_slots = RTE_SWX_PACKET_MIRRORING_SLOTS_DEFAULT;
4255 : 0 : s->mirroring_params.n_sessions = RTE_SWX_PACKET_MIRRORING_SESSIONS_DEFAULT;
4256 : :
4257 : 0 : for (n_lines = 1; ; n_lines++) {
4258 : : char line[MAX_LINE_LENGTH];
4259 : 0 : char *tokens[MAX_TOKENS], *ptr = line;
4260 : : uint32_t n_tokens = 0;
4261 : :
4262 : : /* Read next line. */
4263 [ # # ]: 0 : if (!fgets(line, sizeof(line), spec))
4264 : : break;
4265 : :
4266 : : /* Parse the line into tokens. */
4267 : 0 : for ( ; ; ) {
4268 : : char *token;
4269 : :
4270 : : /* Get token. */
4271 : 0 : token = strtok_r(ptr, " \f\n\r\t\v", &ptr);
4272 [ # # ]: 0 : if (!token)
4273 : : break;
4274 : :
4275 : : /* Handle comments. */
4276 [ # # ]: 0 : if ((token[0] == '#') ||
4277 [ # # ]: 0 : (token[0] == ';') ||
4278 [ # # ]: 0 : ((token[0] == '/') && (token[1] == '/'))) {
4279 : : break;
4280 : : }
4281 : :
4282 : : /* Handle excessively long lines. */
4283 [ # # ]: 0 : if (n_tokens >= RTE_DIM(tokens)) {
4284 [ # # ]: 0 : if (err_line)
4285 : 0 : *err_line = n_lines;
4286 [ # # ]: 0 : if (err_msg)
4287 : 0 : *err_msg = "Too many tokens.";
4288 : 0 : goto error;
4289 : : }
4290 : :
4291 : : /* Handle excessively long tokens. */
4292 [ # # ]: 0 : if (strnlen(token, RTE_SWX_NAME_SIZE) >=
4293 : : RTE_SWX_NAME_SIZE) {
4294 [ # # ]: 0 : if (err_line)
4295 : 0 : *err_line = n_lines;
4296 [ # # ]: 0 : if (err_msg)
4297 : 0 : *err_msg = "Token too big.";
4298 : 0 : goto error;
4299 : : }
4300 : :
4301 : : /* Save token. */
4302 : 0 : tokens[n_tokens] = token;
4303 : 0 : n_tokens++;
4304 : : }
4305 : :
4306 : : /* Handle empty lines. */
4307 [ # # ]: 0 : if (!n_tokens)
4308 : 0 : continue;
4309 : :
4310 : : /* mirroring. */
4311 [ # # ]: 0 : if ((n_tokens >= 1) && !strcmp(tokens[0], "mirroring")) {
4312 : : int status = 0;
4313 : :
4314 : 0 : status = mirroring_parse(&s->mirroring_params,
4315 : : &tokens[1],
4316 : : n_tokens - 1,
4317 : : err_msg);
4318 [ # # ]: 0 : if (status) {
4319 [ # # ]: 0 : if (err_line)
4320 : 0 : *err_line = n_lines;
4321 : 0 : goto error;
4322 : : }
4323 : :
4324 : 0 : continue;
4325 : : }
4326 : :
4327 : : /* port in. */
4328 [ # # # # : 0 : if ((n_tokens >= 4) && !strcmp(tokens[0], "port") && !strcmp(tokens[1], "in")) {
# # ]
4329 : 0 : char *token = tokens[2];
4330 : : uint32_t *new_id = NULL;
4331 : : const char **new_type = NULL, *port_type = NULL;
4332 : : void **new_params = NULL, *p = NULL;
4333 : : uint32_t port_id;
4334 : :
4335 : : /* <port_id>. */
4336 : 0 : port_id = strtoul(token, &token, 0);
4337 [ # # ]: 0 : if (token[0]) {
4338 [ # # ]: 0 : if (err_line)
4339 : 0 : *err_line = n_lines;
4340 [ # # ]: 0 : if (err_msg)
4341 : 0 : *err_msg = "Invalid port ID.";
4342 : 0 : goto error;
4343 : : }
4344 : :
4345 : : /* <port_type>. */
4346 [ # # ]: 0 : if (!strcmp(tokens[3], "ethdev"))
4347 : 0 : p = port_in_ethdev_parse(&tokens[4], n_tokens - 4, err_msg);
4348 [ # # ]: 0 : else if (!strcmp(tokens[3], "ring"))
4349 : 0 : p = port_in_ring_parse(&tokens[4], n_tokens - 4, err_msg);
4350 [ # # ]: 0 : else if (!strcmp(tokens[3], "source"))
4351 : 0 : p = port_in_source_parse(&tokens[4], n_tokens - 4, err_msg);
4352 [ # # ]: 0 : else if (!strcmp(tokens[3], "fd"))
4353 : 0 : p = port_in_fd_parse(&tokens[4], n_tokens - 4, err_msg);
4354 : : else {
4355 : : p = NULL;
4356 [ # # ]: 0 : if (err_msg)
4357 : 0 : *err_msg = "Invalid port type.";
4358 : : }
4359 : :
4360 [ # # ]: 0 : if (!p) {
4361 [ # # ]: 0 : if (err_line)
4362 : 0 : *err_line = n_lines;
4363 : 0 : goto error;
4364 : : }
4365 : :
4366 : : /* New port. */
4367 : 0 : port_type = strdup(tokens[3]);
4368 : 0 : new_id = realloc(s->port_in_id,
4369 : 0 : (s->n_ports_in + 1) * sizeof(uint32_t));
4370 : 0 : new_type = realloc(s->port_in_type,
4371 : 0 : (s->n_ports_in + 1) * sizeof(char *));
4372 : 0 : new_params = realloc(s->port_in_params,
4373 : 0 : (s->n_ports_in + 1) * sizeof(void *));
4374 [ # # # # ]: 0 : if (!port_type || !new_id || !new_type || !new_params) {
4375 : : uintptr_t pt = (uintptr_t)port_type;
4376 : :
4377 : 0 : port_in_params_free(p, tokens[3]);
4378 : 0 : free((void *)pt);
4379 : 0 : free(new_id);
4380 : 0 : free(new_type);
4381 : 0 : free(new_params);
4382 : :
4383 [ # # ]: 0 : if (err_line)
4384 : 0 : *err_line = n_lines;
4385 [ # # ]: 0 : if (err_msg)
4386 : 0 : *err_msg = "Memory allocation failed.";
4387 : 0 : goto error;
4388 : : }
4389 : :
4390 : 0 : s->port_in_id = new_id;
4391 : 0 : s->port_in_type = new_type;
4392 : 0 : s->port_in_params = new_params;
4393 : :
4394 : 0 : s->port_in_id[s->n_ports_in] = port_id;
4395 : 0 : s->port_in_type[s->n_ports_in] = port_type;
4396 : 0 : s->port_in_params[s->n_ports_in] = p;
4397 : 0 : s->n_ports_in++;
4398 : :
4399 : 0 : continue;
4400 : : }
4401 : :
4402 : : /* port out. */
4403 [ # # # # : 0 : if ((n_tokens >= 4) && !strcmp(tokens[0], "port") && !strcmp(tokens[1], "out")) {
# # ]
4404 : 0 : char *token = tokens[2];
4405 : : uint32_t *new_id = NULL;
4406 : : const char **new_type = NULL, *port_type = NULL;
4407 : : void **new_params = NULL, *p = NULL;
4408 : : uint32_t port_id;
4409 : :
4410 : : /* <port_id>. */
4411 : 0 : port_id = strtoul(token, &token, 0);
4412 [ # # ]: 0 : if (token[0]) {
4413 [ # # ]: 0 : if (err_line)
4414 : 0 : *err_line = n_lines;
4415 [ # # ]: 0 : if (err_msg)
4416 : 0 : *err_msg = "Invalid port ID.";
4417 : 0 : goto error;
4418 : : }
4419 : :
4420 : : /* <port_type>. */
4421 [ # # ]: 0 : if (!strcmp(tokens[3], "ethdev"))
4422 : 0 : p = port_out_ethdev_parse(&tokens[4], n_tokens - 4, err_msg);
4423 [ # # ]: 0 : else if (!strcmp(tokens[3], "ring"))
4424 : 0 : p = port_out_ring_parse(&tokens[4], n_tokens - 4, err_msg);
4425 [ # # ]: 0 : else if (!strcmp(tokens[3], "sink"))
4426 : 0 : p = port_out_sink_parse(&tokens[4], n_tokens - 4, err_msg);
4427 [ # # ]: 0 : else if (!strcmp(tokens[3], "fd"))
4428 : 0 : p = port_out_fd_parse(&tokens[4], n_tokens - 4, err_msg);
4429 : : else {
4430 : : p = NULL;
4431 [ # # ]: 0 : if (err_msg)
4432 : 0 : *err_msg = "Invalid port type.";
4433 : : }
4434 : :
4435 [ # # ]: 0 : if (!p) {
4436 [ # # ]: 0 : if (err_line)
4437 : 0 : *err_line = n_lines;
4438 : 0 : goto error;
4439 : : }
4440 : :
4441 : : /* New port. */
4442 : 0 : port_type = strdup(tokens[3]);
4443 : 0 : new_id = realloc(s->port_out_id,
4444 : 0 : (s->n_ports_out + 1) * sizeof(uint32_t));
4445 : 0 : new_type = realloc(s->port_out_type,
4446 : 0 : (s->n_ports_out + 1) * sizeof(char *));
4447 : 0 : new_params = realloc(s->port_out_params,
4448 : 0 : (s->n_ports_out + 1) * sizeof(void *));
4449 [ # # # # ]: 0 : if (!port_type || !new_id || !new_type || !new_params) {
4450 : : uintptr_t pt = (uintptr_t)port_type;
4451 : :
4452 : 0 : port_out_params_free(p, tokens[3]);
4453 : 0 : free((void *)pt);
4454 : 0 : free(new_id);
4455 : 0 : free(new_type);
4456 : 0 : free(new_params);
4457 : :
4458 [ # # ]: 0 : if (err_line)
4459 : 0 : *err_line = n_lines;
4460 [ # # ]: 0 : if (err_msg)
4461 : 0 : *err_msg = "Memory allocation failed.";
4462 : 0 : goto error;
4463 : : }
4464 : :
4465 : 0 : s->port_out_id = new_id;
4466 : 0 : s->port_out_type = new_type;
4467 : 0 : s->port_out_params = new_params;
4468 : :
4469 : 0 : s->port_out_id[s->n_ports_out] = port_id;
4470 : 0 : s->port_out_type[s->n_ports_out] = port_type;
4471 : 0 : s->port_out_params[s->n_ports_out] = p;
4472 : 0 : s->n_ports_out++;
4473 : :
4474 : 0 : continue;
4475 : : }
4476 : :
4477 : : /* Anything else. */
4478 [ # # ]: 0 : if (err_line)
4479 : 0 : *err_line = n_lines;
4480 [ # # ]: 0 : if (err_msg)
4481 : 0 : *err_msg = "Unknown I/O statement.";
4482 : 0 : goto error;
4483 : : }
4484 : :
4485 : 0 : return s;
4486 : :
4487 : 0 : error:
4488 : 0 : pipeline_iospec_free(s);
4489 : :
4490 : 0 : return NULL;
4491 : : }
4492 : :
4493 : : int
4494 : 0 : pipeline_iospec_configure(struct rte_swx_pipeline *p,
4495 : : struct pipeline_iospec *s,
4496 : : const char **err_msg)
4497 : : {
4498 : : uint32_t i;
4499 : : int status = 0;
4500 : :
4501 : : /* Check input arguments. */
4502 [ # # ]: 0 : if (!p || !s) {
4503 [ # # ]: 0 : if (err_msg)
4504 : 0 : *err_msg = "Invalid input argument";
4505 : 0 : return -EINVAL;
4506 : : }
4507 : :
4508 : : /* Mirroring. */
4509 : 0 : status = rte_swx_pipeline_mirroring_config(p, &s->mirroring_params);
4510 [ # # ]: 0 : if (status) {
4511 [ # # ]: 0 : if (err_msg)
4512 : 0 : *err_msg = "Pipeline mirroring configuration error.";
4513 : 0 : return status;
4514 : : }
4515 : :
4516 : : /* Input ports. */
4517 [ # # ]: 0 : for (i = 0; i < s->n_ports_in; i++) {
4518 : 0 : status = rte_swx_pipeline_port_in_config(p,
4519 : : i,
4520 : 0 : s->port_in_type[i],
4521 : 0 : s->port_in_params[i]);
4522 [ # # ]: 0 : if (status) {
4523 [ # # ]: 0 : if (err_msg)
4524 : 0 : *err_msg = "Pipeline input port configuration error.";
4525 : 0 : return status;
4526 : : }
4527 : : }
4528 : :
4529 : : /* Output ports. */
4530 [ # # ]: 0 : for (i = 0; i < s->n_ports_out; i++) {
4531 : 0 : status = rte_swx_pipeline_port_out_config(p,
4532 : : i,
4533 : 0 : s->port_out_type[i],
4534 : 0 : s->port_out_params[i]);
4535 [ # # ]: 0 : if (status) {
4536 [ # # ]: 0 : if (err_msg)
4537 : 0 : *err_msg = "Pipeline output port configuration error.";
4538 : 0 : return status;
4539 : : }
4540 : : }
4541 : :
4542 : : return 0;
4543 : : }
|