xref: /dpdk/lib/pipeline/rte_swx_pipeline.c (revision 1dd3e5e2ccde33e35e4224241e82f2034aa2fd4d)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2020 Intel Corporation
3  */
4 #include <stdlib.h>
5 #include <stdio.h>
6 #include <errno.h>
7 #include <dlfcn.h>
8 
9 #include <rte_tailq.h>
10 #include <rte_eal_memconfig.h>
11 #include <rte_jhash.h>
12 #include <rte_hash_crc.h>
13 
14 #include <rte_swx_port_ethdev.h>
15 #include <rte_swx_port_fd.h>
16 #include <rte_swx_port_ring.h>
17 #include "rte_swx_port_source_sink.h"
18 
19 #include <rte_swx_table_em.h>
20 #include <rte_swx_table_wm.h>
21 
22 #include "rte_swx_pipeline_internal.h"
23 #include "rte_swx_pipeline_spec.h"
24 
25 #define CHECK(condition, err_code)                                             \
26 do {                                                                           \
27 	if (!(condition))                                                      \
28 		return -(err_code);                                            \
29 } while (0)
30 
31 #define CHECK_NAME(name, err_code)                                             \
32 	CHECK((name) &&                                                        \
33 	      (name)[0] &&                                                     \
34 	      (strnlen((name), RTE_SWX_NAME_SIZE) < RTE_SWX_NAME_SIZE),        \
35 	      err_code)
36 
37 #define CHECK_INSTRUCTION(instr, err_code)                                     \
38 	CHECK((instr) &&                                                       \
39 	      (instr)[0] &&                                                    \
40 	      (strnlen((instr), RTE_SWX_INSTRUCTION_SIZE) <                    \
41 	       RTE_SWX_INSTRUCTION_SIZE),                                      \
42 	      err_code)
43 
44 /*
45  * Environment.
46  */
47 #ifndef RTE_SWX_PIPELINE_HUGE_PAGES_DISABLE
48 
49 #include <rte_malloc.h>
50 
51 static void *
env_malloc(size_t size,size_t alignment,int numa_node)52 env_malloc(size_t size, size_t alignment, int numa_node)
53 {
54 	return rte_zmalloc_socket(NULL, size, alignment, numa_node);
55 }
56 
57 static void
env_free(void * start,size_t size __rte_unused)58 env_free(void *start, size_t size __rte_unused)
59 {
60 	rte_free(start);
61 }
62 
63 #else
64 
65 #include <numa.h>
66 
67 static void *
env_malloc(size_t size,size_t alignment __rte_unused,int numa_node)68 env_malloc(size_t size, size_t alignment __rte_unused, int numa_node)
69 {
70 	void *start;
71 
72 	if (numa_available() == -1)
73 		return NULL;
74 
75 	start = numa_alloc_onnode(size, numa_node);
76 	if (!start)
77 		return NULL;
78 
79 	memset(start, 0, size);
80 	return start;
81 }
82 
83 static void
env_free(void * start,size_t size)84 env_free(void *start, size_t size)
85 {
86 	if (numa_available() == -1)
87 		return;
88 
89 	numa_free(start, size);
90 }
91 
92 #endif
93 
94 /*
95  * Struct.
96  */
97 static struct struct_type *
struct_type_find(struct rte_swx_pipeline * p,const char * name)98 struct_type_find(struct rte_swx_pipeline *p, const char *name)
99 {
100 	struct struct_type *elem;
101 
102 	TAILQ_FOREACH(elem, &p->struct_types, node)
103 		if (strcmp(elem->name, name) == 0)
104 			return elem;
105 
106 	return NULL;
107 }
108 
109 static struct field *
struct_type_field_find(struct struct_type * st,const char * name)110 struct_type_field_find(struct struct_type *st, const char *name)
111 {
112 	uint32_t i;
113 
114 	for (i = 0; i < st->n_fields; i++) {
115 		struct field *f = &st->fields[i];
116 
117 		if (strcmp(f->name, name) == 0)
118 			return f;
119 	}
120 
121 	return NULL;
122 }
123 
124 int
rte_swx_pipeline_struct_type_register(struct rte_swx_pipeline * p,const char * name,struct rte_swx_field_params * fields,uint32_t n_fields,int last_field_has_variable_size)125 rte_swx_pipeline_struct_type_register(struct rte_swx_pipeline *p,
126 				      const char *name,
127 				      struct rte_swx_field_params *fields,
128 				      uint32_t n_fields,
129 				      int last_field_has_variable_size)
130 {
131 	struct struct_type *st;
132 	uint32_t i;
133 
134 	CHECK(p, EINVAL);
135 	CHECK_NAME(name, EINVAL);
136 	CHECK(fields, EINVAL);
137 	CHECK(n_fields, EINVAL);
138 
139 	for (i = 0; i < n_fields; i++) {
140 		struct rte_swx_field_params *f = &fields[i];
141 		uint32_t j;
142 
143 		CHECK_NAME(f->name, EINVAL);
144 		CHECK(f->n_bits, EINVAL);
145 		CHECK((f->n_bits & 7) == 0, EINVAL);
146 
147 		for (j = 0; j < i; j++) {
148 			struct rte_swx_field_params *f_prev = &fields[j];
149 
150 			CHECK(strcmp(f->name, f_prev->name), EINVAL);
151 		}
152 	}
153 
154 	CHECK(!struct_type_find(p, name), EEXIST);
155 
156 	/* Node allocation. */
157 	st = calloc(1, sizeof(struct struct_type));
158 	CHECK(st, ENOMEM);
159 
160 	st->fields = calloc(n_fields, sizeof(struct field));
161 	if (!st->fields) {
162 		free(st);
163 		CHECK(0, ENOMEM);
164 	}
165 
166 	/* Node initialization. */
167 	strcpy(st->name, name);
168 	for (i = 0; i < n_fields; i++) {
169 		struct field *dst = &st->fields[i];
170 		struct rte_swx_field_params *src = &fields[i];
171 		int var_size = ((i == n_fields - 1) && last_field_has_variable_size) ? 1 : 0;
172 
173 		strcpy(dst->name, src->name);
174 		dst->n_bits = src->n_bits;
175 		dst->offset = st->n_bits;
176 		dst->var_size = var_size;
177 
178 		st->n_bits += src->n_bits;
179 		st->n_bits_min += var_size ? 0 : src->n_bits;
180 	}
181 	st->n_fields = n_fields;
182 	st->var_size = last_field_has_variable_size;
183 
184 	/* Node add to tailq. */
185 	TAILQ_INSERT_TAIL(&p->struct_types, st, node);
186 
187 	return 0;
188 }
189 
190 static int
struct_build(struct rte_swx_pipeline * p)191 struct_build(struct rte_swx_pipeline *p)
192 {
193 	uint32_t i;
194 
195 	for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
196 		struct thread *t = &p->threads[i];
197 
198 		t->structs = calloc(p->n_structs, sizeof(uint8_t *));
199 		CHECK(t->structs, ENOMEM);
200 	}
201 
202 	return 0;
203 }
204 
205 static void
struct_build_free(struct rte_swx_pipeline * p)206 struct_build_free(struct rte_swx_pipeline *p)
207 {
208 	uint32_t i;
209 
210 	for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
211 		struct thread *t = &p->threads[i];
212 
213 		free(t->structs);
214 		t->structs = NULL;
215 	}
216 }
217 
218 static void
struct_free(struct rte_swx_pipeline * p)219 struct_free(struct rte_swx_pipeline *p)
220 {
221 	struct_build_free(p);
222 
223 	/* Struct types. */
224 	for ( ; ; ) {
225 		struct struct_type *elem;
226 
227 		elem = TAILQ_FIRST(&p->struct_types);
228 		if (!elem)
229 			break;
230 
231 		TAILQ_REMOVE(&p->struct_types, elem, node);
232 		free(elem->fields);
233 		free(elem);
234 	}
235 }
236 
237 /*
238  * Input port.
239  */
240 static struct port_in_type *
port_in_type_find(struct rte_swx_pipeline * p,const char * name)241 port_in_type_find(struct rte_swx_pipeline *p, const char *name)
242 {
243 	struct port_in_type *elem;
244 
245 	if (!name)
246 		return NULL;
247 
248 	TAILQ_FOREACH(elem, &p->port_in_types, node)
249 		if (strcmp(elem->name, name) == 0)
250 			return elem;
251 
252 	return NULL;
253 }
254 
255 int
rte_swx_pipeline_port_in_type_register(struct rte_swx_pipeline * p,const char * name,struct rte_swx_port_in_ops * ops)256 rte_swx_pipeline_port_in_type_register(struct rte_swx_pipeline *p,
257 				       const char *name,
258 				       struct rte_swx_port_in_ops *ops)
259 {
260 	struct port_in_type *elem;
261 
262 	CHECK(p, EINVAL);
263 	CHECK_NAME(name, EINVAL);
264 	CHECK(ops, EINVAL);
265 	CHECK(ops->create, EINVAL);
266 	CHECK(ops->free, EINVAL);
267 	CHECK(ops->pkt_rx, EINVAL);
268 	CHECK(ops->stats_read, EINVAL);
269 
270 	CHECK(!port_in_type_find(p, name), EEXIST);
271 
272 	/* Node allocation. */
273 	elem = calloc(1, sizeof(struct port_in_type));
274 	CHECK(elem, ENOMEM);
275 
276 	/* Node initialization. */
277 	strcpy(elem->name, name);
278 	memcpy(&elem->ops, ops, sizeof(*ops));
279 
280 	/* Node add to tailq. */
281 	TAILQ_INSERT_TAIL(&p->port_in_types, elem, node);
282 
283 	return 0;
284 }
285 
286 static struct port_in *
port_in_find(struct rte_swx_pipeline * p,uint32_t port_id)287 port_in_find(struct rte_swx_pipeline *p, uint32_t port_id)
288 {
289 	struct port_in *port;
290 
291 	TAILQ_FOREACH(port, &p->ports_in, node)
292 		if (port->id == port_id)
293 			return port;
294 
295 	return NULL;
296 }
297 
298 int
rte_swx_pipeline_port_in_config(struct rte_swx_pipeline * p,uint32_t port_id,const char * port_type_name,void * args)299 rte_swx_pipeline_port_in_config(struct rte_swx_pipeline *p,
300 				uint32_t port_id,
301 				const char *port_type_name,
302 				void *args)
303 {
304 	struct port_in_type *type = NULL;
305 	struct port_in *port = NULL;
306 	void *obj = NULL;
307 
308 	CHECK(p, EINVAL);
309 
310 	CHECK(!port_in_find(p, port_id), EINVAL);
311 
312 	CHECK_NAME(port_type_name, EINVAL);
313 	type = port_in_type_find(p, port_type_name);
314 	CHECK(type, EINVAL);
315 
316 	obj = type->ops.create(args);
317 	CHECK(obj, ENODEV);
318 
319 	/* Node allocation. */
320 	port = calloc(1, sizeof(struct port_in));
321 	CHECK(port, ENOMEM);
322 
323 	/* Node initialization. */
324 	port->type = type;
325 	port->obj = obj;
326 	port->id = port_id;
327 
328 	/* Node add to tailq. */
329 	TAILQ_INSERT_TAIL(&p->ports_in, port, node);
330 	if (p->n_ports_in < port_id + 1)
331 		p->n_ports_in = port_id + 1;
332 
333 	return 0;
334 }
335 
336 static int
port_in_build(struct rte_swx_pipeline * p)337 port_in_build(struct rte_swx_pipeline *p)
338 {
339 	struct port_in *port;
340 	uint32_t i;
341 
342 	CHECK(p->n_ports_in, EINVAL);
343 
344 	for (i = 0; i < p->n_ports_in; i++)
345 		CHECK(port_in_find(p, i), EINVAL);
346 
347 	p->in = calloc(p->n_ports_in, sizeof(struct port_in_runtime));
348 	CHECK(p->in, ENOMEM);
349 
350 	TAILQ_FOREACH(port, &p->ports_in, node) {
351 		struct port_in_runtime *in = &p->in[port->id];
352 
353 		in->pkt_rx = port->type->ops.pkt_rx;
354 		in->obj = port->obj;
355 	}
356 
357 	return 0;
358 }
359 
360 static void
port_in_build_free(struct rte_swx_pipeline * p)361 port_in_build_free(struct rte_swx_pipeline *p)
362 {
363 	free(p->in);
364 	p->in = NULL;
365 }
366 
367 static void
port_in_free(struct rte_swx_pipeline * p)368 port_in_free(struct rte_swx_pipeline *p)
369 {
370 	port_in_build_free(p);
371 
372 	/* Input ports. */
373 	for ( ; ; ) {
374 		struct port_in *port;
375 
376 		port = TAILQ_FIRST(&p->ports_in);
377 		if (!port)
378 			break;
379 
380 		TAILQ_REMOVE(&p->ports_in, port, node);
381 		port->type->ops.free(port->obj);
382 		free(port);
383 	}
384 
385 	/* Input port types. */
386 	for ( ; ; ) {
387 		struct port_in_type *elem;
388 
389 		elem = TAILQ_FIRST(&p->port_in_types);
390 		if (!elem)
391 			break;
392 
393 		TAILQ_REMOVE(&p->port_in_types, elem, node);
394 		free(elem);
395 	}
396 }
397 
398 /*
399  * Output port.
400  */
401 static struct port_out_type *
port_out_type_find(struct rte_swx_pipeline * p,const char * name)402 port_out_type_find(struct rte_swx_pipeline *p, const char *name)
403 {
404 	struct port_out_type *elem;
405 
406 	if (!name)
407 		return NULL;
408 
409 	TAILQ_FOREACH(elem, &p->port_out_types, node)
410 		if (!strcmp(elem->name, name))
411 			return elem;
412 
413 	return NULL;
414 }
415 
416 int
rte_swx_pipeline_port_out_type_register(struct rte_swx_pipeline * p,const char * name,struct rte_swx_port_out_ops * ops)417 rte_swx_pipeline_port_out_type_register(struct rte_swx_pipeline *p,
418 					const char *name,
419 					struct rte_swx_port_out_ops *ops)
420 {
421 	struct port_out_type *elem;
422 
423 	CHECK(p, EINVAL);
424 	CHECK_NAME(name, EINVAL);
425 	CHECK(ops, EINVAL);
426 	CHECK(ops->create, EINVAL);
427 	CHECK(ops->free, EINVAL);
428 	CHECK(ops->pkt_tx, EINVAL);
429 	CHECK(ops->pkt_fast_clone_tx, EINVAL);
430 	CHECK(ops->pkt_clone_tx, EINVAL);
431 	CHECK(ops->stats_read, EINVAL);
432 
433 	CHECK(!port_out_type_find(p, name), EEXIST);
434 
435 	/* Node allocation. */
436 	elem = calloc(1, sizeof(struct port_out_type));
437 	CHECK(elem, ENOMEM);
438 
439 	/* Node initialization. */
440 	strcpy(elem->name, name);
441 	memcpy(&elem->ops, ops, sizeof(*ops));
442 
443 	/* Node add to tailq. */
444 	TAILQ_INSERT_TAIL(&p->port_out_types, elem, node);
445 
446 	return 0;
447 }
448 
449 static struct port_out *
port_out_find(struct rte_swx_pipeline * p,uint32_t port_id)450 port_out_find(struct rte_swx_pipeline *p, uint32_t port_id)
451 {
452 	struct port_out *port;
453 
454 	TAILQ_FOREACH(port, &p->ports_out, node)
455 		if (port->id == port_id)
456 			return port;
457 
458 	return NULL;
459 }
460 
461 int
rte_swx_pipeline_port_out_config(struct rte_swx_pipeline * p,uint32_t port_id,const char * port_type_name,void * args)462 rte_swx_pipeline_port_out_config(struct rte_swx_pipeline *p,
463 				 uint32_t port_id,
464 				 const char *port_type_name,
465 				 void *args)
466 {
467 	struct port_out_type *type = NULL;
468 	struct port_out *port = NULL;
469 	void *obj = NULL;
470 
471 	CHECK(p, EINVAL);
472 
473 	CHECK(!port_out_find(p, port_id), EINVAL);
474 
475 	CHECK_NAME(port_type_name, EINVAL);
476 	type = port_out_type_find(p, port_type_name);
477 	CHECK(type, EINVAL);
478 
479 	obj = type->ops.create(args);
480 	CHECK(obj, ENODEV);
481 
482 	/* Node allocation. */
483 	port = calloc(1, sizeof(struct port_out));
484 	CHECK(port, ENOMEM);
485 
486 	/* Node initialization. */
487 	port->type = type;
488 	port->obj = obj;
489 	port->id = port_id;
490 
491 	/* Node add to tailq. */
492 	TAILQ_INSERT_TAIL(&p->ports_out, port, node);
493 	if (p->n_ports_out < port_id + 1)
494 		p->n_ports_out = port_id + 1;
495 
496 	return 0;
497 }
498 
499 static int
port_out_build(struct rte_swx_pipeline * p)500 port_out_build(struct rte_swx_pipeline *p)
501 {
502 	struct port_out *port;
503 	uint32_t i;
504 
505 	CHECK(p->n_ports_out, EINVAL);
506 
507 	for (i = 0; i < p->n_ports_out; i++)
508 		CHECK(port_out_find(p, i), EINVAL);
509 
510 	p->out = calloc(p->n_ports_out, sizeof(struct port_out_runtime));
511 	CHECK(p->out, ENOMEM);
512 
513 	TAILQ_FOREACH(port, &p->ports_out, node) {
514 		struct port_out_runtime *out = &p->out[port->id];
515 
516 		out->pkt_tx = port->type->ops.pkt_tx;
517 		out->pkt_fast_clone_tx = port->type->ops.pkt_fast_clone_tx;
518 		out->pkt_clone_tx = port->type->ops.pkt_clone_tx;
519 		out->flush = port->type->ops.flush;
520 		out->obj = port->obj;
521 	}
522 
523 	return 0;
524 }
525 
526 static void
port_out_build_free(struct rte_swx_pipeline * p)527 port_out_build_free(struct rte_swx_pipeline *p)
528 {
529 	free(p->out);
530 	p->out = NULL;
531 }
532 
533 static void
port_out_free(struct rte_swx_pipeline * p)534 port_out_free(struct rte_swx_pipeline *p)
535 {
536 	port_out_build_free(p);
537 
538 	/* Output ports. */
539 	for ( ; ; ) {
540 		struct port_out *port;
541 
542 		port = TAILQ_FIRST(&p->ports_out);
543 		if (!port)
544 			break;
545 
546 		TAILQ_REMOVE(&p->ports_out, port, node);
547 		port->type->ops.free(port->obj);
548 		free(port);
549 	}
550 
551 	/* Output port types. */
552 	for ( ; ; ) {
553 		struct port_out_type *elem;
554 
555 		elem = TAILQ_FIRST(&p->port_out_types);
556 		if (!elem)
557 			break;
558 
559 		TAILQ_REMOVE(&p->port_out_types, elem, node);
560 		free(elem);
561 	}
562 }
563 
564 /*
565  * Packet mirroring.
566  */
567 int
rte_swx_pipeline_mirroring_config(struct rte_swx_pipeline * p,struct rte_swx_pipeline_mirroring_params * params)568 rte_swx_pipeline_mirroring_config(struct rte_swx_pipeline *p,
569 				  struct rte_swx_pipeline_mirroring_params *params)
570 {
571 	CHECK(p, EINVAL);
572 	CHECK(params, EINVAL);
573 	CHECK(params->n_slots, EINVAL);
574 	CHECK(params->n_sessions, EINVAL);
575 	CHECK(!p->build_done, EEXIST);
576 
577 	p->n_mirroring_slots = rte_align32pow2(params->n_slots);
578 	if (p->n_mirroring_slots > 64)
579 		p->n_mirroring_slots = 64;
580 
581 	p->n_mirroring_sessions = rte_align32pow2(params->n_sessions);
582 
583 	return 0;
584 }
585 
586 static void
mirroring_build_free(struct rte_swx_pipeline * p)587 mirroring_build_free(struct rte_swx_pipeline *p)
588 {
589 	uint32_t i;
590 
591 	for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
592 		struct thread *t = &p->threads[i];
593 
594 		/* mirroring_slots. */
595 		free(t->mirroring_slots);
596 		t->mirroring_slots = NULL;
597 	}
598 
599 	/* mirroring_sessions. */
600 	free(p->mirroring_sessions);
601 	p->mirroring_sessions = NULL;
602 }
603 
604 static void
mirroring_free(struct rte_swx_pipeline * p)605 mirroring_free(struct rte_swx_pipeline *p)
606 {
607 	mirroring_build_free(p);
608 }
609 
610 static int
mirroring_build(struct rte_swx_pipeline * p)611 mirroring_build(struct rte_swx_pipeline *p)
612 {
613 	uint32_t i;
614 
615 	for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
616 		struct thread *t = &p->threads[i];
617 
618 		/* mirroring_slots. */
619 		t->mirroring_slots = calloc(p->n_mirroring_slots, sizeof(uint32_t));
620 		if (!t->mirroring_slots)
621 			goto error;
622 	}
623 
624 	/* mirroring_sessions. */
625 	p->mirroring_sessions = calloc(p->n_mirroring_sessions, sizeof(struct mirroring_session));
626 	if (!p->mirroring_sessions)
627 		goto error;
628 
629 	return 0;
630 
631 error:
632 	mirroring_build_free(p);
633 	return -ENOMEM;
634 }
635 
636 /*
637  * Extern object.
638  */
639 static struct extern_type *
extern_type_find(struct rte_swx_pipeline * p,const char * name)640 extern_type_find(struct rte_swx_pipeline *p, const char *name)
641 {
642 	struct extern_type *elem;
643 
644 	TAILQ_FOREACH(elem, &p->extern_types, node)
645 		if (strcmp(elem->name, name) == 0)
646 			return elem;
647 
648 	return NULL;
649 }
650 
651 static struct extern_type_member_func *
extern_type_member_func_find(struct extern_type * type,const char * name)652 extern_type_member_func_find(struct extern_type *type, const char *name)
653 {
654 	struct extern_type_member_func *elem;
655 
656 	TAILQ_FOREACH(elem, &type->funcs, node)
657 		if (strcmp(elem->name, name) == 0)
658 			return elem;
659 
660 	return NULL;
661 }
662 
663 static struct extern_obj *
extern_obj_find(struct rte_swx_pipeline * p,const char * name)664 extern_obj_find(struct rte_swx_pipeline *p, const char *name)
665 {
666 	struct extern_obj *elem;
667 
668 	TAILQ_FOREACH(elem, &p->extern_objs, node)
669 		if (strcmp(elem->name, name) == 0)
670 			return elem;
671 
672 	return NULL;
673 }
674 
675 static struct extern_type_member_func *
extern_obj_member_func_parse(struct rte_swx_pipeline * p,const char * name,struct extern_obj ** obj)676 extern_obj_member_func_parse(struct rte_swx_pipeline *p,
677 			     const char *name,
678 			     struct extern_obj **obj)
679 {
680 	struct extern_obj *object;
681 	struct extern_type_member_func *func;
682 	char *object_name, *func_name;
683 
684 	if (name[0] != 'e' || name[1] != '.')
685 		return NULL;
686 
687 	object_name = strdup(&name[2]);
688 	if (!object_name)
689 		return NULL;
690 
691 	func_name = strchr(object_name, '.');
692 	if (!func_name) {
693 		free(object_name);
694 		return NULL;
695 	}
696 
697 	*func_name = 0;
698 	func_name++;
699 
700 	object = extern_obj_find(p, object_name);
701 	if (!object) {
702 		free(object_name);
703 		return NULL;
704 	}
705 
706 	func = extern_type_member_func_find(object->type, func_name);
707 	if (!func) {
708 		free(object_name);
709 		return NULL;
710 	}
711 
712 	if (obj)
713 		*obj = object;
714 
715 	free(object_name);
716 	return func;
717 }
718 
719 static struct field *
extern_obj_mailbox_field_parse(struct rte_swx_pipeline * p,const char * name,struct extern_obj ** object)720 extern_obj_mailbox_field_parse(struct rte_swx_pipeline *p,
721 			       const char *name,
722 			       struct extern_obj **object)
723 {
724 	struct extern_obj *obj;
725 	struct field *f;
726 	char *obj_name, *field_name;
727 
728 	if ((name[0] != 'e') || (name[1] != '.'))
729 		return NULL;
730 
731 	obj_name = strdup(&name[2]);
732 	if (!obj_name)
733 		return NULL;
734 
735 	field_name = strchr(obj_name, '.');
736 	if (!field_name) {
737 		free(obj_name);
738 		return NULL;
739 	}
740 
741 	*field_name = 0;
742 	field_name++;
743 
744 	obj = extern_obj_find(p, obj_name);
745 	if (!obj) {
746 		free(obj_name);
747 		return NULL;
748 	}
749 
750 	f = struct_type_field_find(obj->type->mailbox_struct_type, field_name);
751 	if (!f) {
752 		free(obj_name);
753 		return NULL;
754 	}
755 
756 	if (object)
757 		*object = obj;
758 
759 	free(obj_name);
760 	return f;
761 }
762 
763 int
rte_swx_pipeline_extern_type_register(struct rte_swx_pipeline * p,const char * name,const char * mailbox_struct_type_name,rte_swx_extern_type_constructor_t constructor,rte_swx_extern_type_destructor_t destructor)764 rte_swx_pipeline_extern_type_register(struct rte_swx_pipeline *p,
765 	const char *name,
766 	const char *mailbox_struct_type_name,
767 	rte_swx_extern_type_constructor_t constructor,
768 	rte_swx_extern_type_destructor_t destructor)
769 {
770 	struct extern_type *elem;
771 	struct struct_type *mailbox_struct_type;
772 
773 	CHECK(p, EINVAL);
774 
775 	CHECK_NAME(name, EINVAL);
776 	CHECK(!extern_type_find(p, name), EEXIST);
777 
778 	CHECK_NAME(mailbox_struct_type_name, EINVAL);
779 	mailbox_struct_type = struct_type_find(p, mailbox_struct_type_name);
780 	CHECK(mailbox_struct_type, EINVAL);
781 	CHECK(!mailbox_struct_type->var_size, EINVAL);
782 
783 	CHECK(constructor, EINVAL);
784 	CHECK(destructor, EINVAL);
785 
786 	/* Node allocation. */
787 	elem = calloc(1, sizeof(struct extern_type));
788 	CHECK(elem, ENOMEM);
789 
790 	/* Node initialization. */
791 	strcpy(elem->name, name);
792 	elem->mailbox_struct_type = mailbox_struct_type;
793 	elem->constructor = constructor;
794 	elem->destructor = destructor;
795 	TAILQ_INIT(&elem->funcs);
796 
797 	/* Node add to tailq. */
798 	TAILQ_INSERT_TAIL(&p->extern_types, elem, node);
799 
800 	return 0;
801 }
802 
803 int
rte_swx_pipeline_extern_type_member_func_register(struct rte_swx_pipeline * p,const char * extern_type_name,const char * name,rte_swx_extern_type_member_func_t member_func)804 rte_swx_pipeline_extern_type_member_func_register(struct rte_swx_pipeline *p,
805 	const char *extern_type_name,
806 	const char *name,
807 	rte_swx_extern_type_member_func_t member_func)
808 {
809 	struct extern_type *type;
810 	struct extern_type_member_func *type_member;
811 
812 	CHECK(p, EINVAL);
813 
814 	CHECK_NAME(extern_type_name, EINVAL);
815 	type = extern_type_find(p, extern_type_name);
816 	CHECK(type, EINVAL);
817 	CHECK(type->n_funcs < RTE_SWX_EXTERN_TYPE_MEMBER_FUNCS_MAX, ENOSPC);
818 
819 	CHECK_NAME(name, EINVAL);
820 	CHECK(!extern_type_member_func_find(type, name), EEXIST);
821 
822 	CHECK(member_func, EINVAL);
823 
824 	/* Node allocation. */
825 	type_member = calloc(1, sizeof(struct extern_type_member_func));
826 	CHECK(type_member, ENOMEM);
827 
828 	/* Node initialization. */
829 	strcpy(type_member->name, name);
830 	type_member->func = member_func;
831 	type_member->id = type->n_funcs;
832 
833 	/* Node add to tailq. */
834 	TAILQ_INSERT_TAIL(&type->funcs, type_member, node);
835 	type->n_funcs++;
836 
837 	return 0;
838 }
839 
840 int
rte_swx_pipeline_extern_object_config(struct rte_swx_pipeline * p,const char * extern_type_name,const char * name,const char * args)841 rte_swx_pipeline_extern_object_config(struct rte_swx_pipeline *p,
842 				      const char *extern_type_name,
843 				      const char *name,
844 				      const char *args)
845 {
846 	struct extern_type *type;
847 	struct extern_obj *obj;
848 	void *obj_handle;
849 
850 	CHECK(p, EINVAL);
851 
852 	CHECK_NAME(extern_type_name, EINVAL);
853 	type = extern_type_find(p, extern_type_name);
854 	CHECK(type, EINVAL);
855 
856 	CHECK_NAME(name, EINVAL);
857 	CHECK(!extern_obj_find(p, name), EEXIST);
858 
859 	/* Node allocation. */
860 	obj = calloc(1, sizeof(struct extern_obj));
861 	CHECK(obj, ENOMEM);
862 
863 	/* Object construction. */
864 	obj_handle = type->constructor(args);
865 	if (!obj_handle) {
866 		free(obj);
867 		CHECK(0, ENODEV);
868 	}
869 
870 	/* Node initialization. */
871 	strcpy(obj->name, name);
872 	obj->type = type;
873 	obj->obj = obj_handle;
874 	obj->struct_id = p->n_structs;
875 	obj->id = p->n_extern_objs;
876 
877 	/* Node add to tailq. */
878 	TAILQ_INSERT_TAIL(&p->extern_objs, obj, node);
879 	p->n_extern_objs++;
880 	p->n_structs++;
881 
882 	return 0;
883 }
884 
885 static int
extern_obj_build(struct rte_swx_pipeline * p)886 extern_obj_build(struct rte_swx_pipeline *p)
887 {
888 	uint32_t i;
889 
890 	for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
891 		struct thread *t = &p->threads[i];
892 		struct extern_obj *obj;
893 
894 		t->extern_objs = calloc(p->n_extern_objs,
895 					sizeof(struct extern_obj_runtime));
896 		CHECK(t->extern_objs, ENOMEM);
897 
898 		TAILQ_FOREACH(obj, &p->extern_objs, node) {
899 			struct extern_obj_runtime *r =
900 				&t->extern_objs[obj->id];
901 			struct extern_type_member_func *func;
902 			uint32_t mailbox_size =
903 				obj->type->mailbox_struct_type->n_bits / 8;
904 
905 			r->obj = obj->obj;
906 
907 			r->mailbox = calloc(1, mailbox_size);
908 			CHECK(r->mailbox, ENOMEM);
909 
910 			TAILQ_FOREACH(func, &obj->type->funcs, node)
911 				r->funcs[func->id] = func->func;
912 
913 			t->structs[obj->struct_id] = r->mailbox;
914 		}
915 	}
916 
917 	return 0;
918 }
919 
920 static void
extern_obj_build_free(struct rte_swx_pipeline * p)921 extern_obj_build_free(struct rte_swx_pipeline *p)
922 {
923 	uint32_t i;
924 
925 	for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
926 		struct thread *t = &p->threads[i];
927 		uint32_t j;
928 
929 		if (!t->extern_objs)
930 			continue;
931 
932 		for (j = 0; j < p->n_extern_objs; j++) {
933 			struct extern_obj_runtime *r = &t->extern_objs[j];
934 
935 			free(r->mailbox);
936 		}
937 
938 		free(t->extern_objs);
939 		t->extern_objs = NULL;
940 	}
941 }
942 
943 static void
extern_obj_free(struct rte_swx_pipeline * p)944 extern_obj_free(struct rte_swx_pipeline *p)
945 {
946 	extern_obj_build_free(p);
947 
948 	/* Extern objects. */
949 	for ( ; ; ) {
950 		struct extern_obj *elem;
951 
952 		elem = TAILQ_FIRST(&p->extern_objs);
953 		if (!elem)
954 			break;
955 
956 		TAILQ_REMOVE(&p->extern_objs, elem, node);
957 		if (elem->obj)
958 			elem->type->destructor(elem->obj);
959 		free(elem);
960 	}
961 
962 	/* Extern types. */
963 	for ( ; ; ) {
964 		struct extern_type *elem;
965 
966 		elem = TAILQ_FIRST(&p->extern_types);
967 		if (!elem)
968 			break;
969 
970 		TAILQ_REMOVE(&p->extern_types, elem, node);
971 
972 		for ( ; ; ) {
973 			struct extern_type_member_func *func;
974 
975 			func = TAILQ_FIRST(&elem->funcs);
976 			if (!func)
977 				break;
978 
979 			TAILQ_REMOVE(&elem->funcs, func, node);
980 			free(func);
981 		}
982 
983 		free(elem);
984 	}
985 }
986 
987 /*
988  * Extern function.
989  */
990 static struct extern_func *
extern_func_find(struct rte_swx_pipeline * p,const char * name)991 extern_func_find(struct rte_swx_pipeline *p, const char *name)
992 {
993 	struct extern_func *elem;
994 
995 	TAILQ_FOREACH(elem, &p->extern_funcs, node)
996 		if (strcmp(elem->name, name) == 0)
997 			return elem;
998 
999 	return NULL;
1000 }
1001 
1002 static struct extern_func *
extern_func_parse(struct rte_swx_pipeline * p,const char * name)1003 extern_func_parse(struct rte_swx_pipeline *p,
1004 		  const char *name)
1005 {
1006 	if (name[0] != 'f' || name[1] != '.')
1007 		return NULL;
1008 
1009 	return extern_func_find(p, &name[2]);
1010 }
1011 
1012 static struct field *
extern_func_mailbox_field_parse(struct rte_swx_pipeline * p,const char * name,struct extern_func ** function)1013 extern_func_mailbox_field_parse(struct rte_swx_pipeline *p,
1014 				const char *name,
1015 				struct extern_func **function)
1016 {
1017 	struct extern_func *func;
1018 	struct field *f;
1019 	char *func_name, *field_name;
1020 
1021 	if ((name[0] != 'f') || (name[1] != '.'))
1022 		return NULL;
1023 
1024 	func_name = strdup(&name[2]);
1025 	if (!func_name)
1026 		return NULL;
1027 
1028 	field_name = strchr(func_name, '.');
1029 	if (!field_name) {
1030 		free(func_name);
1031 		return NULL;
1032 	}
1033 
1034 	*field_name = 0;
1035 	field_name++;
1036 
1037 	func = extern_func_find(p, func_name);
1038 	if (!func) {
1039 		free(func_name);
1040 		return NULL;
1041 	}
1042 
1043 	f = struct_type_field_find(func->mailbox_struct_type, field_name);
1044 	if (!f) {
1045 		free(func_name);
1046 		return NULL;
1047 	}
1048 
1049 	if (function)
1050 		*function = func;
1051 
1052 	free(func_name);
1053 	return f;
1054 }
1055 
1056 int
rte_swx_pipeline_extern_func_register(struct rte_swx_pipeline * p,const char * name,const char * mailbox_struct_type_name,rte_swx_extern_func_t func)1057 rte_swx_pipeline_extern_func_register(struct rte_swx_pipeline *p,
1058 				      const char *name,
1059 				      const char *mailbox_struct_type_name,
1060 				      rte_swx_extern_func_t func)
1061 {
1062 	struct extern_func *f;
1063 	struct struct_type *mailbox_struct_type;
1064 
1065 	CHECK(p, EINVAL);
1066 
1067 	CHECK_NAME(name, EINVAL);
1068 	CHECK(!extern_func_find(p, name), EEXIST);
1069 
1070 	CHECK_NAME(mailbox_struct_type_name, EINVAL);
1071 	mailbox_struct_type = struct_type_find(p, mailbox_struct_type_name);
1072 	CHECK(mailbox_struct_type, EINVAL);
1073 	CHECK(!mailbox_struct_type->var_size, EINVAL);
1074 
1075 	CHECK(func, EINVAL);
1076 
1077 	/* Node allocation. */
1078 	f = calloc(1, sizeof(struct extern_func));
1079 	CHECK(func, ENOMEM);
1080 
1081 	/* Node initialization. */
1082 	strcpy(f->name, name);
1083 	f->mailbox_struct_type = mailbox_struct_type;
1084 	f->func = func;
1085 	f->struct_id = p->n_structs;
1086 	f->id = p->n_extern_funcs;
1087 
1088 	/* Node add to tailq. */
1089 	TAILQ_INSERT_TAIL(&p->extern_funcs, f, node);
1090 	p->n_extern_funcs++;
1091 	p->n_structs++;
1092 
1093 	return 0;
1094 }
1095 
1096 static int
extern_func_build(struct rte_swx_pipeline * p)1097 extern_func_build(struct rte_swx_pipeline *p)
1098 {
1099 	uint32_t i;
1100 
1101 	for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1102 		struct thread *t = &p->threads[i];
1103 		struct extern_func *func;
1104 
1105 		/* Memory allocation. */
1106 		t->extern_funcs = calloc(p->n_extern_funcs,
1107 					 sizeof(struct extern_func_runtime));
1108 		CHECK(t->extern_funcs, ENOMEM);
1109 
1110 		/* Extern function. */
1111 		TAILQ_FOREACH(func, &p->extern_funcs, node) {
1112 			struct extern_func_runtime *r =
1113 				&t->extern_funcs[func->id];
1114 			uint32_t mailbox_size =
1115 				func->mailbox_struct_type->n_bits / 8;
1116 
1117 			r->func = func->func;
1118 
1119 			r->mailbox = calloc(1, mailbox_size);
1120 			CHECK(r->mailbox, ENOMEM);
1121 
1122 			t->structs[func->struct_id] = r->mailbox;
1123 		}
1124 	}
1125 
1126 	return 0;
1127 }
1128 
1129 static void
extern_func_build_free(struct rte_swx_pipeline * p)1130 extern_func_build_free(struct rte_swx_pipeline *p)
1131 {
1132 	uint32_t i;
1133 
1134 	for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1135 		struct thread *t = &p->threads[i];
1136 		uint32_t j;
1137 
1138 		if (!t->extern_funcs)
1139 			continue;
1140 
1141 		for (j = 0; j < p->n_extern_funcs; j++) {
1142 			struct extern_func_runtime *r = &t->extern_funcs[j];
1143 
1144 			free(r->mailbox);
1145 		}
1146 
1147 		free(t->extern_funcs);
1148 		t->extern_funcs = NULL;
1149 	}
1150 }
1151 
1152 static void
extern_func_free(struct rte_swx_pipeline * p)1153 extern_func_free(struct rte_swx_pipeline *p)
1154 {
1155 	extern_func_build_free(p);
1156 
1157 	for ( ; ; ) {
1158 		struct extern_func *elem;
1159 
1160 		elem = TAILQ_FIRST(&p->extern_funcs);
1161 		if (!elem)
1162 			break;
1163 
1164 		TAILQ_REMOVE(&p->extern_funcs, elem, node);
1165 		free(elem);
1166 	}
1167 }
1168 
1169 /*
1170  * Hash function.
1171  */
1172 static struct hash_func *
hash_func_find(struct rte_swx_pipeline * p,const char * name)1173 hash_func_find(struct rte_swx_pipeline *p, const char *name)
1174 {
1175 	struct hash_func *elem;
1176 
1177 	TAILQ_FOREACH(elem, &p->hash_funcs, node)
1178 		if (strcmp(elem->name, name) == 0)
1179 			return elem;
1180 
1181 	return NULL;
1182 }
1183 
1184 int
rte_swx_pipeline_hash_func_register(struct rte_swx_pipeline * p,const char * name,rte_swx_hash_func_t func)1185 rte_swx_pipeline_hash_func_register(struct rte_swx_pipeline *p,
1186 				    const char *name,
1187 				    rte_swx_hash_func_t func)
1188 {
1189 	struct hash_func *f;
1190 
1191 	CHECK(p, EINVAL);
1192 
1193 	CHECK_NAME(name, EINVAL);
1194 	CHECK(!hash_func_find(p, name), EEXIST);
1195 
1196 	CHECK(func, EINVAL);
1197 
1198 	/* Node allocation. */
1199 	f = calloc(1, sizeof(struct hash_func));
1200 	CHECK(func, ENOMEM);
1201 
1202 	/* Node initialization. */
1203 	strcpy(f->name, name);
1204 	f->func = func;
1205 	f->id = p->n_hash_funcs;
1206 
1207 	/* Node add to tailq. */
1208 	TAILQ_INSERT_TAIL(&p->hash_funcs, f, node);
1209 	p->n_hash_funcs++;
1210 
1211 	return 0;
1212 }
1213 
1214 static int
hash_func_build(struct rte_swx_pipeline * p)1215 hash_func_build(struct rte_swx_pipeline *p)
1216 {
1217 	struct hash_func *func;
1218 
1219 	/* Memory allocation. */
1220 	p->hash_func_runtime = calloc(p->n_hash_funcs, sizeof(struct hash_func_runtime));
1221 	CHECK(p->hash_func_runtime, ENOMEM);
1222 
1223 	/* Hash function. */
1224 	TAILQ_FOREACH(func, &p->hash_funcs, node) {
1225 		struct hash_func_runtime *r = &p->hash_func_runtime[func->id];
1226 
1227 		r->func = func->func;
1228 	}
1229 
1230 	return 0;
1231 }
1232 
1233 static void
hash_func_build_free(struct rte_swx_pipeline * p)1234 hash_func_build_free(struct rte_swx_pipeline *p)
1235 {
1236 	free(p->hash_func_runtime);
1237 	p->hash_func_runtime = NULL;
1238 }
1239 
1240 static void
hash_func_free(struct rte_swx_pipeline * p)1241 hash_func_free(struct rte_swx_pipeline *p)
1242 {
1243 	hash_func_build_free(p);
1244 
1245 	for ( ; ; ) {
1246 		struct hash_func *elem;
1247 
1248 		elem = TAILQ_FIRST(&p->hash_funcs);
1249 		if (!elem)
1250 			break;
1251 
1252 		TAILQ_REMOVE(&p->hash_funcs, elem, node);
1253 		free(elem);
1254 	}
1255 }
1256 
1257 /*
1258  * RSS.
1259  */
1260 static struct rss *
rss_find(struct rte_swx_pipeline * p,const char * name)1261 rss_find(struct rte_swx_pipeline *p, const char *name)
1262 {
1263 	struct rss *elem;
1264 
1265 	TAILQ_FOREACH(elem, &p->rss, node)
1266 		if (strcmp(elem->name, name) == 0)
1267 			return elem;
1268 
1269 	return NULL;
1270 }
1271 
1272 static struct rss *
rss_find_by_id(struct rte_swx_pipeline * p,uint32_t rss_obj_id)1273 rss_find_by_id(struct rte_swx_pipeline *p, uint32_t rss_obj_id)
1274 {
1275 	struct rss *elem;
1276 
1277 	TAILQ_FOREACH(elem, &p->rss, node)
1278 		if (elem->id == rss_obj_id)
1279 			return elem;
1280 
1281 	return NULL;
1282 }
1283 
1284 int
rte_swx_pipeline_rss_config(struct rte_swx_pipeline * p,const char * name)1285 rte_swx_pipeline_rss_config(struct rte_swx_pipeline *p, const char *name)
1286 {
1287 	struct rss *r;
1288 
1289 	CHECK(p, EINVAL);
1290 
1291 	CHECK_NAME(name, EINVAL);
1292 	CHECK(!rss_find(p, name), EEXIST);
1293 
1294 	/* Memory allocation. */
1295 	r = calloc(1, sizeof(struct rss));
1296 	CHECK(r, ENOMEM);
1297 
1298 	/* Node initialization. */
1299 	strcpy(r->name, name);
1300 	r->id = p->n_rss;
1301 
1302 	/* Node add to tailq. */
1303 	TAILQ_INSERT_TAIL(&p->rss, r, node);
1304 	p->n_rss++;
1305 
1306 	return 0;
1307 }
1308 
1309 static void
rss_build_free(struct rte_swx_pipeline * p)1310 rss_build_free(struct rte_swx_pipeline *p)
1311 {
1312 	uint32_t i;
1313 
1314 	if (!p->rss_runtime)
1315 		return;
1316 
1317 	for (i = 0; i < p->n_rss; i++)
1318 		free(p->rss_runtime[i]);
1319 
1320 	free(p->rss_runtime);
1321 	p->rss_runtime = NULL;
1322 }
1323 
1324 static const struct {
1325 	uint32_t key_size;
1326 	uint8_t key[4];
1327 } rss_runtime_default = {
1328 	.key_size = 4,
1329 	.key = {0, 0, 0, 0},
1330 };
1331 
1332 static int
rss_build(struct rte_swx_pipeline * p)1333 rss_build(struct rte_swx_pipeline *p)
1334 {
1335 	uint32_t i;
1336 	int status = 0;
1337 
1338 	/* Memory allocation. */
1339 	p->rss_runtime = calloc(p->n_rss, sizeof(struct rss_runtime *));
1340 	if (!p->rss_runtime) {
1341 		status = -ENOMEM;
1342 		goto error;
1343 	}
1344 
1345 	/* RSS. */
1346 	for (i = 0; i < p->n_rss; i++) {
1347 		p->rss_runtime[i] = malloc(sizeof(rss_runtime_default));
1348 		if (!p->rss_runtime[i]) {
1349 			status = -ENOMEM;
1350 			goto error;
1351 		}
1352 
1353 		memcpy(p->rss_runtime[i], &rss_runtime_default, sizeof(rss_runtime_default));
1354 	}
1355 
1356 	return 0;
1357 
1358 error:
1359 	rss_build_free(p);
1360 	return status;
1361 }
1362 
1363 static void
rss_free(struct rte_swx_pipeline * p)1364 rss_free(struct rte_swx_pipeline *p)
1365 {
1366 	rss_build_free(p);
1367 
1368 	for ( ; ; ) {
1369 		struct rss *elem;
1370 
1371 		elem = TAILQ_FIRST(&p->rss);
1372 		if (!elem)
1373 			break;
1374 
1375 		TAILQ_REMOVE(&p->rss, elem, node);
1376 		free(elem);
1377 	}
1378 }
1379 
1380 /*
1381  * Header.
1382  */
1383 static struct header *
header_find(struct rte_swx_pipeline * p,const char * name)1384 header_find(struct rte_swx_pipeline *p, const char *name)
1385 {
1386 	struct header *elem;
1387 
1388 	TAILQ_FOREACH(elem, &p->headers, node)
1389 		if (strcmp(elem->name, name) == 0)
1390 			return elem;
1391 
1392 	return NULL;
1393 }
1394 
1395 static struct header *
header_find_by_struct_id(struct rte_swx_pipeline * p,uint32_t struct_id)1396 header_find_by_struct_id(struct rte_swx_pipeline *p, uint32_t struct_id)
1397 {
1398 	struct header *elem;
1399 
1400 	TAILQ_FOREACH(elem, &p->headers, node)
1401 		if (elem->struct_id == struct_id)
1402 			return elem;
1403 
1404 	return NULL;
1405 }
1406 
1407 static struct header *
header_parse(struct rte_swx_pipeline * p,const char * name)1408 header_parse(struct rte_swx_pipeline *p,
1409 	     const char *name)
1410 {
1411 	if (name[0] != 'h' || name[1] != '.')
1412 		return NULL;
1413 
1414 	return header_find(p, &name[2]);
1415 }
1416 
1417 static struct field *
header_field_parse(struct rte_swx_pipeline * p,const char * name,struct header ** header)1418 header_field_parse(struct rte_swx_pipeline *p,
1419 		   const char *name,
1420 		   struct header **header)
1421 {
1422 	struct header *h;
1423 	struct field *f;
1424 	char *header_name, *field_name;
1425 
1426 	if ((name[0] != 'h') || (name[1] != '.'))
1427 		return NULL;
1428 
1429 	header_name = strdup(&name[2]);
1430 	if (!header_name)
1431 		return NULL;
1432 
1433 	field_name = strchr(header_name, '.');
1434 	if (!field_name) {
1435 		free(header_name);
1436 		return NULL;
1437 	}
1438 
1439 	*field_name = 0;
1440 	field_name++;
1441 
1442 	h = header_find(p, header_name);
1443 	if (!h) {
1444 		free(header_name);
1445 		return NULL;
1446 	}
1447 
1448 	f = struct_type_field_find(h->st, field_name);
1449 	if (!f) {
1450 		free(header_name);
1451 		return NULL;
1452 	}
1453 
1454 	if (header)
1455 		*header = h;
1456 
1457 	free(header_name);
1458 	return f;
1459 }
1460 
1461 int
rte_swx_pipeline_packet_header_register(struct rte_swx_pipeline * p,const char * name,const char * struct_type_name)1462 rte_swx_pipeline_packet_header_register(struct rte_swx_pipeline *p,
1463 					const char *name,
1464 					const char *struct_type_name)
1465 {
1466 	struct struct_type *st;
1467 	struct header *h;
1468 	size_t n_headers_max;
1469 
1470 	CHECK(p, EINVAL);
1471 	CHECK_NAME(name, EINVAL);
1472 	CHECK_NAME(struct_type_name, EINVAL);
1473 
1474 	CHECK(!header_find(p, name), EEXIST);
1475 
1476 	st = struct_type_find(p, struct_type_name);
1477 	CHECK(st, EINVAL);
1478 
1479 	n_headers_max = RTE_SIZEOF_FIELD(struct thread, valid_headers) * 8;
1480 	CHECK(p->n_headers < n_headers_max, ENOSPC);
1481 
1482 	/* Node allocation. */
1483 	h = calloc(1, sizeof(struct header));
1484 	CHECK(h, ENOMEM);
1485 
1486 	/* Node initialization. */
1487 	strcpy(h->name, name);
1488 	h->st = st;
1489 	h->struct_id = p->n_structs;
1490 	h->id = p->n_headers;
1491 
1492 	/* Node add to tailq. */
1493 	TAILQ_INSERT_TAIL(&p->headers, h, node);
1494 	p->n_headers++;
1495 	p->n_structs++;
1496 
1497 	return 0;
1498 }
1499 
1500 static int
header_build(struct rte_swx_pipeline * p)1501 header_build(struct rte_swx_pipeline *p)
1502 {
1503 	struct header *h;
1504 	uint32_t n_bytes = 0, i;
1505 
1506 	TAILQ_FOREACH(h, &p->headers, node) {
1507 		n_bytes += h->st->n_bits / 8;
1508 	}
1509 
1510 	for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1511 		struct thread *t = &p->threads[i];
1512 		uint32_t offset = 0;
1513 
1514 		t->headers = calloc(p->n_headers,
1515 				    sizeof(struct header_runtime));
1516 		CHECK(t->headers, ENOMEM);
1517 
1518 		t->headers_out = calloc(p->n_headers,
1519 					sizeof(struct header_out_runtime));
1520 		CHECK(t->headers_out, ENOMEM);
1521 
1522 		t->header_storage = calloc(1, n_bytes);
1523 		CHECK(t->header_storage, ENOMEM);
1524 
1525 		t->header_out_storage = calloc(1, n_bytes);
1526 		CHECK(t->header_out_storage, ENOMEM);
1527 
1528 		TAILQ_FOREACH(h, &p->headers, node) {
1529 			uint8_t *header_storage;
1530 			uint32_t n_bytes =  h->st->n_bits / 8;
1531 
1532 			header_storage = &t->header_storage[offset];
1533 			offset += n_bytes;
1534 
1535 			t->headers[h->id].ptr0 = header_storage;
1536 			t->headers[h->id].n_bytes = n_bytes;
1537 
1538 			t->structs[h->struct_id] = header_storage;
1539 		}
1540 	}
1541 
1542 	return 0;
1543 }
1544 
1545 static void
header_build_free(struct rte_swx_pipeline * p)1546 header_build_free(struct rte_swx_pipeline *p)
1547 {
1548 	uint32_t i;
1549 
1550 	for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1551 		struct thread *t = &p->threads[i];
1552 
1553 		free(t->headers_out);
1554 		t->headers_out = NULL;
1555 
1556 		free(t->headers);
1557 		t->headers = NULL;
1558 
1559 		free(t->header_out_storage);
1560 		t->header_out_storage = NULL;
1561 
1562 		free(t->header_storage);
1563 		t->header_storage = NULL;
1564 	}
1565 }
1566 
1567 static void
header_free(struct rte_swx_pipeline * p)1568 header_free(struct rte_swx_pipeline *p)
1569 {
1570 	header_build_free(p);
1571 
1572 	for ( ; ; ) {
1573 		struct header *elem;
1574 
1575 		elem = TAILQ_FIRST(&p->headers);
1576 		if (!elem)
1577 			break;
1578 
1579 		TAILQ_REMOVE(&p->headers, elem, node);
1580 		free(elem);
1581 	}
1582 }
1583 
1584 /*
1585  * Meta-data.
1586  */
1587 static struct field *
metadata_field_parse(struct rte_swx_pipeline * p,const char * name)1588 metadata_field_parse(struct rte_swx_pipeline *p, const char *name)
1589 {
1590 	if (!p->metadata_st)
1591 		return NULL;
1592 
1593 	if (name[0] != 'm' || name[1] != '.')
1594 		return NULL;
1595 
1596 	return struct_type_field_find(p->metadata_st, &name[2]);
1597 }
1598 
1599 int
rte_swx_pipeline_packet_metadata_register(struct rte_swx_pipeline * p,const char * struct_type_name)1600 rte_swx_pipeline_packet_metadata_register(struct rte_swx_pipeline *p,
1601 					  const char *struct_type_name)
1602 {
1603 	struct struct_type *st = NULL;
1604 
1605 	CHECK(p, EINVAL);
1606 
1607 	CHECK_NAME(struct_type_name, EINVAL);
1608 	st  = struct_type_find(p, struct_type_name);
1609 	CHECK(st, EINVAL);
1610 	CHECK(!st->var_size, EINVAL);
1611 	CHECK(!p->metadata_st, EINVAL);
1612 
1613 	p->metadata_st = st;
1614 	p->metadata_struct_id = p->n_structs;
1615 
1616 	p->n_structs++;
1617 
1618 	return 0;
1619 }
1620 
1621 static int
metadata_build(struct rte_swx_pipeline * p)1622 metadata_build(struct rte_swx_pipeline *p)
1623 {
1624 	uint32_t n_bytes = p->metadata_st->n_bits / 8;
1625 	uint32_t i;
1626 
1627 	/* Thread-level initialization. */
1628 	for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1629 		struct thread *t = &p->threads[i];
1630 		uint8_t *metadata;
1631 
1632 		metadata = calloc(1, n_bytes);
1633 		CHECK(metadata, ENOMEM);
1634 
1635 		t->metadata = metadata;
1636 		t->structs[p->metadata_struct_id] = metadata;
1637 	}
1638 
1639 	return 0;
1640 }
1641 
1642 static void
metadata_build_free(struct rte_swx_pipeline * p)1643 metadata_build_free(struct rte_swx_pipeline *p)
1644 {
1645 	uint32_t i;
1646 
1647 	for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1648 		struct thread *t = &p->threads[i];
1649 
1650 		free(t->metadata);
1651 		t->metadata = NULL;
1652 	}
1653 }
1654 
1655 static void
metadata_free(struct rte_swx_pipeline * p)1656 metadata_free(struct rte_swx_pipeline *p)
1657 {
1658 	metadata_build_free(p);
1659 }
1660 
1661 /*
1662  * Instruction.
1663  */
1664 static int
instruction_is_tx(enum instruction_type type)1665 instruction_is_tx(enum instruction_type type)
1666 {
1667 	switch (type) {
1668 	case INSTR_TX:
1669 	case INSTR_TX_I:
1670 	case INSTR_DROP:
1671 		return 1;
1672 
1673 	default:
1674 		return 0;
1675 	}
1676 }
1677 
1678 static int
instruction_does_tx(struct instruction * instr)1679 instruction_does_tx(struct instruction *instr)
1680 {
1681 	switch (instr->type) {
1682 	case INSTR_TX:
1683 	case INSTR_TX_I:
1684 	case INSTR_DROP:
1685 	case INSTR_HDR_EMIT_TX:
1686 	case INSTR_HDR_EMIT2_TX:
1687 	case INSTR_HDR_EMIT3_TX:
1688 	case INSTR_HDR_EMIT4_TX:
1689 	case INSTR_HDR_EMIT5_TX:
1690 	case INSTR_HDR_EMIT6_TX:
1691 	case INSTR_HDR_EMIT7_TX:
1692 	case INSTR_HDR_EMIT8_TX:
1693 		return 1;
1694 	default:
1695 		return 0;
1696 	}
1697 }
1698 
1699 static int
instruction_is_jmp(struct instruction * instr)1700 instruction_is_jmp(struct instruction *instr)
1701 {
1702 	switch (instr->type) {
1703 	case INSTR_JMP:
1704 	case INSTR_JMP_VALID:
1705 	case INSTR_JMP_INVALID:
1706 	case INSTR_JMP_HIT:
1707 	case INSTR_JMP_MISS:
1708 	case INSTR_JMP_ACTION_HIT:
1709 	case INSTR_JMP_ACTION_MISS:
1710 	case INSTR_JMP_EQ:
1711 	case INSTR_JMP_EQ_MH:
1712 	case INSTR_JMP_EQ_HM:
1713 	case INSTR_JMP_EQ_HH:
1714 	case INSTR_JMP_EQ_I:
1715 	case INSTR_JMP_NEQ:
1716 	case INSTR_JMP_NEQ_MH:
1717 	case INSTR_JMP_NEQ_HM:
1718 	case INSTR_JMP_NEQ_HH:
1719 	case INSTR_JMP_NEQ_I:
1720 	case INSTR_JMP_LT:
1721 	case INSTR_JMP_LT_MH:
1722 	case INSTR_JMP_LT_HM:
1723 	case INSTR_JMP_LT_HH:
1724 	case INSTR_JMP_LT_MI:
1725 	case INSTR_JMP_LT_HI:
1726 	case INSTR_JMP_GT:
1727 	case INSTR_JMP_GT_MH:
1728 	case INSTR_JMP_GT_HM:
1729 	case INSTR_JMP_GT_HH:
1730 	case INSTR_JMP_GT_MI:
1731 	case INSTR_JMP_GT_HI:
1732 		return 1;
1733 
1734 	default:
1735 		return 0;
1736 	}
1737 }
1738 
1739 static int
instruction_does_thread_yield(struct instruction * instr)1740 instruction_does_thread_yield(struct instruction *instr)
1741 {
1742 	switch (instr->type) {
1743 	case INSTR_RX:
1744 	case INSTR_TABLE:
1745 	case INSTR_TABLE_AF:
1746 	case INSTR_SELECTOR:
1747 	case INSTR_LEARNER:
1748 	case INSTR_LEARNER_AF:
1749 	case INSTR_EXTERN_OBJ:
1750 	case INSTR_EXTERN_FUNC:
1751 		return 1;
1752 	default:
1753 		return 0;
1754 	}
1755 }
1756 
1757 static struct field *
1758 action_field_parse(struct action *action, const char *name);
1759 
1760 static struct field *
struct_field_parse(struct rte_swx_pipeline * p,struct action * action,const char * name,uint32_t * struct_id)1761 struct_field_parse(struct rte_swx_pipeline *p,
1762 		   struct action *action,
1763 		   const char *name,
1764 		   uint32_t *struct_id)
1765 {
1766 	struct field *f;
1767 
1768 	switch (name[0]) {
1769 	case 'h':
1770 	{
1771 		struct header *header;
1772 
1773 		f = header_field_parse(p, name, &header);
1774 		if (!f)
1775 			return NULL;
1776 
1777 		*struct_id = header->struct_id;
1778 		return f;
1779 	}
1780 
1781 	case 'm':
1782 	{
1783 		f = metadata_field_parse(p, name);
1784 		if (!f)
1785 			return NULL;
1786 
1787 		*struct_id = p->metadata_struct_id;
1788 		return f;
1789 	}
1790 
1791 	case 't':
1792 	{
1793 		if (!action)
1794 			return NULL;
1795 
1796 		f = action_field_parse(action, name);
1797 		if (!f)
1798 			return NULL;
1799 
1800 		*struct_id = 0;
1801 		return f;
1802 	}
1803 
1804 	case 'e':
1805 	{
1806 		struct extern_obj *obj;
1807 
1808 		f = extern_obj_mailbox_field_parse(p, name, &obj);
1809 		if (!f)
1810 			return NULL;
1811 
1812 		*struct_id = obj->struct_id;
1813 		return f;
1814 	}
1815 
1816 	case 'f':
1817 	{
1818 		struct extern_func *func;
1819 
1820 		f = extern_func_mailbox_field_parse(p, name, &func);
1821 		if (!f)
1822 			return NULL;
1823 
1824 		*struct_id = func->struct_id;
1825 		return f;
1826 	}
1827 
1828 	default:
1829 		return NULL;
1830 	}
1831 }
1832 
1833 /*
1834  * rx.
1835  */
1836 static int
instr_rx_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)1837 instr_rx_translate(struct rte_swx_pipeline *p,
1838 		   struct action *action,
1839 		   char **tokens,
1840 		   int n_tokens,
1841 		   struct instruction *instr,
1842 		   struct instruction_data *data __rte_unused)
1843 {
1844 	struct field *f;
1845 
1846 	CHECK(!action, EINVAL);
1847 	CHECK(n_tokens == 2, EINVAL);
1848 
1849 	f = metadata_field_parse(p, tokens[1]);
1850 	CHECK(f, EINVAL);
1851 	CHECK(f->n_bits <= 64, EINVAL);
1852 
1853 	instr->type = INSTR_RX;
1854 	instr->io.io.offset = f->offset / 8;
1855 	instr->io.io.n_bits = f->n_bits;
1856 	return 0;
1857 }
1858 
1859 /*
1860  * tx.
1861  */
1862 static int
instr_tx_translate(struct rte_swx_pipeline * p,struct action * action __rte_unused,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)1863 instr_tx_translate(struct rte_swx_pipeline *p,
1864 		   struct action *action __rte_unused,
1865 		   char **tokens,
1866 		   int n_tokens,
1867 		   struct instruction *instr,
1868 		   struct instruction_data *data __rte_unused)
1869 {
1870 	char *port = tokens[1];
1871 	struct field *f;
1872 	uint32_t port_val;
1873 
1874 	CHECK(n_tokens == 2, EINVAL);
1875 
1876 	f = metadata_field_parse(p, port);
1877 	if (f) {
1878 		CHECK(f->n_bits <= 64, EINVAL);
1879 		instr->type = INSTR_TX;
1880 		instr->io.io.offset = f->offset / 8;
1881 		instr->io.io.n_bits = f->n_bits;
1882 		return 0;
1883 	}
1884 
1885 	/* TX_I. */
1886 	port_val = strtoul(port, &port, 0);
1887 	CHECK(!port[0], EINVAL);
1888 
1889 	instr->type = INSTR_TX_I;
1890 	instr->io.io.val = port_val;
1891 	return 0;
1892 }
1893 
1894 static int
instr_drop_translate(struct rte_swx_pipeline * p __rte_unused,struct action * action __rte_unused,char ** tokens __rte_unused,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)1895 instr_drop_translate(struct rte_swx_pipeline *p __rte_unused,
1896 		     struct action *action __rte_unused,
1897 		     char **tokens __rte_unused,
1898 		     int n_tokens,
1899 		     struct instruction *instr,
1900 		     struct instruction_data *data __rte_unused)
1901 {
1902 	CHECK(n_tokens == 1, EINVAL);
1903 
1904 	/* DROP. */
1905 	instr->type = INSTR_DROP;
1906 	return 0;
1907 }
1908 
1909 static inline void
instr_tx_exec(struct rte_swx_pipeline * p)1910 instr_tx_exec(struct rte_swx_pipeline *p)
1911 {
1912 	struct thread *t = &p->threads[p->thread_id];
1913 	struct instruction *ip = t->ip;
1914 
1915 	__instr_tx_exec(p, t, ip);
1916 
1917 	/* Thread. */
1918 	thread_ip_reset(p, t);
1919 	instr_rx_exec(p);
1920 }
1921 
1922 static inline void
instr_tx_i_exec(struct rte_swx_pipeline * p)1923 instr_tx_i_exec(struct rte_swx_pipeline *p)
1924 {
1925 	struct thread *t = &p->threads[p->thread_id];
1926 	struct instruction *ip = t->ip;
1927 
1928 	__instr_tx_i_exec(p, t, ip);
1929 
1930 	/* Thread. */
1931 	thread_ip_reset(p, t);
1932 	instr_rx_exec(p);
1933 }
1934 
1935 static inline void
instr_drop_exec(struct rte_swx_pipeline * p)1936 instr_drop_exec(struct rte_swx_pipeline *p)
1937 {
1938 	struct thread *t = &p->threads[p->thread_id];
1939 	struct instruction *ip = t->ip;
1940 
1941 	__instr_drop_exec(p, t, ip);
1942 
1943 	/* Thread. */
1944 	thread_ip_reset(p, t);
1945 	instr_rx_exec(p);
1946 }
1947 
1948 /*
1949  * mirror.
1950  */
1951 static int
instr_mirror_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)1952 instr_mirror_translate(struct rte_swx_pipeline *p,
1953 		       struct action *action,
1954 		       char **tokens,
1955 		       int n_tokens,
1956 		       struct instruction *instr,
1957 		       struct instruction_data *data __rte_unused)
1958 {
1959 	char *dst = tokens[1], *src = tokens[2];
1960 	struct field *fdst, *fsrc;
1961 	uint32_t dst_struct_id = 0, src_struct_id = 0;
1962 
1963 	CHECK(n_tokens == 3, EINVAL);
1964 
1965 	fdst = struct_field_parse(p, action, dst, &dst_struct_id);
1966 	CHECK(fdst, EINVAL);
1967 	CHECK(dst[0] != 'h', EINVAL);
1968 	CHECK(!fdst->var_size && (fdst->n_bits <= 64), EINVAL);
1969 
1970 	fsrc = struct_field_parse(p, action, src, &src_struct_id);
1971 	CHECK(fsrc, EINVAL);
1972 	CHECK(src[0] != 'h', EINVAL);
1973 	CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
1974 
1975 	instr->type = INSTR_MIRROR;
1976 	instr->mirror.dst.struct_id = (uint8_t)dst_struct_id;
1977 	instr->mirror.dst.n_bits = fdst->n_bits;
1978 	instr->mirror.dst.offset = fdst->offset / 8;
1979 	instr->mirror.src.struct_id = (uint8_t)src_struct_id;
1980 	instr->mirror.src.n_bits = fsrc->n_bits;
1981 	instr->mirror.src.offset = fsrc->offset / 8;
1982 
1983 	return 0;
1984 }
1985 
1986 static inline void
instr_mirror_exec(struct rte_swx_pipeline * p)1987 instr_mirror_exec(struct rte_swx_pipeline *p)
1988 {
1989 	struct thread *t = &p->threads[p->thread_id];
1990 	struct instruction *ip = t->ip;
1991 
1992 	__instr_mirror_exec(p, t, ip);
1993 
1994 	/* Thread. */
1995 	thread_ip_inc(p);
1996 }
1997 
1998 /*
1999  * recirculate.
2000  */
2001 static int
instr_recirculate_translate(struct rte_swx_pipeline * p __rte_unused,struct action * action __rte_unused,char ** tokens __rte_unused,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)2002 instr_recirculate_translate(struct rte_swx_pipeline *p __rte_unused,
2003 			    struct action *action __rte_unused,
2004 			    char **tokens __rte_unused,
2005 			    int n_tokens,
2006 			    struct instruction *instr,
2007 			    struct instruction_data *data __rte_unused)
2008 {
2009 	CHECK(n_tokens == 1, EINVAL);
2010 
2011 	instr->type = INSTR_RECIRCULATE;
2012 	return 0;
2013 }
2014 
2015 static int
instr_recircid_translate(struct rte_swx_pipeline * p,struct action * action __rte_unused,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)2016 instr_recircid_translate(struct rte_swx_pipeline *p,
2017 			 struct action *action __rte_unused,
2018 			 char **tokens,
2019 			 int n_tokens,
2020 			 struct instruction *instr,
2021 			 struct instruction_data *data __rte_unused)
2022 {
2023 	struct field *f;
2024 
2025 	CHECK(n_tokens == 2, EINVAL);
2026 
2027 	f = metadata_field_parse(p, tokens[1]);
2028 	CHECK(f, EINVAL);
2029 	CHECK(f->n_bits <= 64, EINVAL);
2030 
2031 	instr->type = INSTR_RECIRCID;
2032 	instr->io.io.offset = f->offset / 8;
2033 	instr->io.io.n_bits = f->n_bits;
2034 	return 0;
2035 }
2036 
2037 static inline void
instr_recirculate_exec(struct rte_swx_pipeline * p)2038 instr_recirculate_exec(struct rte_swx_pipeline *p)
2039 {
2040 	struct thread *t = &p->threads[p->thread_id];
2041 	struct instruction *ip = t->ip;
2042 
2043 	__instr_recirculate_exec(p, t, ip);
2044 
2045 	/* Thread. */
2046 	thread_ip_inc(p);
2047 }
2048 
2049 static inline void
instr_recircid_exec(struct rte_swx_pipeline * p)2050 instr_recircid_exec(struct rte_swx_pipeline *p)
2051 {
2052 	struct thread *t = &p->threads[p->thread_id];
2053 	struct instruction *ip = t->ip;
2054 
2055 	__instr_recircid_exec(p, t, ip);
2056 
2057 	/* Thread. */
2058 	thread_ip_inc(p);
2059 }
2060 
2061 /*
2062  * extract.
2063  */
2064 static int
instr_hdr_extract_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)2065 instr_hdr_extract_translate(struct rte_swx_pipeline *p,
2066 			    struct action *action,
2067 			    char **tokens,
2068 			    int n_tokens,
2069 			    struct instruction *instr,
2070 			    struct instruction_data *data __rte_unused)
2071 {
2072 	struct header *h;
2073 
2074 	CHECK(!action, EINVAL);
2075 	CHECK((n_tokens == 2) || (n_tokens == 3), EINVAL);
2076 
2077 	h = header_parse(p, tokens[1]);
2078 	CHECK(h, EINVAL);
2079 
2080 	if (n_tokens == 2) {
2081 		CHECK(!h->st->var_size, EINVAL);
2082 
2083 		instr->type = INSTR_HDR_EXTRACT;
2084 		instr->io.hdr.header_id[0] = h->id;
2085 		instr->io.hdr.struct_id[0] = h->struct_id;
2086 		instr->io.hdr.n_bytes[0] = h->st->n_bits / 8;
2087 	} else {
2088 		struct field *mf;
2089 
2090 		CHECK(h->st->var_size, EINVAL);
2091 
2092 		mf = metadata_field_parse(p, tokens[2]);
2093 		CHECK(mf, EINVAL);
2094 		CHECK(mf->n_bits <= 64, EINVAL);
2095 
2096 		instr->type = INSTR_HDR_EXTRACT_M;
2097 		instr->io.io.offset = mf->offset / 8;
2098 		instr->io.io.n_bits = mf->n_bits;
2099 		instr->io.hdr.header_id[0] = h->id;
2100 		instr->io.hdr.struct_id[0] = h->struct_id;
2101 		instr->io.hdr.n_bytes[0] = h->st->n_bits_min / 8;
2102 	}
2103 
2104 	return 0;
2105 }
2106 
2107 static int
instr_hdr_lookahead_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)2108 instr_hdr_lookahead_translate(struct rte_swx_pipeline *p,
2109 			      struct action *action,
2110 			      char **tokens,
2111 			      int n_tokens,
2112 			      struct instruction *instr,
2113 			      struct instruction_data *data __rte_unused)
2114 {
2115 	struct header *h;
2116 
2117 	CHECK(!action, EINVAL);
2118 	CHECK(n_tokens == 2, EINVAL);
2119 
2120 	h = header_parse(p, tokens[1]);
2121 	CHECK(h, EINVAL);
2122 	CHECK(!h->st->var_size, EINVAL);
2123 
2124 	instr->type = INSTR_HDR_LOOKAHEAD;
2125 	instr->io.hdr.header_id[0] = h->id;
2126 	instr->io.hdr.struct_id[0] = h->struct_id;
2127 	instr->io.hdr.n_bytes[0] = 0; /* Unused. */
2128 
2129 	return 0;
2130 }
2131 
2132 static inline void
instr_hdr_extract_exec(struct rte_swx_pipeline * p)2133 instr_hdr_extract_exec(struct rte_swx_pipeline *p)
2134 {
2135 	struct thread *t = &p->threads[p->thread_id];
2136 	struct instruction *ip = t->ip;
2137 
2138 	__instr_hdr_extract_exec(p, t, ip);
2139 
2140 	/* Thread. */
2141 	thread_ip_inc(p);
2142 }
2143 
2144 static inline void
instr_hdr_extract2_exec(struct rte_swx_pipeline * p)2145 instr_hdr_extract2_exec(struct rte_swx_pipeline *p)
2146 {
2147 	struct thread *t = &p->threads[p->thread_id];
2148 	struct instruction *ip = t->ip;
2149 
2150 	__instr_hdr_extract2_exec(p, t, ip);
2151 
2152 	/* Thread. */
2153 	thread_ip_inc(p);
2154 }
2155 
2156 static inline void
instr_hdr_extract3_exec(struct rte_swx_pipeline * p)2157 instr_hdr_extract3_exec(struct rte_swx_pipeline *p)
2158 {
2159 	struct thread *t = &p->threads[p->thread_id];
2160 	struct instruction *ip = t->ip;
2161 
2162 	__instr_hdr_extract3_exec(p, t, ip);
2163 
2164 	/* Thread. */
2165 	thread_ip_inc(p);
2166 }
2167 
2168 static inline void
instr_hdr_extract4_exec(struct rte_swx_pipeline * p)2169 instr_hdr_extract4_exec(struct rte_swx_pipeline *p)
2170 {
2171 	struct thread *t = &p->threads[p->thread_id];
2172 	struct instruction *ip = t->ip;
2173 
2174 	__instr_hdr_extract4_exec(p, t, ip);
2175 
2176 	/* Thread. */
2177 	thread_ip_inc(p);
2178 }
2179 
2180 static inline void
instr_hdr_extract5_exec(struct rte_swx_pipeline * p)2181 instr_hdr_extract5_exec(struct rte_swx_pipeline *p)
2182 {
2183 	struct thread *t = &p->threads[p->thread_id];
2184 	struct instruction *ip = t->ip;
2185 
2186 	__instr_hdr_extract5_exec(p, t, ip);
2187 
2188 	/* Thread. */
2189 	thread_ip_inc(p);
2190 }
2191 
2192 static inline void
instr_hdr_extract6_exec(struct rte_swx_pipeline * p)2193 instr_hdr_extract6_exec(struct rte_swx_pipeline *p)
2194 {
2195 	struct thread *t = &p->threads[p->thread_id];
2196 	struct instruction *ip = t->ip;
2197 
2198 	__instr_hdr_extract6_exec(p, t, ip);
2199 
2200 	/* Thread. */
2201 	thread_ip_inc(p);
2202 }
2203 
2204 static inline void
instr_hdr_extract7_exec(struct rte_swx_pipeline * p)2205 instr_hdr_extract7_exec(struct rte_swx_pipeline *p)
2206 {
2207 	struct thread *t = &p->threads[p->thread_id];
2208 	struct instruction *ip = t->ip;
2209 
2210 	__instr_hdr_extract7_exec(p, t, ip);
2211 
2212 	/* Thread. */
2213 	thread_ip_inc(p);
2214 }
2215 
2216 static inline void
instr_hdr_extract8_exec(struct rte_swx_pipeline * p)2217 instr_hdr_extract8_exec(struct rte_swx_pipeline *p)
2218 {
2219 	struct thread *t = &p->threads[p->thread_id];
2220 	struct instruction *ip = t->ip;
2221 
2222 	__instr_hdr_extract8_exec(p, t, ip);
2223 
2224 	/* Thread. */
2225 	thread_ip_inc(p);
2226 }
2227 
2228 static inline void
instr_hdr_extract_m_exec(struct rte_swx_pipeline * p)2229 instr_hdr_extract_m_exec(struct rte_swx_pipeline *p)
2230 {
2231 	struct thread *t = &p->threads[p->thread_id];
2232 	struct instruction *ip = t->ip;
2233 
2234 	__instr_hdr_extract_m_exec(p, t, ip);
2235 
2236 	/* Thread. */
2237 	thread_ip_inc(p);
2238 }
2239 
2240 static inline void
instr_hdr_lookahead_exec(struct rte_swx_pipeline * p)2241 instr_hdr_lookahead_exec(struct rte_swx_pipeline *p)
2242 {
2243 	struct thread *t = &p->threads[p->thread_id];
2244 	struct instruction *ip = t->ip;
2245 
2246 	__instr_hdr_lookahead_exec(p, t, ip);
2247 
2248 	/* Thread. */
2249 	thread_ip_inc(p);
2250 }
2251 
2252 /*
2253  * emit.
2254  */
2255 static int
instr_hdr_emit_translate(struct rte_swx_pipeline * p,struct action * action __rte_unused,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)2256 instr_hdr_emit_translate(struct rte_swx_pipeline *p,
2257 			 struct action *action __rte_unused,
2258 			 char **tokens,
2259 			 int n_tokens,
2260 			 struct instruction *instr,
2261 			 struct instruction_data *data __rte_unused)
2262 {
2263 	struct header *h;
2264 
2265 	CHECK(n_tokens == 2, EINVAL);
2266 
2267 	h = header_parse(p, tokens[1]);
2268 	CHECK(h, EINVAL);
2269 
2270 	instr->type = INSTR_HDR_EMIT;
2271 	instr->io.hdr.header_id[0] = h->id;
2272 	instr->io.hdr.struct_id[0] = h->struct_id;
2273 	instr->io.hdr.n_bytes[0] = h->st->n_bits / 8;
2274 	return 0;
2275 }
2276 
2277 static inline void
instr_hdr_emit_exec(struct rte_swx_pipeline * p)2278 instr_hdr_emit_exec(struct rte_swx_pipeline *p)
2279 {
2280 	struct thread *t = &p->threads[p->thread_id];
2281 	struct instruction *ip = t->ip;
2282 
2283 	__instr_hdr_emit_exec(p, t, ip);
2284 
2285 	/* Thread. */
2286 	thread_ip_inc(p);
2287 }
2288 
2289 static inline void
instr_hdr_emit_tx_exec(struct rte_swx_pipeline * p)2290 instr_hdr_emit_tx_exec(struct rte_swx_pipeline *p)
2291 {
2292 	struct thread *t = &p->threads[p->thread_id];
2293 	struct instruction *ip = t->ip;
2294 
2295 	__instr_hdr_emit_tx_exec(p, t, ip);
2296 
2297 	/* Thread. */
2298 	thread_ip_reset(p, t);
2299 	instr_rx_exec(p);
2300 }
2301 
2302 static inline void
instr_hdr_emit2_tx_exec(struct rte_swx_pipeline * p)2303 instr_hdr_emit2_tx_exec(struct rte_swx_pipeline *p)
2304 {
2305 	struct thread *t = &p->threads[p->thread_id];
2306 	struct instruction *ip = t->ip;
2307 
2308 	__instr_hdr_emit2_tx_exec(p, t, ip);
2309 
2310 	/* Thread. */
2311 	thread_ip_reset(p, t);
2312 	instr_rx_exec(p);
2313 }
2314 
2315 static inline void
instr_hdr_emit3_tx_exec(struct rte_swx_pipeline * p)2316 instr_hdr_emit3_tx_exec(struct rte_swx_pipeline *p)
2317 {
2318 	struct thread *t = &p->threads[p->thread_id];
2319 	struct instruction *ip = t->ip;
2320 
2321 	__instr_hdr_emit3_tx_exec(p, t, ip);
2322 
2323 	/* Thread. */
2324 	thread_ip_reset(p, t);
2325 	instr_rx_exec(p);
2326 }
2327 
2328 static inline void
instr_hdr_emit4_tx_exec(struct rte_swx_pipeline * p)2329 instr_hdr_emit4_tx_exec(struct rte_swx_pipeline *p)
2330 {
2331 	struct thread *t = &p->threads[p->thread_id];
2332 	struct instruction *ip = t->ip;
2333 
2334 	__instr_hdr_emit4_tx_exec(p, t, ip);
2335 
2336 	/* Thread. */
2337 	thread_ip_reset(p, t);
2338 	instr_rx_exec(p);
2339 }
2340 
2341 static inline void
instr_hdr_emit5_tx_exec(struct rte_swx_pipeline * p)2342 instr_hdr_emit5_tx_exec(struct rte_swx_pipeline *p)
2343 {
2344 	struct thread *t = &p->threads[p->thread_id];
2345 	struct instruction *ip = t->ip;
2346 
2347 	__instr_hdr_emit5_tx_exec(p, t, ip);
2348 
2349 	/* Thread. */
2350 	thread_ip_reset(p, t);
2351 	instr_rx_exec(p);
2352 }
2353 
2354 static inline void
instr_hdr_emit6_tx_exec(struct rte_swx_pipeline * p)2355 instr_hdr_emit6_tx_exec(struct rte_swx_pipeline *p)
2356 {
2357 	struct thread *t = &p->threads[p->thread_id];
2358 	struct instruction *ip = t->ip;
2359 
2360 	__instr_hdr_emit6_tx_exec(p, t, ip);
2361 
2362 	/* Thread. */
2363 	thread_ip_reset(p, t);
2364 	instr_rx_exec(p);
2365 }
2366 
2367 static inline void
instr_hdr_emit7_tx_exec(struct rte_swx_pipeline * p)2368 instr_hdr_emit7_tx_exec(struct rte_swx_pipeline *p)
2369 {
2370 	struct thread *t = &p->threads[p->thread_id];
2371 	struct instruction *ip = t->ip;
2372 
2373 	__instr_hdr_emit7_tx_exec(p, t, ip);
2374 
2375 	/* Thread. */
2376 	thread_ip_reset(p, t);
2377 	instr_rx_exec(p);
2378 }
2379 
2380 static inline void
instr_hdr_emit8_tx_exec(struct rte_swx_pipeline * p)2381 instr_hdr_emit8_tx_exec(struct rte_swx_pipeline *p)
2382 {
2383 	struct thread *t = &p->threads[p->thread_id];
2384 	struct instruction *ip = t->ip;
2385 
2386 	__instr_hdr_emit8_tx_exec(p, t, ip);
2387 
2388 	/* Thread. */
2389 	thread_ip_reset(p, t);
2390 	instr_rx_exec(p);
2391 }
2392 
2393 /*
2394  * validate.
2395  */
2396 static int
instr_hdr_validate_translate(struct rte_swx_pipeline * p,struct action * action __rte_unused,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)2397 instr_hdr_validate_translate(struct rte_swx_pipeline *p,
2398 			     struct action *action __rte_unused,
2399 			     char **tokens,
2400 			     int n_tokens,
2401 			     struct instruction *instr,
2402 			     struct instruction_data *data __rte_unused)
2403 {
2404 	struct header *h;
2405 
2406 	CHECK(n_tokens == 2, EINVAL);
2407 
2408 	h = header_parse(p, tokens[1]);
2409 	CHECK(h, EINVAL);
2410 
2411 	instr->type = INSTR_HDR_VALIDATE;
2412 	instr->valid.header_id = h->id;
2413 	instr->valid.struct_id = h->struct_id;
2414 	return 0;
2415 }
2416 
2417 static inline void
instr_hdr_validate_exec(struct rte_swx_pipeline * p)2418 instr_hdr_validate_exec(struct rte_swx_pipeline *p)
2419 {
2420 	struct thread *t = &p->threads[p->thread_id];
2421 	struct instruction *ip = t->ip;
2422 
2423 	__instr_hdr_validate_exec(p, t, ip);
2424 
2425 	/* Thread. */
2426 	thread_ip_inc(p);
2427 }
2428 
2429 /*
2430  * invalidate.
2431  */
2432 static int
instr_hdr_invalidate_translate(struct rte_swx_pipeline * p,struct action * action __rte_unused,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)2433 instr_hdr_invalidate_translate(struct rte_swx_pipeline *p,
2434 			       struct action *action __rte_unused,
2435 			       char **tokens,
2436 			       int n_tokens,
2437 			       struct instruction *instr,
2438 			       struct instruction_data *data __rte_unused)
2439 {
2440 	struct header *h;
2441 
2442 	CHECK(n_tokens == 2, EINVAL);
2443 
2444 	h = header_parse(p, tokens[1]);
2445 	CHECK(h, EINVAL);
2446 
2447 	instr->type = INSTR_HDR_INVALIDATE;
2448 	instr->valid.header_id = h->id;
2449 	return 0;
2450 }
2451 
2452 static inline void
instr_hdr_invalidate_exec(struct rte_swx_pipeline * p)2453 instr_hdr_invalidate_exec(struct rte_swx_pipeline *p)
2454 {
2455 	struct thread *t = &p->threads[p->thread_id];
2456 	struct instruction *ip = t->ip;
2457 
2458 	__instr_hdr_invalidate_exec(p, t, ip);
2459 
2460 	/* Thread. */
2461 	thread_ip_inc(p);
2462 }
2463 
2464 /*
2465  * table.
2466  */
2467 static struct table *
2468 table_find(struct rte_swx_pipeline *p, const char *name);
2469 
2470 static struct selector *
2471 selector_find(struct rte_swx_pipeline *p, const char *name);
2472 
2473 static struct learner *
2474 learner_find(struct rte_swx_pipeline *p, const char *name);
2475 
2476 static int
instr_table_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)2477 instr_table_translate(struct rte_swx_pipeline *p,
2478 		      struct action *action,
2479 		      char **tokens,
2480 		      int n_tokens,
2481 		      struct instruction *instr,
2482 		      struct instruction_data *data __rte_unused)
2483 {
2484 	struct table *t;
2485 	struct selector *s;
2486 	struct learner *l;
2487 
2488 	CHECK(!action, EINVAL);
2489 	CHECK(n_tokens == 2, EINVAL);
2490 
2491 	t = table_find(p, tokens[1]);
2492 	if (t) {
2493 		instr->type = INSTR_TABLE;
2494 		instr->table.table_id = t->id;
2495 		return 0;
2496 	}
2497 
2498 	s = selector_find(p, tokens[1]);
2499 	if (s) {
2500 		instr->type = INSTR_SELECTOR;
2501 		instr->table.table_id = s->id;
2502 		return 0;
2503 	}
2504 
2505 	l = learner_find(p, tokens[1]);
2506 	if (l) {
2507 		instr->type = INSTR_LEARNER;
2508 		instr->table.table_id = l->id;
2509 		return 0;
2510 	}
2511 
2512 	CHECK(0, EINVAL);
2513 }
2514 
2515 static inline void
instr_table_exec(struct rte_swx_pipeline * p)2516 instr_table_exec(struct rte_swx_pipeline *p)
2517 {
2518 	struct thread *t = &p->threads[p->thread_id];
2519 	struct instruction *ip = t->ip;
2520 	uint32_t table_id = ip->table.table_id;
2521 	struct rte_swx_table_state *ts = &t->table_state[table_id];
2522 	struct table_runtime *table = &t->tables[table_id];
2523 	struct table_statistics *stats = &p->table_stats[table_id];
2524 	uint64_t action_id, n_pkts_hit, n_pkts_action;
2525 	uint8_t *action_data;
2526 	size_t entry_id;
2527 	int done, hit;
2528 
2529 	/* Table. */
2530 	done = table->func(ts->obj,
2531 			   table->mailbox,
2532 			   table->key,
2533 			   &action_id,
2534 			   &action_data,
2535 			   &entry_id,
2536 			   &hit);
2537 	if (!done) {
2538 		/* Thread. */
2539 		TRACE("[Thread %2u] table %u (not finalized)\n",
2540 		      p->thread_id,
2541 		      table_id);
2542 
2543 		thread_yield(p);
2544 		return;
2545 	}
2546 
2547 	action_id = hit ? action_id : ts->default_action_id;
2548 	action_data = hit ? action_data : ts->default_action_data;
2549 	entry_id = hit ? (1 + entry_id) : 0;
2550 	n_pkts_hit = stats->n_pkts_hit[hit];
2551 	n_pkts_action = stats->n_pkts_action[action_id];
2552 
2553 	TRACE("[Thread %2u] table %u (%s, action %u)\n",
2554 	      p->thread_id,
2555 	      table_id,
2556 	      hit ? "hit" : "miss",
2557 	      (uint32_t)action_id);
2558 
2559 	t->action_id = action_id;
2560 	t->structs[0] = action_data;
2561 	t->entry_id = entry_id;
2562 	t->hit = hit;
2563 	stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2564 	stats->n_pkts_action[action_id] = n_pkts_action + 1;
2565 
2566 	/* Thread. */
2567 	thread_ip_action_call(p, t, action_id);
2568 }
2569 
2570 static inline void
instr_table_af_exec(struct rte_swx_pipeline * p)2571 instr_table_af_exec(struct rte_swx_pipeline *p)
2572 {
2573 	struct thread *t = &p->threads[p->thread_id];
2574 	struct instruction *ip = t->ip;
2575 	uint32_t table_id = ip->table.table_id;
2576 	struct rte_swx_table_state *ts = &t->table_state[table_id];
2577 	struct table_runtime *table = &t->tables[table_id];
2578 	struct table_statistics *stats = &p->table_stats[table_id];
2579 	uint64_t action_id, n_pkts_hit, n_pkts_action;
2580 	uint8_t *action_data;
2581 	size_t entry_id;
2582 	action_func_t action_func;
2583 	int done, hit;
2584 
2585 	/* Table. */
2586 	done = table->func(ts->obj,
2587 			   table->mailbox,
2588 			   table->key,
2589 			   &action_id,
2590 			   &action_data,
2591 			   &entry_id,
2592 			   &hit);
2593 	if (!done) {
2594 		/* Thread. */
2595 		TRACE("[Thread %2u] table %u (not finalized)\n",
2596 		      p->thread_id,
2597 		      table_id);
2598 
2599 		thread_yield(p);
2600 		return;
2601 	}
2602 
2603 	action_id = hit ? action_id : ts->default_action_id;
2604 	action_data = hit ? action_data : ts->default_action_data;
2605 	entry_id = hit ? (1 + entry_id) : 0;
2606 	action_func = p->action_funcs[action_id];
2607 	n_pkts_hit = stats->n_pkts_hit[hit];
2608 	n_pkts_action = stats->n_pkts_action[action_id];
2609 
2610 	TRACE("[Thread %2u] table %u (%s, action %u)\n",
2611 	      p->thread_id,
2612 	      table_id,
2613 	      hit ? "hit" : "miss",
2614 	      (uint32_t)action_id);
2615 
2616 	t->action_id = action_id;
2617 	t->structs[0] = action_data;
2618 	t->entry_id = entry_id;
2619 	t->hit = hit;
2620 	stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2621 	stats->n_pkts_action[action_id] = n_pkts_action + 1;
2622 
2623 	/* Thread. */
2624 	thread_ip_inc(p);
2625 
2626 	/* Action. */
2627 	action_func(p);
2628 }
2629 
2630 static inline void
instr_selector_exec(struct rte_swx_pipeline * p)2631 instr_selector_exec(struct rte_swx_pipeline *p)
2632 {
2633 	struct thread *t = &p->threads[p->thread_id];
2634 	struct instruction *ip = t->ip;
2635 	uint32_t selector_id = ip->table.table_id;
2636 	struct rte_swx_table_state *ts = &t->table_state[p->n_tables + selector_id];
2637 	struct selector_runtime *selector = &t->selectors[selector_id];
2638 	struct selector_statistics *stats = &p->selector_stats[selector_id];
2639 	uint64_t n_pkts = stats->n_pkts;
2640 	int done;
2641 
2642 	/* Table. */
2643 	done = rte_swx_table_selector_select(ts->obj,
2644 			   selector->mailbox,
2645 			   selector->group_id_buffer,
2646 			   selector->selector_buffer,
2647 			   selector->member_id_buffer);
2648 	if (!done) {
2649 		/* Thread. */
2650 		TRACE("[Thread %2u] selector %u (not finalized)\n",
2651 		      p->thread_id,
2652 		      selector_id);
2653 
2654 		thread_yield(p);
2655 		return;
2656 	}
2657 
2658 
2659 	TRACE("[Thread %2u] selector %u\n",
2660 	      p->thread_id,
2661 	      selector_id);
2662 
2663 	stats->n_pkts = n_pkts + 1;
2664 
2665 	/* Thread. */
2666 	thread_ip_inc(p);
2667 }
2668 
2669 static inline void
instr_learner_exec(struct rte_swx_pipeline * p)2670 instr_learner_exec(struct rte_swx_pipeline *p)
2671 {
2672 	struct thread *t = &p->threads[p->thread_id];
2673 	struct instruction *ip = t->ip;
2674 	uint32_t learner_id = ip->table.table_id;
2675 	struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2676 		p->n_selectors + learner_id];
2677 	struct learner_runtime *l = &t->learners[learner_id];
2678 	struct learner_statistics *stats = &p->learner_stats[learner_id];
2679 	uint64_t action_id, n_pkts_hit, n_pkts_action, time;
2680 	uint8_t *action_data;
2681 	size_t entry_id;
2682 	int done, hit;
2683 
2684 	/* Table. */
2685 	time = rte_get_tsc_cycles();
2686 
2687 	done = rte_swx_table_learner_lookup(ts->obj,
2688 					    l->mailbox,
2689 					    time,
2690 					    l->key,
2691 					    &action_id,
2692 					    &action_data,
2693 					    &entry_id,
2694 					    &hit);
2695 	if (!done) {
2696 		/* Thread. */
2697 		TRACE("[Thread %2u] learner %u (not finalized)\n",
2698 		      p->thread_id,
2699 		      learner_id);
2700 
2701 		thread_yield(p);
2702 		return;
2703 	}
2704 
2705 	action_id = hit ? action_id : ts->default_action_id;
2706 	action_data = hit ? action_data : ts->default_action_data;
2707 	entry_id = hit ? (1 + entry_id) : 0;
2708 	n_pkts_hit = stats->n_pkts_hit[hit];
2709 	n_pkts_action = stats->n_pkts_action[action_id];
2710 
2711 	TRACE("[Thread %2u] learner %u (%s, action %u)\n",
2712 	      p->thread_id,
2713 	      learner_id,
2714 	      hit ? "hit" : "miss",
2715 	      (uint32_t)action_id);
2716 
2717 	t->action_id = action_id;
2718 	t->structs[0] = action_data;
2719 	t->entry_id = entry_id;
2720 	t->hit = hit;
2721 	t->learner_id = learner_id;
2722 	t->time = time;
2723 	stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2724 	stats->n_pkts_action[action_id] = n_pkts_action + 1;
2725 
2726 	/* Thread. */
2727 	thread_ip_action_call(p, t, action_id);
2728 }
2729 
2730 static inline void
instr_learner_af_exec(struct rte_swx_pipeline * p)2731 instr_learner_af_exec(struct rte_swx_pipeline *p)
2732 {
2733 	struct thread *t = &p->threads[p->thread_id];
2734 	struct instruction *ip = t->ip;
2735 	uint32_t learner_id = ip->table.table_id;
2736 	struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2737 		p->n_selectors + learner_id];
2738 	struct learner_runtime *l = &t->learners[learner_id];
2739 	struct learner_statistics *stats = &p->learner_stats[learner_id];
2740 	uint64_t action_id, n_pkts_hit, n_pkts_action, time;
2741 	uint8_t *action_data;
2742 	size_t entry_id;
2743 	action_func_t action_func;
2744 	int done, hit;
2745 
2746 	/* Table. */
2747 	time = rte_get_tsc_cycles();
2748 
2749 	done = rte_swx_table_learner_lookup(ts->obj,
2750 					    l->mailbox,
2751 					    time,
2752 					    l->key,
2753 					    &action_id,
2754 					    &action_data,
2755 					    &entry_id,
2756 					    &hit);
2757 	if (!done) {
2758 		/* Thread. */
2759 		TRACE("[Thread %2u] learner %u (not finalized)\n",
2760 		      p->thread_id,
2761 		      learner_id);
2762 
2763 		thread_yield(p);
2764 		return;
2765 	}
2766 
2767 	action_id = hit ? action_id : ts->default_action_id;
2768 	action_data = hit ? action_data : ts->default_action_data;
2769 	entry_id = hit ? (1 + entry_id) : 0;
2770 	action_func = p->action_funcs[action_id];
2771 	n_pkts_hit = stats->n_pkts_hit[hit];
2772 	n_pkts_action = stats->n_pkts_action[action_id];
2773 
2774 	TRACE("[Thread %2u] learner %u (%s, action %u)\n",
2775 	      p->thread_id,
2776 	      learner_id,
2777 	      hit ? "hit" : "miss",
2778 	      (uint32_t)action_id);
2779 
2780 	t->action_id = action_id;
2781 	t->structs[0] = action_data;
2782 	t->entry_id = entry_id;
2783 	t->hit = hit;
2784 	t->learner_id = learner_id;
2785 	t->time = time;
2786 	stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2787 	stats->n_pkts_action[action_id] = n_pkts_action + 1;
2788 
2789 	/* Thread. */
2790 	thread_ip_inc(p);
2791 
2792 	/* Action */
2793 	action_func(p);
2794 }
2795 
2796 /*
2797  * learn.
2798  */
2799 static struct action *
2800 action_find(struct rte_swx_pipeline *p, const char *name);
2801 
2802 static int
2803 action_has_nbo_args(struct action *a);
2804 
2805 static int
2806 learner_action_args_check(struct rte_swx_pipeline *p, struct action *a, const char *mf_name);
2807 
2808 static int
instr_learn_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)2809 instr_learn_translate(struct rte_swx_pipeline *p,
2810 		      struct action *action,
2811 		      char **tokens,
2812 		      int n_tokens,
2813 		      struct instruction *instr,
2814 		      struct instruction_data *data __rte_unused)
2815 {
2816 	struct action *a;
2817 	struct field *mf_first_arg = NULL, *mf_timeout_id = NULL;
2818 	const char *mf_first_arg_name, *mf_timeout_id_name;
2819 
2820 	CHECK(action, EINVAL);
2821 	CHECK((n_tokens == 3) || (n_tokens == 4), EINVAL);
2822 
2823 	/* Action. */
2824 	a = action_find(p, tokens[1]);
2825 	CHECK(a, EINVAL);
2826 	CHECK(!action_has_nbo_args(a), EINVAL);
2827 
2828 	/* Action first argument. */
2829 	mf_first_arg_name = (n_tokens == 4) ? tokens[2] : NULL;
2830 	CHECK(!learner_action_args_check(p, a, mf_first_arg_name), EINVAL);
2831 
2832 	if (mf_first_arg_name) {
2833 		mf_first_arg = metadata_field_parse(p, mf_first_arg_name);
2834 		CHECK(mf_first_arg, EINVAL);
2835 		CHECK(mf_first_arg->n_bits <= 64, EINVAL);
2836 	}
2837 
2838 	/* Timeout ID. */
2839 	mf_timeout_id_name = (n_tokens == 4) ? tokens[3] : tokens[2];
2840 	CHECK_NAME(mf_timeout_id_name, EINVAL);
2841 	mf_timeout_id = metadata_field_parse(p, mf_timeout_id_name);
2842 	CHECK(mf_timeout_id, EINVAL);
2843 	CHECK(mf_timeout_id->n_bits <= 64, EINVAL);
2844 
2845 	/* Instruction. */
2846 	instr->type = INSTR_LEARNER_LEARN;
2847 	instr->learn.action_id = a->id;
2848 	instr->learn.mf_first_arg_offset = mf_first_arg ? (mf_first_arg->offset / 8) : 0;
2849 	instr->learn.mf_timeout_id_offset = mf_timeout_id->offset / 8;
2850 	instr->learn.mf_timeout_id_n_bits = mf_timeout_id->n_bits;
2851 
2852 	return 0;
2853 }
2854 
2855 static inline void
instr_learn_exec(struct rte_swx_pipeline * p)2856 instr_learn_exec(struct rte_swx_pipeline *p)
2857 {
2858 	struct thread *t = &p->threads[p->thread_id];
2859 	struct instruction *ip = t->ip;
2860 
2861 	__instr_learn_exec(p, t, ip);
2862 
2863 	/* Thread. */
2864 	thread_ip_inc(p);
2865 }
2866 
2867 /*
2868  * rearm.
2869  */
2870 static int
instr_rearm_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)2871 instr_rearm_translate(struct rte_swx_pipeline *p,
2872 		      struct action *action,
2873 		      char **tokens,
2874 		      int n_tokens,
2875 		      struct instruction *instr,
2876 		      struct instruction_data *data __rte_unused)
2877 {
2878 	struct field *mf_timeout_id;
2879 	const char *mf_timeout_id_name;
2880 
2881 	CHECK(action, EINVAL);
2882 	CHECK((n_tokens == 1) || (n_tokens == 2), EINVAL);
2883 
2884 	/* INSTR_LEARNER_REARM. */
2885 	if (n_tokens == 1) {
2886 		instr->type = INSTR_LEARNER_REARM;
2887 		return 0;
2888 	}
2889 
2890 	/* INSTR_LEARNER_REARM_NEW. */
2891 	mf_timeout_id_name = tokens[1];
2892 	CHECK_NAME(mf_timeout_id_name, EINVAL);
2893 	mf_timeout_id = metadata_field_parse(p, mf_timeout_id_name);
2894 	CHECK(mf_timeout_id, EINVAL);
2895 	CHECK(mf_timeout_id->n_bits <= 64, EINVAL);
2896 
2897 	instr->type = INSTR_LEARNER_REARM_NEW;
2898 	instr->learn.mf_timeout_id_offset = mf_timeout_id->offset / 8;
2899 	instr->learn.mf_timeout_id_n_bits = mf_timeout_id->n_bits;
2900 
2901 	return 0;
2902 }
2903 
2904 static inline void
instr_rearm_exec(struct rte_swx_pipeline * p)2905 instr_rearm_exec(struct rte_swx_pipeline *p)
2906 {
2907 	struct thread *t = &p->threads[p->thread_id];
2908 	struct instruction *ip = t->ip;
2909 
2910 	__instr_rearm_exec(p, t, ip);
2911 
2912 	/* Thread. */
2913 	thread_ip_inc(p);
2914 }
2915 
2916 static inline void
instr_rearm_new_exec(struct rte_swx_pipeline * p)2917 instr_rearm_new_exec(struct rte_swx_pipeline *p)
2918 {
2919 	struct thread *t = &p->threads[p->thread_id];
2920 	struct instruction *ip = t->ip;
2921 
2922 	__instr_rearm_new_exec(p, t, ip);
2923 
2924 	/* Thread. */
2925 	thread_ip_inc(p);
2926 }
2927 
2928 /*
2929  * forget.
2930  */
2931 static int
instr_forget_translate(struct rte_swx_pipeline * p __rte_unused,struct action * action,char ** tokens __rte_unused,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)2932 instr_forget_translate(struct rte_swx_pipeline *p __rte_unused,
2933 		       struct action *action,
2934 		       char **tokens __rte_unused,
2935 		       int n_tokens,
2936 		       struct instruction *instr,
2937 		       struct instruction_data *data __rte_unused)
2938 {
2939 	CHECK(action, EINVAL);
2940 	CHECK(n_tokens == 1, EINVAL);
2941 
2942 	instr->type = INSTR_LEARNER_FORGET;
2943 
2944 	return 0;
2945 }
2946 
2947 static inline void
instr_forget_exec(struct rte_swx_pipeline * p)2948 instr_forget_exec(struct rte_swx_pipeline *p)
2949 {
2950 	struct thread *t = &p->threads[p->thread_id];
2951 	struct instruction *ip = t->ip;
2952 
2953 	__instr_forget_exec(p, t, ip);
2954 
2955 	/* Thread. */
2956 	thread_ip_inc(p);
2957 }
2958 
2959 /*
2960  * entryid.
2961  */
2962 static int
instr_entryid_translate(struct rte_swx_pipeline * p,struct action * action __rte_unused,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)2963 instr_entryid_translate(struct rte_swx_pipeline *p,
2964 			struct action *action __rte_unused,
2965 			char **tokens,
2966 			int n_tokens,
2967 			struct instruction *instr,
2968 			struct instruction_data *data __rte_unused)
2969 {
2970 	struct field *f;
2971 
2972 	CHECK(n_tokens == 2, EINVAL);
2973 
2974 	f = metadata_field_parse(p, tokens[1]);
2975 	CHECK(f, EINVAL);
2976 	CHECK(f->n_bits <= 64, EINVAL);
2977 
2978 	instr->type = INSTR_ENTRYID;
2979 	instr->mov.dst.n_bits = f->n_bits;
2980 	instr->mov.dst.offset = f->offset / 8;
2981 	return 0;
2982 }
2983 
2984 static inline void
instr_entryid_exec(struct rte_swx_pipeline * p)2985 instr_entryid_exec(struct rte_swx_pipeline *p)
2986 {
2987 	struct thread *t = &p->threads[p->thread_id];
2988 	struct instruction *ip = t->ip;
2989 
2990 	__instr_entryid_exec(p, t, ip);
2991 
2992 	/* Thread. */
2993 	thread_ip_inc(p);
2994 }
2995 
2996 /*
2997  * extern.
2998  */
2999 static int
instr_extern_translate(struct rte_swx_pipeline * p,struct action * action __rte_unused,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)3000 instr_extern_translate(struct rte_swx_pipeline *p,
3001 		       struct action *action __rte_unused,
3002 		       char **tokens,
3003 		       int n_tokens,
3004 		       struct instruction *instr,
3005 		       struct instruction_data *data __rte_unused)
3006 {
3007 	char *token = tokens[1];
3008 
3009 	CHECK(n_tokens == 2, EINVAL);
3010 
3011 	if (token[0] == 'e') {
3012 		struct extern_obj *obj;
3013 		struct extern_type_member_func *func;
3014 
3015 		func = extern_obj_member_func_parse(p, token, &obj);
3016 		CHECK(func, EINVAL);
3017 
3018 		instr->type = INSTR_EXTERN_OBJ;
3019 		instr->ext_obj.ext_obj_id = obj->id;
3020 		instr->ext_obj.func_id = func->id;
3021 
3022 		return 0;
3023 	}
3024 
3025 	if (token[0] == 'f') {
3026 		struct extern_func *func;
3027 
3028 		func = extern_func_parse(p, token);
3029 		CHECK(func, EINVAL);
3030 
3031 		instr->type = INSTR_EXTERN_FUNC;
3032 		instr->ext_func.ext_func_id = func->id;
3033 
3034 		return 0;
3035 	}
3036 
3037 	CHECK(0, EINVAL);
3038 }
3039 
3040 static inline void
instr_extern_obj_exec(struct rte_swx_pipeline * p)3041 instr_extern_obj_exec(struct rte_swx_pipeline *p)
3042 {
3043 	struct thread *t = &p->threads[p->thread_id];
3044 	struct instruction *ip = t->ip;
3045 	uint32_t done;
3046 
3047 	/* Extern object member function execute. */
3048 	done = __instr_extern_obj_exec(p, t, ip);
3049 
3050 	/* Thread. */
3051 	thread_ip_inc_cond(t, done);
3052 	thread_yield_cond(p, done ^ 1);
3053 }
3054 
3055 static inline void
instr_extern_func_exec(struct rte_swx_pipeline * p)3056 instr_extern_func_exec(struct rte_swx_pipeline *p)
3057 {
3058 	struct thread *t = &p->threads[p->thread_id];
3059 	struct instruction *ip = t->ip;
3060 	uint32_t done;
3061 
3062 	/* Extern function execute. */
3063 	done = __instr_extern_func_exec(p, t, ip);
3064 
3065 	/* Thread. */
3066 	thread_ip_inc_cond(t, done);
3067 	thread_yield_cond(p, done ^ 1);
3068 }
3069 
3070 /*
3071  * hash.
3072  */
3073 static int
instr_hash_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)3074 instr_hash_translate(struct rte_swx_pipeline *p,
3075 		     struct action *action,
3076 		     char **tokens,
3077 		     int n_tokens,
3078 		     struct instruction *instr,
3079 		     struct instruction_data *data __rte_unused)
3080 {
3081 	struct hash_func *func;
3082 	struct field *dst, *src_first, *src_last;
3083 	uint32_t src_struct_id_first = 0, src_struct_id_last = 0;
3084 
3085 	CHECK(n_tokens == 5, EINVAL);
3086 
3087 	func = hash_func_find(p, tokens[1]);
3088 	CHECK(func, EINVAL);
3089 
3090 	dst = metadata_field_parse(p, tokens[2]);
3091 	CHECK(dst, EINVAL);
3092 	CHECK(dst->n_bits <= 64, EINVAL);
3093 
3094 	src_first = struct_field_parse(p, action, tokens[3], &src_struct_id_first);
3095 	CHECK(src_first, EINVAL);
3096 
3097 	src_last = struct_field_parse(p, action, tokens[4], &src_struct_id_last);
3098 	CHECK(src_last, EINVAL);
3099 	CHECK(!src_last->var_size, EINVAL);
3100 	CHECK(src_struct_id_first == src_struct_id_last, EINVAL);
3101 
3102 	instr->type = INSTR_HASH_FUNC;
3103 	instr->hash_func.hash_func_id = (uint8_t)func->id;
3104 	instr->hash_func.dst.offset = (uint8_t)dst->offset / 8;
3105 	instr->hash_func.dst.n_bits = (uint8_t)dst->n_bits;
3106 	instr->hash_func.src.struct_id = (uint8_t)src_struct_id_first;
3107 	instr->hash_func.src.offset = (uint16_t)src_first->offset / 8;
3108 	instr->hash_func.src.n_bytes = (uint16_t)((src_last->offset + src_last->n_bits -
3109 		src_first->offset) / 8);
3110 
3111 	return 0;
3112 }
3113 
3114 static inline void
instr_hash_func_exec(struct rte_swx_pipeline * p)3115 instr_hash_func_exec(struct rte_swx_pipeline *p)
3116 {
3117 	struct thread *t = &p->threads[p->thread_id];
3118 	struct instruction *ip = t->ip;
3119 
3120 	/* Extern function execute. */
3121 	__instr_hash_func_exec(p, t, ip);
3122 
3123 	/* Thread. */
3124 	thread_ip_inc(p);
3125 }
3126 
3127 /*
3128  * rss.
3129  */
3130 static int
instr_rss_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)3131 instr_rss_translate(struct rte_swx_pipeline *p,
3132 		    struct action *action,
3133 		    char **tokens,
3134 		    int n_tokens,
3135 		    struct instruction *instr,
3136 		    struct instruction_data *data __rte_unused)
3137 {
3138 	struct rss *rss;
3139 	struct field *dst, *src_first, *src_last;
3140 	uint32_t src_struct_id_first = 0, src_struct_id_last = 0;
3141 
3142 	CHECK(n_tokens == 5, EINVAL);
3143 
3144 	rss = rss_find(p, tokens[1]);
3145 	CHECK(rss, EINVAL);
3146 
3147 	dst = metadata_field_parse(p, tokens[2]);
3148 	CHECK(dst, EINVAL);
3149 	CHECK(dst->n_bits <= 64, EINVAL);
3150 
3151 	src_first = struct_field_parse(p, action, tokens[3], &src_struct_id_first);
3152 	CHECK(src_first, EINVAL);
3153 
3154 	src_last = struct_field_parse(p, action, tokens[4], &src_struct_id_last);
3155 	CHECK(src_last, EINVAL);
3156 	CHECK(!src_last->var_size, EINVAL);
3157 	CHECK(src_struct_id_first == src_struct_id_last, EINVAL);
3158 
3159 	instr->type = INSTR_RSS;
3160 	instr->rss.rss_obj_id = (uint8_t)rss->id;
3161 	instr->rss.dst.offset = (uint8_t)dst->offset / 8;
3162 	instr->rss.dst.n_bits = (uint8_t)dst->n_bits;
3163 	instr->rss.src.struct_id = (uint8_t)src_struct_id_first;
3164 	instr->rss.src.offset = (uint16_t)src_first->offset / 8;
3165 	instr->rss.src.n_bytes = (uint16_t)((src_last->offset + src_last->n_bits -
3166 		src_first->offset) / 8);
3167 
3168 	return 0;
3169 }
3170 
3171 static inline void
instr_rss_exec(struct rte_swx_pipeline * p)3172 instr_rss_exec(struct rte_swx_pipeline *p)
3173 {
3174 	struct thread *t = &p->threads[p->thread_id];
3175 	struct instruction *ip = t->ip;
3176 
3177 	/* Extern function execute. */
3178 	__instr_rss_exec(p, t, ip);
3179 
3180 	/* Thread. */
3181 	thread_ip_inc(p);
3182 }
3183 
3184 /*
3185  * mov.
3186  */
3187 static int
instr_mov_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)3188 instr_mov_translate(struct rte_swx_pipeline *p,
3189 		    struct action *action,
3190 		    char **tokens,
3191 		    int n_tokens,
3192 		    struct instruction *instr,
3193 		    struct instruction_data *data __rte_unused)
3194 {
3195 	char *dst = tokens[1], *src = tokens[2];
3196 	struct field *fdst, *fsrc;
3197 	uint64_t src_val;
3198 	uint32_t dst_struct_id = 0, src_struct_id = 0;
3199 
3200 	CHECK(n_tokens == 3, EINVAL);
3201 
3202 	fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3203 	CHECK(fdst, EINVAL);
3204 	CHECK(!fdst->var_size, EINVAL);
3205 
3206 	/* MOV, MOV_MH, MOV_HM, MOV_HH, MOV16, MOVDMA. */
3207 	fsrc = struct_field_parse(p, action, src, &src_struct_id);
3208 	if (fsrc) {
3209 		CHECK(!fsrc->var_size, EINVAL);
3210 
3211 		if (fdst->n_bits <= 64 && fsrc->n_bits <= 64) {
3212 			instr->type = INSTR_MOV;
3213 			if (dst[0] != 'h' && src[0] == 'h')
3214 				instr->type = INSTR_MOV_MH;
3215 			if (dst[0] == 'h' && src[0] != 'h')
3216 				instr->type = INSTR_MOV_HM;
3217 			if (dst[0] == 'h' && src[0] == 'h')
3218 				instr->type = INSTR_MOV_HH;
3219 		} else {
3220 			/* The big fields (field with size > 64 bits) are always expected in NBO,
3221 			 * regardless of their type (H or MEFT). In case a big field is involved as
3222 			 * either dst or src, the other field must also be NBO.
3223 			 *
3224 			 * In case the dst field is big, the src field must be either a big field
3225 			 * (of the same or different size as dst) or a small H field. Similarly,
3226 			 * in case the src field is big, the dst field must be either a big field
3227 			 * (of the same or different size as src) or a small H field. Any other case
3228 			 * involving a big field as either dst or src is rejected.
3229 			 */
3230 			CHECK(fdst->n_bits > 64 || dst[0] == 'h', EINVAL);
3231 			CHECK(fsrc->n_bits > 64 || src[0] == 'h', EINVAL);
3232 
3233 			instr->type = INSTR_MOV_DMA;
3234 			if (fdst->n_bits == 128 && fsrc->n_bits == 128)
3235 				instr->type = INSTR_MOV_128;
3236 
3237 			if (fdst->n_bits == 128 && fsrc->n_bits == 64)
3238 				instr->type = INSTR_MOV_128_64;
3239 			if (fdst->n_bits == 64 && fsrc->n_bits == 128)
3240 				instr->type = INSTR_MOV_64_128;
3241 
3242 			if (fdst->n_bits == 128 && fsrc->n_bits == 32)
3243 				instr->type = INSTR_MOV_128_32;
3244 			if (fdst->n_bits == 32 && fsrc->n_bits == 128)
3245 				instr->type = INSTR_MOV_32_128;
3246 		}
3247 
3248 		instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
3249 		instr->mov.dst.n_bits = fdst->n_bits;
3250 		instr->mov.dst.offset = fdst->offset / 8;
3251 		instr->mov.src.struct_id = (uint8_t)src_struct_id;
3252 		instr->mov.src.n_bits = fsrc->n_bits;
3253 		instr->mov.src.offset = fsrc->offset / 8;
3254 		return 0;
3255 	}
3256 
3257 	/* MOV_I. */
3258 	CHECK(fdst->n_bits <= 64, EINVAL);
3259 	src_val = strtoull(src, &src, 0);
3260 	CHECK(!src[0], EINVAL);
3261 
3262 	if (dst[0] == 'h')
3263 		src_val = hton64(src_val) >> (64 - fdst->n_bits);
3264 
3265 	instr->type = INSTR_MOV_I;
3266 	instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
3267 	instr->mov.dst.n_bits = fdst->n_bits;
3268 	instr->mov.dst.offset = fdst->offset / 8;
3269 	instr->mov.src_val = src_val;
3270 	return 0;
3271 }
3272 
3273 static inline void
instr_mov_exec(struct rte_swx_pipeline * p)3274 instr_mov_exec(struct rte_swx_pipeline *p)
3275 {
3276 	struct thread *t = &p->threads[p->thread_id];
3277 	struct instruction *ip = t->ip;
3278 
3279 	__instr_mov_exec(p, t, ip);
3280 
3281 	/* Thread. */
3282 	thread_ip_inc(p);
3283 }
3284 
3285 static inline void
instr_mov_mh_exec(struct rte_swx_pipeline * p)3286 instr_mov_mh_exec(struct rte_swx_pipeline *p)
3287 {
3288 	struct thread *t = &p->threads[p->thread_id];
3289 	struct instruction *ip = t->ip;
3290 
3291 	__instr_mov_mh_exec(p, t, ip);
3292 
3293 	/* Thread. */
3294 	thread_ip_inc(p);
3295 }
3296 
3297 static inline void
instr_mov_hm_exec(struct rte_swx_pipeline * p)3298 instr_mov_hm_exec(struct rte_swx_pipeline *p)
3299 {
3300 	struct thread *t = &p->threads[p->thread_id];
3301 	struct instruction *ip = t->ip;
3302 
3303 	__instr_mov_hm_exec(p, t, ip);
3304 
3305 	/* Thread. */
3306 	thread_ip_inc(p);
3307 }
3308 
3309 static inline void
instr_mov_hh_exec(struct rte_swx_pipeline * p)3310 instr_mov_hh_exec(struct rte_swx_pipeline *p)
3311 {
3312 	struct thread *t = &p->threads[p->thread_id];
3313 	struct instruction *ip = t->ip;
3314 
3315 	__instr_mov_hh_exec(p, t, ip);
3316 
3317 	/* Thread. */
3318 	thread_ip_inc(p);
3319 }
3320 
3321 static inline void
instr_mov_dma_exec(struct rte_swx_pipeline * p)3322 instr_mov_dma_exec(struct rte_swx_pipeline *p)
3323 {
3324 	struct thread *t = &p->threads[p->thread_id];
3325 	struct instruction *ip = t->ip;
3326 
3327 	__instr_mov_dma_exec(p, t, ip);
3328 
3329 	/* Thread. */
3330 	thread_ip_inc(p);
3331 }
3332 
3333 static inline void
instr_mov_128_exec(struct rte_swx_pipeline * p)3334 instr_mov_128_exec(struct rte_swx_pipeline *p)
3335 {
3336 	struct thread *t = &p->threads[p->thread_id];
3337 	struct instruction *ip = t->ip;
3338 
3339 	__instr_mov_128_exec(p, t, ip);
3340 
3341 	/* Thread. */
3342 	thread_ip_inc(p);
3343 }
3344 
3345 static inline void
instr_mov_128_64_exec(struct rte_swx_pipeline * p)3346 instr_mov_128_64_exec(struct rte_swx_pipeline *p)
3347 {
3348 	struct thread *t = &p->threads[p->thread_id];
3349 	struct instruction *ip = t->ip;
3350 
3351 	__instr_mov_128_64_exec(p, t, ip);
3352 
3353 	/* Thread. */
3354 	thread_ip_inc(p);
3355 }
3356 
3357 static inline void
instr_mov_64_128_exec(struct rte_swx_pipeline * p)3358 instr_mov_64_128_exec(struct rte_swx_pipeline *p)
3359 {
3360 	struct thread *t = &p->threads[p->thread_id];
3361 	struct instruction *ip = t->ip;
3362 
3363 	__instr_mov_64_128_exec(p, t, ip);
3364 
3365 	/* Thread. */
3366 	thread_ip_inc(p);
3367 }
3368 
3369 static inline void
instr_mov_128_32_exec(struct rte_swx_pipeline * p)3370 instr_mov_128_32_exec(struct rte_swx_pipeline *p)
3371 {
3372 	struct thread *t = &p->threads[p->thread_id];
3373 	struct instruction *ip = t->ip;
3374 
3375 	__instr_mov_128_32_exec(p, t, ip);
3376 
3377 	/* Thread. */
3378 	thread_ip_inc(p);
3379 }
3380 
3381 static inline void
instr_mov_32_128_exec(struct rte_swx_pipeline * p)3382 instr_mov_32_128_exec(struct rte_swx_pipeline *p)
3383 {
3384 	struct thread *t = &p->threads[p->thread_id];
3385 	struct instruction *ip = t->ip;
3386 
3387 	__instr_mov_32_128_exec(p, t, ip);
3388 
3389 	/* Thread. */
3390 	thread_ip_inc(p);
3391 }
3392 
3393 static inline void
instr_mov_i_exec(struct rte_swx_pipeline * p)3394 instr_mov_i_exec(struct rte_swx_pipeline *p)
3395 {
3396 	struct thread *t = &p->threads[p->thread_id];
3397 	struct instruction *ip = t->ip;
3398 
3399 	__instr_mov_i_exec(p, t, ip);
3400 
3401 	/* Thread. */
3402 	thread_ip_inc(p);
3403 }
3404 
3405 /*
3406  * movh.
3407  */
3408 static int
instr_movh_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)3409 instr_movh_translate(struct rte_swx_pipeline *p,
3410 		     struct action *action,
3411 		     char **tokens,
3412 		     int n_tokens,
3413 		     struct instruction *instr,
3414 		     struct instruction_data *data __rte_unused)
3415 {
3416 	char *dst = tokens[1], *src = tokens[2];
3417 	struct field *fdst, *fsrc;
3418 	uint32_t dst_struct_id = 0, src_struct_id = 0;
3419 
3420 	CHECK(n_tokens == 3, EINVAL);
3421 
3422 	fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3423 	CHECK(fdst, EINVAL);
3424 	CHECK(!fdst->var_size, EINVAL);
3425 
3426 	fsrc = struct_field_parse(p, action, src, &src_struct_id);
3427 	CHECK(fsrc, EINVAL);
3428 	CHECK(!fsrc->var_size, EINVAL);
3429 
3430 	/* MOVH_64_128, MOVH_128_64. */
3431 	if ((dst[0] == 'h' && fdst->n_bits == 64 && fsrc->n_bits == 128) ||
3432 	    (fdst->n_bits == 128 && src[0] == 'h' && fsrc->n_bits == 64)) {
3433 		instr->type = INSTR_MOVH;
3434 
3435 		instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
3436 		instr->mov.dst.n_bits = fdst->n_bits;
3437 		instr->mov.dst.offset = fdst->offset / 8;
3438 
3439 		instr->mov.src.struct_id = (uint8_t)src_struct_id;
3440 		instr->mov.src.n_bits = fsrc->n_bits;
3441 		instr->mov.src.offset = fsrc->offset / 8;
3442 		return 0;
3443 	}
3444 
3445 	CHECK(0, EINVAL);
3446 }
3447 
3448 static inline void
instr_movh_exec(struct rte_swx_pipeline * p)3449 instr_movh_exec(struct rte_swx_pipeline *p)
3450 {
3451 	struct thread *t = &p->threads[p->thread_id];
3452 	struct instruction *ip = t->ip;
3453 
3454 	__instr_movh_exec(p, t, ip);
3455 
3456 	/* Thread. */
3457 	thread_ip_inc(p);
3458 }
3459 
3460 /*
3461  * dma.
3462  */
3463 static inline void
instr_dma_ht_exec(struct rte_swx_pipeline * p)3464 instr_dma_ht_exec(struct rte_swx_pipeline *p)
3465 {
3466 	struct thread *t = &p->threads[p->thread_id];
3467 	struct instruction *ip = t->ip;
3468 
3469 	__instr_dma_ht_exec(p, t, ip);
3470 
3471 	/* Thread. */
3472 	thread_ip_inc(p);
3473 }
3474 
3475 static inline void
instr_dma_ht2_exec(struct rte_swx_pipeline * p)3476 instr_dma_ht2_exec(struct rte_swx_pipeline *p)
3477 {
3478 	struct thread *t = &p->threads[p->thread_id];
3479 	struct instruction *ip = t->ip;
3480 
3481 	__instr_dma_ht2_exec(p, t, ip);
3482 
3483 	/* Thread. */
3484 	thread_ip_inc(p);
3485 }
3486 
3487 static inline void
instr_dma_ht3_exec(struct rte_swx_pipeline * p)3488 instr_dma_ht3_exec(struct rte_swx_pipeline *p)
3489 {
3490 	struct thread *t = &p->threads[p->thread_id];
3491 	struct instruction *ip = t->ip;
3492 
3493 	__instr_dma_ht3_exec(p, t, ip);
3494 
3495 	/* Thread. */
3496 	thread_ip_inc(p);
3497 }
3498 
3499 static inline void
instr_dma_ht4_exec(struct rte_swx_pipeline * p)3500 instr_dma_ht4_exec(struct rte_swx_pipeline *p)
3501 {
3502 	struct thread *t = &p->threads[p->thread_id];
3503 	struct instruction *ip = t->ip;
3504 
3505 	__instr_dma_ht4_exec(p, t, ip);
3506 
3507 	/* Thread. */
3508 	thread_ip_inc(p);
3509 }
3510 
3511 static inline void
instr_dma_ht5_exec(struct rte_swx_pipeline * p)3512 instr_dma_ht5_exec(struct rte_swx_pipeline *p)
3513 {
3514 	struct thread *t = &p->threads[p->thread_id];
3515 	struct instruction *ip = t->ip;
3516 
3517 	__instr_dma_ht5_exec(p, t, ip);
3518 
3519 	/* Thread. */
3520 	thread_ip_inc(p);
3521 }
3522 
3523 static inline void
instr_dma_ht6_exec(struct rte_swx_pipeline * p)3524 instr_dma_ht6_exec(struct rte_swx_pipeline *p)
3525 {
3526 	struct thread *t = &p->threads[p->thread_id];
3527 	struct instruction *ip = t->ip;
3528 
3529 	__instr_dma_ht6_exec(p, t, ip);
3530 
3531 	/* Thread. */
3532 	thread_ip_inc(p);
3533 }
3534 
3535 static inline void
instr_dma_ht7_exec(struct rte_swx_pipeline * p)3536 instr_dma_ht7_exec(struct rte_swx_pipeline *p)
3537 {
3538 	struct thread *t = &p->threads[p->thread_id];
3539 	struct instruction *ip = t->ip;
3540 
3541 	__instr_dma_ht7_exec(p, t, ip);
3542 
3543 	/* Thread. */
3544 	thread_ip_inc(p);
3545 }
3546 
3547 static inline void
instr_dma_ht8_exec(struct rte_swx_pipeline * p)3548 instr_dma_ht8_exec(struct rte_swx_pipeline *p)
3549 {
3550 	struct thread *t = &p->threads[p->thread_id];
3551 	struct instruction *ip = t->ip;
3552 
3553 	__instr_dma_ht8_exec(p, t, ip);
3554 
3555 	/* Thread. */
3556 	thread_ip_inc(p);
3557 }
3558 
3559 /*
3560  * alu.
3561  */
3562 static int
instr_alu_add_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)3563 instr_alu_add_translate(struct rte_swx_pipeline *p,
3564 			struct action *action,
3565 			char **tokens,
3566 			int n_tokens,
3567 			struct instruction *instr,
3568 			struct instruction_data *data __rte_unused)
3569 {
3570 	char *dst = tokens[1], *src = tokens[2];
3571 	struct field *fdst, *fsrc;
3572 	uint64_t src_val;
3573 	uint32_t dst_struct_id = 0, src_struct_id = 0;
3574 
3575 	CHECK(n_tokens == 3, EINVAL);
3576 
3577 	fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3578 	CHECK(fdst, EINVAL);
3579 	CHECK(!fdst->var_size && (fdst->n_bits <= 64), EINVAL);
3580 
3581 	/* ADD, ADD_HM, ADD_MH, ADD_HH. */
3582 	fsrc = struct_field_parse(p, action, src, &src_struct_id);
3583 	if (fsrc) {
3584 		CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
3585 
3586 		instr->type = INSTR_ALU_ADD;
3587 		if (dst[0] == 'h' && src[0] != 'h')
3588 			instr->type = INSTR_ALU_ADD_HM;
3589 		if (dst[0] != 'h' && src[0] == 'h')
3590 			instr->type = INSTR_ALU_ADD_MH;
3591 		if (dst[0] == 'h' && src[0] == 'h')
3592 			instr->type = INSTR_ALU_ADD_HH;
3593 
3594 		instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3595 		instr->alu.dst.n_bits = fdst->n_bits;
3596 		instr->alu.dst.offset = fdst->offset / 8;
3597 		instr->alu.src.struct_id = (uint8_t)src_struct_id;
3598 		instr->alu.src.n_bits = fsrc->n_bits;
3599 		instr->alu.src.offset = fsrc->offset / 8;
3600 		return 0;
3601 	}
3602 
3603 	/* ADD_MI, ADD_HI. */
3604 	src_val = strtoull(src, &src, 0);
3605 	CHECK(!src[0], EINVAL);
3606 
3607 	instr->type = INSTR_ALU_ADD_MI;
3608 	if (dst[0] == 'h')
3609 		instr->type = INSTR_ALU_ADD_HI;
3610 
3611 	instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3612 	instr->alu.dst.n_bits = fdst->n_bits;
3613 	instr->alu.dst.offset = fdst->offset / 8;
3614 	instr->alu.src_val = src_val;
3615 	return 0;
3616 }
3617 
3618 static int
instr_alu_sub_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)3619 instr_alu_sub_translate(struct rte_swx_pipeline *p,
3620 			struct action *action,
3621 			char **tokens,
3622 			int n_tokens,
3623 			struct instruction *instr,
3624 			struct instruction_data *data __rte_unused)
3625 {
3626 	char *dst = tokens[1], *src = tokens[2];
3627 	struct field *fdst, *fsrc;
3628 	uint64_t src_val;
3629 	uint32_t dst_struct_id = 0, src_struct_id = 0;
3630 
3631 	CHECK(n_tokens == 3, EINVAL);
3632 
3633 	fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3634 	CHECK(fdst, EINVAL);
3635 	CHECK(!fdst->var_size && (fdst->n_bits <= 64), EINVAL);
3636 
3637 	/* SUB, SUB_HM, SUB_MH, SUB_HH. */
3638 	fsrc = struct_field_parse(p, action, src, &src_struct_id);
3639 	if (fsrc) {
3640 		CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
3641 
3642 		instr->type = INSTR_ALU_SUB;
3643 		if (dst[0] == 'h' && src[0] != 'h')
3644 			instr->type = INSTR_ALU_SUB_HM;
3645 		if (dst[0] != 'h' && src[0] == 'h')
3646 			instr->type = INSTR_ALU_SUB_MH;
3647 		if (dst[0] == 'h' && src[0] == 'h')
3648 			instr->type = INSTR_ALU_SUB_HH;
3649 
3650 		instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3651 		instr->alu.dst.n_bits = fdst->n_bits;
3652 		instr->alu.dst.offset = fdst->offset / 8;
3653 		instr->alu.src.struct_id = (uint8_t)src_struct_id;
3654 		instr->alu.src.n_bits = fsrc->n_bits;
3655 		instr->alu.src.offset = fsrc->offset / 8;
3656 		return 0;
3657 	}
3658 
3659 	/* SUB_MI, SUB_HI. */
3660 	src_val = strtoull(src, &src, 0);
3661 	CHECK(!src[0], EINVAL);
3662 
3663 	instr->type = INSTR_ALU_SUB_MI;
3664 	if (dst[0] == 'h')
3665 		instr->type = INSTR_ALU_SUB_HI;
3666 
3667 	instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3668 	instr->alu.dst.n_bits = fdst->n_bits;
3669 	instr->alu.dst.offset = fdst->offset / 8;
3670 	instr->alu.src_val = src_val;
3671 	return 0;
3672 }
3673 
3674 static int
instr_alu_ckadd_translate(struct rte_swx_pipeline * p,struct action * action __rte_unused,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)3675 instr_alu_ckadd_translate(struct rte_swx_pipeline *p,
3676 			  struct action *action __rte_unused,
3677 			  char **tokens,
3678 			  int n_tokens,
3679 			  struct instruction *instr,
3680 			  struct instruction_data *data __rte_unused)
3681 {
3682 	char *dst = tokens[1], *src = tokens[2];
3683 	struct header *hdst, *hsrc;
3684 	struct field *fdst, *fsrc;
3685 
3686 	CHECK(n_tokens == 3, EINVAL);
3687 
3688 	fdst = header_field_parse(p, dst, &hdst);
3689 	CHECK(fdst, EINVAL);
3690 	CHECK(!fdst->var_size && (fdst->n_bits == 16), EINVAL);
3691 
3692 	/* CKADD_FIELD. */
3693 	fsrc = header_field_parse(p, src, &hsrc);
3694 	if (fsrc) {
3695 		CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
3696 
3697 		instr->type = INSTR_ALU_CKADD_FIELD;
3698 		instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
3699 		instr->alu.dst.n_bits = fdst->n_bits;
3700 		instr->alu.dst.offset = fdst->offset / 8;
3701 		instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
3702 		instr->alu.src.n_bits = fsrc->n_bits;
3703 		instr->alu.src.offset = fsrc->offset / 8;
3704 		return 0;
3705 	}
3706 
3707 	/* CKADD_STRUCT, CKADD_STRUCT20. */
3708 	hsrc = header_parse(p, src);
3709 	CHECK(hsrc, EINVAL);
3710 
3711 	instr->type = INSTR_ALU_CKADD_STRUCT;
3712 	if (!hsrc->st->var_size && ((hsrc->st->n_bits / 8) == 20))
3713 		instr->type = INSTR_ALU_CKADD_STRUCT20;
3714 
3715 	instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
3716 	instr->alu.dst.n_bits = fdst->n_bits;
3717 	instr->alu.dst.offset = fdst->offset / 8;
3718 	instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
3719 	instr->alu.src.n_bits = (uint8_t)hsrc->id; /* The src header ID is stored here. */
3720 	instr->alu.src.offset = 0; /* Unused. */
3721 	return 0;
3722 }
3723 
3724 static int
instr_alu_cksub_translate(struct rte_swx_pipeline * p,struct action * action __rte_unused,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)3725 instr_alu_cksub_translate(struct rte_swx_pipeline *p,
3726 			  struct action *action __rte_unused,
3727 			  char **tokens,
3728 			  int n_tokens,
3729 			  struct instruction *instr,
3730 			  struct instruction_data *data __rte_unused)
3731 {
3732 	char *dst = tokens[1], *src = tokens[2];
3733 	struct header *hdst, *hsrc;
3734 	struct field *fdst, *fsrc;
3735 
3736 	CHECK(n_tokens == 3, EINVAL);
3737 
3738 	fdst = header_field_parse(p, dst, &hdst);
3739 	CHECK(fdst, EINVAL);
3740 	CHECK(!fdst->var_size && (fdst->n_bits == 16), EINVAL);
3741 
3742 	fsrc = header_field_parse(p, src, &hsrc);
3743 	CHECK(fsrc, EINVAL);
3744 	CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
3745 
3746 	instr->type = INSTR_ALU_CKSUB_FIELD;
3747 	instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
3748 	instr->alu.dst.n_bits = fdst->n_bits;
3749 	instr->alu.dst.offset = fdst->offset / 8;
3750 	instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
3751 	instr->alu.src.n_bits = fsrc->n_bits;
3752 	instr->alu.src.offset = fsrc->offset / 8;
3753 	return 0;
3754 }
3755 
3756 static int
instr_alu_shl_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)3757 instr_alu_shl_translate(struct rte_swx_pipeline *p,
3758 			struct action *action,
3759 			char **tokens,
3760 			int n_tokens,
3761 			struct instruction *instr,
3762 			struct instruction_data *data __rte_unused)
3763 {
3764 	char *dst = tokens[1], *src = tokens[2];
3765 	struct field *fdst, *fsrc;
3766 	uint64_t src_val;
3767 	uint32_t dst_struct_id = 0, src_struct_id = 0;
3768 
3769 	CHECK(n_tokens == 3, EINVAL);
3770 
3771 	fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3772 	CHECK(fdst, EINVAL);
3773 	CHECK(!fdst->var_size && (fdst->n_bits <= 64), EINVAL);
3774 
3775 	/* SHL, SHL_HM, SHL_MH, SHL_HH. */
3776 	fsrc = struct_field_parse(p, action, src, &src_struct_id);
3777 	if (fsrc) {
3778 		CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
3779 
3780 		instr->type = INSTR_ALU_SHL;
3781 		if (dst[0] == 'h' && src[0] != 'h')
3782 			instr->type = INSTR_ALU_SHL_HM;
3783 		if (dst[0] != 'h' && src[0] == 'h')
3784 			instr->type = INSTR_ALU_SHL_MH;
3785 		if (dst[0] == 'h' && src[0] == 'h')
3786 			instr->type = INSTR_ALU_SHL_HH;
3787 
3788 		instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3789 		instr->alu.dst.n_bits = fdst->n_bits;
3790 		instr->alu.dst.offset = fdst->offset / 8;
3791 		instr->alu.src.struct_id = (uint8_t)src_struct_id;
3792 		instr->alu.src.n_bits = fsrc->n_bits;
3793 		instr->alu.src.offset = fsrc->offset / 8;
3794 		return 0;
3795 	}
3796 
3797 	/* SHL_MI, SHL_HI. */
3798 	src_val = strtoull(src, &src, 0);
3799 	CHECK(!src[0], EINVAL);
3800 
3801 	instr->type = INSTR_ALU_SHL_MI;
3802 	if (dst[0] == 'h')
3803 		instr->type = INSTR_ALU_SHL_HI;
3804 
3805 	instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3806 	instr->alu.dst.n_bits = fdst->n_bits;
3807 	instr->alu.dst.offset = fdst->offset / 8;
3808 	instr->alu.src_val = src_val;
3809 	return 0;
3810 }
3811 
3812 static int
instr_alu_shr_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)3813 instr_alu_shr_translate(struct rte_swx_pipeline *p,
3814 			struct action *action,
3815 			char **tokens,
3816 			int n_tokens,
3817 			struct instruction *instr,
3818 			struct instruction_data *data __rte_unused)
3819 {
3820 	char *dst = tokens[1], *src = tokens[2];
3821 	struct field *fdst, *fsrc;
3822 	uint64_t src_val;
3823 	uint32_t dst_struct_id = 0, src_struct_id = 0;
3824 
3825 	CHECK(n_tokens == 3, EINVAL);
3826 
3827 	fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3828 	CHECK(fdst, EINVAL);
3829 	CHECK(!fdst->var_size && (fdst->n_bits <= 64), EINVAL);
3830 
3831 	/* SHR, SHR_HM, SHR_MH, SHR_HH. */
3832 	fsrc = struct_field_parse(p, action, src, &src_struct_id);
3833 	if (fsrc) {
3834 		CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
3835 
3836 		instr->type = INSTR_ALU_SHR;
3837 		if (dst[0] == 'h' && src[0] != 'h')
3838 			instr->type = INSTR_ALU_SHR_HM;
3839 		if (dst[0] != 'h' && src[0] == 'h')
3840 			instr->type = INSTR_ALU_SHR_MH;
3841 		if (dst[0] == 'h' && src[0] == 'h')
3842 			instr->type = INSTR_ALU_SHR_HH;
3843 
3844 		instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3845 		instr->alu.dst.n_bits = fdst->n_bits;
3846 		instr->alu.dst.offset = fdst->offset / 8;
3847 		instr->alu.src.struct_id = (uint8_t)src_struct_id;
3848 		instr->alu.src.n_bits = fsrc->n_bits;
3849 		instr->alu.src.offset = fsrc->offset / 8;
3850 		return 0;
3851 	}
3852 
3853 	/* SHR_MI, SHR_HI. */
3854 	src_val = strtoull(src, &src, 0);
3855 	CHECK(!src[0], EINVAL);
3856 
3857 	instr->type = INSTR_ALU_SHR_MI;
3858 	if (dst[0] == 'h')
3859 		instr->type = INSTR_ALU_SHR_HI;
3860 
3861 	instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3862 	instr->alu.dst.n_bits = fdst->n_bits;
3863 	instr->alu.dst.offset = fdst->offset / 8;
3864 	instr->alu.src_val = src_val;
3865 	return 0;
3866 }
3867 
3868 static int
instr_alu_and_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)3869 instr_alu_and_translate(struct rte_swx_pipeline *p,
3870 			struct action *action,
3871 			char **tokens,
3872 			int n_tokens,
3873 			struct instruction *instr,
3874 			struct instruction_data *data __rte_unused)
3875 {
3876 	char *dst = tokens[1], *src = tokens[2];
3877 	struct field *fdst, *fsrc;
3878 	uint64_t src_val;
3879 	uint32_t dst_struct_id = 0, src_struct_id = 0;
3880 
3881 	CHECK(n_tokens == 3, EINVAL);
3882 
3883 	fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3884 	CHECK(fdst, EINVAL);
3885 	CHECK(!fdst->var_size && (fdst->n_bits <= 64), EINVAL);
3886 
3887 	/* AND, AND_MH, AND_HM, AND_HH. */
3888 	fsrc = struct_field_parse(p, action, src, &src_struct_id);
3889 	if (fsrc) {
3890 		CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
3891 
3892 		instr->type = INSTR_ALU_AND;
3893 		if (dst[0] != 'h' && src[0] == 'h')
3894 			instr->type = INSTR_ALU_AND_MH;
3895 		if (dst[0] == 'h' && src[0] != 'h')
3896 			instr->type = INSTR_ALU_AND_HM;
3897 		if (dst[0] == 'h' && src[0] == 'h')
3898 			instr->type = INSTR_ALU_AND_HH;
3899 
3900 		instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3901 		instr->alu.dst.n_bits = fdst->n_bits;
3902 		instr->alu.dst.offset = fdst->offset / 8;
3903 		instr->alu.src.struct_id = (uint8_t)src_struct_id;
3904 		instr->alu.src.n_bits = fsrc->n_bits;
3905 		instr->alu.src.offset = fsrc->offset / 8;
3906 		return 0;
3907 	}
3908 
3909 	/* AND_I. */
3910 	src_val = strtoull(src, &src, 0);
3911 	CHECK(!src[0], EINVAL);
3912 
3913 	if (dst[0] == 'h')
3914 		src_val = hton64(src_val) >> (64 - fdst->n_bits);
3915 
3916 	instr->type = INSTR_ALU_AND_I;
3917 	instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3918 	instr->alu.dst.n_bits = fdst->n_bits;
3919 	instr->alu.dst.offset = fdst->offset / 8;
3920 	instr->alu.src_val = src_val;
3921 	return 0;
3922 }
3923 
3924 static int
instr_alu_or_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)3925 instr_alu_or_translate(struct rte_swx_pipeline *p,
3926 		       struct action *action,
3927 		       char **tokens,
3928 		       int n_tokens,
3929 		       struct instruction *instr,
3930 		       struct instruction_data *data __rte_unused)
3931 {
3932 	char *dst = tokens[1], *src = tokens[2];
3933 	struct field *fdst, *fsrc;
3934 	uint64_t src_val;
3935 	uint32_t dst_struct_id = 0, src_struct_id = 0;
3936 
3937 	CHECK(n_tokens == 3, EINVAL);
3938 
3939 	fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3940 	CHECK(fdst, EINVAL);
3941 	CHECK(!fdst->var_size && (fdst->n_bits <= 64), EINVAL);
3942 
3943 	/* OR, OR_MH, OR_HM, OR_HH. */
3944 	fsrc = struct_field_parse(p, action, src, &src_struct_id);
3945 	if (fsrc) {
3946 		CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
3947 
3948 		instr->type = INSTR_ALU_OR;
3949 		if (dst[0] != 'h' && src[0] == 'h')
3950 			instr->type = INSTR_ALU_OR_MH;
3951 		if (dst[0] == 'h' && src[0] != 'h')
3952 			instr->type = INSTR_ALU_OR_HM;
3953 		if (dst[0] == 'h' && src[0] == 'h')
3954 			instr->type = INSTR_ALU_OR_HH;
3955 
3956 		instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3957 		instr->alu.dst.n_bits = fdst->n_bits;
3958 		instr->alu.dst.offset = fdst->offset / 8;
3959 		instr->alu.src.struct_id = (uint8_t)src_struct_id;
3960 		instr->alu.src.n_bits = fsrc->n_bits;
3961 		instr->alu.src.offset = fsrc->offset / 8;
3962 		return 0;
3963 	}
3964 
3965 	/* OR_I. */
3966 	src_val = strtoull(src, &src, 0);
3967 	CHECK(!src[0], EINVAL);
3968 
3969 	if (dst[0] == 'h')
3970 		src_val = hton64(src_val) >> (64 - fdst->n_bits);
3971 
3972 	instr->type = INSTR_ALU_OR_I;
3973 	instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3974 	instr->alu.dst.n_bits = fdst->n_bits;
3975 	instr->alu.dst.offset = fdst->offset / 8;
3976 	instr->alu.src_val = src_val;
3977 	return 0;
3978 }
3979 
3980 static int
instr_alu_xor_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)3981 instr_alu_xor_translate(struct rte_swx_pipeline *p,
3982 			struct action *action,
3983 			char **tokens,
3984 			int n_tokens,
3985 			struct instruction *instr,
3986 			struct instruction_data *data __rte_unused)
3987 {
3988 	char *dst = tokens[1], *src = tokens[2];
3989 	struct field *fdst, *fsrc;
3990 	uint64_t src_val;
3991 	uint32_t dst_struct_id = 0, src_struct_id = 0;
3992 
3993 	CHECK(n_tokens == 3, EINVAL);
3994 
3995 	fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3996 	CHECK(fdst, EINVAL);
3997 	CHECK(!fdst->var_size && (fdst->n_bits <= 64), EINVAL);
3998 
3999 	/* XOR, XOR_MH, XOR_HM, XOR_HH. */
4000 	fsrc = struct_field_parse(p, action, src, &src_struct_id);
4001 	if (fsrc) {
4002 		CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
4003 
4004 		instr->type = INSTR_ALU_XOR;
4005 		if (dst[0] != 'h' && src[0] == 'h')
4006 			instr->type = INSTR_ALU_XOR_MH;
4007 		if (dst[0] == 'h' && src[0] != 'h')
4008 			instr->type = INSTR_ALU_XOR_HM;
4009 		if (dst[0] == 'h' && src[0] == 'h')
4010 			instr->type = INSTR_ALU_XOR_HH;
4011 
4012 		instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
4013 		instr->alu.dst.n_bits = fdst->n_bits;
4014 		instr->alu.dst.offset = fdst->offset / 8;
4015 		instr->alu.src.struct_id = (uint8_t)src_struct_id;
4016 		instr->alu.src.n_bits = fsrc->n_bits;
4017 		instr->alu.src.offset = fsrc->offset / 8;
4018 		return 0;
4019 	}
4020 
4021 	/* XOR_I. */
4022 	src_val = strtoull(src, &src, 0);
4023 	CHECK(!src[0], EINVAL);
4024 
4025 	if (dst[0] == 'h')
4026 		src_val = hton64(src_val) >> (64 - fdst->n_bits);
4027 
4028 	instr->type = INSTR_ALU_XOR_I;
4029 	instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
4030 	instr->alu.dst.n_bits = fdst->n_bits;
4031 	instr->alu.dst.offset = fdst->offset / 8;
4032 	instr->alu.src_val = src_val;
4033 	return 0;
4034 }
4035 
4036 static inline void
instr_alu_add_exec(struct rte_swx_pipeline * p)4037 instr_alu_add_exec(struct rte_swx_pipeline *p)
4038 {
4039 	struct thread *t = &p->threads[p->thread_id];
4040 	struct instruction *ip = t->ip;
4041 
4042 	/* Structs */
4043 	__instr_alu_add_exec(p, t, ip);
4044 
4045 	/* Thread. */
4046 	thread_ip_inc(p);
4047 }
4048 
4049 static inline void
instr_alu_add_mh_exec(struct rte_swx_pipeline * p)4050 instr_alu_add_mh_exec(struct rte_swx_pipeline *p)
4051 {
4052 	struct thread *t = &p->threads[p->thread_id];
4053 	struct instruction *ip = t->ip;
4054 
4055 	/* Structs. */
4056 	__instr_alu_add_mh_exec(p, t, ip);
4057 
4058 	/* Thread. */
4059 	thread_ip_inc(p);
4060 }
4061 
4062 static inline void
instr_alu_add_hm_exec(struct rte_swx_pipeline * p)4063 instr_alu_add_hm_exec(struct rte_swx_pipeline *p)
4064 {
4065 	struct thread *t = &p->threads[p->thread_id];
4066 	struct instruction *ip = t->ip;
4067 
4068 	/* Structs. */
4069 	__instr_alu_add_hm_exec(p, t, ip);
4070 
4071 	/* Thread. */
4072 	thread_ip_inc(p);
4073 }
4074 
4075 static inline void
instr_alu_add_hh_exec(struct rte_swx_pipeline * p)4076 instr_alu_add_hh_exec(struct rte_swx_pipeline *p)
4077 {
4078 	struct thread *t = &p->threads[p->thread_id];
4079 	struct instruction *ip = t->ip;
4080 
4081 	/* Structs. */
4082 	__instr_alu_add_hh_exec(p, t, ip);
4083 
4084 	/* Thread. */
4085 	thread_ip_inc(p);
4086 }
4087 
4088 static inline void
instr_alu_add_mi_exec(struct rte_swx_pipeline * p)4089 instr_alu_add_mi_exec(struct rte_swx_pipeline *p)
4090 {
4091 	struct thread *t = &p->threads[p->thread_id];
4092 	struct instruction *ip = t->ip;
4093 
4094 	/* Structs. */
4095 	__instr_alu_add_mi_exec(p, t, ip);
4096 
4097 	/* Thread. */
4098 	thread_ip_inc(p);
4099 }
4100 
4101 static inline void
instr_alu_add_hi_exec(struct rte_swx_pipeline * p)4102 instr_alu_add_hi_exec(struct rte_swx_pipeline *p)
4103 {
4104 	struct thread *t = &p->threads[p->thread_id];
4105 	struct instruction *ip = t->ip;
4106 
4107 	/* Structs. */
4108 	__instr_alu_add_hi_exec(p, t, ip);
4109 
4110 	/* Thread. */
4111 	thread_ip_inc(p);
4112 }
4113 
4114 static inline void
instr_alu_sub_exec(struct rte_swx_pipeline * p)4115 instr_alu_sub_exec(struct rte_swx_pipeline *p)
4116 {
4117 	struct thread *t = &p->threads[p->thread_id];
4118 	struct instruction *ip = t->ip;
4119 
4120 	/* Structs. */
4121 	__instr_alu_sub_exec(p, t, ip);
4122 
4123 	/* Thread. */
4124 	thread_ip_inc(p);
4125 }
4126 
4127 static inline void
instr_alu_sub_mh_exec(struct rte_swx_pipeline * p)4128 instr_alu_sub_mh_exec(struct rte_swx_pipeline *p)
4129 {
4130 	struct thread *t = &p->threads[p->thread_id];
4131 	struct instruction *ip = t->ip;
4132 
4133 	/* Structs. */
4134 	__instr_alu_sub_mh_exec(p, t, ip);
4135 
4136 	/* Thread. */
4137 	thread_ip_inc(p);
4138 }
4139 
4140 static inline void
instr_alu_sub_hm_exec(struct rte_swx_pipeline * p)4141 instr_alu_sub_hm_exec(struct rte_swx_pipeline *p)
4142 {
4143 	struct thread *t = &p->threads[p->thread_id];
4144 	struct instruction *ip = t->ip;
4145 
4146 	/* Structs. */
4147 	__instr_alu_sub_hm_exec(p, t, ip);
4148 
4149 	/* Thread. */
4150 	thread_ip_inc(p);
4151 }
4152 
4153 static inline void
instr_alu_sub_hh_exec(struct rte_swx_pipeline * p)4154 instr_alu_sub_hh_exec(struct rte_swx_pipeline *p)
4155 {
4156 	struct thread *t = &p->threads[p->thread_id];
4157 	struct instruction *ip = t->ip;
4158 
4159 	/* Structs. */
4160 	__instr_alu_sub_hh_exec(p, t, ip);
4161 
4162 	/* Thread. */
4163 	thread_ip_inc(p);
4164 }
4165 
4166 static inline void
instr_alu_sub_mi_exec(struct rte_swx_pipeline * p)4167 instr_alu_sub_mi_exec(struct rte_swx_pipeline *p)
4168 {
4169 	struct thread *t = &p->threads[p->thread_id];
4170 	struct instruction *ip = t->ip;
4171 
4172 	/* Structs. */
4173 	__instr_alu_sub_mi_exec(p, t, ip);
4174 
4175 	/* Thread. */
4176 	thread_ip_inc(p);
4177 }
4178 
4179 static inline void
instr_alu_sub_hi_exec(struct rte_swx_pipeline * p)4180 instr_alu_sub_hi_exec(struct rte_swx_pipeline *p)
4181 {
4182 	struct thread *t = &p->threads[p->thread_id];
4183 	struct instruction *ip = t->ip;
4184 
4185 	/* Structs. */
4186 	__instr_alu_sub_hi_exec(p, t, ip);
4187 
4188 	/* Thread. */
4189 	thread_ip_inc(p);
4190 }
4191 
4192 static inline void
instr_alu_shl_exec(struct rte_swx_pipeline * p)4193 instr_alu_shl_exec(struct rte_swx_pipeline *p)
4194 {
4195 	struct thread *t = &p->threads[p->thread_id];
4196 	struct instruction *ip = t->ip;
4197 
4198 	/* Structs. */
4199 	__instr_alu_shl_exec(p, t, ip);
4200 
4201 	/* Thread. */
4202 	thread_ip_inc(p);
4203 }
4204 
4205 static inline void
instr_alu_shl_mh_exec(struct rte_swx_pipeline * p)4206 instr_alu_shl_mh_exec(struct rte_swx_pipeline *p)
4207 {
4208 	struct thread *t = &p->threads[p->thread_id];
4209 	struct instruction *ip = t->ip;
4210 
4211 	/* Structs. */
4212 	__instr_alu_shl_mh_exec(p, t, ip);
4213 
4214 	/* Thread. */
4215 	thread_ip_inc(p);
4216 }
4217 
4218 static inline void
instr_alu_shl_hm_exec(struct rte_swx_pipeline * p)4219 instr_alu_shl_hm_exec(struct rte_swx_pipeline *p)
4220 {
4221 	struct thread *t = &p->threads[p->thread_id];
4222 	struct instruction *ip = t->ip;
4223 
4224 	/* Structs. */
4225 	__instr_alu_shl_hm_exec(p, t, ip);
4226 
4227 	/* Thread. */
4228 	thread_ip_inc(p);
4229 }
4230 
4231 static inline void
instr_alu_shl_hh_exec(struct rte_swx_pipeline * p)4232 instr_alu_shl_hh_exec(struct rte_swx_pipeline *p)
4233 {
4234 	struct thread *t = &p->threads[p->thread_id];
4235 	struct instruction *ip = t->ip;
4236 
4237 	/* Structs. */
4238 	__instr_alu_shl_hh_exec(p, t, ip);
4239 
4240 	/* Thread. */
4241 	thread_ip_inc(p);
4242 }
4243 
4244 static inline void
instr_alu_shl_mi_exec(struct rte_swx_pipeline * p)4245 instr_alu_shl_mi_exec(struct rte_swx_pipeline *p)
4246 {
4247 	struct thread *t = &p->threads[p->thread_id];
4248 	struct instruction *ip = t->ip;
4249 
4250 	/* Structs. */
4251 	__instr_alu_shl_mi_exec(p, t, ip);
4252 
4253 	/* Thread. */
4254 	thread_ip_inc(p);
4255 }
4256 
4257 static inline void
instr_alu_shl_hi_exec(struct rte_swx_pipeline * p)4258 instr_alu_shl_hi_exec(struct rte_swx_pipeline *p)
4259 {
4260 	struct thread *t = &p->threads[p->thread_id];
4261 	struct instruction *ip = t->ip;
4262 
4263 	/* Structs. */
4264 	__instr_alu_shl_hi_exec(p, t, ip);
4265 
4266 	/* Thread. */
4267 	thread_ip_inc(p);
4268 }
4269 
4270 static inline void
instr_alu_shr_exec(struct rte_swx_pipeline * p)4271 instr_alu_shr_exec(struct rte_swx_pipeline *p)
4272 {
4273 	struct thread *t = &p->threads[p->thread_id];
4274 	struct instruction *ip = t->ip;
4275 
4276 	/* Structs. */
4277 	__instr_alu_shr_exec(p, t, ip);
4278 
4279 	/* Thread. */
4280 	thread_ip_inc(p);
4281 }
4282 
4283 static inline void
instr_alu_shr_mh_exec(struct rte_swx_pipeline * p)4284 instr_alu_shr_mh_exec(struct rte_swx_pipeline *p)
4285 {
4286 	struct thread *t = &p->threads[p->thread_id];
4287 	struct instruction *ip = t->ip;
4288 
4289 	/* Structs. */
4290 	__instr_alu_shr_mh_exec(p, t, ip);
4291 
4292 	/* Thread. */
4293 	thread_ip_inc(p);
4294 }
4295 
4296 static inline void
instr_alu_shr_hm_exec(struct rte_swx_pipeline * p)4297 instr_alu_shr_hm_exec(struct rte_swx_pipeline *p)
4298 {
4299 	struct thread *t = &p->threads[p->thread_id];
4300 	struct instruction *ip = t->ip;
4301 
4302 	/* Structs. */
4303 	__instr_alu_shr_hm_exec(p, t, ip);
4304 
4305 	/* Thread. */
4306 	thread_ip_inc(p);
4307 }
4308 
4309 static inline void
instr_alu_shr_hh_exec(struct rte_swx_pipeline * p)4310 instr_alu_shr_hh_exec(struct rte_swx_pipeline *p)
4311 {
4312 	struct thread *t = &p->threads[p->thread_id];
4313 	struct instruction *ip = t->ip;
4314 
4315 	/* Structs. */
4316 	__instr_alu_shr_hh_exec(p, t, ip);
4317 
4318 	/* Thread. */
4319 	thread_ip_inc(p);
4320 }
4321 
4322 static inline void
instr_alu_shr_mi_exec(struct rte_swx_pipeline * p)4323 instr_alu_shr_mi_exec(struct rte_swx_pipeline *p)
4324 {
4325 	struct thread *t = &p->threads[p->thread_id];
4326 	struct instruction *ip = t->ip;
4327 
4328 	/* Structs. */
4329 	__instr_alu_shr_mi_exec(p, t, ip);
4330 
4331 	/* Thread. */
4332 	thread_ip_inc(p);
4333 }
4334 
4335 static inline void
instr_alu_shr_hi_exec(struct rte_swx_pipeline * p)4336 instr_alu_shr_hi_exec(struct rte_swx_pipeline *p)
4337 {
4338 	struct thread *t = &p->threads[p->thread_id];
4339 	struct instruction *ip = t->ip;
4340 
4341 	/* Structs. */
4342 	__instr_alu_shr_hi_exec(p, t, ip);
4343 
4344 	/* Thread. */
4345 	thread_ip_inc(p);
4346 }
4347 
4348 static inline void
instr_alu_and_exec(struct rte_swx_pipeline * p)4349 instr_alu_and_exec(struct rte_swx_pipeline *p)
4350 {
4351 	struct thread *t = &p->threads[p->thread_id];
4352 	struct instruction *ip = t->ip;
4353 
4354 	/* Structs. */
4355 	__instr_alu_and_exec(p, t, ip);
4356 
4357 	/* Thread. */
4358 	thread_ip_inc(p);
4359 }
4360 
4361 static inline void
instr_alu_and_mh_exec(struct rte_swx_pipeline * p)4362 instr_alu_and_mh_exec(struct rte_swx_pipeline *p)
4363 {
4364 	struct thread *t = &p->threads[p->thread_id];
4365 	struct instruction *ip = t->ip;
4366 
4367 	/* Structs. */
4368 	__instr_alu_and_mh_exec(p, t, ip);
4369 
4370 	/* Thread. */
4371 	thread_ip_inc(p);
4372 }
4373 
4374 static inline void
instr_alu_and_hm_exec(struct rte_swx_pipeline * p)4375 instr_alu_and_hm_exec(struct rte_swx_pipeline *p)
4376 {
4377 	struct thread *t = &p->threads[p->thread_id];
4378 	struct instruction *ip = t->ip;
4379 
4380 	/* Structs. */
4381 	__instr_alu_and_hm_exec(p, t, ip);
4382 
4383 	/* Thread. */
4384 	thread_ip_inc(p);
4385 }
4386 
4387 static inline void
instr_alu_and_hh_exec(struct rte_swx_pipeline * p)4388 instr_alu_and_hh_exec(struct rte_swx_pipeline *p)
4389 {
4390 	struct thread *t = &p->threads[p->thread_id];
4391 	struct instruction *ip = t->ip;
4392 
4393 	/* Structs. */
4394 	__instr_alu_and_hh_exec(p, t, ip);
4395 
4396 	/* Thread. */
4397 	thread_ip_inc(p);
4398 }
4399 
4400 static inline void
instr_alu_and_i_exec(struct rte_swx_pipeline * p)4401 instr_alu_and_i_exec(struct rte_swx_pipeline *p)
4402 {
4403 	struct thread *t = &p->threads[p->thread_id];
4404 	struct instruction *ip = t->ip;
4405 
4406 	/* Structs. */
4407 	__instr_alu_and_i_exec(p, t, ip);
4408 
4409 	/* Thread. */
4410 	thread_ip_inc(p);
4411 }
4412 
4413 static inline void
instr_alu_or_exec(struct rte_swx_pipeline * p)4414 instr_alu_or_exec(struct rte_swx_pipeline *p)
4415 {
4416 	struct thread *t = &p->threads[p->thread_id];
4417 	struct instruction *ip = t->ip;
4418 
4419 	/* Structs. */
4420 	__instr_alu_or_exec(p, t, ip);
4421 
4422 	/* Thread. */
4423 	thread_ip_inc(p);
4424 }
4425 
4426 static inline void
instr_alu_or_mh_exec(struct rte_swx_pipeline * p)4427 instr_alu_or_mh_exec(struct rte_swx_pipeline *p)
4428 {
4429 	struct thread *t = &p->threads[p->thread_id];
4430 	struct instruction *ip = t->ip;
4431 
4432 	/* Structs. */
4433 	__instr_alu_or_mh_exec(p, t, ip);
4434 
4435 	/* Thread. */
4436 	thread_ip_inc(p);
4437 }
4438 
4439 static inline void
instr_alu_or_hm_exec(struct rte_swx_pipeline * p)4440 instr_alu_or_hm_exec(struct rte_swx_pipeline *p)
4441 {
4442 	struct thread *t = &p->threads[p->thread_id];
4443 	struct instruction *ip = t->ip;
4444 
4445 	/* Structs. */
4446 	__instr_alu_or_hm_exec(p, t, ip);
4447 
4448 	/* Thread. */
4449 	thread_ip_inc(p);
4450 }
4451 
4452 static inline void
instr_alu_or_hh_exec(struct rte_swx_pipeline * p)4453 instr_alu_or_hh_exec(struct rte_swx_pipeline *p)
4454 {
4455 	struct thread *t = &p->threads[p->thread_id];
4456 	struct instruction *ip = t->ip;
4457 
4458 	/* Structs. */
4459 	__instr_alu_or_hh_exec(p, t, ip);
4460 
4461 	/* Thread. */
4462 	thread_ip_inc(p);
4463 }
4464 
4465 static inline void
instr_alu_or_i_exec(struct rte_swx_pipeline * p)4466 instr_alu_or_i_exec(struct rte_swx_pipeline *p)
4467 {
4468 	struct thread *t = &p->threads[p->thread_id];
4469 	struct instruction *ip = t->ip;
4470 
4471 	/* Structs. */
4472 	__instr_alu_or_i_exec(p, t, ip);
4473 
4474 	/* Thread. */
4475 	thread_ip_inc(p);
4476 }
4477 
4478 static inline void
instr_alu_xor_exec(struct rte_swx_pipeline * p)4479 instr_alu_xor_exec(struct rte_swx_pipeline *p)
4480 {
4481 	struct thread *t = &p->threads[p->thread_id];
4482 	struct instruction *ip = t->ip;
4483 
4484 	/* Structs. */
4485 	__instr_alu_xor_exec(p, t, ip);
4486 
4487 	/* Thread. */
4488 	thread_ip_inc(p);
4489 }
4490 
4491 static inline void
instr_alu_xor_mh_exec(struct rte_swx_pipeline * p)4492 instr_alu_xor_mh_exec(struct rte_swx_pipeline *p)
4493 {
4494 	struct thread *t = &p->threads[p->thread_id];
4495 	struct instruction *ip = t->ip;
4496 
4497 	/* Structs. */
4498 	__instr_alu_xor_mh_exec(p, t, ip);
4499 
4500 	/* Thread. */
4501 	thread_ip_inc(p);
4502 }
4503 
4504 static inline void
instr_alu_xor_hm_exec(struct rte_swx_pipeline * p)4505 instr_alu_xor_hm_exec(struct rte_swx_pipeline *p)
4506 {
4507 	struct thread *t = &p->threads[p->thread_id];
4508 	struct instruction *ip = t->ip;
4509 
4510 	/* Structs. */
4511 	__instr_alu_xor_hm_exec(p, t, ip);
4512 
4513 	/* Thread. */
4514 	thread_ip_inc(p);
4515 }
4516 
4517 static inline void
instr_alu_xor_hh_exec(struct rte_swx_pipeline * p)4518 instr_alu_xor_hh_exec(struct rte_swx_pipeline *p)
4519 {
4520 	struct thread *t = &p->threads[p->thread_id];
4521 	struct instruction *ip = t->ip;
4522 
4523 	/* Structs. */
4524 	__instr_alu_xor_hh_exec(p, t, ip);
4525 
4526 	/* Thread. */
4527 	thread_ip_inc(p);
4528 }
4529 
4530 static inline void
instr_alu_xor_i_exec(struct rte_swx_pipeline * p)4531 instr_alu_xor_i_exec(struct rte_swx_pipeline *p)
4532 {
4533 	struct thread *t = &p->threads[p->thread_id];
4534 	struct instruction *ip = t->ip;
4535 
4536 	/* Structs. */
4537 	__instr_alu_xor_i_exec(p, t, ip);
4538 
4539 	/* Thread. */
4540 	thread_ip_inc(p);
4541 }
4542 
4543 static inline void
instr_alu_ckadd_field_exec(struct rte_swx_pipeline * p)4544 instr_alu_ckadd_field_exec(struct rte_swx_pipeline *p)
4545 {
4546 	struct thread *t = &p->threads[p->thread_id];
4547 	struct instruction *ip = t->ip;
4548 
4549 	/* Structs. */
4550 	__instr_alu_ckadd_field_exec(p, t, ip);
4551 
4552 	/* Thread. */
4553 	thread_ip_inc(p);
4554 }
4555 
4556 static inline void
instr_alu_cksub_field_exec(struct rte_swx_pipeline * p)4557 instr_alu_cksub_field_exec(struct rte_swx_pipeline *p)
4558 {
4559 	struct thread *t = &p->threads[p->thread_id];
4560 	struct instruction *ip = t->ip;
4561 
4562 	/* Structs. */
4563 	__instr_alu_cksub_field_exec(p, t, ip);
4564 
4565 	/* Thread. */
4566 	thread_ip_inc(p);
4567 }
4568 
4569 static inline void
instr_alu_ckadd_struct20_exec(struct rte_swx_pipeline * p)4570 instr_alu_ckadd_struct20_exec(struct rte_swx_pipeline *p)
4571 {
4572 	struct thread *t = &p->threads[p->thread_id];
4573 	struct instruction *ip = t->ip;
4574 
4575 	/* Structs. */
4576 	__instr_alu_ckadd_struct20_exec(p, t, ip);
4577 
4578 	/* Thread. */
4579 	thread_ip_inc(p);
4580 }
4581 
4582 static inline void
instr_alu_ckadd_struct_exec(struct rte_swx_pipeline * p)4583 instr_alu_ckadd_struct_exec(struct rte_swx_pipeline *p)
4584 {
4585 	struct thread *t = &p->threads[p->thread_id];
4586 	struct instruction *ip = t->ip;
4587 
4588 	/* Structs. */
4589 	__instr_alu_ckadd_struct_exec(p, t, ip);
4590 
4591 	/* Thread. */
4592 	thread_ip_inc(p);
4593 }
4594 
4595 /*
4596  * Register array.
4597  */
4598 static struct regarray *
4599 regarray_find(struct rte_swx_pipeline *p, const char *name);
4600 
4601 static int
instr_regprefetch_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)4602 instr_regprefetch_translate(struct rte_swx_pipeline *p,
4603 		      struct action *action,
4604 		      char **tokens,
4605 		      int n_tokens,
4606 		      struct instruction *instr,
4607 		      struct instruction_data *data __rte_unused)
4608 {
4609 	char *regarray = tokens[1], *idx = tokens[2];
4610 	struct regarray *r;
4611 	struct field *fidx;
4612 	uint32_t idx_struct_id, idx_val;
4613 
4614 	CHECK(n_tokens == 3, EINVAL);
4615 
4616 	r = regarray_find(p, regarray);
4617 	CHECK(r, EINVAL);
4618 
4619 	/* REGPREFETCH_RH, REGPREFETCH_RM. */
4620 	fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4621 	if (fidx) {
4622 		CHECK(!fidx->var_size && (fidx->n_bits <= 64), EINVAL);
4623 
4624 		instr->type = INSTR_REGPREFETCH_RM;
4625 		if (idx[0] == 'h')
4626 			instr->type = INSTR_REGPREFETCH_RH;
4627 
4628 		instr->regarray.regarray_id = r->id;
4629 		instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4630 		instr->regarray.idx.n_bits = fidx->n_bits;
4631 		instr->regarray.idx.offset = fidx->offset / 8;
4632 		instr->regarray.dstsrc_val = 0; /* Unused. */
4633 		return 0;
4634 	}
4635 
4636 	/* REGPREFETCH_RI. */
4637 	idx_val = strtoul(idx, &idx, 0);
4638 	CHECK(!idx[0], EINVAL);
4639 
4640 	instr->type = INSTR_REGPREFETCH_RI;
4641 	instr->regarray.regarray_id = r->id;
4642 	instr->regarray.idx_val = idx_val;
4643 	instr->regarray.dstsrc_val = 0; /* Unused. */
4644 	return 0;
4645 }
4646 
4647 static int
instr_regrd_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)4648 instr_regrd_translate(struct rte_swx_pipeline *p,
4649 		      struct action *action,
4650 		      char **tokens,
4651 		      int n_tokens,
4652 		      struct instruction *instr,
4653 		      struct instruction_data *data __rte_unused)
4654 {
4655 	char *dst = tokens[1], *regarray = tokens[2], *idx = tokens[3];
4656 	struct regarray *r;
4657 	struct field *fdst, *fidx;
4658 	uint32_t dst_struct_id, idx_struct_id, idx_val;
4659 
4660 	CHECK(n_tokens == 4, EINVAL);
4661 
4662 	r = regarray_find(p, regarray);
4663 	CHECK(r, EINVAL);
4664 
4665 	fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
4666 	CHECK(fdst, EINVAL);
4667 	CHECK(!fdst->var_size && (fdst->n_bits <= 64), EINVAL);
4668 
4669 	/* REGRD_HRH, REGRD_HRM, REGRD_MRH, REGRD_MRM. */
4670 	fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4671 	if (fidx) {
4672 		CHECK(!fidx->var_size && (fidx->n_bits <= 64), EINVAL);
4673 
4674 		instr->type = INSTR_REGRD_MRM;
4675 		if (dst[0] == 'h' && idx[0] != 'h')
4676 			instr->type = INSTR_REGRD_HRM;
4677 		if (dst[0] != 'h' && idx[0] == 'h')
4678 			instr->type = INSTR_REGRD_MRH;
4679 		if (dst[0] == 'h' && idx[0] == 'h')
4680 			instr->type = INSTR_REGRD_HRH;
4681 
4682 		instr->regarray.regarray_id = r->id;
4683 		instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4684 		instr->regarray.idx.n_bits = fidx->n_bits;
4685 		instr->regarray.idx.offset = fidx->offset / 8;
4686 		instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id;
4687 		instr->regarray.dstsrc.n_bits = fdst->n_bits;
4688 		instr->regarray.dstsrc.offset = fdst->offset / 8;
4689 		return 0;
4690 	}
4691 
4692 	/* REGRD_MRI, REGRD_HRI. */
4693 	idx_val = strtoul(idx, &idx, 0);
4694 	CHECK(!idx[0], EINVAL);
4695 
4696 	instr->type = INSTR_REGRD_MRI;
4697 	if (dst[0] == 'h')
4698 		instr->type = INSTR_REGRD_HRI;
4699 
4700 	instr->regarray.regarray_id = r->id;
4701 	instr->regarray.idx_val = idx_val;
4702 	instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id;
4703 	instr->regarray.dstsrc.n_bits = fdst->n_bits;
4704 	instr->regarray.dstsrc.offset = fdst->offset / 8;
4705 	return 0;
4706 }
4707 
4708 static int
instr_regwr_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)4709 instr_regwr_translate(struct rte_swx_pipeline *p,
4710 		      struct action *action,
4711 		      char **tokens,
4712 		      int n_tokens,
4713 		      struct instruction *instr,
4714 		      struct instruction_data *data __rte_unused)
4715 {
4716 	char *regarray = tokens[1], *idx = tokens[2], *src = tokens[3];
4717 	struct regarray *r;
4718 	struct field *fidx, *fsrc;
4719 	uint64_t src_val;
4720 	uint32_t idx_struct_id, idx_val, src_struct_id;
4721 
4722 	CHECK(n_tokens == 4, EINVAL);
4723 
4724 	r = regarray_find(p, regarray);
4725 	CHECK(r, EINVAL);
4726 
4727 	/* REGWR_RHH, REGWR_RHM, REGWR_RMH, REGWR_RMM. */
4728 	fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4729 	fsrc = struct_field_parse(p, action, src, &src_struct_id);
4730 	if (fidx && fsrc) {
4731 		CHECK(!fidx->var_size && (fidx->n_bits <= 64), EINVAL);
4732 		CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
4733 
4734 		instr->type = INSTR_REGWR_RMM;
4735 		if (idx[0] == 'h' && src[0] != 'h')
4736 			instr->type = INSTR_REGWR_RHM;
4737 		if (idx[0] != 'h' && src[0] == 'h')
4738 			instr->type = INSTR_REGWR_RMH;
4739 		if (idx[0] == 'h' && src[0] == 'h')
4740 			instr->type = INSTR_REGWR_RHH;
4741 
4742 		instr->regarray.regarray_id = r->id;
4743 		instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4744 		instr->regarray.idx.n_bits = fidx->n_bits;
4745 		instr->regarray.idx.offset = fidx->offset / 8;
4746 		instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4747 		instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4748 		instr->regarray.dstsrc.offset = fsrc->offset / 8;
4749 		return 0;
4750 	}
4751 
4752 	/* REGWR_RHI, REGWR_RMI. */
4753 	if (fidx && !fsrc) {
4754 		CHECK(!fidx->var_size && (fidx->n_bits <= 64), EINVAL);
4755 
4756 		src_val = strtoull(src, &src, 0);
4757 		CHECK(!src[0], EINVAL);
4758 
4759 		instr->type = INSTR_REGWR_RMI;
4760 		if (idx[0] == 'h')
4761 			instr->type = INSTR_REGWR_RHI;
4762 
4763 		instr->regarray.regarray_id = r->id;
4764 		instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4765 		instr->regarray.idx.n_bits = fidx->n_bits;
4766 		instr->regarray.idx.offset = fidx->offset / 8;
4767 		instr->regarray.dstsrc_val = src_val;
4768 		return 0;
4769 	}
4770 
4771 	/* REGWR_RIH, REGWR_RIM. */
4772 	if (!fidx && fsrc) {
4773 		idx_val = strtoul(idx, &idx, 0);
4774 		CHECK(!idx[0], EINVAL);
4775 
4776 		CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
4777 
4778 		instr->type = INSTR_REGWR_RIM;
4779 		if (src[0] == 'h')
4780 			instr->type = INSTR_REGWR_RIH;
4781 
4782 		instr->regarray.regarray_id = r->id;
4783 		instr->regarray.idx_val = idx_val;
4784 		instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4785 		instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4786 		instr->regarray.dstsrc.offset = fsrc->offset / 8;
4787 		return 0;
4788 	}
4789 
4790 	/* REGWR_RII. */
4791 	src_val = strtoull(src, &src, 0);
4792 	CHECK(!src[0], EINVAL);
4793 
4794 	idx_val = strtoul(idx, &idx, 0);
4795 	CHECK(!idx[0], EINVAL);
4796 
4797 	instr->type = INSTR_REGWR_RII;
4798 	instr->regarray.idx_val = idx_val;
4799 	instr->regarray.dstsrc_val = src_val;
4800 
4801 	return 0;
4802 }
4803 
4804 static int
instr_regadd_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)4805 instr_regadd_translate(struct rte_swx_pipeline *p,
4806 		       struct action *action,
4807 		       char **tokens,
4808 		       int n_tokens,
4809 		       struct instruction *instr,
4810 		       struct instruction_data *data __rte_unused)
4811 {
4812 	char *regarray = tokens[1], *idx = tokens[2], *src = tokens[3];
4813 	struct regarray *r;
4814 	struct field *fidx, *fsrc;
4815 	uint64_t src_val;
4816 	uint32_t idx_struct_id, idx_val, src_struct_id;
4817 
4818 	CHECK(n_tokens == 4, EINVAL);
4819 
4820 	r = regarray_find(p, regarray);
4821 	CHECK(r, EINVAL);
4822 
4823 	/* REGADD_RHH, REGADD_RHM, REGADD_RMH, REGADD_RMM. */
4824 	fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4825 	fsrc = struct_field_parse(p, action, src, &src_struct_id);
4826 	if (fidx && fsrc) {
4827 		CHECK(!fidx->var_size && (fidx->n_bits <= 64), EINVAL);
4828 		CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
4829 
4830 		instr->type = INSTR_REGADD_RMM;
4831 		if (idx[0] == 'h' && src[0] != 'h')
4832 			instr->type = INSTR_REGADD_RHM;
4833 		if (idx[0] != 'h' && src[0] == 'h')
4834 			instr->type = INSTR_REGADD_RMH;
4835 		if (idx[0] == 'h' && src[0] == 'h')
4836 			instr->type = INSTR_REGADD_RHH;
4837 
4838 		instr->regarray.regarray_id = r->id;
4839 		instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4840 		instr->regarray.idx.n_bits = fidx->n_bits;
4841 		instr->regarray.idx.offset = fidx->offset / 8;
4842 		instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4843 		instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4844 		instr->regarray.dstsrc.offset = fsrc->offset / 8;
4845 		return 0;
4846 	}
4847 
4848 	/* REGADD_RHI, REGADD_RMI. */
4849 	if (fidx && !fsrc) {
4850 		CHECK(!fidx->var_size && (fidx->n_bits <= 64), EINVAL);
4851 
4852 		src_val = strtoull(src, &src, 0);
4853 		CHECK(!src[0], EINVAL);
4854 
4855 		instr->type = INSTR_REGADD_RMI;
4856 		if (idx[0] == 'h')
4857 			instr->type = INSTR_REGADD_RHI;
4858 
4859 		instr->regarray.regarray_id = r->id;
4860 		instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4861 		instr->regarray.idx.n_bits = fidx->n_bits;
4862 		instr->regarray.idx.offset = fidx->offset / 8;
4863 		instr->regarray.dstsrc_val = src_val;
4864 		return 0;
4865 	}
4866 
4867 	/* REGADD_RIH, REGADD_RIM. */
4868 	if (!fidx && fsrc) {
4869 		idx_val = strtoul(idx, &idx, 0);
4870 		CHECK(!idx[0], EINVAL);
4871 
4872 		CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
4873 
4874 		instr->type = INSTR_REGADD_RIM;
4875 		if (src[0] == 'h')
4876 			instr->type = INSTR_REGADD_RIH;
4877 
4878 		instr->regarray.regarray_id = r->id;
4879 		instr->regarray.idx_val = idx_val;
4880 		instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4881 		instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4882 		instr->regarray.dstsrc.offset = fsrc->offset / 8;
4883 		return 0;
4884 	}
4885 
4886 	/* REGADD_RII. */
4887 	src_val = strtoull(src, &src, 0);
4888 	CHECK(!src[0], EINVAL);
4889 
4890 	idx_val = strtoul(idx, &idx, 0);
4891 	CHECK(!idx[0], EINVAL);
4892 
4893 	instr->type = INSTR_REGADD_RII;
4894 	instr->regarray.idx_val = idx_val;
4895 	instr->regarray.dstsrc_val = src_val;
4896 	return 0;
4897 }
4898 
4899 static inline void
instr_regprefetch_rh_exec(struct rte_swx_pipeline * p)4900 instr_regprefetch_rh_exec(struct rte_swx_pipeline *p)
4901 {
4902 	struct thread *t = &p->threads[p->thread_id];
4903 	struct instruction *ip = t->ip;
4904 
4905 	/* Structs. */
4906 	__instr_regprefetch_rh_exec(p, t, ip);
4907 
4908 	/* Thread. */
4909 	thread_ip_inc(p);
4910 }
4911 
4912 static inline void
instr_regprefetch_rm_exec(struct rte_swx_pipeline * p)4913 instr_regprefetch_rm_exec(struct rte_swx_pipeline *p)
4914 {
4915 	struct thread *t = &p->threads[p->thread_id];
4916 	struct instruction *ip = t->ip;
4917 
4918 	/* Structs. */
4919 	__instr_regprefetch_rm_exec(p, t, ip);
4920 
4921 	/* Thread. */
4922 	thread_ip_inc(p);
4923 }
4924 
4925 static inline void
instr_regprefetch_ri_exec(struct rte_swx_pipeline * p)4926 instr_regprefetch_ri_exec(struct rte_swx_pipeline *p)
4927 {
4928 	struct thread *t = &p->threads[p->thread_id];
4929 	struct instruction *ip = t->ip;
4930 
4931 	/* Structs. */
4932 	__instr_regprefetch_ri_exec(p, t, ip);
4933 
4934 	/* Thread. */
4935 	thread_ip_inc(p);
4936 }
4937 
4938 static inline void
instr_regrd_hrh_exec(struct rte_swx_pipeline * p)4939 instr_regrd_hrh_exec(struct rte_swx_pipeline *p)
4940 {
4941 	struct thread *t = &p->threads[p->thread_id];
4942 	struct instruction *ip = t->ip;
4943 
4944 	/* Structs. */
4945 	__instr_regrd_hrh_exec(p, t, ip);
4946 
4947 	/* Thread. */
4948 	thread_ip_inc(p);
4949 }
4950 
4951 static inline void
instr_regrd_hrm_exec(struct rte_swx_pipeline * p)4952 instr_regrd_hrm_exec(struct rte_swx_pipeline *p)
4953 {
4954 	struct thread *t = &p->threads[p->thread_id];
4955 	struct instruction *ip = t->ip;
4956 
4957 	/* Structs. */
4958 	__instr_regrd_hrm_exec(p, t, ip);
4959 
4960 	/* Thread. */
4961 	thread_ip_inc(p);
4962 }
4963 
4964 static inline void
instr_regrd_mrh_exec(struct rte_swx_pipeline * p)4965 instr_regrd_mrh_exec(struct rte_swx_pipeline *p)
4966 {
4967 	struct thread *t = &p->threads[p->thread_id];
4968 	struct instruction *ip = t->ip;
4969 
4970 	/* Structs. */
4971 	__instr_regrd_mrh_exec(p, t, ip);
4972 
4973 	/* Thread. */
4974 	thread_ip_inc(p);
4975 }
4976 
4977 static inline void
instr_regrd_mrm_exec(struct rte_swx_pipeline * p)4978 instr_regrd_mrm_exec(struct rte_swx_pipeline *p)
4979 {
4980 	struct thread *t = &p->threads[p->thread_id];
4981 	struct instruction *ip = t->ip;
4982 
4983 	/* Structs. */
4984 	__instr_regrd_mrm_exec(p, t, ip);
4985 
4986 	/* Thread. */
4987 	thread_ip_inc(p);
4988 }
4989 
4990 static inline void
instr_regrd_hri_exec(struct rte_swx_pipeline * p)4991 instr_regrd_hri_exec(struct rte_swx_pipeline *p)
4992 {
4993 	struct thread *t = &p->threads[p->thread_id];
4994 	struct instruction *ip = t->ip;
4995 
4996 	/* Structs. */
4997 	__instr_regrd_hri_exec(p, t, ip);
4998 
4999 	/* Thread. */
5000 	thread_ip_inc(p);
5001 }
5002 
5003 static inline void
instr_regrd_mri_exec(struct rte_swx_pipeline * p)5004 instr_regrd_mri_exec(struct rte_swx_pipeline *p)
5005 {
5006 	struct thread *t = &p->threads[p->thread_id];
5007 	struct instruction *ip = t->ip;
5008 
5009 	/* Structs. */
5010 	__instr_regrd_mri_exec(p, t, ip);
5011 
5012 	/* Thread. */
5013 	thread_ip_inc(p);
5014 }
5015 
5016 static inline void
instr_regwr_rhh_exec(struct rte_swx_pipeline * p)5017 instr_regwr_rhh_exec(struct rte_swx_pipeline *p)
5018 {
5019 	struct thread *t = &p->threads[p->thread_id];
5020 	struct instruction *ip = t->ip;
5021 
5022 	/* Structs. */
5023 	__instr_regwr_rhh_exec(p, t, ip);
5024 
5025 	/* Thread. */
5026 	thread_ip_inc(p);
5027 }
5028 
5029 static inline void
instr_regwr_rhm_exec(struct rte_swx_pipeline * p)5030 instr_regwr_rhm_exec(struct rte_swx_pipeline *p)
5031 {
5032 	struct thread *t = &p->threads[p->thread_id];
5033 	struct instruction *ip = t->ip;
5034 
5035 	/* Structs. */
5036 	__instr_regwr_rhm_exec(p, t, ip);
5037 
5038 	/* Thread. */
5039 	thread_ip_inc(p);
5040 }
5041 
5042 static inline void
instr_regwr_rmh_exec(struct rte_swx_pipeline * p)5043 instr_regwr_rmh_exec(struct rte_swx_pipeline *p)
5044 {
5045 	struct thread *t = &p->threads[p->thread_id];
5046 	struct instruction *ip = t->ip;
5047 
5048 	/* Structs. */
5049 	__instr_regwr_rmh_exec(p, t, ip);
5050 
5051 	/* Thread. */
5052 	thread_ip_inc(p);
5053 }
5054 
5055 static inline void
instr_regwr_rmm_exec(struct rte_swx_pipeline * p)5056 instr_regwr_rmm_exec(struct rte_swx_pipeline *p)
5057 {
5058 	struct thread *t = &p->threads[p->thread_id];
5059 	struct instruction *ip = t->ip;
5060 
5061 	/* Structs. */
5062 	__instr_regwr_rmm_exec(p, t, ip);
5063 
5064 	/* Thread. */
5065 	thread_ip_inc(p);
5066 }
5067 
5068 static inline void
instr_regwr_rhi_exec(struct rte_swx_pipeline * p)5069 instr_regwr_rhi_exec(struct rte_swx_pipeline *p)
5070 {
5071 	struct thread *t = &p->threads[p->thread_id];
5072 	struct instruction *ip = t->ip;
5073 
5074 	/* Structs. */
5075 	__instr_regwr_rhi_exec(p, t, ip);
5076 
5077 	/* Thread. */
5078 	thread_ip_inc(p);
5079 }
5080 
5081 static inline void
instr_regwr_rmi_exec(struct rte_swx_pipeline * p)5082 instr_regwr_rmi_exec(struct rte_swx_pipeline *p)
5083 {
5084 	struct thread *t = &p->threads[p->thread_id];
5085 	struct instruction *ip = t->ip;
5086 
5087 	/* Structs. */
5088 	__instr_regwr_rmi_exec(p, t, ip);
5089 
5090 	/* Thread. */
5091 	thread_ip_inc(p);
5092 }
5093 
5094 static inline void
instr_regwr_rih_exec(struct rte_swx_pipeline * p)5095 instr_regwr_rih_exec(struct rte_swx_pipeline *p)
5096 {
5097 	struct thread *t = &p->threads[p->thread_id];
5098 	struct instruction *ip = t->ip;
5099 
5100 	/* Structs. */
5101 	__instr_regwr_rih_exec(p, t, ip);
5102 
5103 	/* Thread. */
5104 	thread_ip_inc(p);
5105 }
5106 
5107 static inline void
instr_regwr_rim_exec(struct rte_swx_pipeline * p)5108 instr_regwr_rim_exec(struct rte_swx_pipeline *p)
5109 {
5110 	struct thread *t = &p->threads[p->thread_id];
5111 	struct instruction *ip = t->ip;
5112 
5113 	/* Structs. */
5114 	__instr_regwr_rim_exec(p, t, ip);
5115 
5116 	/* Thread. */
5117 	thread_ip_inc(p);
5118 }
5119 
5120 static inline void
instr_regwr_rii_exec(struct rte_swx_pipeline * p)5121 instr_regwr_rii_exec(struct rte_swx_pipeline *p)
5122 {
5123 	struct thread *t = &p->threads[p->thread_id];
5124 	struct instruction *ip = t->ip;
5125 
5126 	/* Structs. */
5127 	__instr_regwr_rii_exec(p, t, ip);
5128 
5129 	/* Thread. */
5130 	thread_ip_inc(p);
5131 }
5132 
5133 static inline void
instr_regadd_rhh_exec(struct rte_swx_pipeline * p)5134 instr_regadd_rhh_exec(struct rte_swx_pipeline *p)
5135 {
5136 	struct thread *t = &p->threads[p->thread_id];
5137 	struct instruction *ip = t->ip;
5138 
5139 	/* Structs. */
5140 	__instr_regadd_rhh_exec(p, t, ip);
5141 
5142 	/* Thread. */
5143 	thread_ip_inc(p);
5144 }
5145 
5146 static inline void
instr_regadd_rhm_exec(struct rte_swx_pipeline * p)5147 instr_regadd_rhm_exec(struct rte_swx_pipeline *p)
5148 {
5149 	struct thread *t = &p->threads[p->thread_id];
5150 	struct instruction *ip = t->ip;
5151 
5152 	/* Structs. */
5153 	__instr_regadd_rhm_exec(p, t, ip);
5154 
5155 	/* Thread. */
5156 	thread_ip_inc(p);
5157 }
5158 
5159 static inline void
instr_regadd_rmh_exec(struct rte_swx_pipeline * p)5160 instr_regadd_rmh_exec(struct rte_swx_pipeline *p)
5161 {
5162 	struct thread *t = &p->threads[p->thread_id];
5163 	struct instruction *ip = t->ip;
5164 
5165 	/* Structs. */
5166 	__instr_regadd_rmh_exec(p, t, ip);
5167 
5168 	/* Thread. */
5169 	thread_ip_inc(p);
5170 }
5171 
5172 static inline void
instr_regadd_rmm_exec(struct rte_swx_pipeline * p)5173 instr_regadd_rmm_exec(struct rte_swx_pipeline *p)
5174 {
5175 	struct thread *t = &p->threads[p->thread_id];
5176 	struct instruction *ip = t->ip;
5177 
5178 	/* Structs. */
5179 	__instr_regadd_rmm_exec(p, t, ip);
5180 
5181 	/* Thread. */
5182 	thread_ip_inc(p);
5183 }
5184 
5185 static inline void
instr_regadd_rhi_exec(struct rte_swx_pipeline * p)5186 instr_regadd_rhi_exec(struct rte_swx_pipeline *p)
5187 {
5188 	struct thread *t = &p->threads[p->thread_id];
5189 	struct instruction *ip = t->ip;
5190 
5191 	/* Structs. */
5192 	__instr_regadd_rhi_exec(p, t, ip);
5193 
5194 	/* Thread. */
5195 	thread_ip_inc(p);
5196 }
5197 
5198 static inline void
instr_regadd_rmi_exec(struct rte_swx_pipeline * p)5199 instr_regadd_rmi_exec(struct rte_swx_pipeline *p)
5200 {
5201 	struct thread *t = &p->threads[p->thread_id];
5202 	struct instruction *ip = t->ip;
5203 
5204 	/* Structs. */
5205 	__instr_regadd_rmi_exec(p, t, ip);
5206 
5207 	/* Thread. */
5208 	thread_ip_inc(p);
5209 }
5210 
5211 static inline void
instr_regadd_rih_exec(struct rte_swx_pipeline * p)5212 instr_regadd_rih_exec(struct rte_swx_pipeline *p)
5213 {
5214 	struct thread *t = &p->threads[p->thread_id];
5215 	struct instruction *ip = t->ip;
5216 
5217 	/* Structs. */
5218 	__instr_regadd_rih_exec(p, t, ip);
5219 
5220 	/* Thread. */
5221 	thread_ip_inc(p);
5222 }
5223 
5224 static inline void
instr_regadd_rim_exec(struct rte_swx_pipeline * p)5225 instr_regadd_rim_exec(struct rte_swx_pipeline *p)
5226 {
5227 	struct thread *t = &p->threads[p->thread_id];
5228 	struct instruction *ip = t->ip;
5229 
5230 	/* Structs. */
5231 	__instr_regadd_rim_exec(p, t, ip);
5232 
5233 	/* Thread. */
5234 	thread_ip_inc(p);
5235 }
5236 
5237 static inline void
instr_regadd_rii_exec(struct rte_swx_pipeline * p)5238 instr_regadd_rii_exec(struct rte_swx_pipeline *p)
5239 {
5240 	struct thread *t = &p->threads[p->thread_id];
5241 	struct instruction *ip = t->ip;
5242 
5243 	/* Structs. */
5244 	__instr_regadd_rii_exec(p, t, ip);
5245 
5246 	/* Thread. */
5247 	thread_ip_inc(p);
5248 }
5249 
5250 /*
5251  * metarray.
5252  */
5253 static struct metarray *
5254 metarray_find(struct rte_swx_pipeline *p, const char *name);
5255 
5256 static int
instr_metprefetch_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)5257 instr_metprefetch_translate(struct rte_swx_pipeline *p,
5258 			    struct action *action,
5259 			    char **tokens,
5260 			    int n_tokens,
5261 			    struct instruction *instr,
5262 			    struct instruction_data *data __rte_unused)
5263 {
5264 	char *metarray = tokens[1], *idx = tokens[2];
5265 	struct metarray *m;
5266 	struct field *fidx;
5267 	uint32_t idx_struct_id, idx_val;
5268 
5269 	CHECK(n_tokens == 3, EINVAL);
5270 
5271 	m = metarray_find(p, metarray);
5272 	CHECK(m, EINVAL);
5273 
5274 	/* METPREFETCH_H, METPREFETCH_M. */
5275 	fidx = struct_field_parse(p, action, idx, &idx_struct_id);
5276 	if (fidx) {
5277 		CHECK(!fidx->var_size && (fidx->n_bits <= 64), EINVAL);
5278 
5279 		instr->type = INSTR_METPREFETCH_M;
5280 		if (idx[0] == 'h')
5281 			instr->type = INSTR_METPREFETCH_H;
5282 
5283 		instr->meter.metarray_id = m->id;
5284 		instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
5285 		instr->meter.idx.n_bits = fidx->n_bits;
5286 		instr->meter.idx.offset = fidx->offset / 8;
5287 		return 0;
5288 	}
5289 
5290 	/* METPREFETCH_I. */
5291 	idx_val = strtoul(idx, &idx, 0);
5292 	CHECK(!idx[0], EINVAL);
5293 
5294 	instr->type = INSTR_METPREFETCH_I;
5295 	instr->meter.metarray_id = m->id;
5296 	instr->meter.idx_val = idx_val;
5297 	return 0;
5298 }
5299 
5300 static int
instr_meter_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)5301 instr_meter_translate(struct rte_swx_pipeline *p,
5302 		      struct action *action,
5303 		      char **tokens,
5304 		      int n_tokens,
5305 		      struct instruction *instr,
5306 		      struct instruction_data *data __rte_unused)
5307 {
5308 	char *metarray = tokens[1], *idx = tokens[2], *length = tokens[3];
5309 	char *color_in = tokens[4], *color_out = tokens[5];
5310 	struct metarray *m;
5311 	struct field *fidx, *flength, *fcin, *fcout;
5312 	uint32_t idx_struct_id, length_struct_id;
5313 	uint32_t color_in_struct_id, color_out_struct_id;
5314 
5315 	CHECK(n_tokens == 6, EINVAL);
5316 
5317 	m = metarray_find(p, metarray);
5318 	CHECK(m, EINVAL);
5319 
5320 	fidx = struct_field_parse(p, action, idx, &idx_struct_id);
5321 
5322 	flength = struct_field_parse(p, action, length, &length_struct_id);
5323 	CHECK(flength, EINVAL);
5324 	CHECK(!flength->var_size && (flength->n_bits <= 64), EINVAL);
5325 
5326 	fcin = struct_field_parse(p, action, color_in, &color_in_struct_id);
5327 
5328 	fcout = struct_field_parse(p, NULL, color_out, &color_out_struct_id);
5329 	CHECK(fcout, EINVAL);
5330 	CHECK(!fcout->var_size  && (fcout->n_bits <= 64), EINVAL);
5331 
5332 	/* index = HMEFT, length = HMEFT, color_in = MEFT, color_out = MEF. */
5333 	if (fidx && fcin) {
5334 		CHECK(!fidx->var_size && (fidx->n_bits <= 64), EINVAL);
5335 		CHECK(!fcin->var_size && (fcin->n_bits <= 64), EINVAL);
5336 
5337 		instr->type = INSTR_METER_MMM;
5338 		if (idx[0] == 'h' && length[0] == 'h')
5339 			instr->type = INSTR_METER_HHM;
5340 		if (idx[0] == 'h' && length[0] != 'h')
5341 			instr->type = INSTR_METER_HMM;
5342 		if (idx[0] != 'h' && length[0] == 'h')
5343 			instr->type = INSTR_METER_MHM;
5344 
5345 		instr->meter.metarray_id = m->id;
5346 
5347 		instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
5348 		instr->meter.idx.n_bits = fidx->n_bits;
5349 		instr->meter.idx.offset = fidx->offset / 8;
5350 
5351 		instr->meter.length.struct_id = (uint8_t)length_struct_id;
5352 		instr->meter.length.n_bits = flength->n_bits;
5353 		instr->meter.length.offset = flength->offset / 8;
5354 
5355 		instr->meter.color_in.struct_id = (uint8_t)color_in_struct_id;
5356 		instr->meter.color_in.n_bits = fcin->n_bits;
5357 		instr->meter.color_in.offset = fcin->offset / 8;
5358 
5359 		instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5360 		instr->meter.color_out.n_bits = fcout->n_bits;
5361 		instr->meter.color_out.offset = fcout->offset / 8;
5362 	}
5363 
5364 	/* index = HMEFT, length = HMEFT, color_in = I, color_out = MEF. */
5365 	if (fidx && !fcin) {
5366 		uint32_t color_in_val;
5367 
5368 		CHECK(!fidx->var_size && (fidx->n_bits <= 64), EINVAL);
5369 
5370 		color_in_val = strtoul(color_in, &color_in, 0);
5371 		CHECK(!color_in[0], EINVAL);
5372 
5373 		instr->type = INSTR_METER_MMI;
5374 		if (idx[0] == 'h' && length[0] == 'h')
5375 			instr->type = INSTR_METER_HHI;
5376 		if (idx[0] == 'h' && length[0] != 'h')
5377 			instr->type = INSTR_METER_HMI;
5378 		if (idx[0] != 'h' && length[0] == 'h')
5379 			instr->type = INSTR_METER_MHI;
5380 
5381 		instr->meter.metarray_id = m->id;
5382 
5383 		instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
5384 		instr->meter.idx.n_bits = fidx->n_bits;
5385 		instr->meter.idx.offset = fidx->offset / 8;
5386 
5387 		instr->meter.length.struct_id = (uint8_t)length_struct_id;
5388 		instr->meter.length.n_bits = flength->n_bits;
5389 		instr->meter.length.offset = flength->offset / 8;
5390 
5391 		instr->meter.color_in_val = color_in_val;
5392 
5393 		instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5394 		instr->meter.color_out.n_bits = fcout->n_bits;
5395 		instr->meter.color_out.offset = fcout->offset / 8;
5396 	}
5397 
5398 	/* index = I, length = HMEFT, color_in = MEFT, color_out = MEF. */
5399 	if (!fidx && fcin) {
5400 		uint32_t idx_val;
5401 
5402 		idx_val = strtoul(idx, &idx, 0);
5403 		CHECK(!idx[0], EINVAL);
5404 
5405 		CHECK(!fcin->var_size && (fcin->n_bits <= 64), EINVAL);
5406 
5407 		instr->type = INSTR_METER_IMM;
5408 		if (length[0] == 'h')
5409 			instr->type = INSTR_METER_IHM;
5410 
5411 		instr->meter.metarray_id = m->id;
5412 
5413 		instr->meter.idx_val = idx_val;
5414 
5415 		instr->meter.length.struct_id = (uint8_t)length_struct_id;
5416 		instr->meter.length.n_bits = flength->n_bits;
5417 		instr->meter.length.offset = flength->offset / 8;
5418 
5419 		instr->meter.color_in.struct_id = (uint8_t)color_in_struct_id;
5420 		instr->meter.color_in.n_bits = fcin->n_bits;
5421 		instr->meter.color_in.offset = fcin->offset / 8;
5422 
5423 		instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5424 		instr->meter.color_out.n_bits = fcout->n_bits;
5425 		instr->meter.color_out.offset = fcout->offset / 8;
5426 	}
5427 
5428 	/* index = I, length = HMEFT, color_in = I, color_out = MEF. */
5429 	if (!fidx && !fcin) {
5430 		uint32_t idx_val, color_in_val;
5431 
5432 		idx_val = strtoul(idx, &idx, 0);
5433 		CHECK(!idx[0], EINVAL);
5434 
5435 		color_in_val = strtoul(color_in, &color_in, 0);
5436 		CHECK(!color_in[0], EINVAL);
5437 
5438 		instr->type = INSTR_METER_IMI;
5439 		if (length[0] == 'h')
5440 			instr->type = INSTR_METER_IHI;
5441 
5442 		instr->meter.metarray_id = m->id;
5443 
5444 		instr->meter.idx_val = idx_val;
5445 
5446 		instr->meter.length.struct_id = (uint8_t)length_struct_id;
5447 		instr->meter.length.n_bits = flength->n_bits;
5448 		instr->meter.length.offset = flength->offset / 8;
5449 
5450 		instr->meter.color_in_val = color_in_val;
5451 
5452 		instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5453 		instr->meter.color_out.n_bits = fcout->n_bits;
5454 		instr->meter.color_out.offset = fcout->offset / 8;
5455 	}
5456 
5457 	return 0;
5458 }
5459 
5460 static inline void
instr_metprefetch_h_exec(struct rte_swx_pipeline * p)5461 instr_metprefetch_h_exec(struct rte_swx_pipeline *p)
5462 {
5463 	struct thread *t = &p->threads[p->thread_id];
5464 	struct instruction *ip = t->ip;
5465 
5466 	/* Structs. */
5467 	__instr_metprefetch_h_exec(p, t, ip);
5468 
5469 	/* Thread. */
5470 	thread_ip_inc(p);
5471 }
5472 
5473 static inline void
instr_metprefetch_m_exec(struct rte_swx_pipeline * p)5474 instr_metprefetch_m_exec(struct rte_swx_pipeline *p)
5475 {
5476 	struct thread *t = &p->threads[p->thread_id];
5477 	struct instruction *ip = t->ip;
5478 
5479 	/* Structs. */
5480 	__instr_metprefetch_m_exec(p, t, ip);
5481 
5482 	/* Thread. */
5483 	thread_ip_inc(p);
5484 }
5485 
5486 static inline void
instr_metprefetch_i_exec(struct rte_swx_pipeline * p)5487 instr_metprefetch_i_exec(struct rte_swx_pipeline *p)
5488 {
5489 	struct thread *t = &p->threads[p->thread_id];
5490 	struct instruction *ip = t->ip;
5491 
5492 	/* Structs. */
5493 	__instr_metprefetch_i_exec(p, t, ip);
5494 
5495 	/* Thread. */
5496 	thread_ip_inc(p);
5497 }
5498 
5499 static inline void
instr_meter_hhm_exec(struct rte_swx_pipeline * p)5500 instr_meter_hhm_exec(struct rte_swx_pipeline *p)
5501 {
5502 	struct thread *t = &p->threads[p->thread_id];
5503 	struct instruction *ip = t->ip;
5504 
5505 	/* Structs. */
5506 	__instr_meter_hhm_exec(p, t, ip);
5507 
5508 	/* Thread. */
5509 	thread_ip_inc(p);
5510 }
5511 
5512 static inline void
instr_meter_hhi_exec(struct rte_swx_pipeline * p)5513 instr_meter_hhi_exec(struct rte_swx_pipeline *p)
5514 {
5515 	struct thread *t = &p->threads[p->thread_id];
5516 	struct instruction *ip = t->ip;
5517 
5518 	/* Structs. */
5519 	__instr_meter_hhi_exec(p, t, ip);
5520 
5521 	/* Thread. */
5522 	thread_ip_inc(p);
5523 }
5524 
5525 static inline void
instr_meter_hmm_exec(struct rte_swx_pipeline * p)5526 instr_meter_hmm_exec(struct rte_swx_pipeline *p)
5527 {
5528 	struct thread *t = &p->threads[p->thread_id];
5529 	struct instruction *ip = t->ip;
5530 
5531 	/* Structs. */
5532 	__instr_meter_hmm_exec(p, t, ip);
5533 
5534 	/* Thread. */
5535 	thread_ip_inc(p);
5536 }
5537 
5538 static inline void
instr_meter_hmi_exec(struct rte_swx_pipeline * p)5539 instr_meter_hmi_exec(struct rte_swx_pipeline *p)
5540 {
5541 	struct thread *t = &p->threads[p->thread_id];
5542 	struct instruction *ip = t->ip;
5543 
5544 	/* Structs. */
5545 	__instr_meter_hmi_exec(p, t, ip);
5546 
5547 	/* Thread. */
5548 	thread_ip_inc(p);
5549 }
5550 
5551 static inline void
instr_meter_mhm_exec(struct rte_swx_pipeline * p)5552 instr_meter_mhm_exec(struct rte_swx_pipeline *p)
5553 {
5554 	struct thread *t = &p->threads[p->thread_id];
5555 	struct instruction *ip = t->ip;
5556 
5557 	/* Structs. */
5558 	__instr_meter_mhm_exec(p, t, ip);
5559 
5560 	/* Thread. */
5561 	thread_ip_inc(p);
5562 }
5563 
5564 static inline void
instr_meter_mhi_exec(struct rte_swx_pipeline * p)5565 instr_meter_mhi_exec(struct rte_swx_pipeline *p)
5566 {
5567 	struct thread *t = &p->threads[p->thread_id];
5568 	struct instruction *ip = t->ip;
5569 
5570 	/* Structs. */
5571 	__instr_meter_mhi_exec(p, t, ip);
5572 
5573 	/* Thread. */
5574 	thread_ip_inc(p);
5575 }
5576 
5577 static inline void
instr_meter_mmm_exec(struct rte_swx_pipeline * p)5578 instr_meter_mmm_exec(struct rte_swx_pipeline *p)
5579 {
5580 	struct thread *t = &p->threads[p->thread_id];
5581 	struct instruction *ip = t->ip;
5582 
5583 	/* Structs. */
5584 	__instr_meter_mmm_exec(p, t, ip);
5585 
5586 	/* Thread. */
5587 	thread_ip_inc(p);
5588 }
5589 
5590 static inline void
instr_meter_mmi_exec(struct rte_swx_pipeline * p)5591 instr_meter_mmi_exec(struct rte_swx_pipeline *p)
5592 {
5593 	struct thread *t = &p->threads[p->thread_id];
5594 	struct instruction *ip = t->ip;
5595 
5596 	/* Structs. */
5597 	__instr_meter_mmi_exec(p, t, ip);
5598 
5599 	/* Thread. */
5600 	thread_ip_inc(p);
5601 }
5602 
5603 static inline void
instr_meter_ihm_exec(struct rte_swx_pipeline * p)5604 instr_meter_ihm_exec(struct rte_swx_pipeline *p)
5605 {
5606 	struct thread *t = &p->threads[p->thread_id];
5607 	struct instruction *ip = t->ip;
5608 
5609 	/* Structs. */
5610 	__instr_meter_ihm_exec(p, t, ip);
5611 
5612 	/* Thread. */
5613 	thread_ip_inc(p);
5614 }
5615 
5616 static inline void
instr_meter_ihi_exec(struct rte_swx_pipeline * p)5617 instr_meter_ihi_exec(struct rte_swx_pipeline *p)
5618 {
5619 	struct thread *t = &p->threads[p->thread_id];
5620 	struct instruction *ip = t->ip;
5621 
5622 	/* Structs. */
5623 	__instr_meter_ihi_exec(p, t, ip);
5624 
5625 	/* Thread. */
5626 	thread_ip_inc(p);
5627 }
5628 
5629 static inline void
instr_meter_imm_exec(struct rte_swx_pipeline * p)5630 instr_meter_imm_exec(struct rte_swx_pipeline *p)
5631 {
5632 	struct thread *t = &p->threads[p->thread_id];
5633 	struct instruction *ip = t->ip;
5634 
5635 	/* Structs. */
5636 	__instr_meter_imm_exec(p, t, ip);
5637 
5638 	/* Thread. */
5639 	thread_ip_inc(p);
5640 }
5641 
5642 static inline void
instr_meter_imi_exec(struct rte_swx_pipeline * p)5643 instr_meter_imi_exec(struct rte_swx_pipeline *p)
5644 {
5645 	struct thread *t = &p->threads[p->thread_id];
5646 	struct instruction *ip = t->ip;
5647 
5648 	/* Structs. */
5649 	__instr_meter_imi_exec(p, t, ip);
5650 
5651 	/* Thread. */
5652 	thread_ip_inc(p);
5653 }
5654 
5655 /*
5656  * jmp.
5657  */
5658 static int
instr_jmp_translate(struct rte_swx_pipeline * p __rte_unused,struct action * action __rte_unused,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data)5659 instr_jmp_translate(struct rte_swx_pipeline *p __rte_unused,
5660 		    struct action *action __rte_unused,
5661 		    char **tokens,
5662 		    int n_tokens,
5663 		    struct instruction *instr,
5664 		    struct instruction_data *data)
5665 {
5666 	CHECK(n_tokens == 2, EINVAL);
5667 
5668 	strcpy(data->jmp_label, tokens[1]);
5669 
5670 	instr->type = INSTR_JMP;
5671 	instr->jmp.ip = NULL; /* Resolved later. */
5672 	return 0;
5673 }
5674 
5675 static int
instr_jmp_valid_translate(struct rte_swx_pipeline * p,struct action * action __rte_unused,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data)5676 instr_jmp_valid_translate(struct rte_swx_pipeline *p,
5677 			  struct action *action __rte_unused,
5678 			  char **tokens,
5679 			  int n_tokens,
5680 			  struct instruction *instr,
5681 			  struct instruction_data *data)
5682 {
5683 	struct header *h;
5684 
5685 	CHECK(n_tokens == 3, EINVAL);
5686 
5687 	strcpy(data->jmp_label, tokens[1]);
5688 
5689 	h = header_parse(p, tokens[2]);
5690 	CHECK(h, EINVAL);
5691 
5692 	instr->type = INSTR_JMP_VALID;
5693 	instr->jmp.ip = NULL; /* Resolved later. */
5694 	instr->jmp.header_id = h->id;
5695 	return 0;
5696 }
5697 
5698 static int
instr_jmp_invalid_translate(struct rte_swx_pipeline * p,struct action * action __rte_unused,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data)5699 instr_jmp_invalid_translate(struct rte_swx_pipeline *p,
5700 			    struct action *action __rte_unused,
5701 			    char **tokens,
5702 			    int n_tokens,
5703 			    struct instruction *instr,
5704 			    struct instruction_data *data)
5705 {
5706 	struct header *h;
5707 
5708 	CHECK(n_tokens == 3, EINVAL);
5709 
5710 	strcpy(data->jmp_label, tokens[1]);
5711 
5712 	h = header_parse(p, tokens[2]);
5713 	CHECK(h, EINVAL);
5714 
5715 	instr->type = INSTR_JMP_INVALID;
5716 	instr->jmp.ip = NULL; /* Resolved later. */
5717 	instr->jmp.header_id = h->id;
5718 	return 0;
5719 }
5720 
5721 static int
instr_jmp_hit_translate(struct rte_swx_pipeline * p __rte_unused,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data)5722 instr_jmp_hit_translate(struct rte_swx_pipeline *p __rte_unused,
5723 			struct action *action,
5724 			char **tokens,
5725 			int n_tokens,
5726 			struct instruction *instr,
5727 			struct instruction_data *data)
5728 {
5729 	CHECK(!action, EINVAL);
5730 	CHECK(n_tokens == 2, EINVAL);
5731 
5732 	strcpy(data->jmp_label, tokens[1]);
5733 
5734 	instr->type = INSTR_JMP_HIT;
5735 	instr->jmp.ip = NULL; /* Resolved later. */
5736 	return 0;
5737 }
5738 
5739 static int
instr_jmp_miss_translate(struct rte_swx_pipeline * p __rte_unused,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data)5740 instr_jmp_miss_translate(struct rte_swx_pipeline *p __rte_unused,
5741 			 struct action *action,
5742 			 char **tokens,
5743 			 int n_tokens,
5744 			 struct instruction *instr,
5745 			 struct instruction_data *data)
5746 {
5747 	CHECK(!action, EINVAL);
5748 	CHECK(n_tokens == 2, EINVAL);
5749 
5750 	strcpy(data->jmp_label, tokens[1]);
5751 
5752 	instr->type = INSTR_JMP_MISS;
5753 	instr->jmp.ip = NULL; /* Resolved later. */
5754 	return 0;
5755 }
5756 
5757 static int
instr_jmp_action_hit_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data)5758 instr_jmp_action_hit_translate(struct rte_swx_pipeline *p,
5759 			       struct action *action,
5760 			       char **tokens,
5761 			       int n_tokens,
5762 			       struct instruction *instr,
5763 			       struct instruction_data *data)
5764 {
5765 	struct action *a;
5766 
5767 	CHECK(!action, EINVAL);
5768 	CHECK(n_tokens == 3, EINVAL);
5769 
5770 	strcpy(data->jmp_label, tokens[1]);
5771 
5772 	a = action_find(p, tokens[2]);
5773 	CHECK(a, EINVAL);
5774 
5775 	instr->type = INSTR_JMP_ACTION_HIT;
5776 	instr->jmp.ip = NULL; /* Resolved later. */
5777 	instr->jmp.action_id = a->id;
5778 	return 0;
5779 }
5780 
5781 static int
instr_jmp_action_miss_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data)5782 instr_jmp_action_miss_translate(struct rte_swx_pipeline *p,
5783 				struct action *action,
5784 				char **tokens,
5785 				int n_tokens,
5786 				struct instruction *instr,
5787 				struct instruction_data *data)
5788 {
5789 	struct action *a;
5790 
5791 	CHECK(!action, EINVAL);
5792 	CHECK(n_tokens == 3, EINVAL);
5793 
5794 	strcpy(data->jmp_label, tokens[1]);
5795 
5796 	a = action_find(p, tokens[2]);
5797 	CHECK(a, EINVAL);
5798 
5799 	instr->type = INSTR_JMP_ACTION_MISS;
5800 	instr->jmp.ip = NULL; /* Resolved later. */
5801 	instr->jmp.action_id = a->id;
5802 	return 0;
5803 }
5804 
5805 static int
instr_jmp_eq_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data)5806 instr_jmp_eq_translate(struct rte_swx_pipeline *p,
5807 		       struct action *action,
5808 		       char **tokens,
5809 		       int n_tokens,
5810 		       struct instruction *instr,
5811 		       struct instruction_data *data)
5812 {
5813 	char *a = tokens[2], *b = tokens[3];
5814 	struct field *fa, *fb;
5815 	uint64_t b_val;
5816 	uint32_t a_struct_id, b_struct_id;
5817 
5818 	CHECK(n_tokens == 4, EINVAL);
5819 
5820 	strcpy(data->jmp_label, tokens[1]);
5821 
5822 	fa = struct_field_parse(p, action, a, &a_struct_id);
5823 	CHECK(fa, EINVAL);
5824 	CHECK(!fa->var_size && (fa->n_bits <= 64), EINVAL);
5825 
5826 	/* JMP_EQ, JMP_EQ_MH, JMP_EQ_HM, JMP_EQ_HH. */
5827 	fb = struct_field_parse(p, action, b, &b_struct_id);
5828 	if (fb) {
5829 		CHECK(!fb->var_size && (fb->n_bits <= 64), EINVAL);
5830 
5831 		instr->type = INSTR_JMP_EQ;
5832 		if (a[0] != 'h' && b[0] == 'h')
5833 			instr->type = INSTR_JMP_EQ_MH;
5834 		if (a[0] == 'h' && b[0] != 'h')
5835 			instr->type = INSTR_JMP_EQ_HM;
5836 		if (a[0] == 'h' && b[0] == 'h')
5837 			instr->type = INSTR_JMP_EQ_HH;
5838 		instr->jmp.ip = NULL; /* Resolved later. */
5839 
5840 		instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5841 		instr->jmp.a.n_bits = fa->n_bits;
5842 		instr->jmp.a.offset = fa->offset / 8;
5843 		instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5844 		instr->jmp.b.n_bits = fb->n_bits;
5845 		instr->jmp.b.offset = fb->offset / 8;
5846 		return 0;
5847 	}
5848 
5849 	/* JMP_EQ_I. */
5850 	b_val = strtoull(b, &b, 0);
5851 	CHECK(!b[0], EINVAL);
5852 
5853 	if (a[0] == 'h')
5854 		b_val = hton64(b_val) >> (64 - fa->n_bits);
5855 
5856 	instr->type = INSTR_JMP_EQ_I;
5857 	instr->jmp.ip = NULL; /* Resolved later. */
5858 	instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5859 	instr->jmp.a.n_bits = fa->n_bits;
5860 	instr->jmp.a.offset = fa->offset / 8;
5861 	instr->jmp.b_val = b_val;
5862 	return 0;
5863 }
5864 
5865 static int
instr_jmp_neq_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data)5866 instr_jmp_neq_translate(struct rte_swx_pipeline *p,
5867 			struct action *action,
5868 			char **tokens,
5869 			int n_tokens,
5870 			struct instruction *instr,
5871 			struct instruction_data *data)
5872 {
5873 	char *a = tokens[2], *b = tokens[3];
5874 	struct field *fa, *fb;
5875 	uint64_t b_val;
5876 	uint32_t a_struct_id, b_struct_id;
5877 
5878 	CHECK(n_tokens == 4, EINVAL);
5879 
5880 	strcpy(data->jmp_label, tokens[1]);
5881 
5882 	fa = struct_field_parse(p, action, a, &a_struct_id);
5883 	CHECK(fa, EINVAL);
5884 	CHECK(!fa->var_size && (fa->n_bits <= 64), EINVAL);
5885 
5886 	/* JMP_NEQ, JMP_NEQ_MH, JMP_NEQ_HM, JMP_NEQ_HH. */
5887 	fb = struct_field_parse(p, action, b, &b_struct_id);
5888 	if (fb) {
5889 		CHECK(!fb->var_size && (fb->n_bits <= 64), EINVAL);
5890 
5891 		instr->type = INSTR_JMP_NEQ;
5892 		if (a[0] != 'h' && b[0] == 'h')
5893 			instr->type = INSTR_JMP_NEQ_MH;
5894 		if (a[0] == 'h' && b[0] != 'h')
5895 			instr->type = INSTR_JMP_NEQ_HM;
5896 		if (a[0] == 'h' && b[0] == 'h')
5897 			instr->type = INSTR_JMP_NEQ_HH;
5898 		instr->jmp.ip = NULL; /* Resolved later. */
5899 
5900 		instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5901 		instr->jmp.a.n_bits = fa->n_bits;
5902 		instr->jmp.a.offset = fa->offset / 8;
5903 		instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5904 		instr->jmp.b.n_bits = fb->n_bits;
5905 		instr->jmp.b.offset = fb->offset / 8;
5906 		return 0;
5907 	}
5908 
5909 	/* JMP_NEQ_I. */
5910 	b_val = strtoull(b, &b, 0);
5911 	CHECK(!b[0], EINVAL);
5912 
5913 	if (a[0] == 'h')
5914 		b_val = hton64(b_val) >> (64 - fa->n_bits);
5915 
5916 	instr->type = INSTR_JMP_NEQ_I;
5917 	instr->jmp.ip = NULL; /* Resolved later. */
5918 	instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5919 	instr->jmp.a.n_bits = fa->n_bits;
5920 	instr->jmp.a.offset = fa->offset / 8;
5921 	instr->jmp.b_val = b_val;
5922 	return 0;
5923 }
5924 
5925 static int
instr_jmp_lt_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data)5926 instr_jmp_lt_translate(struct rte_swx_pipeline *p,
5927 		       struct action *action,
5928 		       char **tokens,
5929 		       int n_tokens,
5930 		       struct instruction *instr,
5931 		       struct instruction_data *data)
5932 {
5933 	char *a = tokens[2], *b = tokens[3];
5934 	struct field *fa, *fb;
5935 	uint64_t b_val;
5936 	uint32_t a_struct_id, b_struct_id;
5937 
5938 	CHECK(n_tokens == 4, EINVAL);
5939 
5940 	strcpy(data->jmp_label, tokens[1]);
5941 
5942 	fa = struct_field_parse(p, action, a, &a_struct_id);
5943 	CHECK(fa, EINVAL);
5944 	CHECK(!fa->var_size && (fa->n_bits <= 64), EINVAL);
5945 
5946 	/* JMP_LT, JMP_LT_MH, JMP_LT_HM, JMP_LT_HH. */
5947 	fb = struct_field_parse(p, action, b, &b_struct_id);
5948 	if (fb) {
5949 		CHECK(!fb->var_size && (fb->n_bits <= 64), EINVAL);
5950 
5951 		instr->type = INSTR_JMP_LT;
5952 		if (a[0] == 'h' && b[0] != 'h')
5953 			instr->type = INSTR_JMP_LT_HM;
5954 		if (a[0] != 'h' && b[0] == 'h')
5955 			instr->type = INSTR_JMP_LT_MH;
5956 		if (a[0] == 'h' && b[0] == 'h')
5957 			instr->type = INSTR_JMP_LT_HH;
5958 		instr->jmp.ip = NULL; /* Resolved later. */
5959 
5960 		instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5961 		instr->jmp.a.n_bits = fa->n_bits;
5962 		instr->jmp.a.offset = fa->offset / 8;
5963 		instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5964 		instr->jmp.b.n_bits = fb->n_bits;
5965 		instr->jmp.b.offset = fb->offset / 8;
5966 		return 0;
5967 	}
5968 
5969 	/* JMP_LT_MI, JMP_LT_HI. */
5970 	b_val = strtoull(b, &b, 0);
5971 	CHECK(!b[0], EINVAL);
5972 
5973 	instr->type = INSTR_JMP_LT_MI;
5974 	if (a[0] == 'h')
5975 		instr->type = INSTR_JMP_LT_HI;
5976 	instr->jmp.ip = NULL; /* Resolved later. */
5977 
5978 	instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5979 	instr->jmp.a.n_bits = fa->n_bits;
5980 	instr->jmp.a.offset = fa->offset / 8;
5981 	instr->jmp.b_val = b_val;
5982 	return 0;
5983 }
5984 
5985 static int
instr_jmp_gt_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data)5986 instr_jmp_gt_translate(struct rte_swx_pipeline *p,
5987 		       struct action *action,
5988 		       char **tokens,
5989 		       int n_tokens,
5990 		       struct instruction *instr,
5991 		       struct instruction_data *data)
5992 {
5993 	char *a = tokens[2], *b = tokens[3];
5994 	struct field *fa, *fb;
5995 	uint64_t b_val;
5996 	uint32_t a_struct_id, b_struct_id;
5997 
5998 	CHECK(n_tokens == 4, EINVAL);
5999 
6000 	strcpy(data->jmp_label, tokens[1]);
6001 
6002 	fa = struct_field_parse(p, action, a, &a_struct_id);
6003 	CHECK(fa, EINVAL);
6004 	CHECK(!fa->var_size && (fa->n_bits <= 64), EINVAL);
6005 
6006 	/* JMP_GT, JMP_GT_MH, JMP_GT_HM, JMP_GT_HH. */
6007 	fb = struct_field_parse(p, action, b, &b_struct_id);
6008 	if (fb) {
6009 		CHECK(!fb->var_size && (fb->n_bits <= 64), EINVAL);
6010 
6011 		instr->type = INSTR_JMP_GT;
6012 		if (a[0] == 'h' && b[0] != 'h')
6013 			instr->type = INSTR_JMP_GT_HM;
6014 		if (a[0] != 'h' && b[0] == 'h')
6015 			instr->type = INSTR_JMP_GT_MH;
6016 		if (a[0] == 'h' && b[0] == 'h')
6017 			instr->type = INSTR_JMP_GT_HH;
6018 		instr->jmp.ip = NULL; /* Resolved later. */
6019 
6020 		instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6021 		instr->jmp.a.n_bits = fa->n_bits;
6022 		instr->jmp.a.offset = fa->offset / 8;
6023 		instr->jmp.b.struct_id = (uint8_t)b_struct_id;
6024 		instr->jmp.b.n_bits = fb->n_bits;
6025 		instr->jmp.b.offset = fb->offset / 8;
6026 		return 0;
6027 	}
6028 
6029 	/* JMP_GT_MI, JMP_GT_HI. */
6030 	b_val = strtoull(b, &b, 0);
6031 	CHECK(!b[0], EINVAL);
6032 
6033 	instr->type = INSTR_JMP_GT_MI;
6034 	if (a[0] == 'h')
6035 		instr->type = INSTR_JMP_GT_HI;
6036 	instr->jmp.ip = NULL; /* Resolved later. */
6037 
6038 	instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6039 	instr->jmp.a.n_bits = fa->n_bits;
6040 	instr->jmp.a.offset = fa->offset / 8;
6041 	instr->jmp.b_val = b_val;
6042 	return 0;
6043 }
6044 
6045 static inline void
instr_jmp_exec(struct rte_swx_pipeline * p)6046 instr_jmp_exec(struct rte_swx_pipeline *p)
6047 {
6048 	struct thread *t = &p->threads[p->thread_id];
6049 	struct instruction *ip = t->ip;
6050 
6051 	TRACE("[Thread %2u] jmp\n", p->thread_id);
6052 
6053 	thread_ip_set(t, ip->jmp.ip);
6054 }
6055 
6056 static inline void
instr_jmp_valid_exec(struct rte_swx_pipeline * p)6057 instr_jmp_valid_exec(struct rte_swx_pipeline *p)
6058 {
6059 	struct thread *t = &p->threads[p->thread_id];
6060 	struct instruction *ip = t->ip;
6061 	uint32_t header_id = ip->jmp.header_id;
6062 
6063 	TRACE("[Thread %2u] jmpv\n", p->thread_id);
6064 
6065 	t->ip = HEADER_VALID(t, header_id) ? ip->jmp.ip : (t->ip + 1);
6066 }
6067 
6068 static inline void
instr_jmp_invalid_exec(struct rte_swx_pipeline * p)6069 instr_jmp_invalid_exec(struct rte_swx_pipeline *p)
6070 {
6071 	struct thread *t = &p->threads[p->thread_id];
6072 	struct instruction *ip = t->ip;
6073 	uint32_t header_id = ip->jmp.header_id;
6074 
6075 	TRACE("[Thread %2u] jmpnv\n", p->thread_id);
6076 
6077 	t->ip = HEADER_VALID(t, header_id) ? (t->ip + 1) : ip->jmp.ip;
6078 }
6079 
6080 static inline void
instr_jmp_hit_exec(struct rte_swx_pipeline * p)6081 instr_jmp_hit_exec(struct rte_swx_pipeline *p)
6082 {
6083 	struct thread *t = &p->threads[p->thread_id];
6084 	struct instruction *ip = t->ip;
6085 	struct instruction *ip_next[] = {t->ip + 1, ip->jmp.ip};
6086 
6087 	TRACE("[Thread %2u] jmph\n", p->thread_id);
6088 
6089 	t->ip = ip_next[t->hit];
6090 }
6091 
6092 static inline void
instr_jmp_miss_exec(struct rte_swx_pipeline * p)6093 instr_jmp_miss_exec(struct rte_swx_pipeline *p)
6094 {
6095 	struct thread *t = &p->threads[p->thread_id];
6096 	struct instruction *ip = t->ip;
6097 	struct instruction *ip_next[] = {ip->jmp.ip, t->ip + 1};
6098 
6099 	TRACE("[Thread %2u] jmpnh\n", p->thread_id);
6100 
6101 	t->ip = ip_next[t->hit];
6102 }
6103 
6104 static inline void
instr_jmp_action_hit_exec(struct rte_swx_pipeline * p)6105 instr_jmp_action_hit_exec(struct rte_swx_pipeline *p)
6106 {
6107 	struct thread *t = &p->threads[p->thread_id];
6108 	struct instruction *ip = t->ip;
6109 
6110 	TRACE("[Thread %2u] jmpa\n", p->thread_id);
6111 
6112 	t->ip = (ip->jmp.action_id == t->action_id) ? ip->jmp.ip : (t->ip + 1);
6113 }
6114 
6115 static inline void
instr_jmp_action_miss_exec(struct rte_swx_pipeline * p)6116 instr_jmp_action_miss_exec(struct rte_swx_pipeline *p)
6117 {
6118 	struct thread *t = &p->threads[p->thread_id];
6119 	struct instruction *ip = t->ip;
6120 
6121 	TRACE("[Thread %2u] jmpna\n", p->thread_id);
6122 
6123 	t->ip = (ip->jmp.action_id == t->action_id) ? (t->ip + 1) : ip->jmp.ip;
6124 }
6125 
6126 static inline void
instr_jmp_eq_exec(struct rte_swx_pipeline * p)6127 instr_jmp_eq_exec(struct rte_swx_pipeline *p)
6128 {
6129 	struct thread *t = &p->threads[p->thread_id];
6130 	struct instruction *ip = t->ip;
6131 
6132 	TRACE("[Thread %2u] jmpeq\n", p->thread_id);
6133 
6134 	JMP_CMP(t, ip, ==);
6135 }
6136 
6137 static inline void
instr_jmp_eq_mh_exec(struct rte_swx_pipeline * p)6138 instr_jmp_eq_mh_exec(struct rte_swx_pipeline *p)
6139 {
6140 	struct thread *t = &p->threads[p->thread_id];
6141 	struct instruction *ip = t->ip;
6142 
6143 	TRACE("[Thread %2u] jmpeq (mh)\n", p->thread_id);
6144 
6145 	JMP_CMP_MH(t, ip, ==);
6146 }
6147 
6148 static inline void
instr_jmp_eq_hm_exec(struct rte_swx_pipeline * p)6149 instr_jmp_eq_hm_exec(struct rte_swx_pipeline *p)
6150 {
6151 	struct thread *t = &p->threads[p->thread_id];
6152 	struct instruction *ip = t->ip;
6153 
6154 	TRACE("[Thread %2u] jmpeq (hm)\n", p->thread_id);
6155 
6156 	JMP_CMP_HM(t, ip, ==);
6157 }
6158 
6159 static inline void
instr_jmp_eq_hh_exec(struct rte_swx_pipeline * p)6160 instr_jmp_eq_hh_exec(struct rte_swx_pipeline *p)
6161 {
6162 	struct thread *t = &p->threads[p->thread_id];
6163 	struct instruction *ip = t->ip;
6164 
6165 	TRACE("[Thread %2u] jmpeq (hh)\n", p->thread_id);
6166 
6167 	JMP_CMP_HH_FAST(t, ip, ==);
6168 }
6169 
6170 static inline void
instr_jmp_eq_i_exec(struct rte_swx_pipeline * p)6171 instr_jmp_eq_i_exec(struct rte_swx_pipeline *p)
6172 {
6173 	struct thread *t = &p->threads[p->thread_id];
6174 	struct instruction *ip = t->ip;
6175 
6176 	TRACE("[Thread %2u] jmpeq (i)\n", p->thread_id);
6177 
6178 	JMP_CMP_I(t, ip, ==);
6179 }
6180 
6181 static inline void
instr_jmp_neq_exec(struct rte_swx_pipeline * p)6182 instr_jmp_neq_exec(struct rte_swx_pipeline *p)
6183 {
6184 	struct thread *t = &p->threads[p->thread_id];
6185 	struct instruction *ip = t->ip;
6186 
6187 	TRACE("[Thread %2u] jmpneq\n", p->thread_id);
6188 
6189 	JMP_CMP(t, ip, !=);
6190 }
6191 
6192 static inline void
instr_jmp_neq_mh_exec(struct rte_swx_pipeline * p)6193 instr_jmp_neq_mh_exec(struct rte_swx_pipeline *p)
6194 {
6195 	struct thread *t = &p->threads[p->thread_id];
6196 	struct instruction *ip = t->ip;
6197 
6198 	TRACE("[Thread %2u] jmpneq (mh)\n", p->thread_id);
6199 
6200 	JMP_CMP_MH(t, ip, !=);
6201 }
6202 
6203 static inline void
instr_jmp_neq_hm_exec(struct rte_swx_pipeline * p)6204 instr_jmp_neq_hm_exec(struct rte_swx_pipeline *p)
6205 {
6206 	struct thread *t = &p->threads[p->thread_id];
6207 	struct instruction *ip = t->ip;
6208 
6209 	TRACE("[Thread %2u] jmpneq (hm)\n", p->thread_id);
6210 
6211 	JMP_CMP_HM(t, ip, !=);
6212 }
6213 
6214 static inline void
instr_jmp_neq_hh_exec(struct rte_swx_pipeline * p)6215 instr_jmp_neq_hh_exec(struct rte_swx_pipeline *p)
6216 {
6217 	struct thread *t = &p->threads[p->thread_id];
6218 	struct instruction *ip = t->ip;
6219 
6220 	TRACE("[Thread %2u] jmpneq (hh)\n", p->thread_id);
6221 
6222 	JMP_CMP_HH_FAST(t, ip, !=);
6223 }
6224 
6225 static inline void
instr_jmp_neq_i_exec(struct rte_swx_pipeline * p)6226 instr_jmp_neq_i_exec(struct rte_swx_pipeline *p)
6227 {
6228 	struct thread *t = &p->threads[p->thread_id];
6229 	struct instruction *ip = t->ip;
6230 
6231 	TRACE("[Thread %2u] jmpneq (i)\n", p->thread_id);
6232 
6233 	JMP_CMP_I(t, ip, !=);
6234 }
6235 
6236 static inline void
instr_jmp_lt_exec(struct rte_swx_pipeline * p)6237 instr_jmp_lt_exec(struct rte_swx_pipeline *p)
6238 {
6239 	struct thread *t = &p->threads[p->thread_id];
6240 	struct instruction *ip = t->ip;
6241 
6242 	TRACE("[Thread %2u] jmplt\n", p->thread_id);
6243 
6244 	JMP_CMP(t, ip, <);
6245 }
6246 
6247 static inline void
instr_jmp_lt_mh_exec(struct rte_swx_pipeline * p)6248 instr_jmp_lt_mh_exec(struct rte_swx_pipeline *p)
6249 {
6250 	struct thread *t = &p->threads[p->thread_id];
6251 	struct instruction *ip = t->ip;
6252 
6253 	TRACE("[Thread %2u] jmplt (mh)\n", p->thread_id);
6254 
6255 	JMP_CMP_MH(t, ip, <);
6256 }
6257 
6258 static inline void
instr_jmp_lt_hm_exec(struct rte_swx_pipeline * p)6259 instr_jmp_lt_hm_exec(struct rte_swx_pipeline *p)
6260 {
6261 	struct thread *t = &p->threads[p->thread_id];
6262 	struct instruction *ip = t->ip;
6263 
6264 	TRACE("[Thread %2u] jmplt (hm)\n", p->thread_id);
6265 
6266 	JMP_CMP_HM(t, ip, <);
6267 }
6268 
6269 static inline void
instr_jmp_lt_hh_exec(struct rte_swx_pipeline * p)6270 instr_jmp_lt_hh_exec(struct rte_swx_pipeline *p)
6271 {
6272 	struct thread *t = &p->threads[p->thread_id];
6273 	struct instruction *ip = t->ip;
6274 
6275 	TRACE("[Thread %2u] jmplt (hh)\n", p->thread_id);
6276 
6277 	JMP_CMP_HH(t, ip, <);
6278 }
6279 
6280 static inline void
instr_jmp_lt_mi_exec(struct rte_swx_pipeline * p)6281 instr_jmp_lt_mi_exec(struct rte_swx_pipeline *p)
6282 {
6283 	struct thread *t = &p->threads[p->thread_id];
6284 	struct instruction *ip = t->ip;
6285 
6286 	TRACE("[Thread %2u] jmplt (mi)\n", p->thread_id);
6287 
6288 	JMP_CMP_MI(t, ip, <);
6289 }
6290 
6291 static inline void
instr_jmp_lt_hi_exec(struct rte_swx_pipeline * p)6292 instr_jmp_lt_hi_exec(struct rte_swx_pipeline *p)
6293 {
6294 	struct thread *t = &p->threads[p->thread_id];
6295 	struct instruction *ip = t->ip;
6296 
6297 	TRACE("[Thread %2u] jmplt (hi)\n", p->thread_id);
6298 
6299 	JMP_CMP_HI(t, ip, <);
6300 }
6301 
6302 static inline void
instr_jmp_gt_exec(struct rte_swx_pipeline * p)6303 instr_jmp_gt_exec(struct rte_swx_pipeline *p)
6304 {
6305 	struct thread *t = &p->threads[p->thread_id];
6306 	struct instruction *ip = t->ip;
6307 
6308 	TRACE("[Thread %2u] jmpgt\n", p->thread_id);
6309 
6310 	JMP_CMP(t, ip, >);
6311 }
6312 
6313 static inline void
instr_jmp_gt_mh_exec(struct rte_swx_pipeline * p)6314 instr_jmp_gt_mh_exec(struct rte_swx_pipeline *p)
6315 {
6316 	struct thread *t = &p->threads[p->thread_id];
6317 	struct instruction *ip = t->ip;
6318 
6319 	TRACE("[Thread %2u] jmpgt (mh)\n", p->thread_id);
6320 
6321 	JMP_CMP_MH(t, ip, >);
6322 }
6323 
6324 static inline void
instr_jmp_gt_hm_exec(struct rte_swx_pipeline * p)6325 instr_jmp_gt_hm_exec(struct rte_swx_pipeline *p)
6326 {
6327 	struct thread *t = &p->threads[p->thread_id];
6328 	struct instruction *ip = t->ip;
6329 
6330 	TRACE("[Thread %2u] jmpgt (hm)\n", p->thread_id);
6331 
6332 	JMP_CMP_HM(t, ip, >);
6333 }
6334 
6335 static inline void
instr_jmp_gt_hh_exec(struct rte_swx_pipeline * p)6336 instr_jmp_gt_hh_exec(struct rte_swx_pipeline *p)
6337 {
6338 	struct thread *t = &p->threads[p->thread_id];
6339 	struct instruction *ip = t->ip;
6340 
6341 	TRACE("[Thread %2u] jmpgt (hh)\n", p->thread_id);
6342 
6343 	JMP_CMP_HH(t, ip, >);
6344 }
6345 
6346 static inline void
instr_jmp_gt_mi_exec(struct rte_swx_pipeline * p)6347 instr_jmp_gt_mi_exec(struct rte_swx_pipeline *p)
6348 {
6349 	struct thread *t = &p->threads[p->thread_id];
6350 	struct instruction *ip = t->ip;
6351 
6352 	TRACE("[Thread %2u] jmpgt (mi)\n", p->thread_id);
6353 
6354 	JMP_CMP_MI(t, ip, >);
6355 }
6356 
6357 static inline void
instr_jmp_gt_hi_exec(struct rte_swx_pipeline * p)6358 instr_jmp_gt_hi_exec(struct rte_swx_pipeline *p)
6359 {
6360 	struct thread *t = &p->threads[p->thread_id];
6361 	struct instruction *ip = t->ip;
6362 
6363 	TRACE("[Thread %2u] jmpgt (hi)\n", p->thread_id);
6364 
6365 	JMP_CMP_HI(t, ip, >);
6366 }
6367 
6368 /*
6369  * return.
6370  */
6371 static int
instr_return_translate(struct rte_swx_pipeline * p __rte_unused,struct action * action,char ** tokens __rte_unused,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)6372 instr_return_translate(struct rte_swx_pipeline *p __rte_unused,
6373 		       struct action *action,
6374 		       char **tokens __rte_unused,
6375 		       int n_tokens,
6376 		       struct instruction *instr,
6377 		       struct instruction_data *data __rte_unused)
6378 {
6379 	CHECK(action, EINVAL);
6380 	CHECK(n_tokens == 1, EINVAL);
6381 
6382 	instr->type = INSTR_RETURN;
6383 	return 0;
6384 }
6385 
6386 static inline void
instr_return_exec(struct rte_swx_pipeline * p)6387 instr_return_exec(struct rte_swx_pipeline *p)
6388 {
6389 	struct thread *t = &p->threads[p->thread_id];
6390 
6391 	TRACE("[Thread %2u] return\n", p->thread_id);
6392 
6393 	t->ip = t->ret;
6394 }
6395 
6396 static int
instr_translate(struct rte_swx_pipeline * p,struct action * action,char * string,struct instruction * instr,struct instruction_data * data)6397 instr_translate(struct rte_swx_pipeline *p,
6398 		struct action *action,
6399 		char *string,
6400 		struct instruction *instr,
6401 		struct instruction_data *data)
6402 {
6403 	char *tokens[RTE_SWX_INSTRUCTION_TOKENS_MAX];
6404 	int n_tokens = 0, tpos = 0;
6405 
6406 	/* Parse the instruction string into tokens. */
6407 	for ( ; ; ) {
6408 		char *token;
6409 
6410 		token = strtok_r(string, " \t\v", &string);
6411 		if (!token)
6412 			break;
6413 
6414 		CHECK(n_tokens < RTE_SWX_INSTRUCTION_TOKENS_MAX, EINVAL);
6415 		CHECK_NAME(token, EINVAL);
6416 
6417 		tokens[n_tokens] = token;
6418 		n_tokens++;
6419 	}
6420 
6421 	CHECK(n_tokens, EINVAL);
6422 
6423 	/* Handle the optional instruction label. */
6424 	if ((n_tokens >= 2) && !strcmp(tokens[1], ":")) {
6425 		strcpy(data->label, tokens[0]);
6426 
6427 		tpos += 2;
6428 		CHECK(n_tokens - tpos, EINVAL);
6429 	}
6430 
6431 	/* Identify the instruction type. */
6432 	if (!strcmp(tokens[tpos], "rx"))
6433 		return instr_rx_translate(p,
6434 					  action,
6435 					  &tokens[tpos],
6436 					  n_tokens - tpos,
6437 					  instr,
6438 					  data);
6439 
6440 	if (!strcmp(tokens[tpos], "tx"))
6441 		return instr_tx_translate(p,
6442 					  action,
6443 					  &tokens[tpos],
6444 					  n_tokens - tpos,
6445 					  instr,
6446 					  data);
6447 
6448 	if (!strcmp(tokens[tpos], "drop"))
6449 		return instr_drop_translate(p,
6450 					    action,
6451 					    &tokens[tpos],
6452 					    n_tokens - tpos,
6453 					    instr,
6454 					    data);
6455 
6456 	if (!strcmp(tokens[tpos], "mirror"))
6457 		return instr_mirror_translate(p,
6458 					      action,
6459 					      &tokens[tpos],
6460 					      n_tokens - tpos,
6461 					      instr,
6462 					      data);
6463 
6464 	if (!strcmp(tokens[tpos], "recirculate"))
6465 		return instr_recirculate_translate(p,
6466 					      action,
6467 					      &tokens[tpos],
6468 					      n_tokens - tpos,
6469 					      instr,
6470 					      data);
6471 
6472 	if (!strcmp(tokens[tpos], "recircid"))
6473 		return instr_recircid_translate(p,
6474 					      action,
6475 					      &tokens[tpos],
6476 					      n_tokens - tpos,
6477 					      instr,
6478 					      data);
6479 
6480 	if (!strcmp(tokens[tpos], "extract"))
6481 		return instr_hdr_extract_translate(p,
6482 						   action,
6483 						   &tokens[tpos],
6484 						   n_tokens - tpos,
6485 						   instr,
6486 						   data);
6487 
6488 	if (!strcmp(tokens[tpos], "lookahead"))
6489 		return instr_hdr_lookahead_translate(p,
6490 						     action,
6491 						     &tokens[tpos],
6492 						     n_tokens - tpos,
6493 						     instr,
6494 						     data);
6495 
6496 	if (!strcmp(tokens[tpos], "emit"))
6497 		return instr_hdr_emit_translate(p,
6498 						action,
6499 						&tokens[tpos],
6500 						n_tokens - tpos,
6501 						instr,
6502 						data);
6503 
6504 	if (!strcmp(tokens[tpos], "validate"))
6505 		return instr_hdr_validate_translate(p,
6506 						    action,
6507 						    &tokens[tpos],
6508 						    n_tokens - tpos,
6509 						    instr,
6510 						    data);
6511 
6512 	if (!strcmp(tokens[tpos], "invalidate"))
6513 		return instr_hdr_invalidate_translate(p,
6514 						      action,
6515 						      &tokens[tpos],
6516 						      n_tokens - tpos,
6517 						      instr,
6518 						      data);
6519 
6520 	if (!strcmp(tokens[tpos], "mov"))
6521 		return instr_mov_translate(p,
6522 					   action,
6523 					   &tokens[tpos],
6524 					   n_tokens - tpos,
6525 					   instr,
6526 					   data);
6527 
6528 	if (!strcmp(tokens[tpos], "movh"))
6529 		return instr_movh_translate(p,
6530 					    action,
6531 					    &tokens[tpos],
6532 					    n_tokens - tpos,
6533 					    instr,
6534 					    data);
6535 
6536 	if (!strcmp(tokens[tpos], "add"))
6537 		return instr_alu_add_translate(p,
6538 					       action,
6539 					       &tokens[tpos],
6540 					       n_tokens - tpos,
6541 					       instr,
6542 					       data);
6543 
6544 	if (!strcmp(tokens[tpos], "sub"))
6545 		return instr_alu_sub_translate(p,
6546 					       action,
6547 					       &tokens[tpos],
6548 					       n_tokens - tpos,
6549 					       instr,
6550 					       data);
6551 
6552 	if (!strcmp(tokens[tpos], "ckadd"))
6553 		return instr_alu_ckadd_translate(p,
6554 						 action,
6555 						 &tokens[tpos],
6556 						 n_tokens - tpos,
6557 						 instr,
6558 						 data);
6559 
6560 	if (!strcmp(tokens[tpos], "cksub"))
6561 		return instr_alu_cksub_translate(p,
6562 						 action,
6563 						 &tokens[tpos],
6564 						 n_tokens - tpos,
6565 						 instr,
6566 						 data);
6567 
6568 	if (!strcmp(tokens[tpos], "and"))
6569 		return instr_alu_and_translate(p,
6570 					       action,
6571 					       &tokens[tpos],
6572 					       n_tokens - tpos,
6573 					       instr,
6574 					       data);
6575 
6576 	if (!strcmp(tokens[tpos], "or"))
6577 		return instr_alu_or_translate(p,
6578 					      action,
6579 					      &tokens[tpos],
6580 					      n_tokens - tpos,
6581 					      instr,
6582 					      data);
6583 
6584 	if (!strcmp(tokens[tpos], "xor"))
6585 		return instr_alu_xor_translate(p,
6586 					       action,
6587 					       &tokens[tpos],
6588 					       n_tokens - tpos,
6589 					       instr,
6590 					       data);
6591 
6592 	if (!strcmp(tokens[tpos], "shl"))
6593 		return instr_alu_shl_translate(p,
6594 					       action,
6595 					       &tokens[tpos],
6596 					       n_tokens - tpos,
6597 					       instr,
6598 					       data);
6599 
6600 	if (!strcmp(tokens[tpos], "shr"))
6601 		return instr_alu_shr_translate(p,
6602 					       action,
6603 					       &tokens[tpos],
6604 					       n_tokens - tpos,
6605 					       instr,
6606 					       data);
6607 
6608 	if (!strcmp(tokens[tpos], "regprefetch"))
6609 		return instr_regprefetch_translate(p,
6610 						   action,
6611 						   &tokens[tpos],
6612 						   n_tokens - tpos,
6613 						   instr,
6614 						   data);
6615 
6616 	if (!strcmp(tokens[tpos], "regrd"))
6617 		return instr_regrd_translate(p,
6618 					     action,
6619 					     &tokens[tpos],
6620 					     n_tokens - tpos,
6621 					     instr,
6622 					     data);
6623 
6624 	if (!strcmp(tokens[tpos], "regwr"))
6625 		return instr_regwr_translate(p,
6626 					     action,
6627 					     &tokens[tpos],
6628 					     n_tokens - tpos,
6629 					     instr,
6630 					     data);
6631 
6632 	if (!strcmp(tokens[tpos], "regadd"))
6633 		return instr_regadd_translate(p,
6634 					      action,
6635 					      &tokens[tpos],
6636 					      n_tokens - tpos,
6637 					      instr,
6638 					      data);
6639 
6640 	if (!strcmp(tokens[tpos], "metprefetch"))
6641 		return instr_metprefetch_translate(p,
6642 						   action,
6643 						   &tokens[tpos],
6644 						   n_tokens - tpos,
6645 						   instr,
6646 						   data);
6647 
6648 	if (!strcmp(tokens[tpos], "meter"))
6649 		return instr_meter_translate(p,
6650 					     action,
6651 					     &tokens[tpos],
6652 					     n_tokens - tpos,
6653 					     instr,
6654 					     data);
6655 
6656 	if (!strcmp(tokens[tpos], "table"))
6657 		return instr_table_translate(p,
6658 					     action,
6659 					     &tokens[tpos],
6660 					     n_tokens - tpos,
6661 					     instr,
6662 					     data);
6663 
6664 	if (!strcmp(tokens[tpos], "learn"))
6665 		return instr_learn_translate(p,
6666 					     action,
6667 					     &tokens[tpos],
6668 					     n_tokens - tpos,
6669 					     instr,
6670 					     data);
6671 	if (!strcmp(tokens[tpos], "rearm"))
6672 		return instr_rearm_translate(p,
6673 					     action,
6674 					     &tokens[tpos],
6675 					     n_tokens - tpos,
6676 					     instr,
6677 					     data);
6678 
6679 	if (!strcmp(tokens[tpos], "forget"))
6680 		return instr_forget_translate(p,
6681 					      action,
6682 					      &tokens[tpos],
6683 					      n_tokens - tpos,
6684 					      instr,
6685 					      data);
6686 
6687 	if (!strcmp(tokens[tpos], "entryid"))
6688 		return instr_entryid_translate(p,
6689 					       action,
6690 					       &tokens[tpos],
6691 					       n_tokens - tpos,
6692 					       instr,
6693 					       data);
6694 
6695 	if (!strcmp(tokens[tpos], "extern"))
6696 		return instr_extern_translate(p,
6697 					      action,
6698 					      &tokens[tpos],
6699 					      n_tokens - tpos,
6700 					      instr,
6701 					      data);
6702 
6703 	if (!strcmp(tokens[tpos], "hash"))
6704 		return instr_hash_translate(p,
6705 					    action,
6706 					    &tokens[tpos],
6707 					    n_tokens - tpos,
6708 					    instr,
6709 					    data);
6710 
6711 	if (!strcmp(tokens[tpos], "rss"))
6712 		return instr_rss_translate(p,
6713 					   action,
6714 					   &tokens[tpos],
6715 					   n_tokens - tpos,
6716 					   instr,
6717 					   data);
6718 
6719 	if (!strcmp(tokens[tpos], "jmp"))
6720 		return instr_jmp_translate(p,
6721 					   action,
6722 					   &tokens[tpos],
6723 					   n_tokens - tpos,
6724 					   instr,
6725 					   data);
6726 
6727 	if (!strcmp(tokens[tpos], "jmpv"))
6728 		return instr_jmp_valid_translate(p,
6729 						 action,
6730 						 &tokens[tpos],
6731 						 n_tokens - tpos,
6732 						 instr,
6733 						 data);
6734 
6735 	if (!strcmp(tokens[tpos], "jmpnv"))
6736 		return instr_jmp_invalid_translate(p,
6737 						   action,
6738 						   &tokens[tpos],
6739 						   n_tokens - tpos,
6740 						   instr,
6741 						   data);
6742 
6743 	if (!strcmp(tokens[tpos], "jmph"))
6744 		return instr_jmp_hit_translate(p,
6745 					       action,
6746 					       &tokens[tpos],
6747 					       n_tokens - tpos,
6748 					       instr,
6749 					       data);
6750 
6751 	if (!strcmp(tokens[tpos], "jmpnh"))
6752 		return instr_jmp_miss_translate(p,
6753 						action,
6754 						&tokens[tpos],
6755 						n_tokens - tpos,
6756 						instr,
6757 						data);
6758 
6759 	if (!strcmp(tokens[tpos], "jmpa"))
6760 		return instr_jmp_action_hit_translate(p,
6761 						      action,
6762 						      &tokens[tpos],
6763 						      n_tokens - tpos,
6764 						      instr,
6765 						      data);
6766 
6767 	if (!strcmp(tokens[tpos], "jmpna"))
6768 		return instr_jmp_action_miss_translate(p,
6769 						       action,
6770 						       &tokens[tpos],
6771 						       n_tokens - tpos,
6772 						       instr,
6773 						       data);
6774 
6775 	if (!strcmp(tokens[tpos], "jmpeq"))
6776 		return instr_jmp_eq_translate(p,
6777 					      action,
6778 					      &tokens[tpos],
6779 					      n_tokens - tpos,
6780 					      instr,
6781 					      data);
6782 
6783 	if (!strcmp(tokens[tpos], "jmpneq"))
6784 		return instr_jmp_neq_translate(p,
6785 					       action,
6786 					       &tokens[tpos],
6787 					       n_tokens - tpos,
6788 					       instr,
6789 					       data);
6790 
6791 	if (!strcmp(tokens[tpos], "jmplt"))
6792 		return instr_jmp_lt_translate(p,
6793 					      action,
6794 					      &tokens[tpos],
6795 					      n_tokens - tpos,
6796 					      instr,
6797 					      data);
6798 
6799 	if (!strcmp(tokens[tpos], "jmpgt"))
6800 		return instr_jmp_gt_translate(p,
6801 					      action,
6802 					      &tokens[tpos],
6803 					      n_tokens - tpos,
6804 					      instr,
6805 					      data);
6806 
6807 	if (!strcmp(tokens[tpos], "return"))
6808 		return instr_return_translate(p,
6809 					      action,
6810 					      &tokens[tpos],
6811 					      n_tokens - tpos,
6812 					      instr,
6813 					      data);
6814 
6815 	return -EINVAL;
6816 }
6817 
6818 static struct instruction_data *
label_find(struct instruction_data * data,uint32_t n,const char * label)6819 label_find(struct instruction_data *data, uint32_t n, const char *label)
6820 {
6821 	uint32_t i;
6822 
6823 	for (i = 0; i < n; i++)
6824 		if (!strcmp(label, data[i].label))
6825 			return &data[i];
6826 
6827 	return NULL;
6828 }
6829 
6830 static uint32_t
label_is_used(struct instruction_data * data,uint32_t n,const char * label)6831 label_is_used(struct instruction_data *data, uint32_t n, const char *label)
6832 {
6833 	uint32_t count = 0, i;
6834 
6835 	if (!label[0])
6836 		return 0;
6837 
6838 	for (i = 0; i < n; i++)
6839 		if (!strcmp(label, data[i].jmp_label))
6840 			count++;
6841 
6842 	return count;
6843 }
6844 
6845 static int
instr_label_check(struct instruction_data * instruction_data,uint32_t n_instructions)6846 instr_label_check(struct instruction_data *instruction_data,
6847 		  uint32_t n_instructions)
6848 {
6849 	uint32_t i;
6850 
6851 	/* Check that all instruction labels are unique. */
6852 	for (i = 0; i < n_instructions; i++) {
6853 		struct instruction_data *data = &instruction_data[i];
6854 		char *label = data->label;
6855 		uint32_t j;
6856 
6857 		if (!label[0])
6858 			continue;
6859 
6860 		for (j = i + 1; j < n_instructions; j++)
6861 			CHECK(strcmp(label, instruction_data[j].label), EINVAL);
6862 	}
6863 
6864 	/* Check that no jump instruction (either conditional or not) can jump to itself (loop). */
6865 	for (i = 0; i < n_instructions; i++) {
6866 		struct instruction_data *data = &instruction_data[i];
6867 		char *label = data->label;
6868 		char *jmp_label = data->jmp_label;
6869 
6870 		/* Continue if this instruction does not have a label or it is not a jump. */
6871 		if (!label[0] || !jmp_label[0])
6872 			continue;
6873 
6874 		CHECK(strcmp(label, jmp_label), EINVAL);
6875 	}
6876 
6877 	/* Get users for each instruction label. */
6878 	for (i = 0; i < n_instructions; i++) {
6879 		struct instruction_data *data = &instruction_data[i];
6880 		char *label = data->label;
6881 
6882 		data->n_users = label_is_used(instruction_data,
6883 					      n_instructions,
6884 					      label);
6885 	}
6886 
6887 	return 0;
6888 }
6889 
6890 static int
instr_jmp_resolve(struct instruction * instructions,struct instruction_data * instruction_data,uint32_t n_instructions)6891 instr_jmp_resolve(struct instruction *instructions,
6892 		  struct instruction_data *instruction_data,
6893 		  uint32_t n_instructions)
6894 {
6895 	uint32_t i;
6896 
6897 	for (i = 0; i < n_instructions; i++) {
6898 		struct instruction *instr = &instructions[i];
6899 		struct instruction_data *data = &instruction_data[i];
6900 		struct instruction_data *found;
6901 
6902 		if (!instruction_is_jmp(instr))
6903 			continue;
6904 
6905 		found = label_find(instruction_data,
6906 				   n_instructions,
6907 				   data->jmp_label);
6908 		CHECK(found, EINVAL);
6909 
6910 		instr->jmp.ip = &instructions[found - instruction_data];
6911 	}
6912 
6913 	return 0;
6914 }
6915 
6916 static int
instr_verify(struct rte_swx_pipeline * p __rte_unused,struct action * a,struct instruction * instr,struct instruction_data * data __rte_unused,uint32_t n_instructions)6917 instr_verify(struct rte_swx_pipeline *p __rte_unused,
6918 	     struct action *a,
6919 	     struct instruction *instr,
6920 	     struct instruction_data *data __rte_unused,
6921 	     uint32_t n_instructions)
6922 {
6923 	if (!a) {
6924 		enum instruction_type type;
6925 		uint32_t i;
6926 
6927 		/* Check that the first instruction is rx. */
6928 		CHECK(instr[0].type == INSTR_RX, EINVAL);
6929 
6930 		/* Check that there is at least one tx instruction. */
6931 		for (i = 0; i < n_instructions; i++) {
6932 			type = instr[i].type;
6933 
6934 			if (instruction_is_tx(type))
6935 				break;
6936 		}
6937 		CHECK(i < n_instructions, EINVAL);
6938 
6939 		/* Check that the last instruction is either tx or unconditional
6940 		 * jump.
6941 		 */
6942 		type = instr[n_instructions - 1].type;
6943 		CHECK(instruction_is_tx(type) || (type == INSTR_JMP), EINVAL);
6944 	}
6945 
6946 	if (a) {
6947 		enum instruction_type type;
6948 		uint32_t i;
6949 
6950 		/* Check that there is at least one return or tx instruction. */
6951 		for (i = 0; i < n_instructions; i++) {
6952 			type = instr[i].type;
6953 
6954 			if ((type == INSTR_RETURN) || instruction_is_tx(type))
6955 				break;
6956 		}
6957 		CHECK(i < n_instructions, EINVAL);
6958 	}
6959 
6960 	return 0;
6961 }
6962 
6963 static uint32_t
instr_compact(struct instruction * instructions,struct instruction_data * instruction_data,uint32_t n_instructions)6964 instr_compact(struct instruction *instructions,
6965 	      struct instruction_data *instruction_data,
6966 	      uint32_t n_instructions)
6967 {
6968 	uint32_t i, pos = 0;
6969 
6970 	/* Eliminate the invalid instructions that have been optimized out. */
6971 	for (i = 0; i < n_instructions; i++) {
6972 		struct instruction *instr = &instructions[i];
6973 		struct instruction_data *data = &instruction_data[i];
6974 
6975 		if (data->invalid)
6976 			continue;
6977 
6978 		if (i != pos) {
6979 			memcpy(&instructions[pos], instr, sizeof(*instr));
6980 			memcpy(&instruction_data[pos], data, sizeof(*data));
6981 		}
6982 
6983 		pos++;
6984 	}
6985 
6986 	return pos;
6987 }
6988 
6989 static int
instr_pattern_extract_many_search(struct instruction * instr,struct instruction_data * data,uint32_t n_instr,uint32_t * n_pattern_instr)6990 instr_pattern_extract_many_search(struct instruction *instr,
6991 				  struct instruction_data *data,
6992 				  uint32_t n_instr,
6993 				  uint32_t *n_pattern_instr)
6994 {
6995 	uint32_t i;
6996 
6997 	for (i = 0; i < n_instr; i++) {
6998 		if (data[i].invalid)
6999 			break;
7000 
7001 		if (instr[i].type != INSTR_HDR_EXTRACT)
7002 			break;
7003 
7004 		if (i == RTE_DIM(instr->io.hdr.header_id))
7005 			break;
7006 
7007 		if (i && data[i].n_users)
7008 			break;
7009 	}
7010 
7011 	if (i < 2)
7012 		return 0;
7013 
7014 	*n_pattern_instr = i;
7015 	return 1;
7016 }
7017 
7018 static void
instr_pattern_extract_many_replace(struct instruction * instr,struct instruction_data * data,uint32_t n_instr)7019 instr_pattern_extract_many_replace(struct instruction *instr,
7020 				   struct instruction_data *data,
7021 				   uint32_t n_instr)
7022 {
7023 	uint32_t i;
7024 
7025 	for (i = 1; i < n_instr; i++) {
7026 		instr[0].type++;
7027 		instr[0].io.hdr.header_id[i] = instr[i].io.hdr.header_id[0];
7028 		instr[0].io.hdr.struct_id[i] = instr[i].io.hdr.struct_id[0];
7029 		instr[0].io.hdr.n_bytes[i] = instr[i].io.hdr.n_bytes[0];
7030 
7031 		data[i].invalid = 1;
7032 	}
7033 }
7034 
7035 static uint32_t
instr_pattern_extract_many_optimize(struct instruction * instructions,struct instruction_data * instruction_data,uint32_t n_instructions)7036 instr_pattern_extract_many_optimize(struct instruction *instructions,
7037 				    struct instruction_data *instruction_data,
7038 				    uint32_t n_instructions)
7039 {
7040 	uint32_t i;
7041 
7042 	for (i = 0; i < n_instructions; ) {
7043 		struct instruction *instr = &instructions[i];
7044 		struct instruction_data *data = &instruction_data[i];
7045 		uint32_t n_instr = 0;
7046 		int detected;
7047 
7048 		/* Extract many. */
7049 		detected = instr_pattern_extract_many_search(instr,
7050 							     data,
7051 							     n_instructions - i,
7052 							     &n_instr);
7053 		if (detected) {
7054 			instr_pattern_extract_many_replace(instr,
7055 							   data,
7056 							   n_instr);
7057 			i += n_instr;
7058 			continue;
7059 		}
7060 
7061 		/* No pattern starting at the current instruction. */
7062 		i++;
7063 	}
7064 
7065 	/* Eliminate the invalid instructions that have been optimized out. */
7066 	n_instructions = instr_compact(instructions,
7067 				       instruction_data,
7068 				       n_instructions);
7069 
7070 	return n_instructions;
7071 }
7072 
7073 static int
instr_pattern_emit_many_tx_search(struct instruction * instr,struct instruction_data * data,uint32_t n_instr,uint32_t * n_pattern_instr)7074 instr_pattern_emit_many_tx_search(struct instruction *instr,
7075 				  struct instruction_data *data,
7076 				  uint32_t n_instr,
7077 				  uint32_t *n_pattern_instr)
7078 {
7079 	uint32_t i;
7080 
7081 	for (i = 0; i < n_instr; i++) {
7082 		if (data[i].invalid)
7083 			break;
7084 
7085 		if (instr[i].type != INSTR_HDR_EMIT)
7086 			break;
7087 
7088 		if (i == RTE_DIM(instr->io.hdr.header_id))
7089 			break;
7090 
7091 		if (i && data[i].n_users)
7092 			break;
7093 	}
7094 
7095 	if (!i)
7096 		return 0;
7097 
7098 	if (instr[i].type != INSTR_TX)
7099 		return 0;
7100 
7101 	if (data[i].n_users)
7102 		return 0;
7103 
7104 	i++;
7105 
7106 	*n_pattern_instr = i;
7107 	return 1;
7108 }
7109 
7110 static void
instr_pattern_emit_many_tx_replace(struct instruction * instr,struct instruction_data * data,uint32_t n_instr)7111 instr_pattern_emit_many_tx_replace(struct instruction *instr,
7112 				   struct instruction_data *data,
7113 				   uint32_t n_instr)
7114 {
7115 	uint32_t i;
7116 
7117 	/* Any emit instruction in addition to the first one. */
7118 	for (i = 1; i < n_instr - 1; i++) {
7119 		instr[0].type++;
7120 		instr[0].io.hdr.header_id[i] = instr[i].io.hdr.header_id[0];
7121 		instr[0].io.hdr.struct_id[i] = instr[i].io.hdr.struct_id[0];
7122 		instr[0].io.hdr.n_bytes[i] = instr[i].io.hdr.n_bytes[0];
7123 
7124 		data[i].invalid = 1;
7125 	}
7126 
7127 	/* The TX instruction is the last one in the pattern. */
7128 	instr[0].type++;
7129 	instr[0].io.io.offset = instr[i].io.io.offset;
7130 	instr[0].io.io.n_bits = instr[i].io.io.n_bits;
7131 	data[i].invalid = 1;
7132 }
7133 
7134 static uint32_t
instr_pattern_emit_many_tx_optimize(struct instruction * instructions,struct instruction_data * instruction_data,uint32_t n_instructions)7135 instr_pattern_emit_many_tx_optimize(struct instruction *instructions,
7136 				    struct instruction_data *instruction_data,
7137 				    uint32_t n_instructions)
7138 {
7139 	uint32_t i;
7140 
7141 	for (i = 0; i < n_instructions; ) {
7142 		struct instruction *instr = &instructions[i];
7143 		struct instruction_data *data = &instruction_data[i];
7144 		uint32_t n_instr = 0;
7145 		int detected;
7146 
7147 		/* Emit many + TX. */
7148 		detected = instr_pattern_emit_many_tx_search(instr,
7149 							     data,
7150 							     n_instructions - i,
7151 							     &n_instr);
7152 		if (detected) {
7153 			instr_pattern_emit_many_tx_replace(instr,
7154 							   data,
7155 							   n_instr);
7156 			i += n_instr;
7157 			continue;
7158 		}
7159 
7160 		/* No pattern starting at the current instruction. */
7161 		i++;
7162 	}
7163 
7164 	/* Eliminate the invalid instructions that have been optimized out. */
7165 	n_instructions = instr_compact(instructions,
7166 				       instruction_data,
7167 				       n_instructions);
7168 
7169 	return n_instructions;
7170 }
7171 
7172 static uint32_t
7173 action_arg_src_mov_count(struct action *a,
7174 			 uint32_t arg_id,
7175 			 struct instruction *instructions,
7176 			 struct instruction_data *instruction_data,
7177 			 uint32_t n_instructions);
7178 
7179 static int
instr_pattern_validate_mov_all_search(struct rte_swx_pipeline * p,struct action * a,struct instruction * instr,struct instruction_data * data,uint32_t n_instr,struct instruction * instructions,struct instruction_data * instruction_data,uint32_t n_instructions,uint32_t * n_pattern_instr)7180 instr_pattern_validate_mov_all_search(struct rte_swx_pipeline *p,
7181 				      struct action *a,
7182 				      struct instruction *instr,
7183 				      struct instruction_data *data,
7184 				      uint32_t n_instr,
7185 				      struct instruction *instructions,
7186 				      struct instruction_data *instruction_data,
7187 				      uint32_t n_instructions,
7188 				      uint32_t *n_pattern_instr)
7189 {
7190 	struct header *h;
7191 	uint32_t src_field_id, i, j;
7192 
7193 	/* Prerequisites. */
7194 	if (!a || !a->st)
7195 		return 0;
7196 
7197 	/* First instruction: HDR_VALIDATE. Second instruction: MOV_HM, MOV_DMA or MOV_128. */
7198 	if (data[0].invalid ||
7199 	    (instr[0].type != INSTR_HDR_VALIDATE) ||
7200 	    (n_instr < 2) ||
7201 	    data[1].invalid ||
7202 	    (instr[1].type != INSTR_MOV_HM &&
7203 	     instr[1].type != INSTR_MOV_DMA &&
7204 	     instr[1].type != INSTR_MOV_128) ||
7205 	    instr[1].mov.src.struct_id)
7206 		return 0;
7207 
7208 	h = header_find_by_struct_id(p, instr[0].valid.struct_id);
7209 	if (!h ||
7210 	    h->st->var_size ||
7211 	    (n_instr < 1 + h->st->n_fields))
7212 		return 0;
7213 
7214 	for (src_field_id = 0; src_field_id < a->st->n_fields; src_field_id++)
7215 		if (instr[1].mov.src.offset == a->st->fields[src_field_id].offset / 8)
7216 			break;
7217 
7218 	if (src_field_id + h->st->n_fields > a->st->n_fields)
7219 		return 0;
7220 
7221 	/* Second and subsequent instructions: MOV_HM. */
7222 	for (i = 0; i < h->st->n_fields; i++)
7223 		if (data[1 + i].invalid ||
7224 		    data[1 + i].n_users ||
7225 		    (instr[1 + i].type != INSTR_MOV_HM &&
7226 		     instr[1 + i].type != INSTR_MOV_DMA &&
7227 		     instr[1 + i].type != INSTR_MOV_128) ||
7228 		    (instr[1 + i].mov.dst.struct_id != h->struct_id) ||
7229 		    (instr[1 + i].mov.dst.offset != h->st->fields[i].offset / 8) ||
7230 		    (instr[1 + i].mov.dst.n_bits != h->st->fields[i].n_bits) ||
7231 		    instr[1 + i].mov.src.struct_id ||
7232 		    (instr[1 + i].mov.src.offset != a->st->fields[src_field_id + i].offset / 8) ||
7233 		    (instr[1 + i].mov.src.n_bits != a->st->fields[src_field_id + i].n_bits) ||
7234 		    (instr[1 + i].mov.dst.n_bits != instr[1 + i].mov.src.n_bits))
7235 			return 0;
7236 
7237 	/* Check that none of the action args that are used as source for this
7238 	 * DMA transfer are not used as source in any other mov instruction.
7239 	 */
7240 	for (j = src_field_id; j < src_field_id + h->st->n_fields; j++) {
7241 		uint32_t n_users;
7242 
7243 		n_users = action_arg_src_mov_count(a,
7244 						   j,
7245 						   instructions,
7246 						   instruction_data,
7247 						   n_instructions);
7248 		if (n_users > 1)
7249 			return 0;
7250 	}
7251 
7252 	*n_pattern_instr = 1 + h->st->n_fields;
7253 	return 1;
7254 }
7255 
7256 static void
instr_pattern_validate_mov_all_replace(struct rte_swx_pipeline * p,struct action * a,struct instruction * instr,struct instruction_data * data,uint32_t n_instr)7257 instr_pattern_validate_mov_all_replace(struct rte_swx_pipeline *p,
7258 				       struct action *a,
7259 				       struct instruction *instr,
7260 				       struct instruction_data *data,
7261 				       uint32_t n_instr)
7262 {
7263 	struct header *h;
7264 	uint32_t src_field_id, src_offset, i;
7265 
7266 	/* Read from the instructions before they are modified. */
7267 	h = header_find_by_struct_id(p, instr[1].mov.dst.struct_id);
7268 	if (!h)
7269 		return;
7270 
7271 	src_offset = instr[1].mov.src.offset;
7272 
7273 	for (src_field_id = 0; src_field_id < a->st->n_fields; src_field_id++)
7274 		if (src_offset == a->st->fields[src_field_id].offset / 8)
7275 			break;
7276 
7277 	/* Modify the instructions. */
7278 	instr[0].type = INSTR_DMA_HT;
7279 	instr[0].dma.dst.header_id[0] = h->id;
7280 	instr[0].dma.dst.struct_id[0] = h->struct_id;
7281 	instr[0].dma.src.offset[0] = (uint8_t)src_offset;
7282 	instr[0].dma.n_bytes[0] = h->st->n_bits / 8;
7283 
7284 	for (i = 1; i < n_instr; i++)
7285 		data[i].invalid = 1;
7286 
7287 	/* Update the endianness of the action arguments to header endianness. */
7288 	for (i = 0; i < h->st->n_fields; i++)
7289 		a->args_endianness[src_field_id + i] = 1;
7290 }
7291 
7292 static uint32_t
instr_pattern_validate_mov_all_optimize(struct rte_swx_pipeline * p,struct action * a,struct instruction * instructions,struct instruction_data * instruction_data,uint32_t n_instructions)7293 instr_pattern_validate_mov_all_optimize(struct rte_swx_pipeline *p,
7294 					struct action *a,
7295 					struct instruction *instructions,
7296 					struct instruction_data *instruction_data,
7297 					uint32_t n_instructions)
7298 {
7299 	uint32_t i;
7300 
7301 	if (!a || !a->st)
7302 		return n_instructions;
7303 
7304 	for (i = 0; i < n_instructions; ) {
7305 		struct instruction *instr = &instructions[i];
7306 		struct instruction_data *data = &instruction_data[i];
7307 		uint32_t n_instr = 0;
7308 		int detected;
7309 
7310 		/* Validate + mov all. */
7311 		detected = instr_pattern_validate_mov_all_search(p,
7312 								 a,
7313 								 instr,
7314 								 data,
7315 								 n_instructions - i,
7316 								 instructions,
7317 								 instruction_data,
7318 								 n_instructions,
7319 								 &n_instr);
7320 		if (detected) {
7321 			instr_pattern_validate_mov_all_replace(p, a, instr, data, n_instr);
7322 			i += n_instr;
7323 			continue;
7324 		}
7325 
7326 		/* No pattern starting at the current instruction. */
7327 		i++;
7328 	}
7329 
7330 	/* Eliminate the invalid instructions that have been optimized out. */
7331 	n_instructions = instr_compact(instructions,
7332 				       instruction_data,
7333 				       n_instructions);
7334 
7335 	return n_instructions;
7336 }
7337 
7338 static int
instr_pattern_dma_many_search(struct instruction * instr,struct instruction_data * data,uint32_t n_instr,uint32_t * n_pattern_instr)7339 instr_pattern_dma_many_search(struct instruction *instr,
7340 			      struct instruction_data *data,
7341 			      uint32_t n_instr,
7342 			      uint32_t *n_pattern_instr)
7343 {
7344 	uint32_t i;
7345 
7346 	for (i = 0; i < n_instr; i++) {
7347 		if (data[i].invalid)
7348 			break;
7349 
7350 		if (instr[i].type != INSTR_DMA_HT)
7351 			break;
7352 
7353 		if (i == RTE_DIM(instr->dma.dst.header_id))
7354 			break;
7355 
7356 		if (i && data[i].n_users)
7357 			break;
7358 	}
7359 
7360 	if (i < 2)
7361 		return 0;
7362 
7363 	*n_pattern_instr = i;
7364 	return 1;
7365 }
7366 
7367 static void
instr_pattern_dma_many_replace(struct instruction * instr,struct instruction_data * data,uint32_t n_instr)7368 instr_pattern_dma_many_replace(struct instruction *instr,
7369 			       struct instruction_data *data,
7370 			       uint32_t n_instr)
7371 {
7372 	uint32_t i;
7373 
7374 	for (i = 1; i < n_instr; i++) {
7375 		instr[0].type++;
7376 		instr[0].dma.dst.header_id[i] = instr[i].dma.dst.header_id[0];
7377 		instr[0].dma.dst.struct_id[i] = instr[i].dma.dst.struct_id[0];
7378 		instr[0].dma.src.offset[i] = instr[i].dma.src.offset[0];
7379 		instr[0].dma.n_bytes[i] = instr[i].dma.n_bytes[0];
7380 
7381 		data[i].invalid = 1;
7382 	}
7383 }
7384 
7385 static uint32_t
instr_pattern_dma_many_optimize(struct instruction * instructions,struct instruction_data * instruction_data,uint32_t n_instructions)7386 instr_pattern_dma_many_optimize(struct instruction *instructions,
7387 	       struct instruction_data *instruction_data,
7388 	       uint32_t n_instructions)
7389 {
7390 	uint32_t i;
7391 
7392 	for (i = 0; i < n_instructions; ) {
7393 		struct instruction *instr = &instructions[i];
7394 		struct instruction_data *data = &instruction_data[i];
7395 		uint32_t n_instr = 0;
7396 		int detected;
7397 
7398 		/* DMA many. */
7399 		detected = instr_pattern_dma_many_search(instr,
7400 							 data,
7401 							 n_instructions - i,
7402 							 &n_instr);
7403 		if (detected) {
7404 			instr_pattern_dma_many_replace(instr, data, n_instr);
7405 			i += n_instr;
7406 			continue;
7407 		}
7408 
7409 		/* No pattern starting at the current instruction. */
7410 		i++;
7411 	}
7412 
7413 	/* Eliminate the invalid instructions that have been optimized out. */
7414 	n_instructions = instr_compact(instructions,
7415 				       instruction_data,
7416 				       n_instructions);
7417 
7418 	return n_instructions;
7419 }
7420 
7421 static uint32_t
instr_optimize(struct rte_swx_pipeline * p,struct action * a,struct instruction * instructions,struct instruction_data * instruction_data,uint32_t n_instructions)7422 instr_optimize(struct rte_swx_pipeline *p,
7423 	       struct action *a,
7424 	       struct instruction *instructions,
7425 	       struct instruction_data *instruction_data,
7426 	       uint32_t n_instructions)
7427 {
7428 	/* Extract many. */
7429 	n_instructions = instr_pattern_extract_many_optimize(instructions,
7430 							     instruction_data,
7431 							     n_instructions);
7432 
7433 	/* Emit many + TX. */
7434 	n_instructions = instr_pattern_emit_many_tx_optimize(instructions,
7435 							     instruction_data,
7436 							     n_instructions);
7437 
7438 	/* Validate + mov all. */
7439 	n_instructions = instr_pattern_validate_mov_all_optimize(p,
7440 								 a,
7441 								 instructions,
7442 								 instruction_data,
7443 								 n_instructions);
7444 
7445 	/* DMA many. */
7446 	n_instructions = instr_pattern_dma_many_optimize(instructions,
7447 							 instruction_data,
7448 							 n_instructions);
7449 
7450 	return n_instructions;
7451 }
7452 
7453 static int
instruction_config(struct rte_swx_pipeline * p,struct action * a,const char ** instructions,uint32_t n_instructions)7454 instruction_config(struct rte_swx_pipeline *p,
7455 		   struct action *a,
7456 		   const char **instructions,
7457 		   uint32_t n_instructions)
7458 {
7459 	struct instruction *instr = NULL;
7460 	struct instruction_data *data = NULL;
7461 	int err = 0;
7462 	uint32_t i;
7463 
7464 	CHECK(n_instructions, EINVAL);
7465 	CHECK(instructions, EINVAL);
7466 	for (i = 0; i < n_instructions; i++)
7467 		CHECK_INSTRUCTION(instructions[i], EINVAL);
7468 
7469 	/* Memory allocation. */
7470 	instr = calloc(n_instructions, sizeof(struct instruction));
7471 	if (!instr) {
7472 		err = -ENOMEM;
7473 		goto error;
7474 	}
7475 
7476 	data = calloc(n_instructions, sizeof(struct instruction_data));
7477 	if (!data) {
7478 		err = -ENOMEM;
7479 		goto error;
7480 	}
7481 
7482 	for (i = 0; i < n_instructions; i++) {
7483 		char *string = strdup(instructions[i]);
7484 		if (!string) {
7485 			err = -ENOMEM;
7486 			goto error;
7487 		}
7488 
7489 		err = instr_translate(p, a, string, &instr[i], &data[i]);
7490 		if (err) {
7491 			free(string);
7492 			goto error;
7493 		}
7494 
7495 		free(string);
7496 	}
7497 
7498 	err = instr_label_check(data, n_instructions);
7499 	if (err)
7500 		goto error;
7501 
7502 	err = instr_verify(p, a, instr, data, n_instructions);
7503 	if (err)
7504 		goto error;
7505 
7506 	n_instructions = instr_optimize(p, a, instr, data, n_instructions);
7507 
7508 	err = instr_jmp_resolve(instr, data, n_instructions);
7509 	if (err)
7510 		goto error;
7511 
7512 	if (a) {
7513 		a->instructions = instr;
7514 		a->instruction_data = data;
7515 		a->n_instructions = n_instructions;
7516 	} else {
7517 		p->instructions = instr;
7518 		p->instruction_data = data;
7519 		p->n_instructions = n_instructions;
7520 	}
7521 
7522 	return 0;
7523 
7524 error:
7525 	free(data);
7526 	free(instr);
7527 	return err;
7528 }
7529 
7530 static instr_exec_t instruction_table[] = {
7531 	[INSTR_RX] = instr_rx_exec,
7532 	[INSTR_TX] = instr_tx_exec,
7533 	[INSTR_TX_I] = instr_tx_i_exec,
7534 	[INSTR_DROP] = instr_drop_exec,
7535 	[INSTR_MIRROR] = instr_mirror_exec,
7536 	[INSTR_RECIRCULATE] = instr_recirculate_exec,
7537 	[INSTR_RECIRCID] = instr_recircid_exec,
7538 
7539 	[INSTR_HDR_EXTRACT] = instr_hdr_extract_exec,
7540 	[INSTR_HDR_EXTRACT2] = instr_hdr_extract2_exec,
7541 	[INSTR_HDR_EXTRACT3] = instr_hdr_extract3_exec,
7542 	[INSTR_HDR_EXTRACT4] = instr_hdr_extract4_exec,
7543 	[INSTR_HDR_EXTRACT5] = instr_hdr_extract5_exec,
7544 	[INSTR_HDR_EXTRACT6] = instr_hdr_extract6_exec,
7545 	[INSTR_HDR_EXTRACT7] = instr_hdr_extract7_exec,
7546 	[INSTR_HDR_EXTRACT8] = instr_hdr_extract8_exec,
7547 	[INSTR_HDR_EXTRACT_M] = instr_hdr_extract_m_exec,
7548 	[INSTR_HDR_LOOKAHEAD] = instr_hdr_lookahead_exec,
7549 
7550 	[INSTR_HDR_EMIT] = instr_hdr_emit_exec,
7551 	[INSTR_HDR_EMIT_TX] = instr_hdr_emit_tx_exec,
7552 	[INSTR_HDR_EMIT2_TX] = instr_hdr_emit2_tx_exec,
7553 	[INSTR_HDR_EMIT3_TX] = instr_hdr_emit3_tx_exec,
7554 	[INSTR_HDR_EMIT4_TX] = instr_hdr_emit4_tx_exec,
7555 	[INSTR_HDR_EMIT5_TX] = instr_hdr_emit5_tx_exec,
7556 	[INSTR_HDR_EMIT6_TX] = instr_hdr_emit6_tx_exec,
7557 	[INSTR_HDR_EMIT7_TX] = instr_hdr_emit7_tx_exec,
7558 	[INSTR_HDR_EMIT8_TX] = instr_hdr_emit8_tx_exec,
7559 
7560 	[INSTR_HDR_VALIDATE] = instr_hdr_validate_exec,
7561 	[INSTR_HDR_INVALIDATE] = instr_hdr_invalidate_exec,
7562 
7563 	[INSTR_MOV] = instr_mov_exec,
7564 	[INSTR_MOV_MH] = instr_mov_mh_exec,
7565 	[INSTR_MOV_HM] = instr_mov_hm_exec,
7566 	[INSTR_MOV_HH] = instr_mov_hh_exec,
7567 	[INSTR_MOV_DMA] = instr_mov_dma_exec,
7568 	[INSTR_MOV_128] = instr_mov_128_exec,
7569 	[INSTR_MOV_128_64] = instr_mov_128_64_exec,
7570 	[INSTR_MOV_64_128] = instr_mov_64_128_exec,
7571 	[INSTR_MOV_128_32] = instr_mov_128_32_exec,
7572 	[INSTR_MOV_32_128] = instr_mov_32_128_exec,
7573 	[INSTR_MOV_I] = instr_mov_i_exec,
7574 
7575 	[INSTR_MOVH] = instr_movh_exec,
7576 
7577 	[INSTR_DMA_HT] = instr_dma_ht_exec,
7578 	[INSTR_DMA_HT2] = instr_dma_ht2_exec,
7579 	[INSTR_DMA_HT3] = instr_dma_ht3_exec,
7580 	[INSTR_DMA_HT4] = instr_dma_ht4_exec,
7581 	[INSTR_DMA_HT5] = instr_dma_ht5_exec,
7582 	[INSTR_DMA_HT6] = instr_dma_ht6_exec,
7583 	[INSTR_DMA_HT7] = instr_dma_ht7_exec,
7584 	[INSTR_DMA_HT8] = instr_dma_ht8_exec,
7585 
7586 	[INSTR_ALU_ADD] = instr_alu_add_exec,
7587 	[INSTR_ALU_ADD_MH] = instr_alu_add_mh_exec,
7588 	[INSTR_ALU_ADD_HM] = instr_alu_add_hm_exec,
7589 	[INSTR_ALU_ADD_HH] = instr_alu_add_hh_exec,
7590 	[INSTR_ALU_ADD_MI] = instr_alu_add_mi_exec,
7591 	[INSTR_ALU_ADD_HI] = instr_alu_add_hi_exec,
7592 
7593 	[INSTR_ALU_SUB] = instr_alu_sub_exec,
7594 	[INSTR_ALU_SUB_MH] = instr_alu_sub_mh_exec,
7595 	[INSTR_ALU_SUB_HM] = instr_alu_sub_hm_exec,
7596 	[INSTR_ALU_SUB_HH] = instr_alu_sub_hh_exec,
7597 	[INSTR_ALU_SUB_MI] = instr_alu_sub_mi_exec,
7598 	[INSTR_ALU_SUB_HI] = instr_alu_sub_hi_exec,
7599 
7600 	[INSTR_ALU_CKADD_FIELD] = instr_alu_ckadd_field_exec,
7601 	[INSTR_ALU_CKADD_STRUCT] = instr_alu_ckadd_struct_exec,
7602 	[INSTR_ALU_CKADD_STRUCT20] = instr_alu_ckadd_struct20_exec,
7603 	[INSTR_ALU_CKSUB_FIELD] = instr_alu_cksub_field_exec,
7604 
7605 	[INSTR_ALU_AND] = instr_alu_and_exec,
7606 	[INSTR_ALU_AND_MH] = instr_alu_and_mh_exec,
7607 	[INSTR_ALU_AND_HM] = instr_alu_and_hm_exec,
7608 	[INSTR_ALU_AND_HH] = instr_alu_and_hh_exec,
7609 	[INSTR_ALU_AND_I] = instr_alu_and_i_exec,
7610 
7611 	[INSTR_ALU_OR] = instr_alu_or_exec,
7612 	[INSTR_ALU_OR_MH] = instr_alu_or_mh_exec,
7613 	[INSTR_ALU_OR_HM] = instr_alu_or_hm_exec,
7614 	[INSTR_ALU_OR_HH] = instr_alu_or_hh_exec,
7615 	[INSTR_ALU_OR_I] = instr_alu_or_i_exec,
7616 
7617 	[INSTR_ALU_XOR] = instr_alu_xor_exec,
7618 	[INSTR_ALU_XOR_MH] = instr_alu_xor_mh_exec,
7619 	[INSTR_ALU_XOR_HM] = instr_alu_xor_hm_exec,
7620 	[INSTR_ALU_XOR_HH] = instr_alu_xor_hh_exec,
7621 	[INSTR_ALU_XOR_I] = instr_alu_xor_i_exec,
7622 
7623 	[INSTR_ALU_SHL] = instr_alu_shl_exec,
7624 	[INSTR_ALU_SHL_MH] = instr_alu_shl_mh_exec,
7625 	[INSTR_ALU_SHL_HM] = instr_alu_shl_hm_exec,
7626 	[INSTR_ALU_SHL_HH] = instr_alu_shl_hh_exec,
7627 	[INSTR_ALU_SHL_MI] = instr_alu_shl_mi_exec,
7628 	[INSTR_ALU_SHL_HI] = instr_alu_shl_hi_exec,
7629 
7630 	[INSTR_ALU_SHR] = instr_alu_shr_exec,
7631 	[INSTR_ALU_SHR_MH] = instr_alu_shr_mh_exec,
7632 	[INSTR_ALU_SHR_HM] = instr_alu_shr_hm_exec,
7633 	[INSTR_ALU_SHR_HH] = instr_alu_shr_hh_exec,
7634 	[INSTR_ALU_SHR_MI] = instr_alu_shr_mi_exec,
7635 	[INSTR_ALU_SHR_HI] = instr_alu_shr_hi_exec,
7636 
7637 	[INSTR_REGPREFETCH_RH] = instr_regprefetch_rh_exec,
7638 	[INSTR_REGPREFETCH_RM] = instr_regprefetch_rm_exec,
7639 	[INSTR_REGPREFETCH_RI] = instr_regprefetch_ri_exec,
7640 
7641 	[INSTR_REGRD_HRH] = instr_regrd_hrh_exec,
7642 	[INSTR_REGRD_HRM] = instr_regrd_hrm_exec,
7643 	[INSTR_REGRD_MRH] = instr_regrd_mrh_exec,
7644 	[INSTR_REGRD_MRM] = instr_regrd_mrm_exec,
7645 	[INSTR_REGRD_HRI] = instr_regrd_hri_exec,
7646 	[INSTR_REGRD_MRI] = instr_regrd_mri_exec,
7647 
7648 	[INSTR_REGWR_RHH] = instr_regwr_rhh_exec,
7649 	[INSTR_REGWR_RHM] = instr_regwr_rhm_exec,
7650 	[INSTR_REGWR_RMH] = instr_regwr_rmh_exec,
7651 	[INSTR_REGWR_RMM] = instr_regwr_rmm_exec,
7652 	[INSTR_REGWR_RHI] = instr_regwr_rhi_exec,
7653 	[INSTR_REGWR_RMI] = instr_regwr_rmi_exec,
7654 	[INSTR_REGWR_RIH] = instr_regwr_rih_exec,
7655 	[INSTR_REGWR_RIM] = instr_regwr_rim_exec,
7656 	[INSTR_REGWR_RII] = instr_regwr_rii_exec,
7657 
7658 	[INSTR_REGADD_RHH] = instr_regadd_rhh_exec,
7659 	[INSTR_REGADD_RHM] = instr_regadd_rhm_exec,
7660 	[INSTR_REGADD_RMH] = instr_regadd_rmh_exec,
7661 	[INSTR_REGADD_RMM] = instr_regadd_rmm_exec,
7662 	[INSTR_REGADD_RHI] = instr_regadd_rhi_exec,
7663 	[INSTR_REGADD_RMI] = instr_regadd_rmi_exec,
7664 	[INSTR_REGADD_RIH] = instr_regadd_rih_exec,
7665 	[INSTR_REGADD_RIM] = instr_regadd_rim_exec,
7666 	[INSTR_REGADD_RII] = instr_regadd_rii_exec,
7667 
7668 	[INSTR_METPREFETCH_H] = instr_metprefetch_h_exec,
7669 	[INSTR_METPREFETCH_M] = instr_metprefetch_m_exec,
7670 	[INSTR_METPREFETCH_I] = instr_metprefetch_i_exec,
7671 
7672 	[INSTR_METER_HHM] = instr_meter_hhm_exec,
7673 	[INSTR_METER_HHI] = instr_meter_hhi_exec,
7674 	[INSTR_METER_HMM] = instr_meter_hmm_exec,
7675 	[INSTR_METER_HMI] = instr_meter_hmi_exec,
7676 	[INSTR_METER_MHM] = instr_meter_mhm_exec,
7677 	[INSTR_METER_MHI] = instr_meter_mhi_exec,
7678 	[INSTR_METER_MMM] = instr_meter_mmm_exec,
7679 	[INSTR_METER_MMI] = instr_meter_mmi_exec,
7680 	[INSTR_METER_IHM] = instr_meter_ihm_exec,
7681 	[INSTR_METER_IHI] = instr_meter_ihi_exec,
7682 	[INSTR_METER_IMM] = instr_meter_imm_exec,
7683 	[INSTR_METER_IMI] = instr_meter_imi_exec,
7684 
7685 	[INSTR_TABLE] = instr_table_exec,
7686 	[INSTR_TABLE_AF] = instr_table_af_exec,
7687 	[INSTR_SELECTOR] = instr_selector_exec,
7688 	[INSTR_LEARNER] = instr_learner_exec,
7689 	[INSTR_LEARNER_AF] = instr_learner_af_exec,
7690 	[INSTR_LEARNER_LEARN] = instr_learn_exec,
7691 	[INSTR_LEARNER_REARM] = instr_rearm_exec,
7692 	[INSTR_LEARNER_REARM_NEW] = instr_rearm_new_exec,
7693 	[INSTR_LEARNER_FORGET] = instr_forget_exec,
7694 	[INSTR_ENTRYID] = instr_entryid_exec,
7695 
7696 	[INSTR_EXTERN_OBJ] = instr_extern_obj_exec,
7697 	[INSTR_EXTERN_FUNC] = instr_extern_func_exec,
7698 	[INSTR_HASH_FUNC] = instr_hash_func_exec,
7699 	[INSTR_RSS] = instr_rss_exec,
7700 
7701 	[INSTR_JMP] = instr_jmp_exec,
7702 	[INSTR_JMP_VALID] = instr_jmp_valid_exec,
7703 	[INSTR_JMP_INVALID] = instr_jmp_invalid_exec,
7704 	[INSTR_JMP_HIT] = instr_jmp_hit_exec,
7705 	[INSTR_JMP_MISS] = instr_jmp_miss_exec,
7706 	[INSTR_JMP_ACTION_HIT] = instr_jmp_action_hit_exec,
7707 	[INSTR_JMP_ACTION_MISS] = instr_jmp_action_miss_exec,
7708 
7709 	[INSTR_JMP_EQ] = instr_jmp_eq_exec,
7710 	[INSTR_JMP_EQ_MH] = instr_jmp_eq_mh_exec,
7711 	[INSTR_JMP_EQ_HM] = instr_jmp_eq_hm_exec,
7712 	[INSTR_JMP_EQ_HH] = instr_jmp_eq_hh_exec,
7713 	[INSTR_JMP_EQ_I] = instr_jmp_eq_i_exec,
7714 
7715 	[INSTR_JMP_NEQ] = instr_jmp_neq_exec,
7716 	[INSTR_JMP_NEQ_MH] = instr_jmp_neq_mh_exec,
7717 	[INSTR_JMP_NEQ_HM] = instr_jmp_neq_hm_exec,
7718 	[INSTR_JMP_NEQ_HH] = instr_jmp_neq_hh_exec,
7719 	[INSTR_JMP_NEQ_I] = instr_jmp_neq_i_exec,
7720 
7721 	[INSTR_JMP_LT] = instr_jmp_lt_exec,
7722 	[INSTR_JMP_LT_MH] = instr_jmp_lt_mh_exec,
7723 	[INSTR_JMP_LT_HM] = instr_jmp_lt_hm_exec,
7724 	[INSTR_JMP_LT_HH] = instr_jmp_lt_hh_exec,
7725 	[INSTR_JMP_LT_MI] = instr_jmp_lt_mi_exec,
7726 	[INSTR_JMP_LT_HI] = instr_jmp_lt_hi_exec,
7727 
7728 	[INSTR_JMP_GT] = instr_jmp_gt_exec,
7729 	[INSTR_JMP_GT_MH] = instr_jmp_gt_mh_exec,
7730 	[INSTR_JMP_GT_HM] = instr_jmp_gt_hm_exec,
7731 	[INSTR_JMP_GT_HH] = instr_jmp_gt_hh_exec,
7732 	[INSTR_JMP_GT_MI] = instr_jmp_gt_mi_exec,
7733 	[INSTR_JMP_GT_HI] = instr_jmp_gt_hi_exec,
7734 
7735 	[INSTR_RETURN] = instr_return_exec,
7736 };
7737 
7738 static int
instruction_table_build(struct rte_swx_pipeline * p)7739 instruction_table_build(struct rte_swx_pipeline *p)
7740 {
7741 	p->instruction_table = calloc(RTE_SWX_PIPELINE_INSTRUCTION_TABLE_SIZE_MAX,
7742 				      sizeof(struct instr_exec_t *));
7743 	if (!p->instruction_table)
7744 		return -EINVAL;
7745 
7746 	memcpy(p->instruction_table, instruction_table, sizeof(instruction_table));
7747 
7748 	return 0;
7749 }
7750 
7751 static void
instruction_table_build_free(struct rte_swx_pipeline * p)7752 instruction_table_build_free(struct rte_swx_pipeline *p)
7753 {
7754 	if (!p->instruction_table)
7755 		return;
7756 
7757 	free(p->instruction_table);
7758 	p->instruction_table = NULL;
7759 }
7760 
7761 static void
instruction_table_free(struct rte_swx_pipeline * p)7762 instruction_table_free(struct rte_swx_pipeline *p)
7763 {
7764 	instruction_table_build_free(p);
7765 }
7766 
7767 static inline void
instr_exec(struct rte_swx_pipeline * p)7768 instr_exec(struct rte_swx_pipeline *p)
7769 {
7770 	struct thread *t = &p->threads[p->thread_id];
7771 	struct instruction *ip = t->ip;
7772 	instr_exec_t instr = p->instruction_table[ip->type];
7773 
7774 	instr(p);
7775 }
7776 
7777 /*
7778  * Action.
7779  */
7780 static struct action *
action_find(struct rte_swx_pipeline * p,const char * name)7781 action_find(struct rte_swx_pipeline *p, const char *name)
7782 {
7783 	struct action *elem;
7784 
7785 	if (!name)
7786 		return NULL;
7787 
7788 	TAILQ_FOREACH(elem, &p->actions, node)
7789 		if (strcmp(elem->name, name) == 0)
7790 			return elem;
7791 
7792 	return NULL;
7793 }
7794 
7795 static struct action *
action_find_by_id(struct rte_swx_pipeline * p,uint32_t id)7796 action_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
7797 {
7798 	struct action *action = NULL;
7799 
7800 	TAILQ_FOREACH(action, &p->actions, node)
7801 		if (action->id == id)
7802 			return action;
7803 
7804 	return NULL;
7805 }
7806 
7807 static struct field *
action_field_find(struct action * a,const char * name)7808 action_field_find(struct action *a, const char *name)
7809 {
7810 	return a->st ? struct_type_field_find(a->st, name) : NULL;
7811 }
7812 
7813 static struct field *
action_field_parse(struct action * action,const char * name)7814 action_field_parse(struct action *action, const char *name)
7815 {
7816 	if (name[0] != 't' || name[1] != '.')
7817 		return NULL;
7818 
7819 	return action_field_find(action, &name[2]);
7820 }
7821 
7822 static int
action_has_nbo_args(struct action * a)7823 action_has_nbo_args(struct action *a)
7824 {
7825 	uint32_t i;
7826 
7827 	/* Return if the action does not have any args. */
7828 	if (!a->st)
7829 		return 0; /* FALSE */
7830 
7831 	for (i = 0; i < a->st->n_fields; i++)
7832 		if (a->args_endianness[i])
7833 			return 1; /* TRUE */
7834 
7835 	return 0; /* FALSE */
7836 }
7837 
7838 static int
action_does_learning(struct action * a)7839 action_does_learning(struct action *a)
7840 {
7841 	uint32_t i;
7842 
7843 	for (i = 0; i < a->n_instructions; i++)
7844 		switch (a->instructions[i].type) {
7845 		case INSTR_LEARNER_LEARN:
7846 			return 1; /* TRUE */
7847 
7848 		case INSTR_LEARNER_FORGET:
7849 			return 1; /* TRUE */
7850 
7851 		default:
7852 			continue;
7853 		}
7854 
7855 	return 0; /* FALSE */
7856 }
7857 
7858 int
rte_swx_pipeline_action_config(struct rte_swx_pipeline * p,const char * name,const char * args_struct_type_name,const char ** instructions,uint32_t n_instructions)7859 rte_swx_pipeline_action_config(struct rte_swx_pipeline *p,
7860 			       const char *name,
7861 			       const char *args_struct_type_name,
7862 			       const char **instructions,
7863 			       uint32_t n_instructions)
7864 {
7865 	struct struct_type *args_struct_type = NULL;
7866 	struct action *a = NULL;
7867 	int status = 0;
7868 
7869 	CHECK(p, EINVAL);
7870 
7871 	CHECK_NAME(name, EINVAL);
7872 	CHECK(!action_find(p, name), EEXIST);
7873 
7874 	if (args_struct_type_name) {
7875 		CHECK_NAME(args_struct_type_name, EINVAL);
7876 		args_struct_type = struct_type_find(p, args_struct_type_name);
7877 		CHECK(args_struct_type, EINVAL);
7878 		CHECK(!args_struct_type->var_size, EINVAL);
7879 	}
7880 
7881 	/* Node allocation. */
7882 	a = calloc(1, sizeof(struct action));
7883 	if (!a) {
7884 		status = -ENOMEM;
7885 		goto error;
7886 	}
7887 
7888 	if (args_struct_type) {
7889 		a->args_endianness = calloc(args_struct_type->n_fields, sizeof(int));
7890 		if (!a->args_endianness) {
7891 			status = -ENOMEM;
7892 			goto error;
7893 		}
7894 	}
7895 
7896 	/* Node initialization. */
7897 	strcpy(a->name, name);
7898 	a->st = args_struct_type;
7899 	a->id = p->n_actions;
7900 
7901 	/* Instruction translation. */
7902 	status = instruction_config(p, a, instructions, n_instructions);
7903 	if (status)
7904 		goto error;
7905 
7906 	/* Node add to tailq. */
7907 	TAILQ_INSERT_TAIL(&p->actions, a, node);
7908 	p->n_actions++;
7909 
7910 	return 0;
7911 
7912 error:
7913 	if (!a)
7914 		return status;
7915 
7916 	free(a->args_endianness);
7917 	free(a->instructions);
7918 	free(a->instruction_data);
7919 	free(a);
7920 
7921 	return status;
7922 }
7923 
7924 static int
action_build(struct rte_swx_pipeline * p)7925 action_build(struct rte_swx_pipeline *p)
7926 {
7927 	struct action *action;
7928 
7929 	/* p->action_instructions. */
7930 	p->action_instructions = calloc(p->n_actions, sizeof(struct instruction *));
7931 	CHECK(p->action_instructions, ENOMEM);
7932 
7933 	TAILQ_FOREACH(action, &p->actions, node)
7934 		p->action_instructions[action->id] = action->instructions;
7935 
7936 	/* p->action_funcs. */
7937 	p->action_funcs = calloc(p->n_actions, sizeof(action_func_t));
7938 	CHECK(p->action_funcs, ENOMEM);
7939 
7940 	return 0;
7941 }
7942 
7943 static void
action_build_free(struct rte_swx_pipeline * p)7944 action_build_free(struct rte_swx_pipeline *p)
7945 {
7946 	free(p->action_funcs);
7947 	p->action_funcs = NULL;
7948 
7949 	free(p->action_instructions);
7950 	p->action_instructions = NULL;
7951 }
7952 
7953 static void
action_free(struct rte_swx_pipeline * p)7954 action_free(struct rte_swx_pipeline *p)
7955 {
7956 	action_build_free(p);
7957 
7958 	for ( ; ; ) {
7959 		struct action *action;
7960 
7961 		action = TAILQ_FIRST(&p->actions);
7962 		if (!action)
7963 			break;
7964 
7965 		TAILQ_REMOVE(&p->actions, action, node);
7966 		free(action->args_endianness);
7967 		free(action->instructions);
7968 		free(action->instruction_data);
7969 		free(action);
7970 	}
7971 }
7972 
7973 static uint32_t
action_arg_src_mov_count(struct action * a,uint32_t arg_id,struct instruction * instructions,struct instruction_data * instruction_data,uint32_t n_instructions)7974 action_arg_src_mov_count(struct action *a,
7975 			 uint32_t arg_id,
7976 			 struct instruction *instructions,
7977 			 struct instruction_data *instruction_data,
7978 			 uint32_t n_instructions)
7979 {
7980 	uint32_t offset, n_users = 0, i;
7981 
7982 	if (!a->st ||
7983 	    (arg_id >= a->st->n_fields) ||
7984 	    !instructions ||
7985 	    !instruction_data ||
7986 	    !n_instructions)
7987 		return 0;
7988 
7989 	offset = a->st->fields[arg_id].offset / 8;
7990 
7991 	for (i = 0; i < n_instructions; i++) {
7992 		struct instruction *instr = &instructions[i];
7993 		struct instruction_data *data = &instruction_data[i];
7994 
7995 		if (data->invalid ||
7996 		    ((instr->type != INSTR_MOV) && (instr->type != INSTR_MOV_HM)) ||
7997 		    instr->mov.src.struct_id ||
7998 		    (instr->mov.src.offset != offset))
7999 			continue;
8000 
8001 		n_users++;
8002 	}
8003 
8004 	return n_users;
8005 }
8006 
8007 static int
char_to_hex(char c,uint8_t * val)8008 char_to_hex(char c, uint8_t *val)
8009 {
8010 	if (c >= '0' && c <= '9') {
8011 		*val = c - '0';
8012 		return 0;
8013 	}
8014 
8015 	if (c >= 'A' && c <= 'F') {
8016 		*val = c - 'A' + 10;
8017 		return 0;
8018 	}
8019 
8020 	if (c >= 'a' && c <= 'f') {
8021 		*val = c - 'a' + 10;
8022 		return 0;
8023 	}
8024 
8025 	return -EINVAL;
8026 }
8027 
8028 static int
hex_string_parse(char * src,uint8_t * dst,uint32_t n_dst_bytes)8029 hex_string_parse(char *src, uint8_t *dst, uint32_t n_dst_bytes)
8030 {
8031 	uint32_t i;
8032 
8033 	/* Check input arguments. */
8034 	if (!src || !src[0] || !dst || !n_dst_bytes)
8035 		return -EINVAL;
8036 
8037 	/* Skip any leading "0x" or "0X" in the src string. */
8038 	if ((src[0] == '0') && (src[1] == 'x' || src[1] == 'X'))
8039 		src += 2;
8040 
8041 	/* Convert each group of two hex characters in the src string to one byte in dst array. */
8042 	for (i = 0; i < n_dst_bytes; i++) {
8043 		uint8_t a, b;
8044 		int status;
8045 
8046 		status = char_to_hex(*src, &a);
8047 		if (status)
8048 			return status;
8049 		src++;
8050 
8051 		status = char_to_hex(*src, &b);
8052 		if (status)
8053 			return status;
8054 		src++;
8055 
8056 		dst[i] = a * 16 + b;
8057 	}
8058 
8059 	/* Check for the end of the src string. */
8060 	if (*src)
8061 		return -EINVAL;
8062 
8063 	return 0;
8064 }
8065 
8066 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
8067 #define field_ntoh(val, n_bits) (ntoh64((val) << (64 - n_bits)))
8068 #define field_hton(val, n_bits) (hton64((val) << (64 - n_bits)))
8069 #else
8070 #define field_ntoh(val, n_bits) (val)
8071 #define field_hton(val, n_bits) (val)
8072 #endif
8073 
8074 #define ACTION_ARGS_TOKENS_MAX 256
8075 
8076 static int
action_args_parse(struct action * a,const char * args,uint8_t * data)8077 action_args_parse(struct action *a, const char *args, uint8_t *data)
8078 {
8079 	char *tokens[ACTION_ARGS_TOKENS_MAX], *s0 = NULL, *s;
8080 	uint32_t n_tokens = 0, offset = 0, i;
8081 	int status = 0;
8082 
8083 	/* Checks. */
8084 	if (!a->st || !args || !args[0]) {
8085 		status = -EINVAL;
8086 		goto error;
8087 	}
8088 
8089 	/* Memory allocation. */
8090 	s0 = strdup(args);
8091 	if (!s0) {
8092 		status = -ENOMEM;
8093 		goto error;
8094 	}
8095 
8096 	/* Parse the string into tokens. */
8097 	for (s = s0; ; ) {
8098 		char *token;
8099 
8100 		token = strtok_r(s, " \f\n\r\t\v", &s);
8101 		if (!token)
8102 			break;
8103 
8104 		if (n_tokens >= RTE_DIM(tokens)) {
8105 			status = -EINVAL;
8106 			goto error;
8107 		}
8108 
8109 		tokens[n_tokens] = token;
8110 		n_tokens++;
8111 	}
8112 
8113 	/* More checks. */
8114 	if (n_tokens != a->st->n_fields * 2) {
8115 		status = -EINVAL;
8116 		goto error;
8117 	}
8118 
8119 	/* Process the action arguments. */
8120 	for (i = 0; i < a->st->n_fields; i++) {
8121 		struct field *f = &a->st->fields[i];
8122 		char *arg_name = tokens[i * 2];
8123 		char *arg_val = tokens[i * 2 + 1];
8124 
8125 		if (strcmp(arg_name, f->name)) {
8126 			status = -EINVAL;
8127 			goto error;
8128 		}
8129 
8130 		if (f->n_bits <= 64) {
8131 			uint64_t val;
8132 
8133 			val = strtoull(arg_val, &arg_val, 0);
8134 			if (arg_val[0]) {
8135 				status = -EINVAL;
8136 				goto error;
8137 			}
8138 
8139 			/* Endianness conversion. */
8140 			if (a->args_endianness[i])
8141 				val = field_hton(val, f->n_bits);
8142 
8143 			/* Copy to entry. */
8144 			memcpy(&data[offset], (uint8_t *)&val, f->n_bits / 8);
8145 		} else {
8146 			status = hex_string_parse(arg_val, &data[offset], f->n_bits / 8);
8147 			if (status)
8148 				goto error;
8149 		}
8150 
8151 		offset += f->n_bits / 8;
8152 	}
8153 
8154 error:
8155 	free(s0);
8156 	return status;
8157 }
8158 
8159 /*
8160  * Table.
8161  */
8162 static struct table_type *
table_type_find(struct rte_swx_pipeline * p,const char * name)8163 table_type_find(struct rte_swx_pipeline *p, const char *name)
8164 {
8165 	struct table_type *elem;
8166 
8167 	TAILQ_FOREACH(elem, &p->table_types, node)
8168 		if (strcmp(elem->name, name) == 0)
8169 			return elem;
8170 
8171 	return NULL;
8172 }
8173 
8174 static struct table_type *
table_type_resolve(struct rte_swx_pipeline * p,const char * recommended_type_name,enum rte_swx_table_match_type match_type)8175 table_type_resolve(struct rte_swx_pipeline *p,
8176 		   const char *recommended_type_name,
8177 		   enum rte_swx_table_match_type match_type)
8178 {
8179 	struct table_type *elem;
8180 
8181 	/* Only consider the recommended type if the match type is correct. */
8182 	if (recommended_type_name)
8183 		TAILQ_FOREACH(elem, &p->table_types, node)
8184 			if (!strcmp(elem->name, recommended_type_name) &&
8185 			    (elem->match_type == match_type))
8186 				return elem;
8187 
8188 	/* Ignore the recommended type and get the first element with this match
8189 	 * type.
8190 	 */
8191 	TAILQ_FOREACH(elem, &p->table_types, node)
8192 		if (elem->match_type == match_type)
8193 			return elem;
8194 
8195 	return NULL;
8196 }
8197 
8198 static struct table *
table_find(struct rte_swx_pipeline * p,const char * name)8199 table_find(struct rte_swx_pipeline *p, const char *name)
8200 {
8201 	struct table *elem;
8202 
8203 	TAILQ_FOREACH(elem, &p->tables, node)
8204 		if (strcmp(elem->name, name) == 0)
8205 			return elem;
8206 
8207 	return NULL;
8208 }
8209 
8210 static struct table *
table_find_by_id(struct rte_swx_pipeline * p,uint32_t id)8211 table_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8212 {
8213 	struct table *table = NULL;
8214 
8215 	TAILQ_FOREACH(table, &p->tables, node)
8216 		if (table->id == id)
8217 			return table;
8218 
8219 	return NULL;
8220 }
8221 
8222 int
rte_swx_pipeline_table_type_register(struct rte_swx_pipeline * p,const char * name,enum rte_swx_table_match_type match_type,struct rte_swx_table_ops * ops)8223 rte_swx_pipeline_table_type_register(struct rte_swx_pipeline *p,
8224 				     const char *name,
8225 				     enum rte_swx_table_match_type match_type,
8226 				     struct rte_swx_table_ops *ops)
8227 {
8228 	struct table_type *elem;
8229 
8230 	CHECK(p, EINVAL);
8231 
8232 	CHECK_NAME(name, EINVAL);
8233 	CHECK(!table_type_find(p, name), EEXIST);
8234 
8235 	CHECK(ops, EINVAL);
8236 	CHECK(ops->create, EINVAL);
8237 	CHECK(ops->lkp, EINVAL);
8238 	CHECK(ops->free, EINVAL);
8239 
8240 	/* Node allocation. */
8241 	elem = calloc(1, sizeof(struct table_type));
8242 	CHECK(elem, ENOMEM);
8243 
8244 	/* Node initialization. */
8245 	strcpy(elem->name, name);
8246 	elem->match_type = match_type;
8247 	memcpy(&elem->ops, ops, sizeof(*ops));
8248 
8249 	/* Node add to tailq. */
8250 	TAILQ_INSERT_TAIL(&p->table_types, elem, node);
8251 
8252 	return 0;
8253 }
8254 
8255 static int
table_match_type_resolve(struct rte_swx_match_field_params * fields,uint32_t n_fields,int contiguous_fields,enum rte_swx_table_match_type * match_type)8256 table_match_type_resolve(struct rte_swx_match_field_params *fields,
8257 			 uint32_t n_fields,
8258 			 int contiguous_fields,
8259 			 enum rte_swx_table_match_type *match_type)
8260 {
8261 	uint32_t n_fields_em = 0, n_fields_lpm = 0, i;
8262 
8263 	for (i = 0; i < n_fields; i++) {
8264 		struct rte_swx_match_field_params  *f = &fields[i];
8265 
8266 		if (f->match_type == RTE_SWX_TABLE_MATCH_EXACT)
8267 			n_fields_em++;
8268 
8269 		if (f->match_type == RTE_SWX_TABLE_MATCH_LPM)
8270 			n_fields_lpm++;
8271 	}
8272 
8273 	if ((n_fields_lpm > 1) ||
8274 	    (n_fields_lpm && (n_fields_em != n_fields - 1)))
8275 		return -EINVAL;
8276 
8277 	*match_type = ((n_fields_em == n_fields) && contiguous_fields) ?
8278 		       RTE_SWX_TABLE_MATCH_EXACT :
8279 		       RTE_SWX_TABLE_MATCH_WILDCARD;
8280 
8281 	return 0;
8282 }
8283 
8284 static int
table_match_fields_check(struct rte_swx_pipeline * p,struct rte_swx_pipeline_table_params * params,struct header ** header,int * contiguous_fields)8285 table_match_fields_check(struct rte_swx_pipeline *p,
8286 			 struct rte_swx_pipeline_table_params *params,
8287 			 struct header **header,
8288 			 int *contiguous_fields)
8289 {
8290 	struct header *h0 = NULL;
8291 	struct field *hf, *mf;
8292 	uint32_t *offset = NULL, *n_bits = NULL, n_fields_with_valid_next = 0, i;
8293 	int status = 0;
8294 
8295 	/* Return if no match fields. */
8296 	if (!params->n_fields) {
8297 		if (params->fields) {
8298 			status = -EINVAL;
8299 			goto end;
8300 		}
8301 
8302 		if (header)
8303 			*header = NULL;
8304 
8305 		if (contiguous_fields)
8306 			*contiguous_fields = 0;
8307 
8308 		return 0;
8309 	}
8310 
8311 	/* Memory allocation. */
8312 	offset = calloc(params->n_fields, sizeof(uint32_t));
8313 	n_bits = calloc(params->n_fields, sizeof(uint32_t));
8314 	if (!offset || !n_bits) {
8315 		status = -ENOMEM;
8316 		goto end;
8317 	}
8318 
8319 	/* Check that all the match fields belong to either the same header or
8320 	 * to the meta-data.
8321 	 */
8322 	hf = header_field_parse(p, params->fields[0].name, &h0);
8323 	mf = metadata_field_parse(p, params->fields[0].name);
8324 	if ((!hf && !mf) || (hf && hf->var_size)) {
8325 		status = -EINVAL;
8326 		goto end;
8327 	}
8328 
8329 	offset[0] = h0 ? hf->offset : mf->offset;
8330 	n_bits[0] = h0 ? hf->n_bits : mf->n_bits;
8331 
8332 	for (i = 1; i < params->n_fields; i++)
8333 		if (h0) {
8334 			struct header *h;
8335 
8336 			hf = header_field_parse(p, params->fields[i].name, &h);
8337 			if (!hf || (h->id != h0->id) || hf->var_size) {
8338 				status = -EINVAL;
8339 				goto end;
8340 			}
8341 
8342 			offset[i] = hf->offset;
8343 			n_bits[i] = hf->n_bits;
8344 		} else {
8345 			mf = metadata_field_parse(p, params->fields[i].name);
8346 			if (!mf) {
8347 				status = -EINVAL;
8348 				goto end;
8349 			}
8350 
8351 			offset[i] = mf->offset;
8352 			n_bits[i] = mf->n_bits;
8353 		}
8354 
8355 	/* Check that there are no duplicated match fields. */
8356 	for (i = 0; i < params->n_fields; i++) {
8357 		uint32_t j;
8358 
8359 		for (j = 0; j < i; j++)
8360 			if (offset[j] == offset[i]) {
8361 				status = -EINVAL;
8362 				goto end;
8363 			}
8364 	}
8365 
8366 	/* Detect if the match fields are contiguous or not. */
8367 	for (i = 0; i < params->n_fields; i++) {
8368 		uint32_t offset_next = offset[i] + n_bits[i];
8369 		uint32_t j;
8370 
8371 		for (j = 0; j < params->n_fields; j++)
8372 			if (offset[j] == offset_next) {
8373 				n_fields_with_valid_next++;
8374 				break;
8375 			}
8376 	}
8377 
8378 	/* Return. */
8379 	if (header)
8380 		*header = h0;
8381 
8382 	if (contiguous_fields)
8383 		*contiguous_fields = (n_fields_with_valid_next == params->n_fields - 1) ? 1 : 0;
8384 
8385 end:
8386 	free(offset);
8387 	free(n_bits);
8388 	return status;
8389 }
8390 
8391 int
rte_swx_pipeline_table_config(struct rte_swx_pipeline * p,const char * name,struct rte_swx_pipeline_table_params * params,const char * recommended_table_type_name,const char * args,uint32_t size)8392 rte_swx_pipeline_table_config(struct rte_swx_pipeline *p,
8393 			      const char *name,
8394 			      struct rte_swx_pipeline_table_params *params,
8395 			      const char *recommended_table_type_name,
8396 			      const char *args,
8397 			      uint32_t size)
8398 {
8399 	struct table_type *type = NULL;
8400 	struct table *t = NULL;
8401 	struct action *default_action;
8402 	struct header *header = NULL;
8403 	struct hash_func *hf = NULL;
8404 	uint32_t action_data_size_max = 0, i;
8405 	int contiguous_fields = 0, status = 0;
8406 
8407 	CHECK(p, EINVAL);
8408 
8409 	CHECK_NAME(name, EINVAL);
8410 	CHECK(!table_find(p, name), EEXIST);
8411 	CHECK(!selector_find(p, name), EEXIST);
8412 	CHECK(!learner_find(p, name), EEXIST);
8413 
8414 	CHECK(params, EINVAL);
8415 
8416 	/* Match checks. */
8417 	status = table_match_fields_check(p, params, &header, &contiguous_fields);
8418 	if (status)
8419 		return status;
8420 
8421 	/* Action checks. */
8422 	CHECK(params->n_actions, EINVAL);
8423 	CHECK(params->action_names, EINVAL);
8424 	for (i = 0; i < params->n_actions; i++) {
8425 		const char *action_name = params->action_names[i];
8426 		struct action *a;
8427 		uint32_t action_data_size;
8428 		int action_is_for_table_entries = 1, action_is_for_default_entry = 1;
8429 
8430 		CHECK_NAME(action_name, EINVAL);
8431 
8432 		a = action_find(p, action_name);
8433 		CHECK(a, EINVAL);
8434 		CHECK(!action_does_learning(a), EINVAL);
8435 
8436 		action_data_size = a->st ? a->st->n_bits / 8 : 0;
8437 		if (action_data_size > action_data_size_max)
8438 			action_data_size_max = action_data_size;
8439 
8440 		if (params->action_is_for_table_entries)
8441 			action_is_for_table_entries = params->action_is_for_table_entries[i];
8442 		if (params->action_is_for_default_entry)
8443 			action_is_for_default_entry = params->action_is_for_default_entry[i];
8444 		CHECK(action_is_for_table_entries || action_is_for_default_entry, EINVAL);
8445 	}
8446 
8447 	CHECK_NAME(params->default_action_name, EINVAL);
8448 	for (i = 0; i < p->n_actions; i++)
8449 		if (!strcmp(params->action_names[i],
8450 			    params->default_action_name))
8451 			break;
8452 	CHECK(i < params->n_actions, EINVAL);
8453 	CHECK(!params->action_is_for_default_entry || params->action_is_for_default_entry[i],
8454 	      EINVAL);
8455 
8456 	default_action = action_find(p, params->default_action_name);
8457 	CHECK((default_action->st && params->default_action_args) || !params->default_action_args,
8458 	      EINVAL);
8459 
8460 	/* Hash function checks. */
8461 	if (params->hash_func_name) {
8462 		hf = hash_func_find(p, params->hash_func_name);
8463 		CHECK(hf, EINVAL);
8464 	}
8465 
8466 	/* Table type checks. */
8467 	if (recommended_table_type_name)
8468 		CHECK_NAME(recommended_table_type_name, EINVAL);
8469 
8470 	if (params->n_fields) {
8471 		enum rte_swx_table_match_type match_type;
8472 
8473 		status = table_match_type_resolve(params->fields,
8474 						  params->n_fields,
8475 						  contiguous_fields,
8476 						  &match_type);
8477 		if (status)
8478 			return status;
8479 
8480 		type = table_type_resolve(p, recommended_table_type_name, match_type);
8481 		CHECK(type, EINVAL);
8482 	}
8483 
8484 	/* Memory allocation. */
8485 	t = calloc(1, sizeof(struct table));
8486 	if (!t) {
8487 		status = -ENOMEM;
8488 		goto error;
8489 	}
8490 
8491 	t->fields = calloc(params->n_fields, sizeof(struct match_field));
8492 	if (!t->fields) {
8493 		status = -ENOMEM;
8494 		goto error;
8495 	}
8496 
8497 	t->actions = calloc(params->n_actions, sizeof(struct action *));
8498 	if (!t->actions) {
8499 		status = -ENOMEM;
8500 		goto error;
8501 	}
8502 
8503 	if (action_data_size_max) {
8504 		t->default_action_data = calloc(1, action_data_size_max);
8505 		if (!t->default_action_data) {
8506 			status = -ENOMEM;
8507 			goto error;
8508 		}
8509 	}
8510 
8511 	t->action_is_for_table_entries = calloc(params->n_actions, sizeof(int));
8512 	if (!t->action_is_for_table_entries) {
8513 		status = -ENOMEM;
8514 		goto error;
8515 	}
8516 
8517 	t->action_is_for_default_entry = calloc(params->n_actions, sizeof(int));
8518 	if (!t->action_is_for_default_entry) {
8519 		status = -ENOMEM;
8520 		goto error;
8521 	}
8522 
8523 	/* Node initialization. */
8524 	strcpy(t->name, name);
8525 	if (args && args[0])
8526 		strcpy(t->args, args);
8527 	t->type = type;
8528 
8529 	for (i = 0; i < params->n_fields; i++) {
8530 		struct rte_swx_match_field_params *field = &params->fields[i];
8531 		struct match_field *f = &t->fields[i];
8532 
8533 		f->match_type = field->match_type;
8534 		f->field = header ?
8535 			header_field_parse(p, field->name, NULL) :
8536 			metadata_field_parse(p, field->name);
8537 	}
8538 	t->n_fields = params->n_fields;
8539 	t->header = header;
8540 
8541 	for (i = 0; i < params->n_actions; i++) {
8542 		int action_is_for_table_entries = 1, action_is_for_default_entry = 1;
8543 
8544 		if (params->action_is_for_table_entries)
8545 			action_is_for_table_entries = params->action_is_for_table_entries[i];
8546 		if (params->action_is_for_default_entry)
8547 			action_is_for_default_entry = params->action_is_for_default_entry[i];
8548 
8549 		t->actions[i] = action_find(p, params->action_names[i]);
8550 		t->action_is_for_table_entries[i] = action_is_for_table_entries;
8551 		t->action_is_for_default_entry[i] = action_is_for_default_entry;
8552 	}
8553 	t->default_action = default_action;
8554 	if (default_action->st) {
8555 		status = action_args_parse(default_action,
8556 					   params->default_action_args,
8557 					   t->default_action_data);
8558 		if (status)
8559 			goto error;
8560 	}
8561 
8562 	t->n_actions = params->n_actions;
8563 	t->default_action_is_const = params->default_action_is_const;
8564 	t->action_data_size_max = action_data_size_max;
8565 
8566 	t->hf = hf;
8567 	t->size = size;
8568 	t->id = p->n_tables;
8569 
8570 	/* Node add to tailq. */
8571 	TAILQ_INSERT_TAIL(&p->tables, t, node);
8572 	p->n_tables++;
8573 
8574 	return 0;
8575 
8576 error:
8577 	if (!t)
8578 		return status;
8579 
8580 	free(t->action_is_for_default_entry);
8581 	free(t->action_is_for_table_entries);
8582 	free(t->default_action_data);
8583 	free(t->actions);
8584 	free(t->fields);
8585 	free(t);
8586 
8587 	return status;
8588 }
8589 
8590 static uint32_t
table_params_offset_get(struct table * table)8591 table_params_offset_get(struct table *table)
8592 {
8593 	struct field *first;
8594 	uint32_t i;
8595 
8596 	first = table->fields[0].field;
8597 
8598 	for (i = 1; i < table->n_fields; i++) {
8599 		struct field *f = table->fields[i].field;
8600 
8601 		if (f->offset < first->offset)
8602 			first = f;
8603 	}
8604 
8605 	return first->offset / 8;
8606 }
8607 
8608 static struct rte_swx_table_params *
table_params_get(struct table * table)8609 table_params_get(struct table *table)
8610 {
8611 	struct rte_swx_table_params *params;
8612 	struct field *first, *last;
8613 	uint8_t *key_mask;
8614 	uint32_t key_size, key_offset, action_data_size, i;
8615 
8616 	/* Memory allocation. */
8617 	params = calloc(1, sizeof(struct rte_swx_table_params));
8618 	if (!params)
8619 		return NULL;
8620 
8621 	/* Find first (smallest offset) and last (biggest offset) match fields. */
8622 	first = table->fields[0].field;
8623 	last = table->fields[0].field;
8624 
8625 	for (i = 0; i < table->n_fields; i++) {
8626 		struct field *f = table->fields[i].field;
8627 
8628 		if (f->offset < first->offset)
8629 			first = f;
8630 
8631 		if (f->offset > last->offset)
8632 			last = f;
8633 	}
8634 
8635 	/* Key offset and size. */
8636 	key_offset = first->offset / 8;
8637 	key_size = (last->offset + last->n_bits - first->offset) / 8;
8638 
8639 	/* Memory allocation. */
8640 	key_mask = calloc(1, key_size);
8641 	if (!key_mask) {
8642 		free(params);
8643 		return NULL;
8644 	}
8645 
8646 	/* Key mask. */
8647 	for (i = 0; i < table->n_fields; i++) {
8648 		struct field *f = table->fields[i].field;
8649 		uint32_t start = (f->offset - first->offset) / 8;
8650 		size_t size = f->n_bits / 8;
8651 
8652 		memset(&key_mask[start], 0xFF, size);
8653 	}
8654 
8655 	/* Action data size. */
8656 	action_data_size = 0;
8657 	for (i = 0; i < table->n_actions; i++) {
8658 		struct action *action = table->actions[i];
8659 		uint32_t ads = action->st ? action->st->n_bits / 8 : 0;
8660 
8661 		if (ads > action_data_size)
8662 			action_data_size = ads;
8663 	}
8664 
8665 	/* Fill in. */
8666 	params->match_type = table->type->match_type;
8667 	params->key_size = key_size;
8668 	params->key_offset = key_offset;
8669 	params->key_mask0 = key_mask;
8670 	params->action_data_size = action_data_size;
8671 	params->hash_func = table->hf ? table->hf->func : NULL;
8672 	params->n_keys_max = table->size;
8673 
8674 	return params;
8675 }
8676 
8677 static void
table_params_free(struct rte_swx_table_params * params)8678 table_params_free(struct rte_swx_table_params *params)
8679 {
8680 	if (!params)
8681 		return;
8682 
8683 	free(params->key_mask0);
8684 	free(params);
8685 }
8686 
8687 static int
table_stub_lkp(void * table __rte_unused,void * mailbox __rte_unused,uint8_t ** key __rte_unused,uint64_t * action_id __rte_unused,uint8_t ** action_data __rte_unused,size_t * entry_id __rte_unused,int * hit)8688 table_stub_lkp(void *table __rte_unused,
8689 	       void *mailbox __rte_unused,
8690 	       uint8_t **key __rte_unused,
8691 	       uint64_t *action_id __rte_unused,
8692 	       uint8_t **action_data __rte_unused,
8693 	       size_t *entry_id __rte_unused,
8694 	       int *hit)
8695 {
8696 	*hit = 0;
8697 	return 1; /* DONE. */
8698 }
8699 
8700 static int
table_build(struct rte_swx_pipeline * p)8701 table_build(struct rte_swx_pipeline *p)
8702 {
8703 	uint32_t i;
8704 
8705 	/* Per pipeline: table statistics. */
8706 	p->table_stats = calloc(p->n_tables, sizeof(struct table_statistics));
8707 	CHECK(p->table_stats, ENOMEM);
8708 
8709 	for (i = 0; i < p->n_tables; i++) {
8710 		p->table_stats[i].n_pkts_action = calloc(p->n_actions, sizeof(uint64_t));
8711 		CHECK(p->table_stats[i].n_pkts_action, ENOMEM);
8712 	}
8713 
8714 	/* Per thread: table runt-time. */
8715 	for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8716 		struct thread *t = &p->threads[i];
8717 		struct table *table;
8718 
8719 		t->tables = calloc(p->n_tables, sizeof(struct table_runtime));
8720 		CHECK(t->tables, ENOMEM);
8721 
8722 		TAILQ_FOREACH(table, &p->tables, node) {
8723 			struct table_runtime *r = &t->tables[table->id];
8724 
8725 			if (table->type) {
8726 				uint64_t size;
8727 
8728 				size = table->type->ops.mailbox_size_get();
8729 
8730 				/* r->func. */
8731 				r->func = table->type->ops.lkp;
8732 
8733 				/* r->mailbox. */
8734 				if (size) {
8735 					r->mailbox = calloc(1, size);
8736 					CHECK(r->mailbox, ENOMEM);
8737 				}
8738 
8739 				/* r->key. */
8740 				r->key = table->header ?
8741 					&t->structs[table->header->struct_id] :
8742 					&t->structs[p->metadata_struct_id];
8743 			} else {
8744 				r->func = table_stub_lkp;
8745 			}
8746 		}
8747 	}
8748 
8749 	return 0;
8750 }
8751 
8752 static void
table_build_free(struct rte_swx_pipeline * p)8753 table_build_free(struct rte_swx_pipeline *p)
8754 {
8755 	uint32_t i;
8756 
8757 	for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8758 		struct thread *t = &p->threads[i];
8759 		uint32_t j;
8760 
8761 		if (!t->tables)
8762 			continue;
8763 
8764 		for (j = 0; j < p->n_tables; j++) {
8765 			struct table_runtime *r = &t->tables[j];
8766 
8767 			free(r->mailbox);
8768 		}
8769 
8770 		free(t->tables);
8771 		t->tables = NULL;
8772 	}
8773 
8774 	if (p->table_stats) {
8775 		for (i = 0; i < p->n_tables; i++)
8776 			free(p->table_stats[i].n_pkts_action);
8777 
8778 		free(p->table_stats);
8779 		p->table_stats = NULL;
8780 	}
8781 }
8782 
8783 static void
table_free(struct rte_swx_pipeline * p)8784 table_free(struct rte_swx_pipeline *p)
8785 {
8786 	table_build_free(p);
8787 
8788 	/* Tables. */
8789 	for ( ; ; ) {
8790 		struct table *elem;
8791 
8792 		elem = TAILQ_FIRST(&p->tables);
8793 		if (!elem)
8794 			break;
8795 
8796 		TAILQ_REMOVE(&p->tables, elem, node);
8797 		free(elem->fields);
8798 		free(elem->actions);
8799 		free(elem->default_action_data);
8800 		free(elem);
8801 	}
8802 
8803 	/* Table types. */
8804 	for ( ; ; ) {
8805 		struct table_type *elem;
8806 
8807 		elem = TAILQ_FIRST(&p->table_types);
8808 		if (!elem)
8809 			break;
8810 
8811 		TAILQ_REMOVE(&p->table_types, elem, node);
8812 		free(elem);
8813 	}
8814 }
8815 
8816 /*
8817  * Selector.
8818  */
8819 static struct selector *
selector_find(struct rte_swx_pipeline * p,const char * name)8820 selector_find(struct rte_swx_pipeline *p, const char *name)
8821 {
8822 	struct selector *s;
8823 
8824 	TAILQ_FOREACH(s, &p->selectors, node)
8825 		if (strcmp(s->name, name) == 0)
8826 			return s;
8827 
8828 	return NULL;
8829 }
8830 
8831 static struct selector *
selector_find_by_id(struct rte_swx_pipeline * p,uint32_t id)8832 selector_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8833 {
8834 	struct selector *s = NULL;
8835 
8836 	TAILQ_FOREACH(s, &p->selectors, node)
8837 		if (s->id == id)
8838 			return s;
8839 
8840 	return NULL;
8841 }
8842 
8843 static int
selector_fields_check(struct rte_swx_pipeline * p,struct rte_swx_pipeline_selector_params * params,struct header ** header)8844 selector_fields_check(struct rte_swx_pipeline *p,
8845 		      struct rte_swx_pipeline_selector_params *params,
8846 		      struct header **header)
8847 {
8848 	struct header *h0 = NULL;
8849 	struct field *hf, *mf;
8850 	uint32_t i;
8851 
8852 	/* Return if no selector fields. */
8853 	if (!params->n_selector_fields || !params->selector_field_names)
8854 		return -EINVAL;
8855 
8856 	/* Check that all the selector fields either belong to the same header
8857 	 * or are all meta-data fields.
8858 	 */
8859 	hf = header_field_parse(p, params->selector_field_names[0], &h0);
8860 	mf = metadata_field_parse(p, params->selector_field_names[0]);
8861 	if (!hf && !mf)
8862 		return -EINVAL;
8863 
8864 	for (i = 1; i < params->n_selector_fields; i++)
8865 		if (h0) {
8866 			struct header *h;
8867 
8868 			hf = header_field_parse(p, params->selector_field_names[i], &h);
8869 			if (!hf || (h->id != h0->id))
8870 				return -EINVAL;
8871 		} else {
8872 			mf = metadata_field_parse(p, params->selector_field_names[i]);
8873 			if (!mf)
8874 				return -EINVAL;
8875 		}
8876 
8877 	/* Check that there are no duplicated match fields. */
8878 	for (i = 0; i < params->n_selector_fields; i++) {
8879 		const char *field_name = params->selector_field_names[i];
8880 		uint32_t j;
8881 
8882 		for (j = i + 1; j < params->n_selector_fields; j++)
8883 			if (!strcmp(params->selector_field_names[j], field_name))
8884 				return -EINVAL;
8885 	}
8886 
8887 	/* Return. */
8888 	if (header)
8889 		*header = h0;
8890 
8891 	return 0;
8892 }
8893 
8894 int
rte_swx_pipeline_selector_config(struct rte_swx_pipeline * p,const char * name,struct rte_swx_pipeline_selector_params * params)8895 rte_swx_pipeline_selector_config(struct rte_swx_pipeline *p,
8896 				 const char *name,
8897 				 struct rte_swx_pipeline_selector_params *params)
8898 {
8899 	struct selector *s;
8900 	struct header *selector_header = NULL;
8901 	struct field *group_id_field, *member_id_field;
8902 	uint32_t i;
8903 	int status = 0;
8904 
8905 	CHECK(p, EINVAL);
8906 
8907 	CHECK_NAME(name, EINVAL);
8908 	CHECK(!table_find(p, name), EEXIST);
8909 	CHECK(!selector_find(p, name), EEXIST);
8910 	CHECK(!learner_find(p, name), EEXIST);
8911 
8912 	CHECK(params, EINVAL);
8913 
8914 	CHECK_NAME(params->group_id_field_name, EINVAL);
8915 	group_id_field = metadata_field_parse(p, params->group_id_field_name);
8916 	CHECK(group_id_field, EINVAL);
8917 
8918 	for (i = 0; i < params->n_selector_fields; i++) {
8919 		const char *field_name = params->selector_field_names[i];
8920 
8921 		CHECK_NAME(field_name, EINVAL);
8922 	}
8923 	status = selector_fields_check(p, params, &selector_header);
8924 	if (status)
8925 		return status;
8926 
8927 	CHECK_NAME(params->member_id_field_name, EINVAL);
8928 	member_id_field = metadata_field_parse(p, params->member_id_field_name);
8929 	CHECK(member_id_field, EINVAL);
8930 
8931 	CHECK(params->n_groups_max, EINVAL);
8932 
8933 	CHECK(params->n_members_per_group_max, EINVAL);
8934 
8935 	/* Memory allocation. */
8936 	s = calloc(1, sizeof(struct selector));
8937 	if (!s) {
8938 		status = -ENOMEM;
8939 		goto error;
8940 	}
8941 
8942 	s->selector_fields = calloc(params->n_selector_fields, sizeof(struct field *));
8943 	if (!s->selector_fields) {
8944 		status = -ENOMEM;
8945 		goto error;
8946 	}
8947 
8948 	/* Node initialization. */
8949 	strcpy(s->name, name);
8950 
8951 	s->group_id_field = group_id_field;
8952 
8953 	for (i = 0; i < params->n_selector_fields; i++) {
8954 		const char *field_name = params->selector_field_names[i];
8955 
8956 		s->selector_fields[i] = selector_header ?
8957 			header_field_parse(p, field_name, NULL) :
8958 			metadata_field_parse(p, field_name);
8959 	}
8960 
8961 	s->n_selector_fields = params->n_selector_fields;
8962 
8963 	s->selector_header = selector_header;
8964 
8965 	s->member_id_field = member_id_field;
8966 
8967 	s->n_groups_max = params->n_groups_max;
8968 
8969 	s->n_members_per_group_max = params->n_members_per_group_max;
8970 
8971 	s->id = p->n_selectors;
8972 
8973 	/* Node add to tailq. */
8974 	TAILQ_INSERT_TAIL(&p->selectors, s, node);
8975 	p->n_selectors++;
8976 
8977 	return 0;
8978 
8979 error:
8980 	if (!s)
8981 		return status;
8982 
8983 	free(s->selector_fields);
8984 
8985 	free(s);
8986 
8987 	return status;
8988 }
8989 
8990 static void
selector_params_free(struct rte_swx_table_selector_params * params)8991 selector_params_free(struct rte_swx_table_selector_params *params)
8992 {
8993 	if (!params)
8994 		return;
8995 
8996 	free(params->selector_mask);
8997 
8998 	free(params);
8999 }
9000 
9001 static struct rte_swx_table_selector_params *
selector_table_params_get(struct selector * s)9002 selector_table_params_get(struct selector *s)
9003 {
9004 	struct rte_swx_table_selector_params *params = NULL;
9005 	struct field *first, *last;
9006 	uint32_t i;
9007 
9008 	/* Memory allocation. */
9009 	params = calloc(1, sizeof(struct rte_swx_table_selector_params));
9010 	if (!params)
9011 		goto error;
9012 
9013 	/* Group ID. */
9014 	params->group_id_offset = s->group_id_field->offset / 8;
9015 
9016 	/* Find first (smallest offset) and last (biggest offset) selector fields. */
9017 	first = s->selector_fields[0];
9018 	last = s->selector_fields[0];
9019 
9020 	for (i = 0; i < s->n_selector_fields; i++) {
9021 		struct field *f = s->selector_fields[i];
9022 
9023 		if (f->offset < first->offset)
9024 			first = f;
9025 
9026 		if (f->offset > last->offset)
9027 			last = f;
9028 	}
9029 
9030 	/* Selector offset and size. */
9031 	params->selector_offset = first->offset / 8;
9032 	params->selector_size = (last->offset + last->n_bits - first->offset) / 8;
9033 
9034 	/* Memory allocation. */
9035 	params->selector_mask = calloc(1, params->selector_size);
9036 	if (!params->selector_mask)
9037 		goto error;
9038 
9039 	/* Selector mask. */
9040 	for (i = 0; i < s->n_selector_fields; i++) {
9041 		struct field *f = s->selector_fields[i];
9042 		uint32_t start = (f->offset - first->offset) / 8;
9043 		size_t size = f->n_bits / 8;
9044 
9045 		memset(&params->selector_mask[start], 0xFF, size);
9046 	}
9047 
9048 	/* Member ID. */
9049 	params->member_id_offset = s->member_id_field->offset / 8;
9050 
9051 	/* Maximum number of groups. */
9052 	params->n_groups_max = s->n_groups_max;
9053 
9054 	/* Maximum number of members per group. */
9055 	params->n_members_per_group_max = s->n_members_per_group_max;
9056 
9057 	return params;
9058 
9059 error:
9060 	selector_params_free(params);
9061 	return NULL;
9062 }
9063 
9064 static void
selector_build_free(struct rte_swx_pipeline * p)9065 selector_build_free(struct rte_swx_pipeline *p)
9066 {
9067 	uint32_t i;
9068 
9069 	for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9070 		struct thread *t = &p->threads[i];
9071 		uint32_t j;
9072 
9073 		if (!t->selectors)
9074 			continue;
9075 
9076 		for (j = 0; j < p->n_selectors; j++) {
9077 			struct selector_runtime *r = &t->selectors[j];
9078 
9079 			free(r->mailbox);
9080 		}
9081 
9082 		free(t->selectors);
9083 		t->selectors = NULL;
9084 	}
9085 
9086 	free(p->selector_stats);
9087 	p->selector_stats = NULL;
9088 }
9089 
9090 static int
selector_build(struct rte_swx_pipeline * p)9091 selector_build(struct rte_swx_pipeline *p)
9092 {
9093 	uint32_t i;
9094 	int status = 0;
9095 
9096 	/* Per pipeline: selector statistics. */
9097 	p->selector_stats = calloc(p->n_selectors, sizeof(struct selector_statistics));
9098 	if (!p->selector_stats) {
9099 		status = -ENOMEM;
9100 		goto error;
9101 	}
9102 
9103 	/* Per thread: selector run-time. */
9104 	for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9105 		struct thread *t = &p->threads[i];
9106 		struct selector *s;
9107 
9108 		t->selectors = calloc(p->n_selectors, sizeof(struct selector_runtime));
9109 		if (!t->selectors) {
9110 			status = -ENOMEM;
9111 			goto error;
9112 		}
9113 
9114 		TAILQ_FOREACH(s, &p->selectors, node) {
9115 			struct selector_runtime *r = &t->selectors[s->id];
9116 			uint64_t size;
9117 
9118 			/* r->mailbox. */
9119 			size = rte_swx_table_selector_mailbox_size_get();
9120 			if (size) {
9121 				r->mailbox = calloc(1, size);
9122 				if (!r->mailbox) {
9123 					status = -ENOMEM;
9124 					goto error;
9125 				}
9126 			}
9127 
9128 			/* r->group_id_buffer. */
9129 			r->group_id_buffer = &t->structs[p->metadata_struct_id];
9130 
9131 			/* r->selector_buffer. */
9132 			r->selector_buffer = s->selector_header ?
9133 				&t->structs[s->selector_header->struct_id] :
9134 				&t->structs[p->metadata_struct_id];
9135 
9136 			/* r->member_id_buffer. */
9137 			r->member_id_buffer = &t->structs[p->metadata_struct_id];
9138 		}
9139 	}
9140 
9141 	return 0;
9142 
9143 error:
9144 	selector_build_free(p);
9145 	return status;
9146 }
9147 
9148 static void
selector_free(struct rte_swx_pipeline * p)9149 selector_free(struct rte_swx_pipeline *p)
9150 {
9151 	selector_build_free(p);
9152 
9153 	/* Selector tables. */
9154 	for ( ; ; ) {
9155 		struct selector *elem;
9156 
9157 		elem = TAILQ_FIRST(&p->selectors);
9158 		if (!elem)
9159 			break;
9160 
9161 		TAILQ_REMOVE(&p->selectors, elem, node);
9162 		free(elem->selector_fields);
9163 		free(elem);
9164 	}
9165 }
9166 
9167 /*
9168  * Learner table.
9169  */
9170 static struct learner *
learner_find(struct rte_swx_pipeline * p,const char * name)9171 learner_find(struct rte_swx_pipeline *p, const char *name)
9172 {
9173 	struct learner *l;
9174 
9175 	TAILQ_FOREACH(l, &p->learners, node)
9176 		if (!strcmp(l->name, name))
9177 			return l;
9178 
9179 	return NULL;
9180 }
9181 
9182 static struct learner *
learner_find_by_id(struct rte_swx_pipeline * p,uint32_t id)9183 learner_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
9184 {
9185 	struct learner *l = NULL;
9186 
9187 	TAILQ_FOREACH(l, &p->learners, node)
9188 		if (l->id == id)
9189 			return l;
9190 
9191 	return NULL;
9192 }
9193 
9194 static int
learner_match_fields_check(struct rte_swx_pipeline * p,struct rte_swx_pipeline_learner_params * params,struct header ** header)9195 learner_match_fields_check(struct rte_swx_pipeline *p,
9196 			   struct rte_swx_pipeline_learner_params *params,
9197 			   struct header **header)
9198 {
9199 	struct header *h0 = NULL;
9200 	struct field *hf, *mf;
9201 	uint32_t *offset = NULL, *n_bits = NULL, n_fields_with_valid_next = 0, i;
9202 	int status = 0;
9203 
9204 	/* Return if no match fields. */
9205 	if (!params->n_fields || !params->field_names)
9206 		return -EINVAL;
9207 
9208 	/* Memory allocation. */
9209 	offset = calloc(params->n_fields, sizeof(uint32_t));
9210 	n_bits = calloc(params->n_fields, sizeof(uint32_t));
9211 	if (!offset || !n_bits) {
9212 		status = -ENOMEM;
9213 		goto end;
9214 	}
9215 
9216 	/* Check that all the match fields either belong to the same header
9217 	 * or are all meta-data fields.
9218 	 */
9219 	hf = header_field_parse(p, params->field_names[0], &h0);
9220 	mf = metadata_field_parse(p, params->field_names[0]);
9221 	if ((!hf && !mf) || (hf && hf->var_size)) {
9222 		status = -EINVAL;
9223 		goto end;
9224 	}
9225 
9226 	offset[0] = h0 ? hf->offset : mf->offset;
9227 	n_bits[0] = h0 ? hf->n_bits : mf->n_bits;
9228 
9229 	for (i = 1; i < params->n_fields; i++)
9230 		if (h0) {
9231 			struct header *h;
9232 
9233 			hf = header_field_parse(p, params->field_names[i], &h);
9234 			if (!hf || (h->id != h0->id) || hf->var_size) {
9235 				status = -EINVAL;
9236 				goto end;
9237 			}
9238 
9239 			offset[i] = hf->offset;
9240 			n_bits[i] = hf->n_bits;
9241 		} else {
9242 			mf = metadata_field_parse(p, params->field_names[i]);
9243 			if (!mf) {
9244 				status = -EINVAL;
9245 				goto end;
9246 			}
9247 
9248 			offset[i] = mf->offset;
9249 			n_bits[i] = mf->n_bits;
9250 		}
9251 
9252 	/* Check that there are no duplicated match fields. */
9253 	for (i = 0; i < params->n_fields; i++) {
9254 		const char *field_name = params->field_names[i];
9255 		uint32_t j;
9256 
9257 		for (j = i + 1; j < params->n_fields; j++)
9258 			if (!strcmp(params->field_names[j], field_name)) {
9259 				status = -EINVAL;
9260 				goto end;
9261 			}
9262 	}
9263 
9264 	/* Check that the match fields are contiguous. */
9265 	for (i = 0; i < params->n_fields; i++) {
9266 		uint32_t offset_next = offset[i] + n_bits[i];
9267 		uint32_t j;
9268 
9269 		for (j = 0; j < params->n_fields; j++)
9270 			if (offset[j] == offset_next) {
9271 				n_fields_with_valid_next++;
9272 				break;
9273 			}
9274 	}
9275 
9276 	if (n_fields_with_valid_next != params->n_fields - 1) {
9277 		status = -EINVAL;
9278 		goto end;
9279 	}
9280 
9281 	/* Return. */
9282 	if (header)
9283 		*header = h0;
9284 
9285 end:
9286 	free(offset);
9287 	free(n_bits);
9288 	return status;
9289 }
9290 
9291 static int
learner_action_args_check(struct rte_swx_pipeline * p,struct action * a,const char * mf_name)9292 learner_action_args_check(struct rte_swx_pipeline *p, struct action *a, const char *mf_name)
9293 {
9294 	struct struct_type *mst = p->metadata_st, *ast = a->st;
9295 	struct field *mf, *af;
9296 	uint32_t mf_pos, i;
9297 
9298 	if (!ast) {
9299 		if (mf_name)
9300 			return -EINVAL;
9301 
9302 		return 0;
9303 	}
9304 
9305 	/* Check that mf_name is the name of a valid meta-data field. */
9306 	CHECK_NAME(mf_name, EINVAL);
9307 	mf = metadata_field_parse(p, mf_name);
9308 	CHECK(mf, EINVAL);
9309 
9310 	/* Check that there are enough meta-data fields, starting with the mf_name field, to cover
9311 	 * all the action arguments.
9312 	 */
9313 	mf_pos = mf - mst->fields;
9314 	CHECK(mst->n_fields - mf_pos >= ast->n_fields, EINVAL);
9315 
9316 	/* Check that the size of each of the identified meta-data fields matches exactly the size
9317 	 * of the corresponding action argument.
9318 	 */
9319 	for (i = 0; i < ast->n_fields; i++) {
9320 		mf = &mst->fields[mf_pos + i];
9321 		af = &ast->fields[i];
9322 
9323 		CHECK(mf->n_bits == af->n_bits, EINVAL);
9324 	}
9325 
9326 	return 0;
9327 }
9328 
9329 static int
learner_action_learning_check(struct rte_swx_pipeline * p,struct action * action,const char ** action_names,uint32_t n_actions)9330 learner_action_learning_check(struct rte_swx_pipeline *p,
9331 			      struct action *action,
9332 			      const char **action_names,
9333 			      uint32_t n_actions)
9334 {
9335 	uint32_t i;
9336 
9337 	/* For each "learn" instruction of the current action, check that the learned action (i.e.
9338 	 * the action passed as argument to the "learn" instruction) is also enabled for the
9339 	 * current learner table.
9340 	 */
9341 	for (i = 0; i < action->n_instructions; i++) {
9342 		struct instruction *instr = &action->instructions[i];
9343 		uint32_t found = 0, j;
9344 
9345 		if (instr->type != INSTR_LEARNER_LEARN)
9346 			continue;
9347 
9348 		for (j = 0; j < n_actions; j++) {
9349 			struct action *a;
9350 
9351 			a = action_find(p, action_names[j]);
9352 			if (!a)
9353 				return -EINVAL;
9354 
9355 			if (a->id == instr->learn.action_id)
9356 				found = 1;
9357 		}
9358 
9359 		if (!found)
9360 			return -EINVAL;
9361 	}
9362 
9363 	return 0;
9364 }
9365 
9366 int
rte_swx_pipeline_learner_config(struct rte_swx_pipeline * p,const char * name,struct rte_swx_pipeline_learner_params * params,uint32_t size,uint32_t * timeout,uint32_t n_timeouts)9367 rte_swx_pipeline_learner_config(struct rte_swx_pipeline *p,
9368 			      const char *name,
9369 			      struct rte_swx_pipeline_learner_params *params,
9370 			      uint32_t size,
9371 			      uint32_t *timeout,
9372 			      uint32_t n_timeouts)
9373 {
9374 	struct learner *l = NULL;
9375 	struct action *default_action;
9376 	struct header *header = NULL;
9377 	struct hash_func *hf = NULL;
9378 	uint32_t action_data_size_max = 0, i;
9379 	int status = 0;
9380 
9381 	CHECK(p, EINVAL);
9382 
9383 	CHECK_NAME(name, EINVAL);
9384 	CHECK(!table_find(p, name), EEXIST);
9385 	CHECK(!selector_find(p, name), EEXIST);
9386 	CHECK(!learner_find(p, name), EEXIST);
9387 
9388 	CHECK(params, EINVAL);
9389 
9390 	/* Match checks. */
9391 	status = learner_match_fields_check(p, params, &header);
9392 	if (status)
9393 		return status;
9394 
9395 	/* Action checks. */
9396 	CHECK(params->n_actions, EINVAL);
9397 	CHECK(params->action_names, EINVAL);
9398 	for (i = 0; i < params->n_actions; i++) {
9399 		const char *action_name = params->action_names[i];
9400 		struct action *a;
9401 		uint32_t action_data_size;
9402 		int action_is_for_table_entries = 1, action_is_for_default_entry = 1;
9403 
9404 		CHECK_NAME(action_name, EINVAL);
9405 
9406 		a = action_find(p, action_name);
9407 		CHECK(a, EINVAL);
9408 
9409 		status = learner_action_learning_check(p,
9410 						       a,
9411 						       params->action_names,
9412 						       params->n_actions);
9413 		if (status)
9414 			return status;
9415 
9416 		action_data_size = a->st ? a->st->n_bits / 8 : 0;
9417 		if (action_data_size > action_data_size_max)
9418 			action_data_size_max = action_data_size;
9419 
9420 		if (params->action_is_for_table_entries)
9421 			action_is_for_table_entries = params->action_is_for_table_entries[i];
9422 		if (params->action_is_for_default_entry)
9423 			action_is_for_default_entry = params->action_is_for_default_entry[i];
9424 		CHECK(action_is_for_table_entries || action_is_for_default_entry, EINVAL);
9425 	}
9426 
9427 	CHECK_NAME(params->default_action_name, EINVAL);
9428 	for (i = 0; i < p->n_actions; i++)
9429 		if (!strcmp(params->action_names[i],
9430 			    params->default_action_name))
9431 			break;
9432 	CHECK(i < params->n_actions, EINVAL);
9433 	CHECK(!params->action_is_for_default_entry || params->action_is_for_default_entry[i],
9434 	      EINVAL);
9435 
9436 	default_action = action_find(p, params->default_action_name);
9437 	CHECK((default_action->st && params->default_action_args) || !params->default_action_args,
9438 	      EINVAL);
9439 
9440 	/* Hash function checks. */
9441 	if (params->hash_func_name) {
9442 		hf = hash_func_find(p, params->hash_func_name);
9443 		CHECK(hf, EINVAL);
9444 	}
9445 
9446 	/* Any other checks. */
9447 	CHECK(size, EINVAL);
9448 	CHECK(timeout, EINVAL);
9449 	CHECK(n_timeouts && (n_timeouts <= RTE_SWX_TABLE_LEARNER_N_KEY_TIMEOUTS_MAX), EINVAL);
9450 
9451 	/* Memory allocation. */
9452 	l = calloc(1, sizeof(struct learner));
9453 	if (!l) {
9454 		status = -ENOMEM;
9455 		goto error;
9456 	}
9457 
9458 	l->fields = calloc(params->n_fields, sizeof(struct field *));
9459 	if (!l->fields) {
9460 		status = -ENOMEM;
9461 		goto error;
9462 	}
9463 
9464 	l->actions = calloc(params->n_actions, sizeof(struct action *));
9465 	if (!l->actions) {
9466 		status = -ENOMEM;
9467 		goto error;
9468 	}
9469 
9470 	if (action_data_size_max) {
9471 		l->default_action_data = calloc(1, action_data_size_max);
9472 		if (!l->default_action_data) {
9473 			status = -ENOMEM;
9474 			goto error;
9475 		}
9476 	}
9477 
9478 	l->action_is_for_table_entries = calloc(params->n_actions, sizeof(int));
9479 	if (!l->action_is_for_table_entries) {
9480 		status = -ENOMEM;
9481 		goto error;
9482 	}
9483 
9484 	l->action_is_for_default_entry = calloc(params->n_actions, sizeof(int));
9485 	if (!l->action_is_for_default_entry) {
9486 		status = -ENOMEM;
9487 		goto error;
9488 	}
9489 
9490 	/* Node initialization. */
9491 	strcpy(l->name, name);
9492 
9493 	for (i = 0; i < params->n_fields; i++) {
9494 		const char *field_name = params->field_names[i];
9495 
9496 		l->fields[i] = header ?
9497 			header_field_parse(p, field_name, NULL) :
9498 			metadata_field_parse(p, field_name);
9499 	}
9500 
9501 	l->n_fields = params->n_fields;
9502 
9503 	l->header = header;
9504 
9505 	for (i = 0; i < params->n_actions; i++) {
9506 		int action_is_for_table_entries = 1, action_is_for_default_entry = 1;
9507 
9508 		if (params->action_is_for_table_entries)
9509 			action_is_for_table_entries = params->action_is_for_table_entries[i];
9510 		if (params->action_is_for_default_entry)
9511 			action_is_for_default_entry = params->action_is_for_default_entry[i];
9512 
9513 		l->actions[i] = action_find(p, params->action_names[i]);
9514 		l->action_is_for_table_entries[i] = action_is_for_table_entries;
9515 		l->action_is_for_default_entry[i] = action_is_for_default_entry;
9516 	}
9517 
9518 	l->default_action = default_action;
9519 
9520 	if (default_action->st) {
9521 		status = action_args_parse(default_action,
9522 					   params->default_action_args,
9523 					   l->default_action_data);
9524 		if (status)
9525 			goto error;
9526 	}
9527 
9528 	l->n_actions = params->n_actions;
9529 
9530 	l->default_action_is_const = params->default_action_is_const;
9531 
9532 	l->action_data_size_max = action_data_size_max;
9533 
9534 	l->hf = hf;
9535 
9536 	l->size = size;
9537 
9538 	for (i = 0; i < n_timeouts; i++)
9539 		l->timeout[i] = timeout[i];
9540 
9541 	l->n_timeouts = n_timeouts;
9542 
9543 	l->id = p->n_learners;
9544 
9545 	/* Node add to tailq. */
9546 	TAILQ_INSERT_TAIL(&p->learners, l, node);
9547 	p->n_learners++;
9548 
9549 	return 0;
9550 
9551 error:
9552 	if (!l)
9553 		return status;
9554 
9555 	free(l->action_is_for_default_entry);
9556 	free(l->action_is_for_table_entries);
9557 	free(l->default_action_data);
9558 	free(l->actions);
9559 	free(l->fields);
9560 	free(l);
9561 
9562 	return status;
9563 }
9564 
9565 static uint32_t
learner_params_offset_get(struct learner * l)9566 learner_params_offset_get(struct learner *l)
9567 {
9568 	struct field *first;
9569 	uint32_t i;
9570 
9571 	first = l->fields[0];
9572 
9573 	for (i = 1; i < l->n_fields; i++) {
9574 		struct field *f = l->fields[i];
9575 
9576 		if (f->offset < first->offset)
9577 			first = f;
9578 	}
9579 
9580 	return first->offset / 8;
9581 }
9582 
9583 static void
learner_params_free(struct rte_swx_table_learner_params * params)9584 learner_params_free(struct rte_swx_table_learner_params *params)
9585 {
9586 	if (!params)
9587 		return;
9588 
9589 	free(params->key_mask0);
9590 
9591 	free(params->key_timeout);
9592 
9593 	free(params);
9594 }
9595 
9596 static struct rte_swx_table_learner_params *
learner_params_get(struct learner * l)9597 learner_params_get(struct learner *l)
9598 {
9599 	struct rte_swx_table_learner_params *params = NULL;
9600 	struct field *first, *last;
9601 	uint32_t i;
9602 
9603 	/* Memory allocation. */
9604 	params = calloc(1, sizeof(struct rte_swx_table_learner_params));
9605 	if (!params)
9606 		goto error;
9607 
9608 	/* Find first (smallest offset) and last (biggest offset) match fields. */
9609 	first = l->fields[0];
9610 	last = l->fields[0];
9611 
9612 	for (i = 0; i < l->n_fields; i++) {
9613 		struct field *f = l->fields[i];
9614 
9615 		if (f->offset < first->offset)
9616 			first = f;
9617 
9618 		if (f->offset > last->offset)
9619 			last = f;
9620 	}
9621 
9622 	/* Key offset and size. */
9623 	params->key_offset = first->offset / 8;
9624 	params->key_size = (last->offset + last->n_bits - first->offset) / 8;
9625 
9626 	/* Memory allocation. */
9627 	params->key_mask0 = calloc(1, params->key_size);
9628 	if (!params->key_mask0)
9629 		goto error;
9630 
9631 	/* Key mask. */
9632 	for (i = 0; i < l->n_fields; i++) {
9633 		struct field *f = l->fields[i];
9634 		uint32_t start = (f->offset - first->offset) / 8;
9635 		size_t size = f->n_bits / 8;
9636 
9637 		memset(&params->key_mask0[start], 0xFF, size);
9638 	}
9639 
9640 	/* Action data size. */
9641 	params->action_data_size = l->action_data_size_max;
9642 
9643 	/* Hash function. */
9644 	params->hash_func = l->hf ? l->hf->func : NULL;
9645 
9646 	/* Maximum number of keys. */
9647 	params->n_keys_max = l->size;
9648 
9649 	/* Memory allocation. */
9650 	params->key_timeout = calloc(l->n_timeouts, sizeof(uint32_t));
9651 	if (!params->key_timeout)
9652 		goto error;
9653 
9654 	/* Timeout. */
9655 	for (i = 0; i < l->n_timeouts; i++)
9656 		params->key_timeout[i] = l->timeout[i];
9657 
9658 	params->n_key_timeouts = l->n_timeouts;
9659 
9660 	return params;
9661 
9662 error:
9663 	learner_params_free(params);
9664 	return NULL;
9665 }
9666 
9667 static void
learner_build_free(struct rte_swx_pipeline * p)9668 learner_build_free(struct rte_swx_pipeline *p)
9669 {
9670 	uint32_t i;
9671 
9672 	for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9673 		struct thread *t = &p->threads[i];
9674 		uint32_t j;
9675 
9676 		if (!t->learners)
9677 			continue;
9678 
9679 		for (j = 0; j < p->n_learners; j++) {
9680 			struct learner_runtime *r = &t->learners[j];
9681 
9682 			free(r->mailbox);
9683 		}
9684 
9685 		free(t->learners);
9686 		t->learners = NULL;
9687 	}
9688 
9689 	if (p->learner_stats) {
9690 		for (i = 0; i < p->n_learners; i++)
9691 			free(p->learner_stats[i].n_pkts_action);
9692 
9693 		free(p->learner_stats);
9694 		p->learner_stats = NULL;
9695 	}
9696 }
9697 
9698 static int
learner_build(struct rte_swx_pipeline * p)9699 learner_build(struct rte_swx_pipeline *p)
9700 {
9701 	uint32_t i;
9702 	int status = 0;
9703 
9704 	/* Per pipeline: learner statistics. */
9705 	p->learner_stats = calloc(p->n_learners, sizeof(struct learner_statistics));
9706 	CHECK(p->learner_stats, ENOMEM);
9707 
9708 	for (i = 0; i < p->n_learners; i++) {
9709 		p->learner_stats[i].n_pkts_action = calloc(p->n_actions, sizeof(uint64_t));
9710 		CHECK(p->learner_stats[i].n_pkts_action, ENOMEM);
9711 	}
9712 
9713 	/* Per thread: learner run-time. */
9714 	for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9715 		struct thread *t = &p->threads[i];
9716 		struct learner *l;
9717 
9718 		t->learners = calloc(p->n_learners, sizeof(struct learner_runtime));
9719 		if (!t->learners) {
9720 			status = -ENOMEM;
9721 			goto error;
9722 		}
9723 
9724 		TAILQ_FOREACH(l, &p->learners, node) {
9725 			struct learner_runtime *r = &t->learners[l->id];
9726 			uint64_t size;
9727 
9728 			/* r->mailbox. */
9729 			size = rte_swx_table_learner_mailbox_size_get();
9730 			if (size) {
9731 				r->mailbox = calloc(1, size);
9732 				if (!r->mailbox) {
9733 					status = -ENOMEM;
9734 					goto error;
9735 				}
9736 			}
9737 
9738 			/* r->key. */
9739 			r->key = l->header ?
9740 				&t->structs[l->header->struct_id] :
9741 				&t->structs[p->metadata_struct_id];
9742 		}
9743 	}
9744 
9745 	return 0;
9746 
9747 error:
9748 	learner_build_free(p);
9749 	return status;
9750 }
9751 
9752 static void
learner_free(struct rte_swx_pipeline * p)9753 learner_free(struct rte_swx_pipeline *p)
9754 {
9755 	learner_build_free(p);
9756 
9757 	/* Learner tables. */
9758 	for ( ; ; ) {
9759 		struct learner *l;
9760 
9761 		l = TAILQ_FIRST(&p->learners);
9762 		if (!l)
9763 			break;
9764 
9765 		TAILQ_REMOVE(&p->learners, l, node);
9766 		free(l->fields);
9767 		free(l->actions);
9768 		free(l->default_action_data);
9769 		free(l);
9770 	}
9771 }
9772 
9773 /*
9774  * Table state.
9775  */
9776 static int
table_state_build(struct rte_swx_pipeline * p)9777 table_state_build(struct rte_swx_pipeline *p)
9778 {
9779 	struct table *table;
9780 	struct selector *s;
9781 	struct learner *l;
9782 
9783 	p->table_state = calloc(p->n_tables + p->n_selectors + p->n_learners,
9784 				sizeof(struct rte_swx_table_state));
9785 	CHECK(p->table_state, ENOMEM);
9786 
9787 	TAILQ_FOREACH(table, &p->tables, node) {
9788 		struct rte_swx_table_state *ts = &p->table_state[table->id];
9789 
9790 		if (table->type) {
9791 			struct rte_swx_table_params *params;
9792 
9793 			/* ts->obj. */
9794 			params = table_params_get(table);
9795 			CHECK(params, ENOMEM);
9796 
9797 			ts->obj = table->type->ops.create(params,
9798 				NULL,
9799 				table->args,
9800 				p->numa_node);
9801 
9802 			table_params_free(params);
9803 			CHECK(ts->obj, ENODEV);
9804 		}
9805 
9806 		/* ts->default_action_data. */
9807 		if (table->action_data_size_max) {
9808 			ts->default_action_data =
9809 				malloc(table->action_data_size_max);
9810 			CHECK(ts->default_action_data, ENOMEM);
9811 
9812 			memcpy(ts->default_action_data,
9813 			       table->default_action_data,
9814 			       table->action_data_size_max);
9815 		}
9816 
9817 		/* ts->default_action_id. */
9818 		ts->default_action_id = table->default_action->id;
9819 	}
9820 
9821 	TAILQ_FOREACH(s, &p->selectors, node) {
9822 		struct rte_swx_table_state *ts = &p->table_state[p->n_tables + s->id];
9823 		struct rte_swx_table_selector_params *params;
9824 
9825 		/* ts->obj. */
9826 		params = selector_table_params_get(s);
9827 		CHECK(params, ENOMEM);
9828 
9829 		ts->obj = rte_swx_table_selector_create(params, NULL, p->numa_node);
9830 
9831 		selector_params_free(params);
9832 		CHECK(ts->obj, ENODEV);
9833 	}
9834 
9835 	TAILQ_FOREACH(l, &p->learners, node) {
9836 		struct rte_swx_table_state *ts = &p->table_state[p->n_tables +
9837 			p->n_selectors + l->id];
9838 		struct rte_swx_table_learner_params *params;
9839 
9840 		/* ts->obj. */
9841 		params = learner_params_get(l);
9842 		CHECK(params, ENOMEM);
9843 
9844 		ts->obj = rte_swx_table_learner_create(params, p->numa_node);
9845 		learner_params_free(params);
9846 		CHECK(ts->obj, ENODEV);
9847 
9848 		/* ts->default_action_data. */
9849 		if (l->action_data_size_max) {
9850 			ts->default_action_data = malloc(l->action_data_size_max);
9851 			CHECK(ts->default_action_data, ENOMEM);
9852 
9853 			memcpy(ts->default_action_data,
9854 			       l->default_action_data,
9855 			       l->action_data_size_max);
9856 		}
9857 
9858 		/* ts->default_action_id. */
9859 		ts->default_action_id = l->default_action->id;
9860 	}
9861 
9862 	return 0;
9863 }
9864 
9865 static void
table_state_build_free(struct rte_swx_pipeline * p)9866 table_state_build_free(struct rte_swx_pipeline *p)
9867 {
9868 	uint32_t i;
9869 
9870 	if (!p->table_state)
9871 		return;
9872 
9873 	for (i = 0; i < p->n_tables; i++) {
9874 		struct rte_swx_table_state *ts = &p->table_state[i];
9875 		struct table *table = table_find_by_id(p, i);
9876 
9877 		/* ts->obj. */
9878 		if (table->type && ts->obj)
9879 			table->type->ops.free(ts->obj);
9880 
9881 		/* ts->default_action_data. */
9882 		free(ts->default_action_data);
9883 	}
9884 
9885 	for (i = 0; i < p->n_selectors; i++) {
9886 		struct rte_swx_table_state *ts = &p->table_state[p->n_tables + i];
9887 
9888 		/* ts->obj. */
9889 		rte_swx_table_selector_free(ts->obj);
9890 	}
9891 
9892 	for (i = 0; i < p->n_learners; i++) {
9893 		struct rte_swx_table_state *ts = &p->table_state[p->n_tables + p->n_selectors + i];
9894 
9895 		/* ts->obj. */
9896 		rte_swx_table_learner_free(ts->obj);
9897 
9898 		/* ts->default_action_data. */
9899 		free(ts->default_action_data);
9900 	}
9901 
9902 	free(p->table_state);
9903 	p->table_state = NULL;
9904 }
9905 
9906 static void
table_state_free(struct rte_swx_pipeline * p)9907 table_state_free(struct rte_swx_pipeline *p)
9908 {
9909 	table_state_build_free(p);
9910 }
9911 
9912 /*
9913  * Register array.
9914  */
9915 static struct regarray *
regarray_find(struct rte_swx_pipeline * p,const char * name)9916 regarray_find(struct rte_swx_pipeline *p, const char *name)
9917 {
9918 	struct regarray *elem;
9919 
9920 	TAILQ_FOREACH(elem, &p->regarrays, node)
9921 		if (!strcmp(elem->name, name))
9922 			return elem;
9923 
9924 	return NULL;
9925 }
9926 
9927 static struct regarray *
regarray_find_by_id(struct rte_swx_pipeline * p,uint32_t id)9928 regarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
9929 {
9930 	struct regarray *elem = NULL;
9931 
9932 	TAILQ_FOREACH(elem, &p->regarrays, node)
9933 		if (elem->id == id)
9934 			return elem;
9935 
9936 	return NULL;
9937 }
9938 
9939 int
rte_swx_pipeline_regarray_config(struct rte_swx_pipeline * p,const char * name,uint32_t size,uint64_t init_val)9940 rte_swx_pipeline_regarray_config(struct rte_swx_pipeline *p,
9941 			      const char *name,
9942 			      uint32_t size,
9943 			      uint64_t init_val)
9944 {
9945 	struct regarray *r;
9946 
9947 	CHECK(p, EINVAL);
9948 
9949 	CHECK_NAME(name, EINVAL);
9950 	CHECK(!regarray_find(p, name), EEXIST);
9951 
9952 	CHECK(size, EINVAL);
9953 	size = rte_align32pow2(size);
9954 
9955 	/* Memory allocation. */
9956 	r = calloc(1, sizeof(struct regarray));
9957 	CHECK(r, ENOMEM);
9958 
9959 	/* Node initialization. */
9960 	strcpy(r->name, name);
9961 	r->init_val = init_val;
9962 	r->size = size;
9963 	r->id = p->n_regarrays;
9964 
9965 	/* Node add to tailq. */
9966 	TAILQ_INSERT_TAIL(&p->regarrays, r, node);
9967 	p->n_regarrays++;
9968 
9969 	return 0;
9970 }
9971 
9972 static int
regarray_build(struct rte_swx_pipeline * p)9973 regarray_build(struct rte_swx_pipeline *p)
9974 {
9975 	struct regarray *regarray;
9976 
9977 	if (!p->n_regarrays)
9978 		return 0;
9979 
9980 	p->regarray_runtime = calloc(p->n_regarrays, sizeof(struct regarray_runtime));
9981 	CHECK(p->regarray_runtime, ENOMEM);
9982 
9983 	TAILQ_FOREACH(regarray, &p->regarrays, node) {
9984 		struct regarray_runtime *r = &p->regarray_runtime[regarray->id];
9985 		uint32_t i;
9986 
9987 		r->regarray = env_malloc(regarray->size * sizeof(uint64_t),
9988 					 RTE_CACHE_LINE_SIZE,
9989 					 p->numa_node);
9990 		CHECK(r->regarray, ENOMEM);
9991 
9992 		if (regarray->init_val)
9993 			for (i = 0; i < regarray->size; i++)
9994 				r->regarray[i] = regarray->init_val;
9995 
9996 		r->size_mask = regarray->size - 1;
9997 	}
9998 
9999 	return 0;
10000 }
10001 
10002 static void
regarray_build_free(struct rte_swx_pipeline * p)10003 regarray_build_free(struct rte_swx_pipeline *p)
10004 {
10005 	uint32_t i;
10006 
10007 	if (!p->regarray_runtime)
10008 		return;
10009 
10010 	for (i = 0; i < p->n_regarrays; i++) {
10011 		struct regarray *regarray = regarray_find_by_id(p, i);
10012 		struct regarray_runtime *r = &p->regarray_runtime[i];
10013 
10014 		env_free(r->regarray, regarray->size * sizeof(uint64_t));
10015 	}
10016 
10017 	free(p->regarray_runtime);
10018 	p->regarray_runtime = NULL;
10019 }
10020 
10021 static void
regarray_free(struct rte_swx_pipeline * p)10022 regarray_free(struct rte_swx_pipeline *p)
10023 {
10024 	regarray_build_free(p);
10025 
10026 	for ( ; ; ) {
10027 		struct regarray *elem;
10028 
10029 		elem = TAILQ_FIRST(&p->regarrays);
10030 		if (!elem)
10031 			break;
10032 
10033 		TAILQ_REMOVE(&p->regarrays, elem, node);
10034 		free(elem);
10035 	}
10036 }
10037 
10038 /*
10039  * Meter array.
10040  */
10041 static struct meter_profile *
meter_profile_find(struct rte_swx_pipeline * p,const char * name)10042 meter_profile_find(struct rte_swx_pipeline *p, const char *name)
10043 {
10044 	struct meter_profile *elem;
10045 
10046 	TAILQ_FOREACH(elem, &p->meter_profiles, node)
10047 		if (!strcmp(elem->name, name))
10048 			return elem;
10049 
10050 	return NULL;
10051 }
10052 
10053 static struct metarray *
metarray_find(struct rte_swx_pipeline * p,const char * name)10054 metarray_find(struct rte_swx_pipeline *p, const char *name)
10055 {
10056 	struct metarray *elem;
10057 
10058 	TAILQ_FOREACH(elem, &p->metarrays, node)
10059 		if (!strcmp(elem->name, name))
10060 			return elem;
10061 
10062 	return NULL;
10063 }
10064 
10065 static struct metarray *
metarray_find_by_id(struct rte_swx_pipeline * p,uint32_t id)10066 metarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
10067 {
10068 	struct metarray *elem = NULL;
10069 
10070 	TAILQ_FOREACH(elem, &p->metarrays, node)
10071 		if (elem->id == id)
10072 			return elem;
10073 
10074 	return NULL;
10075 }
10076 
10077 int
rte_swx_pipeline_metarray_config(struct rte_swx_pipeline * p,const char * name,uint32_t size)10078 rte_swx_pipeline_metarray_config(struct rte_swx_pipeline *p,
10079 				 const char *name,
10080 				 uint32_t size)
10081 {
10082 	struct metarray *m;
10083 
10084 	CHECK(p, EINVAL);
10085 
10086 	CHECK_NAME(name, EINVAL);
10087 	CHECK(!metarray_find(p, name), EEXIST);
10088 
10089 	CHECK(size, EINVAL);
10090 	size = rte_align32pow2(size);
10091 
10092 	/* Memory allocation. */
10093 	m = calloc(1, sizeof(struct metarray));
10094 	CHECK(m, ENOMEM);
10095 
10096 	/* Node initialization. */
10097 	strcpy(m->name, name);
10098 	m->size = size;
10099 	m->id = p->n_metarrays;
10100 
10101 	/* Node add to tailq. */
10102 	TAILQ_INSERT_TAIL(&p->metarrays, m, node);
10103 	p->n_metarrays++;
10104 
10105 	return 0;
10106 }
10107 
10108 struct meter_profile meter_profile_default = {
10109 	.node = {0},
10110 	.name = "",
10111 	.params = {0},
10112 
10113 	.profile = {
10114 		.cbs = 10000,
10115 		.pbs = 10000,
10116 		.cir_period = 1,
10117 		.cir_bytes_per_period = 1,
10118 		.pir_period = 1,
10119 		.pir_bytes_per_period = 1,
10120 	},
10121 
10122 	.n_users = 0,
10123 };
10124 
10125 static void
meter_init(struct meter * m)10126 meter_init(struct meter *m)
10127 {
10128 	memset(m, 0, sizeof(struct meter));
10129 	rte_meter_trtcm_config(&m->m, &meter_profile_default.profile);
10130 	m->profile = &meter_profile_default;
10131 	m->color_mask = RTE_COLOR_GREEN;
10132 
10133 	meter_profile_default.n_users++;
10134 }
10135 
10136 static int
metarray_build(struct rte_swx_pipeline * p)10137 metarray_build(struct rte_swx_pipeline *p)
10138 {
10139 	struct metarray *m;
10140 
10141 	if (!p->n_metarrays)
10142 		return 0;
10143 
10144 	p->metarray_runtime = calloc(p->n_metarrays, sizeof(struct metarray_runtime));
10145 	CHECK(p->metarray_runtime, ENOMEM);
10146 
10147 	TAILQ_FOREACH(m, &p->metarrays, node) {
10148 		struct metarray_runtime *r = &p->metarray_runtime[m->id];
10149 		uint32_t i;
10150 
10151 		r->metarray = env_malloc(m->size * sizeof(struct meter),
10152 					 RTE_CACHE_LINE_SIZE,
10153 					 p->numa_node);
10154 		CHECK(r->metarray, ENOMEM);
10155 
10156 		for (i = 0; i < m->size; i++)
10157 			meter_init(&r->metarray[i]);
10158 
10159 		r->size_mask = m->size - 1;
10160 	}
10161 
10162 	return 0;
10163 }
10164 
10165 static void
metarray_build_free(struct rte_swx_pipeline * p)10166 metarray_build_free(struct rte_swx_pipeline *p)
10167 {
10168 	uint32_t i;
10169 
10170 	if (!p->metarray_runtime)
10171 		return;
10172 
10173 	for (i = 0; i < p->n_metarrays; i++) {
10174 		struct metarray *m = metarray_find_by_id(p, i);
10175 		struct metarray_runtime *r = &p->metarray_runtime[i];
10176 
10177 		env_free(r->metarray, m->size * sizeof(struct meter));
10178 	}
10179 
10180 	free(p->metarray_runtime);
10181 	p->metarray_runtime = NULL;
10182 }
10183 
10184 static void
metarray_free(struct rte_swx_pipeline * p)10185 metarray_free(struct rte_swx_pipeline *p)
10186 {
10187 	metarray_build_free(p);
10188 
10189 	/* Meter arrays. */
10190 	for ( ; ; ) {
10191 		struct metarray *elem;
10192 
10193 		elem = TAILQ_FIRST(&p->metarrays);
10194 		if (!elem)
10195 			break;
10196 
10197 		TAILQ_REMOVE(&p->metarrays, elem, node);
10198 		free(elem);
10199 	}
10200 
10201 	/* Meter profiles. */
10202 	for ( ; ; ) {
10203 		struct meter_profile *elem;
10204 
10205 		elem = TAILQ_FIRST(&p->meter_profiles);
10206 		if (!elem)
10207 			break;
10208 
10209 		TAILQ_REMOVE(&p->meter_profiles, elem, node);
10210 		free(elem);
10211 	}
10212 }
10213 
10214 /*
10215  * Pipeline.
10216  */
10217 
10218 /* Global list of pipeline instances. */
10219 TAILQ_HEAD(rte_swx_pipeline_list, rte_tailq_entry);
10220 
10221 static struct rte_tailq_elem rte_swx_pipeline_tailq = {
10222 	.name = "RTE_SWX_PIPELINE",
10223 };
10224 
EAL_REGISTER_TAILQ(rte_swx_pipeline_tailq)10225 EAL_REGISTER_TAILQ(rte_swx_pipeline_tailq)
10226 
10227 struct rte_swx_pipeline *
10228 rte_swx_pipeline_find(const char *name)
10229 {
10230 	struct rte_swx_pipeline_list *pipeline_list;
10231 	struct rte_tailq_entry *te = NULL;
10232 
10233 	if (!name || !name[0] || (strnlen(name, RTE_SWX_NAME_SIZE) >= RTE_SWX_NAME_SIZE))
10234 		return NULL;
10235 
10236 	pipeline_list = RTE_TAILQ_CAST(rte_swx_pipeline_tailq.head, rte_swx_pipeline_list);
10237 
10238 	rte_mcfg_tailq_read_lock();
10239 
10240 	TAILQ_FOREACH(te, pipeline_list, next) {
10241 		struct rte_swx_pipeline *p = (struct rte_swx_pipeline *)te->data;
10242 
10243 		if (!strncmp(name, p->name, sizeof(p->name))) {
10244 			rte_mcfg_tailq_read_unlock();
10245 			return p;
10246 		}
10247 	}
10248 
10249 	rte_mcfg_tailq_read_unlock();
10250 	return NULL;
10251 }
10252 
10253 static int
pipeline_register(struct rte_swx_pipeline * p)10254 pipeline_register(struct rte_swx_pipeline *p)
10255 {
10256 	struct rte_swx_pipeline_list *pipeline_list;
10257 	struct rte_tailq_entry *te = NULL;
10258 
10259 	pipeline_list = RTE_TAILQ_CAST(rte_swx_pipeline_tailq.head, rte_swx_pipeline_list);
10260 
10261 	rte_mcfg_tailq_write_lock();
10262 
10263 	TAILQ_FOREACH(te, pipeline_list, next) {
10264 		struct rte_swx_pipeline *pipeline = (struct rte_swx_pipeline *)te->data;
10265 
10266 		if (!strncmp(p->name, pipeline->name, sizeof(p->name))) {
10267 			rte_mcfg_tailq_write_unlock();
10268 			return -EEXIST;
10269 		}
10270 	}
10271 
10272 	te = calloc(1, sizeof(struct rte_tailq_entry));
10273 	if (!te) {
10274 		rte_mcfg_tailq_write_unlock();
10275 		return -ENOMEM;
10276 	}
10277 
10278 	te->data = (void *)p;
10279 	TAILQ_INSERT_TAIL(pipeline_list, te, next);
10280 	rte_mcfg_tailq_write_unlock();
10281 	return 0;
10282 }
10283 
10284 static void
pipeline_unregister(struct rte_swx_pipeline * p)10285 pipeline_unregister(struct rte_swx_pipeline *p)
10286 {
10287 	struct rte_swx_pipeline_list *pipeline_list;
10288 	struct rte_tailq_entry *te = NULL;
10289 
10290 	pipeline_list = RTE_TAILQ_CAST(rte_swx_pipeline_tailq.head, rte_swx_pipeline_list);
10291 
10292 	rte_mcfg_tailq_write_lock();
10293 
10294 	TAILQ_FOREACH(te, pipeline_list, next) {
10295 		if (te->data == (void *)p) {
10296 			TAILQ_REMOVE(pipeline_list, te, next);
10297 			rte_mcfg_tailq_write_unlock();
10298 			free(te);
10299 			return;
10300 		}
10301 	}
10302 
10303 	rte_mcfg_tailq_write_unlock();
10304 }
10305 
10306 void
rte_swx_pipeline_free(struct rte_swx_pipeline * p)10307 rte_swx_pipeline_free(struct rte_swx_pipeline *p)
10308 {
10309 	void *lib;
10310 
10311 	if (!p)
10312 		return;
10313 
10314 	if (p->name[0])
10315 		pipeline_unregister(p);
10316 
10317 	lib = p->lib;
10318 
10319 	free(p->instruction_data);
10320 	free(p->instructions);
10321 
10322 	metarray_free(p);
10323 	regarray_free(p);
10324 	table_state_free(p);
10325 	learner_free(p);
10326 	selector_free(p);
10327 	table_free(p);
10328 	action_free(p);
10329 	instruction_table_free(p);
10330 	metadata_free(p);
10331 	header_free(p);
10332 	rss_free(p);
10333 	hash_func_free(p);
10334 	extern_func_free(p);
10335 	extern_obj_free(p);
10336 	mirroring_free(p);
10337 	port_out_free(p);
10338 	port_in_free(p);
10339 	struct_free(p);
10340 
10341 	free(p);
10342 
10343 	if (lib)
10344 		dlclose(lib);
10345 }
10346 
10347 static int
port_in_types_register(struct rte_swx_pipeline * p)10348 port_in_types_register(struct rte_swx_pipeline *p)
10349 {
10350 	int status;
10351 
10352 	status = rte_swx_pipeline_port_in_type_register(p,
10353 		"ethdev",
10354 		&rte_swx_port_ethdev_reader_ops);
10355 	if (status)
10356 		return status;
10357 
10358 	status = rte_swx_pipeline_port_in_type_register(p,
10359 		"ring",
10360 		&rte_swx_port_ring_reader_ops);
10361 	if (status)
10362 		return status;
10363 
10364 #ifdef RTE_PORT_PCAP
10365 	status = rte_swx_pipeline_port_in_type_register(p,
10366 		"source",
10367 		&rte_swx_port_source_ops);
10368 	if (status)
10369 		return status;
10370 #endif
10371 
10372 	status = rte_swx_pipeline_port_in_type_register(p,
10373 		"fd",
10374 		&rte_swx_port_fd_reader_ops);
10375 	if (status)
10376 		return status;
10377 
10378 	return 0;
10379 }
10380 
10381 static int
port_out_types_register(struct rte_swx_pipeline * p)10382 port_out_types_register(struct rte_swx_pipeline *p)
10383 {
10384 	int status;
10385 
10386 	status = rte_swx_pipeline_port_out_type_register(p,
10387 		"ethdev",
10388 		&rte_swx_port_ethdev_writer_ops);
10389 	if (status)
10390 		return status;
10391 
10392 	status = rte_swx_pipeline_port_out_type_register(p,
10393 		"ring",
10394 		&rte_swx_port_ring_writer_ops);
10395 	if (status)
10396 		return status;
10397 
10398 	status = rte_swx_pipeline_port_out_type_register(p,
10399 		"sink",
10400 		&rte_swx_port_sink_ops);
10401 	if (status)
10402 		return status;
10403 
10404 	status = rte_swx_pipeline_port_out_type_register(p,
10405 		"fd",
10406 		&rte_swx_port_fd_writer_ops);
10407 	if (status)
10408 		return status;
10409 
10410 	return 0;
10411 }
10412 
10413 static int
table_types_register(struct rte_swx_pipeline * p)10414 table_types_register(struct rte_swx_pipeline *p)
10415 {
10416 	int status;
10417 
10418 	status = rte_swx_pipeline_table_type_register(p,
10419 		"exact",
10420 		RTE_SWX_TABLE_MATCH_EXACT,
10421 		&rte_swx_table_exact_match_ops);
10422 	if (status)
10423 		return status;
10424 
10425 	status = rte_swx_pipeline_table_type_register(p,
10426 		"wildcard",
10427 		RTE_SWX_TABLE_MATCH_WILDCARD,
10428 		&rte_swx_table_wildcard_match_ops);
10429 	if (status)
10430 		return status;
10431 
10432 	return 0;
10433 }
10434 
10435 static int
hash_funcs_register(struct rte_swx_pipeline * p)10436 hash_funcs_register(struct rte_swx_pipeline *p)
10437 {
10438 	int status;
10439 
10440 	status = rte_swx_pipeline_hash_func_register(p, "jhash", rte_jhash);
10441 	if (status)
10442 		return status;
10443 
10444 	status = rte_swx_pipeline_hash_func_register(p, "crc32", rte_hash_crc);
10445 	if (status)
10446 		return status;
10447 
10448 	return 0;
10449 }
10450 
10451 int
rte_swx_pipeline_config(struct rte_swx_pipeline ** p,const char * name,int numa_node)10452 rte_swx_pipeline_config(struct rte_swx_pipeline **p, const char *name, int numa_node)
10453 {
10454 	struct rte_swx_pipeline *pipeline = NULL;
10455 	int status = 0;
10456 
10457 	/* Check input parameters. */
10458 	CHECK(p, EINVAL);
10459 	CHECK(!name || (strnlen(name, RTE_SWX_NAME_SIZE) < RTE_SWX_NAME_SIZE), EINVAL);
10460 
10461 	/* Memory allocation. */
10462 	pipeline = calloc(1, sizeof(struct rte_swx_pipeline));
10463 	if (!pipeline) {
10464 		status = -ENOMEM;
10465 		goto error;
10466 	}
10467 
10468 	/* Initialization. */
10469 	if (name)
10470 		strcpy(pipeline->name, name);
10471 
10472 	TAILQ_INIT(&pipeline->struct_types);
10473 	TAILQ_INIT(&pipeline->port_in_types);
10474 	TAILQ_INIT(&pipeline->ports_in);
10475 	TAILQ_INIT(&pipeline->port_out_types);
10476 	TAILQ_INIT(&pipeline->ports_out);
10477 	TAILQ_INIT(&pipeline->extern_types);
10478 	TAILQ_INIT(&pipeline->extern_objs);
10479 	TAILQ_INIT(&pipeline->extern_funcs);
10480 	TAILQ_INIT(&pipeline->hash_funcs);
10481 	TAILQ_INIT(&pipeline->rss);
10482 	TAILQ_INIT(&pipeline->headers);
10483 	TAILQ_INIT(&pipeline->actions);
10484 	TAILQ_INIT(&pipeline->table_types);
10485 	TAILQ_INIT(&pipeline->tables);
10486 	TAILQ_INIT(&pipeline->selectors);
10487 	TAILQ_INIT(&pipeline->learners);
10488 	TAILQ_INIT(&pipeline->regarrays);
10489 	TAILQ_INIT(&pipeline->meter_profiles);
10490 	TAILQ_INIT(&pipeline->metarrays);
10491 
10492 	pipeline->n_structs = 1; /* Struct 0 is reserved for action_data. */
10493 	pipeline->n_mirroring_slots = RTE_SWX_PACKET_MIRRORING_SLOTS_DEFAULT;
10494 	pipeline->n_mirroring_sessions = RTE_SWX_PACKET_MIRRORING_SESSIONS_DEFAULT;
10495 	pipeline->numa_node = numa_node;
10496 
10497 	status = port_in_types_register(pipeline);
10498 	if (status)
10499 		goto error;
10500 
10501 	status = port_out_types_register(pipeline);
10502 	if (status)
10503 		goto error;
10504 
10505 	status = table_types_register(pipeline);
10506 	if (status)
10507 		goto error;
10508 
10509 	status = hash_funcs_register(pipeline);
10510 	if (status)
10511 		goto error;
10512 
10513 	if (pipeline->name[0]) {
10514 		status = pipeline_register(pipeline);
10515 		if (status)
10516 			goto error;
10517 	}
10518 
10519 	*p = pipeline;
10520 	return 0;
10521 
10522 error:
10523 	rte_swx_pipeline_free(pipeline);
10524 	return status;
10525 }
10526 
10527 int
rte_swx_pipeline_instructions_config(struct rte_swx_pipeline * p,const char ** instructions,uint32_t n_instructions)10528 rte_swx_pipeline_instructions_config(struct rte_swx_pipeline *p,
10529 				     const char **instructions,
10530 				     uint32_t n_instructions)
10531 {
10532 	int err;
10533 	uint32_t i;
10534 
10535 	err = instruction_config(p, NULL, instructions, n_instructions);
10536 	if (err)
10537 		return err;
10538 
10539 	/* Thread instruction pointer reset. */
10540 	for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
10541 		struct thread *t = &p->threads[i];
10542 
10543 		thread_ip_reset(p, t);
10544 	}
10545 
10546 	return 0;
10547 }
10548 
10549 int
rte_swx_pipeline_build(struct rte_swx_pipeline * p)10550 rte_swx_pipeline_build(struct rte_swx_pipeline *p)
10551 {
10552 	struct rte_swx_port_sink_params drop_port_params = {
10553 		.file_name = NULL,
10554 	};
10555 	int status;
10556 
10557 	CHECK(p, EINVAL);
10558 	CHECK(p->build_done == 0, EEXIST);
10559 
10560 	status = port_in_build(p);
10561 	if (status)
10562 		goto error;
10563 
10564 	/* Drop port. */
10565 	status = rte_swx_pipeline_port_out_config(p,
10566 						  p->n_ports_out,
10567 						  "sink",
10568 						  &drop_port_params);
10569 	if (status)
10570 		goto error;
10571 
10572 	status = port_out_build(p);
10573 	if (status)
10574 		goto error;
10575 
10576 	status = mirroring_build(p);
10577 	if (status)
10578 		goto error;
10579 
10580 	status = struct_build(p);
10581 	if (status)
10582 		goto error;
10583 
10584 	status = extern_obj_build(p);
10585 	if (status)
10586 		goto error;
10587 
10588 	status = extern_func_build(p);
10589 	if (status)
10590 		goto error;
10591 
10592 	status = hash_func_build(p);
10593 	if (status)
10594 		goto error;
10595 
10596 	status = rss_build(p);
10597 	if (status)
10598 		goto error;
10599 
10600 	status = header_build(p);
10601 	if (status)
10602 		goto error;
10603 
10604 	status = metadata_build(p);
10605 	if (status)
10606 		goto error;
10607 
10608 	status = instruction_table_build(p);
10609 	if (status)
10610 		goto error;
10611 
10612 	status = action_build(p);
10613 	if (status)
10614 		goto error;
10615 
10616 	status = table_build(p);
10617 	if (status)
10618 		goto error;
10619 
10620 	status = selector_build(p);
10621 	if (status)
10622 		goto error;
10623 
10624 	status = learner_build(p);
10625 	if (status)
10626 		goto error;
10627 
10628 	status = table_state_build(p);
10629 	if (status)
10630 		goto error;
10631 
10632 	status = regarray_build(p);
10633 	if (status)
10634 		goto error;
10635 
10636 	status = metarray_build(p);
10637 	if (status)
10638 		goto error;
10639 
10640 	p->build_done = 1;
10641 
10642 	return 0;
10643 
10644 error:
10645 	metarray_build_free(p);
10646 	regarray_build_free(p);
10647 	table_state_build_free(p);
10648 	learner_build_free(p);
10649 	selector_build_free(p);
10650 	table_build_free(p);
10651 	action_build_free(p);
10652 	instruction_table_build_free(p);
10653 	metadata_build_free(p);
10654 	header_build_free(p);
10655 	rss_build_free(p);
10656 	hash_func_build_free(p);
10657 	extern_func_build_free(p);
10658 	extern_obj_build_free(p);
10659 	mirroring_build_free(p);
10660 	port_out_build_free(p);
10661 	port_in_build_free(p);
10662 	struct_build_free(p);
10663 
10664 	return status;
10665 }
10666 
10667 void
rte_swx_pipeline_run(struct rte_swx_pipeline * p,uint32_t n_instructions)10668 rte_swx_pipeline_run(struct rte_swx_pipeline *p, uint32_t n_instructions)
10669 {
10670 	uint32_t i;
10671 
10672 	for (i = 0; i < n_instructions; i++)
10673 		instr_exec(p);
10674 }
10675 
10676 void
rte_swx_pipeline_flush(struct rte_swx_pipeline * p)10677 rte_swx_pipeline_flush(struct rte_swx_pipeline *p)
10678 {
10679 	uint32_t i;
10680 
10681 	for (i = 0; i < p->n_ports_out; i++) {
10682 		struct port_out_runtime *port = &p->out[i];
10683 
10684 		if (port->flush)
10685 			port->flush(port->obj);
10686 	}
10687 }
10688 
10689 /*
10690  * Control.
10691  */
10692 int
rte_swx_ctl_pipeline_info_get(struct rte_swx_pipeline * p,struct rte_swx_ctl_pipeline_info * pipeline)10693 rte_swx_ctl_pipeline_info_get(struct rte_swx_pipeline *p,
10694 			      struct rte_swx_ctl_pipeline_info *pipeline)
10695 {
10696 	struct action *action;
10697 	struct table *table;
10698 	uint32_t n_actions = 0, n_tables = 0;
10699 
10700 	if (!p || !pipeline)
10701 		return -EINVAL;
10702 
10703 	TAILQ_FOREACH(action, &p->actions, node)
10704 		n_actions++;
10705 
10706 	TAILQ_FOREACH(table, &p->tables, node)
10707 		n_tables++;
10708 
10709 	strcpy(pipeline->name, p->name);
10710 	pipeline->n_ports_in = p->n_ports_in;
10711 	pipeline->n_ports_out = p->n_ports_out;
10712 	pipeline->n_mirroring_slots = p->n_mirroring_slots;
10713 	pipeline->n_mirroring_sessions = p->n_mirroring_sessions;
10714 	pipeline->n_actions = n_actions;
10715 	pipeline->n_tables = n_tables;
10716 	pipeline->n_selectors = p->n_selectors;
10717 	pipeline->n_learners = p->n_learners;
10718 	pipeline->n_regarrays = p->n_regarrays;
10719 	pipeline->n_metarrays = p->n_metarrays;
10720 	pipeline->n_rss = p->n_rss;
10721 
10722 	return 0;
10723 }
10724 
10725 int
rte_swx_ctl_pipeline_numa_node_get(struct rte_swx_pipeline * p,int * numa_node)10726 rte_swx_ctl_pipeline_numa_node_get(struct rte_swx_pipeline *p, int *numa_node)
10727 {
10728 	if (!p || !numa_node)
10729 		return -EINVAL;
10730 
10731 	*numa_node = p->numa_node;
10732 	return 0;
10733 }
10734 
10735 int
rte_swx_ctl_action_info_get(struct rte_swx_pipeline * p,uint32_t action_id,struct rte_swx_ctl_action_info * action)10736 rte_swx_ctl_action_info_get(struct rte_swx_pipeline *p,
10737 			    uint32_t action_id,
10738 			    struct rte_swx_ctl_action_info *action)
10739 {
10740 	struct action *a = NULL;
10741 
10742 	if (!p || (action_id >= p->n_actions) || !action)
10743 		return -EINVAL;
10744 
10745 	a = action_find_by_id(p, action_id);
10746 	if (!a)
10747 		return -EINVAL;
10748 
10749 	strcpy(action->name, a->name);
10750 	action->n_args = a->st ? a->st->n_fields : 0;
10751 	return 0;
10752 }
10753 
10754 int
rte_swx_ctl_action_arg_info_get(struct rte_swx_pipeline * p,uint32_t action_id,uint32_t action_arg_id,struct rte_swx_ctl_action_arg_info * action_arg)10755 rte_swx_ctl_action_arg_info_get(struct rte_swx_pipeline *p,
10756 				uint32_t action_id,
10757 				uint32_t action_arg_id,
10758 				struct rte_swx_ctl_action_arg_info *action_arg)
10759 {
10760 	struct action *a = NULL;
10761 	struct field *arg = NULL;
10762 
10763 	if (!p || (action_id >= p->n_actions) || !action_arg)
10764 		return -EINVAL;
10765 
10766 	a = action_find_by_id(p, action_id);
10767 	if (!a || !a->st || (action_arg_id >= a->st->n_fields))
10768 		return -EINVAL;
10769 
10770 	arg = &a->st->fields[action_arg_id];
10771 	strcpy(action_arg->name, arg->name);
10772 	action_arg->n_bits = arg->n_bits;
10773 	action_arg->is_network_byte_order = a->args_endianness[action_arg_id];
10774 
10775 	return 0;
10776 }
10777 
10778 int
rte_swx_ctl_table_info_get(struct rte_swx_pipeline * p,uint32_t table_id,struct rte_swx_ctl_table_info * table)10779 rte_swx_ctl_table_info_get(struct rte_swx_pipeline *p,
10780 			   uint32_t table_id,
10781 			   struct rte_swx_ctl_table_info *table)
10782 {
10783 	struct table *t = NULL;
10784 
10785 	if (!p || !table)
10786 		return -EINVAL;
10787 
10788 	t = table_find_by_id(p, table_id);
10789 	if (!t)
10790 		return -EINVAL;
10791 
10792 	strcpy(table->name, t->name);
10793 	strcpy(table->args, t->args);
10794 	table->n_match_fields = t->n_fields;
10795 	table->n_actions = t->n_actions;
10796 	table->default_action_is_const = t->default_action_is_const;
10797 	table->hash_func = t->hf ? t->hf->func : NULL;
10798 	table->size = t->size;
10799 	return 0;
10800 }
10801 
10802 int
rte_swx_ctl_table_match_field_info_get(struct rte_swx_pipeline * p,uint32_t table_id,uint32_t match_field_id,struct rte_swx_ctl_table_match_field_info * match_field)10803 rte_swx_ctl_table_match_field_info_get(struct rte_swx_pipeline *p,
10804 	uint32_t table_id,
10805 	uint32_t match_field_id,
10806 	struct rte_swx_ctl_table_match_field_info *match_field)
10807 {
10808 	struct table *t;
10809 	struct match_field *f;
10810 
10811 	if (!p || (table_id >= p->n_tables) || !match_field)
10812 		return -EINVAL;
10813 
10814 	t = table_find_by_id(p, table_id);
10815 	if (!t || (match_field_id >= t->n_fields))
10816 		return -EINVAL;
10817 
10818 	f = &t->fields[match_field_id];
10819 	match_field->match_type = f->match_type;
10820 	match_field->is_header = t->header ? 1 : 0;
10821 	match_field->n_bits = f->field->n_bits;
10822 	match_field->offset = f->field->offset;
10823 
10824 	return 0;
10825 }
10826 
10827 int
rte_swx_ctl_table_action_info_get(struct rte_swx_pipeline * p,uint32_t table_id,uint32_t table_action_id,struct rte_swx_ctl_table_action_info * table_action)10828 rte_swx_ctl_table_action_info_get(struct rte_swx_pipeline *p,
10829 	uint32_t table_id,
10830 	uint32_t table_action_id,
10831 	struct rte_swx_ctl_table_action_info *table_action)
10832 {
10833 	struct table *t;
10834 
10835 	if (!p || (table_id >= p->n_tables) || !table_action)
10836 		return -EINVAL;
10837 
10838 	t = table_find_by_id(p, table_id);
10839 	if (!t || (table_action_id >= t->n_actions))
10840 		return -EINVAL;
10841 
10842 	table_action->action_id = t->actions[table_action_id]->id;
10843 
10844 	table_action->action_is_for_table_entries = t->action_is_for_table_entries[table_action_id];
10845 	table_action->action_is_for_default_entry = t->action_is_for_default_entry[table_action_id];
10846 
10847 	return 0;
10848 }
10849 
10850 int
rte_swx_ctl_table_ops_get(struct rte_swx_pipeline * p,uint32_t table_id,struct rte_swx_table_ops * table_ops,int * is_stub)10851 rte_swx_ctl_table_ops_get(struct rte_swx_pipeline *p,
10852 			  uint32_t table_id,
10853 			  struct rte_swx_table_ops *table_ops,
10854 			  int *is_stub)
10855 {
10856 	struct table *t;
10857 
10858 	if (!p || (table_id >= p->n_tables))
10859 		return -EINVAL;
10860 
10861 	t = table_find_by_id(p, table_id);
10862 	if (!t)
10863 		return -EINVAL;
10864 
10865 	if (t->type) {
10866 		if (table_ops)
10867 			memcpy(table_ops, &t->type->ops, sizeof(*table_ops));
10868 		*is_stub = 0;
10869 	} else {
10870 		*is_stub = 1;
10871 	}
10872 
10873 	return 0;
10874 }
10875 
10876 int
rte_swx_ctl_selector_info_get(struct rte_swx_pipeline * p,uint32_t selector_id,struct rte_swx_ctl_selector_info * selector)10877 rte_swx_ctl_selector_info_get(struct rte_swx_pipeline *p,
10878 			      uint32_t selector_id,
10879 			      struct rte_swx_ctl_selector_info *selector)
10880 {
10881 	struct selector *s = NULL;
10882 
10883 	if (!p || !selector)
10884 		return -EINVAL;
10885 
10886 	s = selector_find_by_id(p, selector_id);
10887 	if (!s)
10888 		return -EINVAL;
10889 
10890 	strcpy(selector->name, s->name);
10891 
10892 	selector->n_selector_fields = s->n_selector_fields;
10893 	selector->n_groups_max = s->n_groups_max;
10894 	selector->n_members_per_group_max = s->n_members_per_group_max;
10895 
10896 	return 0;
10897 }
10898 
10899 int
rte_swx_ctl_selector_group_id_field_info_get(struct rte_swx_pipeline * p,uint32_t selector_id,struct rte_swx_ctl_table_match_field_info * field)10900 rte_swx_ctl_selector_group_id_field_info_get(struct rte_swx_pipeline *p,
10901 	 uint32_t selector_id,
10902 	 struct rte_swx_ctl_table_match_field_info *field)
10903 {
10904 	struct selector *s;
10905 
10906 	if (!p || (selector_id >= p->n_selectors) || !field)
10907 		return -EINVAL;
10908 
10909 	s = selector_find_by_id(p, selector_id);
10910 	if (!s)
10911 		return -EINVAL;
10912 
10913 	field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10914 	field->is_header = 0;
10915 	field->n_bits = s->group_id_field->n_bits;
10916 	field->offset = s->group_id_field->offset;
10917 
10918 	return 0;
10919 }
10920 
10921 int
rte_swx_ctl_selector_field_info_get(struct rte_swx_pipeline * p,uint32_t selector_id,uint32_t selector_field_id,struct rte_swx_ctl_table_match_field_info * field)10922 rte_swx_ctl_selector_field_info_get(struct rte_swx_pipeline *p,
10923 	 uint32_t selector_id,
10924 	 uint32_t selector_field_id,
10925 	 struct rte_swx_ctl_table_match_field_info *field)
10926 {
10927 	struct selector *s;
10928 	struct field *f;
10929 
10930 	if (!p || (selector_id >= p->n_selectors) || !field)
10931 		return -EINVAL;
10932 
10933 	s = selector_find_by_id(p, selector_id);
10934 	if (!s || (selector_field_id >= s->n_selector_fields))
10935 		return -EINVAL;
10936 
10937 	f = s->selector_fields[selector_field_id];
10938 	field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10939 	field->is_header = s->selector_header ? 1 : 0;
10940 	field->n_bits = f->n_bits;
10941 	field->offset = f->offset;
10942 
10943 	return 0;
10944 }
10945 
10946 int
rte_swx_ctl_selector_member_id_field_info_get(struct rte_swx_pipeline * p,uint32_t selector_id,struct rte_swx_ctl_table_match_field_info * field)10947 rte_swx_ctl_selector_member_id_field_info_get(struct rte_swx_pipeline *p,
10948 	 uint32_t selector_id,
10949 	 struct rte_swx_ctl_table_match_field_info *field)
10950 {
10951 	struct selector *s;
10952 
10953 	if (!p || (selector_id >= p->n_selectors) || !field)
10954 		return -EINVAL;
10955 
10956 	s = selector_find_by_id(p, selector_id);
10957 	if (!s)
10958 		return -EINVAL;
10959 
10960 	field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10961 	field->is_header = 0;
10962 	field->n_bits = s->member_id_field->n_bits;
10963 	field->offset = s->member_id_field->offset;
10964 
10965 	return 0;
10966 }
10967 
10968 int
rte_swx_ctl_learner_info_get(struct rte_swx_pipeline * p,uint32_t learner_id,struct rte_swx_ctl_learner_info * learner)10969 rte_swx_ctl_learner_info_get(struct rte_swx_pipeline *p,
10970 			     uint32_t learner_id,
10971 			     struct rte_swx_ctl_learner_info *learner)
10972 {
10973 	struct learner *l = NULL;
10974 
10975 	if (!p || !learner)
10976 		return -EINVAL;
10977 
10978 	l = learner_find_by_id(p, learner_id);
10979 	if (!l)
10980 		return -EINVAL;
10981 
10982 	strcpy(learner->name, l->name);
10983 
10984 	learner->n_match_fields = l->n_fields;
10985 	learner->n_actions = l->n_actions;
10986 	learner->default_action_is_const = l->default_action_is_const;
10987 	learner->size = l->size;
10988 	learner->n_key_timeouts = l->n_timeouts;
10989 
10990 	return 0;
10991 }
10992 
10993 int
rte_swx_ctl_learner_match_field_info_get(struct rte_swx_pipeline * p,uint32_t learner_id,uint32_t match_field_id,struct rte_swx_ctl_table_match_field_info * match_field)10994 rte_swx_ctl_learner_match_field_info_get(struct rte_swx_pipeline *p,
10995 					 uint32_t learner_id,
10996 					 uint32_t match_field_id,
10997 					 struct rte_swx_ctl_table_match_field_info *match_field)
10998 {
10999 	struct learner *l;
11000 	struct field *f;
11001 
11002 	if (!p || (learner_id >= p->n_learners) || !match_field)
11003 		return -EINVAL;
11004 
11005 	l = learner_find_by_id(p, learner_id);
11006 	if (!l || (match_field_id >= l->n_fields))
11007 		return -EINVAL;
11008 
11009 	f = l->fields[match_field_id];
11010 	match_field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
11011 	match_field->is_header = l->header ? 1 : 0;
11012 	match_field->n_bits = f->n_bits;
11013 	match_field->offset = f->offset;
11014 
11015 	return 0;
11016 }
11017 
11018 int
rte_swx_ctl_learner_action_info_get(struct rte_swx_pipeline * p,uint32_t learner_id,uint32_t learner_action_id,struct rte_swx_ctl_table_action_info * learner_action)11019 rte_swx_ctl_learner_action_info_get(struct rte_swx_pipeline *p,
11020 				    uint32_t learner_id,
11021 				    uint32_t learner_action_id,
11022 				    struct rte_swx_ctl_table_action_info *learner_action)
11023 {
11024 	struct learner *l;
11025 
11026 	if (!p || (learner_id >= p->n_learners) || !learner_action)
11027 		return -EINVAL;
11028 
11029 	l = learner_find_by_id(p, learner_id);
11030 	if (!l || (learner_action_id >= l->n_actions))
11031 		return -EINVAL;
11032 
11033 	learner_action->action_id = l->actions[learner_action_id]->id;
11034 
11035 	learner_action->action_is_for_table_entries =
11036 		l->action_is_for_table_entries[learner_action_id];
11037 
11038 	learner_action->action_is_for_default_entry =
11039 		l->action_is_for_default_entry[learner_action_id];
11040 
11041 	return 0;
11042 }
11043 
11044 int
rte_swx_ctl_pipeline_learner_timeout_get(struct rte_swx_pipeline * p,uint32_t learner_id,uint32_t timeout_id,uint32_t * timeout)11045 rte_swx_ctl_pipeline_learner_timeout_get(struct rte_swx_pipeline *p,
11046 					 uint32_t learner_id,
11047 					 uint32_t timeout_id,
11048 					 uint32_t *timeout)
11049 {
11050 	struct learner *l;
11051 
11052 	if (!p || (learner_id >= p->n_learners) || !timeout)
11053 		return -EINVAL;
11054 
11055 	l = learner_find_by_id(p, learner_id);
11056 	if (!l || (timeout_id >= l->n_timeouts))
11057 		return -EINVAL;
11058 
11059 	*timeout = l->timeout[timeout_id];
11060 	return 0;
11061 }
11062 
11063 int
rte_swx_ctl_pipeline_learner_timeout_set(struct rte_swx_pipeline * p,uint32_t learner_id,uint32_t timeout_id,uint32_t timeout)11064 rte_swx_ctl_pipeline_learner_timeout_set(struct rte_swx_pipeline *p,
11065 					 uint32_t learner_id,
11066 					 uint32_t timeout_id,
11067 					 uint32_t timeout)
11068 {
11069 	struct learner *l;
11070 	struct rte_swx_table_state *ts;
11071 	int status;
11072 
11073 	if (!p || (learner_id >= p->n_learners) || !timeout)
11074 		return -EINVAL;
11075 
11076 	l = learner_find_by_id(p, learner_id);
11077 	if (!l || (timeout_id >= l->n_timeouts))
11078 		return -EINVAL;
11079 
11080 	if (!p->build_done)
11081 		return -EINVAL;
11082 
11083 	ts = &p->table_state[p->n_tables + p->n_selectors + l->id];
11084 
11085 	status = rte_swx_table_learner_timeout_update(ts->obj, timeout_id, timeout);
11086 	if (status)
11087 		return -EINVAL;
11088 
11089 	l->timeout[timeout_id] = timeout;
11090 
11091 	return 0;
11092 }
11093 
11094 int
rte_swx_pipeline_table_state_get(struct rte_swx_pipeline * p,struct rte_swx_table_state ** table_state)11095 rte_swx_pipeline_table_state_get(struct rte_swx_pipeline *p,
11096 				 struct rte_swx_table_state **table_state)
11097 {
11098 	if (!p || !table_state || !p->build_done)
11099 		return -EINVAL;
11100 
11101 	*table_state = p->table_state;
11102 	return 0;
11103 }
11104 
11105 int
rte_swx_pipeline_table_state_set(struct rte_swx_pipeline * p,struct rte_swx_table_state * table_state)11106 rte_swx_pipeline_table_state_set(struct rte_swx_pipeline *p,
11107 				 struct rte_swx_table_state *table_state)
11108 {
11109 	if (!p || !table_state || !p->build_done)
11110 		return -EINVAL;
11111 
11112 	p->table_state = table_state;
11113 	return 0;
11114 }
11115 
11116 int
rte_swx_ctl_pipeline_port_in_stats_read(struct rte_swx_pipeline * p,uint32_t port_id,struct rte_swx_port_in_stats * stats)11117 rte_swx_ctl_pipeline_port_in_stats_read(struct rte_swx_pipeline *p,
11118 					uint32_t port_id,
11119 					struct rte_swx_port_in_stats *stats)
11120 {
11121 	struct port_in *port;
11122 
11123 	if (!p || !stats)
11124 		return -EINVAL;
11125 
11126 	port = port_in_find(p, port_id);
11127 	if (!port)
11128 		return -EINVAL;
11129 
11130 	port->type->ops.stats_read(port->obj, stats);
11131 	return 0;
11132 }
11133 
11134 int
rte_swx_ctl_pipeline_port_out_stats_read(struct rte_swx_pipeline * p,uint32_t port_id,struct rte_swx_port_out_stats * stats)11135 rte_swx_ctl_pipeline_port_out_stats_read(struct rte_swx_pipeline *p,
11136 					 uint32_t port_id,
11137 					 struct rte_swx_port_out_stats *stats)
11138 {
11139 	struct port_out *port;
11140 
11141 	if (!p || !stats)
11142 		return -EINVAL;
11143 
11144 	port = port_out_find(p, port_id);
11145 	if (!port)
11146 		return -EINVAL;
11147 
11148 	port->type->ops.stats_read(port->obj, stats);
11149 	return 0;
11150 }
11151 
11152 int
rte_swx_ctl_pipeline_table_stats_read(struct rte_swx_pipeline * p,const char * table_name,struct rte_swx_table_stats * stats)11153 rte_swx_ctl_pipeline_table_stats_read(struct rte_swx_pipeline *p,
11154 				      const char *table_name,
11155 				      struct rte_swx_table_stats *stats)
11156 {
11157 	struct table *table;
11158 	struct table_statistics *table_stats;
11159 
11160 	if (!p || !table_name || !table_name[0] || !stats || !stats->n_pkts_action)
11161 		return -EINVAL;
11162 
11163 	table = table_find(p, table_name);
11164 	if (!table)
11165 		return -EINVAL;
11166 
11167 	table_stats = &p->table_stats[table->id];
11168 
11169 	memcpy(stats->n_pkts_action,
11170 	       table_stats->n_pkts_action,
11171 	       p->n_actions * sizeof(uint64_t));
11172 
11173 	stats->n_pkts_hit = table_stats->n_pkts_hit[1];
11174 	stats->n_pkts_miss = table_stats->n_pkts_hit[0];
11175 
11176 	return 0;
11177 }
11178 
11179 int
rte_swx_ctl_pipeline_selector_stats_read(struct rte_swx_pipeline * p,const char * selector_name,struct rte_swx_pipeline_selector_stats * stats)11180 rte_swx_ctl_pipeline_selector_stats_read(struct rte_swx_pipeline *p,
11181 	const char *selector_name,
11182 	struct rte_swx_pipeline_selector_stats *stats)
11183 {
11184 	struct selector *s;
11185 
11186 	if (!p || !selector_name || !selector_name[0] || !stats)
11187 		return -EINVAL;
11188 
11189 	s = selector_find(p, selector_name);
11190 	if (!s)
11191 		return -EINVAL;
11192 
11193 	stats->n_pkts = p->selector_stats[s->id].n_pkts;
11194 
11195 	return 0;
11196 }
11197 
11198 int
rte_swx_ctl_pipeline_learner_stats_read(struct rte_swx_pipeline * p,const char * learner_name,struct rte_swx_learner_stats * stats)11199 rte_swx_ctl_pipeline_learner_stats_read(struct rte_swx_pipeline *p,
11200 					const char *learner_name,
11201 					struct rte_swx_learner_stats *stats)
11202 {
11203 	struct learner *l;
11204 	struct learner_statistics *learner_stats;
11205 
11206 	if (!p || !learner_name || !learner_name[0] || !stats || !stats->n_pkts_action)
11207 		return -EINVAL;
11208 
11209 	l = learner_find(p, learner_name);
11210 	if (!l)
11211 		return -EINVAL;
11212 
11213 	learner_stats = &p->learner_stats[l->id];
11214 
11215 	memcpy(stats->n_pkts_action,
11216 	       learner_stats->n_pkts_action,
11217 	       p->n_actions * sizeof(uint64_t));
11218 
11219 	stats->n_pkts_hit = learner_stats->n_pkts_hit[1];
11220 	stats->n_pkts_miss = learner_stats->n_pkts_hit[0];
11221 
11222 	stats->n_pkts_learn_ok = learner_stats->n_pkts_learn[0];
11223 	stats->n_pkts_learn_err = learner_stats->n_pkts_learn[1];
11224 
11225 	stats->n_pkts_rearm = learner_stats->n_pkts_rearm;
11226 	stats->n_pkts_forget = learner_stats->n_pkts_forget;
11227 
11228 	return 0;
11229 }
11230 
11231 int
rte_swx_ctl_regarray_info_get(struct rte_swx_pipeline * p,uint32_t regarray_id,struct rte_swx_ctl_regarray_info * regarray)11232 rte_swx_ctl_regarray_info_get(struct rte_swx_pipeline *p,
11233 			      uint32_t regarray_id,
11234 			      struct rte_swx_ctl_regarray_info *regarray)
11235 {
11236 	struct regarray *r;
11237 
11238 	if (!p || !regarray)
11239 		return -EINVAL;
11240 
11241 	r = regarray_find_by_id(p, regarray_id);
11242 	if (!r)
11243 		return -EINVAL;
11244 
11245 	strcpy(regarray->name, r->name);
11246 	regarray->size = r->size;
11247 	return 0;
11248 }
11249 
11250 int
rte_swx_ctl_pipeline_regarray_read(struct rte_swx_pipeline * p,const char * regarray_name,uint32_t regarray_index,uint64_t * value)11251 rte_swx_ctl_pipeline_regarray_read(struct rte_swx_pipeline *p,
11252 				   const char *regarray_name,
11253 				   uint32_t regarray_index,
11254 				   uint64_t *value)
11255 {
11256 	struct regarray *regarray;
11257 	struct regarray_runtime *r;
11258 
11259 	if (!p || !regarray_name || !value)
11260 		return -EINVAL;
11261 
11262 	regarray = regarray_find(p, regarray_name);
11263 	if (!regarray || (regarray_index >= regarray->size))
11264 		return -EINVAL;
11265 
11266 	r = &p->regarray_runtime[regarray->id];
11267 	*value = r->regarray[regarray_index];
11268 	return 0;
11269 }
11270 
11271 int
rte_swx_ctl_pipeline_regarray_write(struct rte_swx_pipeline * p,const char * regarray_name,uint32_t regarray_index,uint64_t value)11272 rte_swx_ctl_pipeline_regarray_write(struct rte_swx_pipeline *p,
11273 				   const char *regarray_name,
11274 				   uint32_t regarray_index,
11275 				   uint64_t value)
11276 {
11277 	struct regarray *regarray;
11278 	struct regarray_runtime *r;
11279 
11280 	if (!p || !regarray_name)
11281 		return -EINVAL;
11282 
11283 	regarray = regarray_find(p, regarray_name);
11284 	if (!regarray || (regarray_index >= regarray->size))
11285 		return -EINVAL;
11286 
11287 	r = &p->regarray_runtime[regarray->id];
11288 	r->regarray[regarray_index] = value;
11289 	return 0;
11290 }
11291 
11292 int
rte_swx_ctl_metarray_info_get(struct rte_swx_pipeline * p,uint32_t metarray_id,struct rte_swx_ctl_metarray_info * metarray)11293 rte_swx_ctl_metarray_info_get(struct rte_swx_pipeline *p,
11294 			      uint32_t metarray_id,
11295 			      struct rte_swx_ctl_metarray_info *metarray)
11296 {
11297 	struct metarray *m;
11298 
11299 	if (!p || !metarray)
11300 		return -EINVAL;
11301 
11302 	m = metarray_find_by_id(p, metarray_id);
11303 	if (!m)
11304 		return -EINVAL;
11305 
11306 	strcpy(metarray->name, m->name);
11307 	metarray->size = m->size;
11308 	return 0;
11309 }
11310 
11311 int
rte_swx_ctl_meter_profile_add(struct rte_swx_pipeline * p,const char * name,struct rte_meter_trtcm_params * params)11312 rte_swx_ctl_meter_profile_add(struct rte_swx_pipeline *p,
11313 			      const char *name,
11314 			      struct rte_meter_trtcm_params *params)
11315 {
11316 	struct meter_profile *mp;
11317 	int status;
11318 
11319 	CHECK(p, EINVAL);
11320 	CHECK_NAME(name, EINVAL);
11321 	CHECK(params, EINVAL);
11322 	CHECK(!meter_profile_find(p, name), EEXIST);
11323 
11324 	/* Node allocation. */
11325 	mp = calloc(1, sizeof(struct meter_profile));
11326 	CHECK(mp, ENOMEM);
11327 
11328 	/* Node initialization. */
11329 	strcpy(mp->name, name);
11330 	memcpy(&mp->params, params, sizeof(struct rte_meter_trtcm_params));
11331 	status = rte_meter_trtcm_profile_config(&mp->profile, params);
11332 	if (status) {
11333 		free(mp);
11334 		CHECK(0, EINVAL);
11335 	}
11336 
11337 	/* Node add to tailq. */
11338 	TAILQ_INSERT_TAIL(&p->meter_profiles, mp, node);
11339 
11340 	return 0;
11341 }
11342 
11343 int
rte_swx_ctl_meter_profile_delete(struct rte_swx_pipeline * p,const char * name)11344 rte_swx_ctl_meter_profile_delete(struct rte_swx_pipeline *p,
11345 				 const char *name)
11346 {
11347 	struct meter_profile *mp;
11348 
11349 	CHECK(p, EINVAL);
11350 	CHECK_NAME(name, EINVAL);
11351 
11352 	mp = meter_profile_find(p, name);
11353 	CHECK(mp, EINVAL);
11354 	CHECK(!mp->n_users, EBUSY);
11355 
11356 	/* Remove node from tailq. */
11357 	TAILQ_REMOVE(&p->meter_profiles, mp, node);
11358 	free(mp);
11359 
11360 	return 0;
11361 }
11362 
11363 int
rte_swx_ctl_meter_reset(struct rte_swx_pipeline * p,const char * metarray_name,uint32_t metarray_index)11364 rte_swx_ctl_meter_reset(struct rte_swx_pipeline *p,
11365 			const char *metarray_name,
11366 			uint32_t metarray_index)
11367 {
11368 	struct meter_profile *mp_old;
11369 	struct metarray *metarray;
11370 	struct metarray_runtime *metarray_runtime;
11371 	struct meter *m;
11372 
11373 	CHECK(p, EINVAL);
11374 	CHECK_NAME(metarray_name, EINVAL);
11375 
11376 	metarray = metarray_find(p, metarray_name);
11377 	CHECK(metarray, EINVAL);
11378 	CHECK(metarray_index < metarray->size, EINVAL);
11379 
11380 	metarray_runtime = &p->metarray_runtime[metarray->id];
11381 	m = &metarray_runtime->metarray[metarray_index];
11382 	mp_old = m->profile;
11383 
11384 	meter_init(m);
11385 
11386 	mp_old->n_users--;
11387 
11388 	return 0;
11389 }
11390 
11391 int
rte_swx_ctl_meter_set(struct rte_swx_pipeline * p,const char * metarray_name,uint32_t metarray_index,const char * profile_name)11392 rte_swx_ctl_meter_set(struct rte_swx_pipeline *p,
11393 		      const char *metarray_name,
11394 		      uint32_t metarray_index,
11395 		      const char *profile_name)
11396 {
11397 	struct meter_profile *mp, *mp_old;
11398 	struct metarray *metarray;
11399 	struct metarray_runtime *metarray_runtime;
11400 	struct meter *m;
11401 
11402 	CHECK(p, EINVAL);
11403 	CHECK_NAME(metarray_name, EINVAL);
11404 
11405 	metarray = metarray_find(p, metarray_name);
11406 	CHECK(metarray, EINVAL);
11407 	CHECK(metarray_index < metarray->size, EINVAL);
11408 
11409 	mp = meter_profile_find(p, profile_name);
11410 	CHECK(mp, EINVAL);
11411 
11412 	metarray_runtime = &p->metarray_runtime[metarray->id];
11413 	m = &metarray_runtime->metarray[metarray_index];
11414 	mp_old = m->profile;
11415 
11416 	memset(m, 0, sizeof(struct meter));
11417 	rte_meter_trtcm_config(&m->m, &mp->profile);
11418 	m->profile = mp;
11419 	m->color_mask = RTE_COLORS;
11420 
11421 	mp->n_users++;
11422 	mp_old->n_users--;
11423 
11424 	return 0;
11425 }
11426 
11427 int
rte_swx_ctl_meter_stats_read(struct rte_swx_pipeline * p,const char * metarray_name,uint32_t metarray_index,struct rte_swx_ctl_meter_stats * stats)11428 rte_swx_ctl_meter_stats_read(struct rte_swx_pipeline *p,
11429 			     const char *metarray_name,
11430 			     uint32_t metarray_index,
11431 			     struct rte_swx_ctl_meter_stats *stats)
11432 {
11433 	struct metarray *metarray;
11434 	struct metarray_runtime *metarray_runtime;
11435 	struct meter *m;
11436 
11437 	CHECK(p, EINVAL);
11438 	CHECK_NAME(metarray_name, EINVAL);
11439 
11440 	metarray = metarray_find(p, metarray_name);
11441 	CHECK(metarray, EINVAL);
11442 	CHECK(metarray_index < metarray->size, EINVAL);
11443 
11444 	CHECK(stats, EINVAL);
11445 
11446 	metarray_runtime = &p->metarray_runtime[metarray->id];
11447 	m = &metarray_runtime->metarray[metarray_index];
11448 
11449 	memcpy(stats->n_pkts, m->n_pkts, sizeof(m->n_pkts));
11450 	memcpy(stats->n_bytes, m->n_bytes, sizeof(m->n_bytes));
11451 
11452 	return 0;
11453 }
11454 
11455 int
rte_swx_ctl_pipeline_mirroring_session_set(struct rte_swx_pipeline * p,uint32_t session_id,struct rte_swx_pipeline_mirroring_session_params * params)11456 rte_swx_ctl_pipeline_mirroring_session_set(struct rte_swx_pipeline *p,
11457 					   uint32_t session_id,
11458 					   struct rte_swx_pipeline_mirroring_session_params *params)
11459 {
11460 	struct mirroring_session *s;
11461 
11462 	CHECK(p, EINVAL);
11463 	CHECK(p->build_done, EEXIST);
11464 	CHECK(session_id < p->n_mirroring_sessions, EINVAL);
11465 	CHECK(params, EINVAL);
11466 	CHECK(params->port_id < p->n_ports_out, EINVAL);
11467 
11468 	s = &p->mirroring_sessions[session_id];
11469 	s->port_id = params->port_id;
11470 	s->fast_clone = params->fast_clone;
11471 	s->truncation_length = params->truncation_length ? params->truncation_length : UINT32_MAX;
11472 
11473 	return 0;
11474 }
11475 
11476 static int
rte_swx_ctl_pipeline_table_lookup(struct rte_swx_pipeline * p,const char * table_name,uint8_t * key,uint64_t * action_id,uint8_t ** action_data,size_t * entry_id,int * hit)11477 rte_swx_ctl_pipeline_table_lookup(struct rte_swx_pipeline *p,
11478 				  const char *table_name,
11479 				  uint8_t *key,
11480 				  uint64_t *action_id,
11481 				  uint8_t **action_data,
11482 				  size_t *entry_id,
11483 				  int *hit)
11484 {
11485 	struct table *t;
11486 	void *mailbox = NULL;
11487 
11488 	/* Check input arguments. */
11489 	if (!p ||
11490 	    !p->build_done ||
11491 	    !table_name ||
11492 	    !table_name[0] ||
11493 	    !key ||
11494 	    !entry_id ||
11495 	    !hit)
11496 		return -EINVAL;
11497 
11498 	/* Find the table. */
11499 	t = table_find(p, table_name);
11500 	if (!t)
11501 		return -EINVAL;
11502 
11503 	if (!t->type) {
11504 		*hit = 0;
11505 		return 0;
11506 	}
11507 
11508 	/* Setup mailbox.  */
11509 	if (t->type->ops.mailbox_size_get) {
11510 		uint64_t mailbox_size;
11511 
11512 		mailbox_size = t->type->ops.mailbox_size_get();
11513 		if (mailbox_size) {
11514 			mailbox = calloc(1, mailbox_size);
11515 			if (!mailbox)
11516 				return -ENOMEM;
11517 		}
11518 	}
11519 
11520 	/* Table lookup operation. */
11521 	key -= table_params_offset_get(t);
11522 
11523 	for ( ; ; ) {
11524 		struct rte_swx_table_state *ts = &p->table_state[t->id];
11525 		int done;
11526 
11527 		done = t->type->ops.lkp(ts->obj,
11528 					mailbox,
11529 					&key,
11530 					action_id,
11531 					action_data,
11532 					entry_id,
11533 					hit);
11534 		if (done)
11535 			break;
11536 	}
11537 
11538 	/* Free mailbox. */
11539 	free(mailbox);
11540 
11541 	return 0;
11542 }
11543 
11544 static int
rte_swx_ctl_pipeline_learner_lookup(struct rte_swx_pipeline * p,const char * learner_name,uint8_t * key,uint64_t * action_id,uint8_t ** action_data,size_t * entry_id,int * hit)11545 rte_swx_ctl_pipeline_learner_lookup(struct rte_swx_pipeline *p,
11546 				    const char *learner_name,
11547 				    uint8_t *key,
11548 				    uint64_t *action_id,
11549 				    uint8_t **action_data,
11550 				    size_t *entry_id,
11551 				    int *hit)
11552 {
11553 	struct learner *l;
11554 	void *mailbox = NULL;
11555 	uint64_t mailbox_size, time;
11556 
11557 	/* Check input arguments. */
11558 	if (!p ||
11559 	    !p->build_done ||
11560 	    !learner_name ||
11561 	    !learner_name[0] ||
11562 	    !key ||
11563 	    !entry_id ||
11564 	    !hit)
11565 		return -EINVAL;
11566 
11567 	/* Find the learner table. */
11568 	l = learner_find(p, learner_name);
11569 	if (!l)
11570 		return -EINVAL;
11571 
11572 	/* Setup mailbox.  */
11573 	mailbox_size = rte_swx_table_learner_mailbox_size_get();
11574 	if (mailbox_size) {
11575 		mailbox = calloc(1, mailbox_size);
11576 		if (!mailbox)
11577 			return -ENOMEM;
11578 	}
11579 
11580 	/* Learner table lookup operation. */
11581 	key -= learner_params_offset_get(l);
11582 
11583 	time = rte_get_tsc_cycles();
11584 
11585 	for ( ; ; ) {
11586 		uint32_t pos = p->n_tables + p->n_selectors + l->id;
11587 		struct rte_swx_table_state *ts = &p->table_state[pos];
11588 		int done;
11589 
11590 		done = rte_swx_table_learner_lookup(ts->obj,
11591 						    mailbox,
11592 						    time,
11593 						    &key,
11594 						    action_id,
11595 						    action_data,
11596 						    entry_id,
11597 						    hit);
11598 		if (done)
11599 			break;
11600 	}
11601 
11602 	/* Free mailbox. */
11603 	free(mailbox);
11604 
11605 	return 0;
11606 }
11607 
11608 static int
rte_swx_ctl_pipeline_table_entry_id_get(struct rte_swx_pipeline * p,const char * table_name,uint8_t * table_key,size_t * table_entry_id)11609 rte_swx_ctl_pipeline_table_entry_id_get(struct rte_swx_pipeline *p,
11610 					const char *table_name,
11611 					uint8_t *table_key,
11612 					size_t *table_entry_id)
11613 {
11614 	struct table *t;
11615 	struct learner *l;
11616 	uint64_t action_id;
11617 	uint8_t *action_data;
11618 	size_t entry_id = 0;
11619 	int hit = 0, status;
11620 
11621 	/* Check input arguments. */
11622 	if (!p ||
11623 	    !p->build_done ||
11624 	    !table_name ||
11625 	    !table_name[0] ||
11626 	    !table_key ||
11627 	    !table_entry_id)
11628 		return -EINVAL;
11629 
11630 	t = table_find(p, table_name);
11631 	l = learner_find(p, table_name);
11632 	if (!t && !l)
11633 		return -EINVAL;
11634 
11635 	/* Table lookup operation. */
11636 	if (t)
11637 		status = rte_swx_ctl_pipeline_table_lookup(p,
11638 							   table_name,
11639 							   table_key,
11640 							   &action_id,
11641 							   &action_data,
11642 							   &entry_id,
11643 							   &hit);
11644 	else
11645 		status = rte_swx_ctl_pipeline_learner_lookup(p,
11646 							     table_name,
11647 							     table_key,
11648 							     &action_id,
11649 							     &action_data,
11650 							     &entry_id,
11651 							     &hit);
11652 	if (status)
11653 		return status;
11654 
11655 	/* Reserve entry ID 0 for the table default entry. */
11656 	*table_entry_id = hit ? (1 + entry_id) : 0;
11657 
11658 	return 0;
11659 }
11660 
11661 int
rte_swx_ctl_pipeline_regarray_read_with_key(struct rte_swx_pipeline * p,const char * regarray_name,const char * table_name,uint8_t * table_key,uint64_t * value)11662 rte_swx_ctl_pipeline_regarray_read_with_key(struct rte_swx_pipeline *p,
11663 					    const char *regarray_name,
11664 					    const char *table_name,
11665 					    uint8_t *table_key,
11666 					    uint64_t *value)
11667 {
11668 	size_t entry_id = 0;
11669 	int status;
11670 
11671 	status = rte_swx_ctl_pipeline_table_entry_id_get(p, table_name, table_key, &entry_id);
11672 	if (status)
11673 		return status;
11674 
11675 	return rte_swx_ctl_pipeline_regarray_read(p, regarray_name, entry_id, value);
11676 }
11677 
11678 int
rte_swx_ctl_pipeline_regarray_write_with_key(struct rte_swx_pipeline * p,const char * regarray_name,const char * table_name,uint8_t * table_key,uint64_t value)11679 rte_swx_ctl_pipeline_regarray_write_with_key(struct rte_swx_pipeline *p,
11680 					     const char *regarray_name,
11681 					     const char *table_name,
11682 					     uint8_t *table_key,
11683 					     uint64_t value)
11684 {
11685 	size_t entry_id = 0;
11686 	int status;
11687 
11688 	status = rte_swx_ctl_pipeline_table_entry_id_get(p, table_name, table_key, &entry_id);
11689 	if (status)
11690 		return status;
11691 
11692 	return rte_swx_ctl_pipeline_regarray_write(p, regarray_name, entry_id, value);
11693 }
11694 
11695 int
rte_swx_ctl_meter_reset_with_key(struct rte_swx_pipeline * p,const char * metarray_name,const char * table_name,uint8_t * table_key)11696 rte_swx_ctl_meter_reset_with_key(struct rte_swx_pipeline *p,
11697 				 const char *metarray_name,
11698 				 const char *table_name,
11699 				 uint8_t *table_key)
11700 {
11701 	size_t entry_id = 0;
11702 	int status;
11703 
11704 	status = rte_swx_ctl_pipeline_table_entry_id_get(p, table_name, table_key, &entry_id);
11705 	if (status)
11706 		return status;
11707 
11708 	return rte_swx_ctl_meter_reset(p, metarray_name, entry_id);
11709 }
11710 
11711 int
rte_swx_ctl_meter_set_with_key(struct rte_swx_pipeline * p,const char * metarray_name,const char * table_name,uint8_t * table_key,const char * profile_name)11712 rte_swx_ctl_meter_set_with_key(struct rte_swx_pipeline *p,
11713 			       const char *metarray_name,
11714 			       const char *table_name,
11715 			       uint8_t *table_key,
11716 			       const char *profile_name)
11717 {
11718 	size_t entry_id = 0;
11719 	int status;
11720 
11721 	status = rte_swx_ctl_pipeline_table_entry_id_get(p, table_name, table_key, &entry_id);
11722 	if (status)
11723 		return status;
11724 
11725 	return rte_swx_ctl_meter_set(p, metarray_name, entry_id, profile_name);
11726 }
11727 
11728 int
rte_swx_ctl_meter_stats_read_with_key(struct rte_swx_pipeline * p,const char * metarray_name,const char * table_name,uint8_t * table_key,struct rte_swx_ctl_meter_stats * stats)11729 rte_swx_ctl_meter_stats_read_with_key(struct rte_swx_pipeline *p,
11730 				      const char *metarray_name,
11731 				      const char *table_name,
11732 				      uint8_t *table_key,
11733 				      struct rte_swx_ctl_meter_stats *stats)
11734 {
11735 	size_t entry_id = 0;
11736 	int status;
11737 
11738 	status = rte_swx_ctl_pipeline_table_entry_id_get(p, table_name, table_key, &entry_id);
11739 	if (status)
11740 		return status;
11741 
11742 	return rte_swx_ctl_meter_stats_read(p, metarray_name, entry_id, stats);
11743 }
11744 
11745 int
rte_swx_ctl_rss_info_get(struct rte_swx_pipeline * p,uint32_t rss_obj_id,struct rte_swx_ctl_rss_info * info)11746 rte_swx_ctl_rss_info_get(struct rte_swx_pipeline *p,
11747 			 uint32_t rss_obj_id,
11748 			 struct rte_swx_ctl_rss_info *info)
11749 {
11750 	struct rss *rss;
11751 
11752 	/* Check the input arguments. */
11753 	if (!p || !info)
11754 		return -EINVAL;
11755 
11756 	rss = rss_find_by_id(p, rss_obj_id);
11757 	if (!rss)
11758 		return -EINVAL;
11759 
11760 	/* Read from the internal data structures. */
11761 	strcpy(info->name, rss->name);
11762 	return 0;
11763 }
11764 
11765 int
rte_swx_ctl_pipeline_rss_key_size_read(struct rte_swx_pipeline * p,const char * rss_name,uint32_t * key_size)11766 rte_swx_ctl_pipeline_rss_key_size_read(struct rte_swx_pipeline *p,
11767 				       const char *rss_name,
11768 				       uint32_t *key_size)
11769 {
11770 	struct rss *rss;
11771 	struct rss_runtime *r;
11772 
11773 	/* Check the input arguments. */
11774 	CHECK(p, EINVAL);
11775 
11776 	CHECK_NAME(rss_name, EINVAL);
11777 	rss = rss_find(p, rss_name);
11778 	CHECK(rss, EINVAL);
11779 	r = p->rss_runtime[rss->id];
11780 
11781 	CHECK(key_size, EINVAL);
11782 
11783 	/* Read from the internal data structures. */
11784 	*key_size = r->key_size;
11785 
11786 	return 0;
11787 }
11788 
11789 int
rte_swx_ctl_pipeline_rss_key_read(struct rte_swx_pipeline * p,const char * rss_name,uint8_t * key)11790 rte_swx_ctl_pipeline_rss_key_read(struct rte_swx_pipeline *p,
11791 				  const char *rss_name,
11792 				  uint8_t *key)
11793 {
11794 	struct rss *rss;
11795 	struct rss_runtime *r;
11796 
11797 	/* Check the input arguments. */
11798 	CHECK(p, EINVAL);
11799 
11800 	CHECK_NAME(rss_name, EINVAL);
11801 	rss = rss_find(p, rss_name);
11802 	CHECK(rss, EINVAL);
11803 	r = p->rss_runtime[rss->id];
11804 
11805 	CHECK(key, EINVAL);
11806 
11807 	/* Read from the internal data structures. */
11808 	memcpy(key, r->key, r->key_size);
11809 
11810 	return 0;
11811 }
11812 
11813 int
rte_swx_ctl_pipeline_rss_key_write(struct rte_swx_pipeline * p,const char * rss_name,uint32_t key_size,uint8_t * key)11814 rte_swx_ctl_pipeline_rss_key_write(struct rte_swx_pipeline *p,
11815 				   const char *rss_name,
11816 				   uint32_t key_size,
11817 				   uint8_t *key)
11818 {
11819 	struct rss *rss;
11820 	struct rss_runtime *r, *r_new;
11821 
11822 	/* Check the input arguments. */
11823 	CHECK(p, EINVAL);
11824 
11825 	CHECK_NAME(rss_name, EINVAL);
11826 	rss = rss_find(p, rss_name);
11827 	CHECK(rss, EINVAL);
11828 	r = p->rss_runtime[rss->id];
11829 
11830 	CHECK(key_size >= 4, EINVAL);
11831 	CHECK(key, EINVAL);
11832 
11833 	/* Allocate new RSS run-time entry. */
11834 	r_new = malloc(sizeof(struct rss_runtime) + key_size * sizeof(uint32_t));
11835 	if (!r_new)
11836 		return -ENOMEM;
11837 
11838 	/* Fill in the new RSS run-time entry. */
11839 	r_new->key_size = key_size;
11840 	memcpy(r_new->key, key, key_size);
11841 
11842 	/* Commit the RSS run-time change atomically. */
11843 	p->rss_runtime[rss->id] = r_new;
11844 
11845 	/* Free the old RSS run-time entry. */
11846 	free(r);
11847 
11848 	return 0;
11849 }
11850 
11851 /*
11852  * Pipeline compilation.
11853  */
11854 static const char *
instr_type_to_name(struct instruction * instr)11855 instr_type_to_name(struct instruction *instr)
11856 {
11857 	switch (instr->type) {
11858 	case INSTR_RX: return "INSTR_RX";
11859 
11860 	case INSTR_TX: return "INSTR_TX";
11861 	case INSTR_TX_I: return "INSTR_TX_I";
11862 	case INSTR_DROP: return "INSTR_DROP";
11863 	case INSTR_MIRROR: return "INSTR_MIRROR";
11864 	case INSTR_RECIRCULATE: return "INSTR_RECIRCULATE";
11865 	case INSTR_RECIRCID: return "INSTR_RECIRCID";
11866 
11867 	case INSTR_HDR_EXTRACT: return "INSTR_HDR_EXTRACT";
11868 	case INSTR_HDR_EXTRACT2: return "INSTR_HDR_EXTRACT2";
11869 	case INSTR_HDR_EXTRACT3: return "INSTR_HDR_EXTRACT3";
11870 	case INSTR_HDR_EXTRACT4: return "INSTR_HDR_EXTRACT4";
11871 	case INSTR_HDR_EXTRACT5: return "INSTR_HDR_EXTRACT5";
11872 	case INSTR_HDR_EXTRACT6: return "INSTR_HDR_EXTRACT6";
11873 	case INSTR_HDR_EXTRACT7: return "INSTR_HDR_EXTRACT7";
11874 	case INSTR_HDR_EXTRACT8: return "INSTR_HDR_EXTRACT8";
11875 
11876 	case INSTR_HDR_EXTRACT_M: return "INSTR_HDR_EXTRACT_M";
11877 
11878 	case INSTR_HDR_LOOKAHEAD: return "INSTR_HDR_LOOKAHEAD";
11879 
11880 	case INSTR_HDR_EMIT: return "INSTR_HDR_EMIT";
11881 	case INSTR_HDR_EMIT_TX: return "INSTR_HDR_EMIT_TX";
11882 	case INSTR_HDR_EMIT2_TX: return "INSTR_HDR_EMIT2_TX";
11883 	case INSTR_HDR_EMIT3_TX: return "INSTR_HDR_EMIT3_TX";
11884 	case INSTR_HDR_EMIT4_TX: return "INSTR_HDR_EMIT4_TX";
11885 	case INSTR_HDR_EMIT5_TX: return "INSTR_HDR_EMIT5_TX";
11886 	case INSTR_HDR_EMIT6_TX: return "INSTR_HDR_EMIT6_TX";
11887 	case INSTR_HDR_EMIT7_TX: return "INSTR_HDR_EMIT7_TX";
11888 	case INSTR_HDR_EMIT8_TX: return "INSTR_HDR_EMIT8_TX";
11889 
11890 	case INSTR_HDR_VALIDATE: return "INSTR_HDR_VALIDATE";
11891 	case INSTR_HDR_INVALIDATE: return "INSTR_HDR_INVALIDATE";
11892 
11893 	case INSTR_MOV: return "INSTR_MOV";
11894 	case INSTR_MOV_MH: return "INSTR_MOV_MH";
11895 	case INSTR_MOV_HM: return "INSTR_MOV_HM";
11896 	case INSTR_MOV_HH: return "INSTR_MOV_HH";
11897 	case INSTR_MOV_DMA: return "INSTR_MOV_DMA";
11898 	case INSTR_MOV_128: return "INSTR_MOV_128";
11899 	case INSTR_MOV_128_64: return "INSTR_MOV_128_64";
11900 	case INSTR_MOV_64_128: return "INSTR_MOV_64_128";
11901 	case INSTR_MOV_128_32: return "INSTR_MOV_128_32";
11902 	case INSTR_MOV_32_128: return "INSTR_MOV_32_128";
11903 	case INSTR_MOV_I: return "INSTR_MOV_I";
11904 
11905 	case INSTR_MOVH: return "INSTR_MOVH";
11906 
11907 	case INSTR_DMA_HT: return "INSTR_DMA_HT";
11908 	case INSTR_DMA_HT2: return "INSTR_DMA_HT2";
11909 	case INSTR_DMA_HT3: return "INSTR_DMA_HT3";
11910 	case INSTR_DMA_HT4: return "INSTR_DMA_HT4";
11911 	case INSTR_DMA_HT5: return "INSTR_DMA_HT5";
11912 	case INSTR_DMA_HT6: return "INSTR_DMA_HT6";
11913 	case INSTR_DMA_HT7: return "INSTR_DMA_HT7";
11914 	case INSTR_DMA_HT8: return "INSTR_DMA_HT8";
11915 
11916 	case INSTR_ALU_ADD: return "INSTR_ALU_ADD";
11917 	case INSTR_ALU_ADD_MH: return "INSTR_ALU_ADD_MH";
11918 	case INSTR_ALU_ADD_HM: return "INSTR_ALU_ADD_HM";
11919 	case INSTR_ALU_ADD_HH: return "INSTR_ALU_ADD_HH";
11920 	case INSTR_ALU_ADD_MI: return "INSTR_ALU_ADD_MI";
11921 	case INSTR_ALU_ADD_HI: return "INSTR_ALU_ADD_HI";
11922 
11923 	case INSTR_ALU_SUB: return "INSTR_ALU_SUB";
11924 	case INSTR_ALU_SUB_MH: return "INSTR_ALU_SUB_MH";
11925 	case INSTR_ALU_SUB_HM: return "INSTR_ALU_SUB_HM";
11926 	case INSTR_ALU_SUB_HH: return "INSTR_ALU_SUB_HH";
11927 	case INSTR_ALU_SUB_MI: return "INSTR_ALU_SUB_MI";
11928 	case INSTR_ALU_SUB_HI: return "INSTR_ALU_SUB_HI";
11929 
11930 	case INSTR_ALU_CKADD_FIELD: return "INSTR_ALU_CKADD_FIELD";
11931 	case INSTR_ALU_CKADD_STRUCT20: return "INSTR_ALU_CKADD_STRUCT20";
11932 	case INSTR_ALU_CKADD_STRUCT: return "INSTR_ALU_CKADD_STRUCT";
11933 	case INSTR_ALU_CKSUB_FIELD: return "INSTR_ALU_CKSUB_FIELD";
11934 
11935 	case INSTR_ALU_AND: return "INSTR_ALU_AND";
11936 	case INSTR_ALU_AND_MH: return "INSTR_ALU_AND_MH";
11937 	case INSTR_ALU_AND_HM: return "INSTR_ALU_AND_HM";
11938 	case INSTR_ALU_AND_HH: return "INSTR_ALU_AND_HH";
11939 	case INSTR_ALU_AND_I: return "INSTR_ALU_AND_I";
11940 
11941 	case INSTR_ALU_OR: return "INSTR_ALU_OR";
11942 	case INSTR_ALU_OR_MH: return "INSTR_ALU_OR_MH";
11943 	case INSTR_ALU_OR_HM: return "INSTR_ALU_OR_HM";
11944 	case INSTR_ALU_OR_HH: return "INSTR_ALU_OR_HH";
11945 	case INSTR_ALU_OR_I: return "INSTR_ALU_OR_I";
11946 
11947 	case INSTR_ALU_XOR: return "INSTR_ALU_XOR";
11948 	case INSTR_ALU_XOR_MH: return "INSTR_ALU_XOR_MH";
11949 	case INSTR_ALU_XOR_HM: return "INSTR_ALU_XOR_HM";
11950 	case INSTR_ALU_XOR_HH: return "INSTR_ALU_XOR_HH";
11951 	case INSTR_ALU_XOR_I: return "INSTR_ALU_XOR_I";
11952 
11953 	case INSTR_ALU_SHL: return "INSTR_ALU_SHL";
11954 	case INSTR_ALU_SHL_MH: return "INSTR_ALU_SHL_MH";
11955 	case INSTR_ALU_SHL_HM: return "INSTR_ALU_SHL_HM";
11956 	case INSTR_ALU_SHL_HH: return "INSTR_ALU_SHL_HH";
11957 	case INSTR_ALU_SHL_MI: return "INSTR_ALU_SHL_MI";
11958 	case INSTR_ALU_SHL_HI: return "INSTR_ALU_SHL_HI";
11959 
11960 	case INSTR_ALU_SHR: return "INSTR_ALU_SHR";
11961 	case INSTR_ALU_SHR_MH: return "INSTR_ALU_SHR_MH";
11962 	case INSTR_ALU_SHR_HM: return "INSTR_ALU_SHR_HM";
11963 	case INSTR_ALU_SHR_HH: return "INSTR_ALU_SHR_HH";
11964 	case INSTR_ALU_SHR_MI: return "INSTR_ALU_SHR_MI";
11965 	case INSTR_ALU_SHR_HI: return "INSTR_ALU_SHR_HI";
11966 
11967 	case INSTR_REGPREFETCH_RH: return "INSTR_REGPREFETCH_RH";
11968 	case INSTR_REGPREFETCH_RM: return "INSTR_REGPREFETCH_RM";
11969 	case INSTR_REGPREFETCH_RI: return "INSTR_REGPREFETCH_RI";
11970 
11971 	case INSTR_REGRD_HRH: return "INSTR_REGRD_HRH";
11972 	case INSTR_REGRD_HRM: return "INSTR_REGRD_HRM";
11973 	case INSTR_REGRD_HRI: return "INSTR_REGRD_HRI";
11974 	case INSTR_REGRD_MRH: return "INSTR_REGRD_MRH";
11975 	case INSTR_REGRD_MRM: return "INSTR_REGRD_MRM";
11976 	case INSTR_REGRD_MRI: return "INSTR_REGRD_MRI";
11977 
11978 	case INSTR_REGWR_RHH: return "INSTR_REGWR_RHH";
11979 	case INSTR_REGWR_RHM: return "INSTR_REGWR_RHM";
11980 	case INSTR_REGWR_RHI: return "INSTR_REGWR_RHI";
11981 	case INSTR_REGWR_RMH: return "INSTR_REGWR_RMH";
11982 	case INSTR_REGWR_RMM: return "INSTR_REGWR_RMM";
11983 	case INSTR_REGWR_RMI: return "INSTR_REGWR_RMI";
11984 	case INSTR_REGWR_RIH: return "INSTR_REGWR_RIH";
11985 	case INSTR_REGWR_RIM: return "INSTR_REGWR_RIM";
11986 	case INSTR_REGWR_RII: return "INSTR_REGWR_RII";
11987 
11988 	case INSTR_REGADD_RHH: return "INSTR_REGADD_RHH";
11989 	case INSTR_REGADD_RHM: return "INSTR_REGADD_RHM";
11990 	case INSTR_REGADD_RHI: return "INSTR_REGADD_RHI";
11991 	case INSTR_REGADD_RMH: return "INSTR_REGADD_RMH";
11992 	case INSTR_REGADD_RMM: return "INSTR_REGADD_RMM";
11993 	case INSTR_REGADD_RMI: return "INSTR_REGADD_RMI";
11994 	case INSTR_REGADD_RIH: return "INSTR_REGADD_RIH";
11995 	case INSTR_REGADD_RIM: return "INSTR_REGADD_RIM";
11996 	case INSTR_REGADD_RII: return "INSTR_REGADD_RII";
11997 
11998 	case INSTR_METPREFETCH_H: return "INSTR_METPREFETCH_H";
11999 	case INSTR_METPREFETCH_M: return "INSTR_METPREFETCH_M";
12000 	case INSTR_METPREFETCH_I: return "INSTR_METPREFETCH_I";
12001 
12002 	case INSTR_METER_HHM: return "INSTR_METER_HHM";
12003 	case INSTR_METER_HHI: return "INSTR_METER_HHI";
12004 	case INSTR_METER_HMM: return "INSTR_METER_HMM";
12005 	case INSTR_METER_HMI: return "INSTR_METER_HMI";
12006 	case INSTR_METER_MHM: return "INSTR_METER_MHM";
12007 	case INSTR_METER_MHI: return "INSTR_METER_MHI";
12008 	case INSTR_METER_MMM: return "INSTR_METER_MMM";
12009 	case INSTR_METER_MMI: return "INSTR_METER_MMI";
12010 	case INSTR_METER_IHM: return "INSTR_METER_IHM";
12011 	case INSTR_METER_IHI: return "INSTR_METER_IHI";
12012 	case INSTR_METER_IMM: return "INSTR_METER_IMM";
12013 	case INSTR_METER_IMI: return "INSTR_METER_IMI";
12014 
12015 	case INSTR_TABLE: return "INSTR_TABLE";
12016 	case INSTR_TABLE_AF: return "INSTR_TABLE_AF";
12017 	case INSTR_SELECTOR: return "INSTR_SELECTOR";
12018 	case INSTR_LEARNER: return "INSTR_LEARNER";
12019 	case INSTR_LEARNER_AF: return "INSTR_LEARNER_AF";
12020 
12021 	case INSTR_LEARNER_LEARN: return "INSTR_LEARNER_LEARN";
12022 	case INSTR_LEARNER_REARM: return "INSTR_LEARNER_REARM";
12023 	case INSTR_LEARNER_REARM_NEW: return "INSTR_LEARNER_REARM_NEW";
12024 	case INSTR_LEARNER_FORGET: return "INSTR_LEARNER_FORGET";
12025 	case INSTR_ENTRYID: return "INSTR_ENTRYID";
12026 
12027 	case INSTR_EXTERN_OBJ: return "INSTR_EXTERN_OBJ";
12028 	case INSTR_EXTERN_FUNC: return "INSTR_EXTERN_FUNC";
12029 	case INSTR_HASH_FUNC: return "INSTR_HASH_FUNC";
12030 	case INSTR_RSS: return "INSTR_RSS";
12031 
12032 	case INSTR_JMP: return "INSTR_JMP";
12033 	case INSTR_JMP_VALID: return "INSTR_JMP_VALID";
12034 	case INSTR_JMP_INVALID: return "INSTR_JMP_INVALID";
12035 	case INSTR_JMP_HIT: return "INSTR_JMP_HIT";
12036 	case INSTR_JMP_MISS: return "INSTR_JMP_MISS";
12037 	case INSTR_JMP_ACTION_HIT: return "INSTR_JMP_ACTION_HIT";
12038 	case INSTR_JMP_ACTION_MISS: return "INSTR_JMP_ACTION_MISS";
12039 	case INSTR_JMP_EQ: return "INSTR_JMP_EQ";
12040 	case INSTR_JMP_EQ_MH: return "INSTR_JMP_EQ_MH";
12041 	case INSTR_JMP_EQ_HM: return "INSTR_JMP_EQ_HM";
12042 	case INSTR_JMP_EQ_HH: return "INSTR_JMP_EQ_HH";
12043 	case INSTR_JMP_EQ_I: return "INSTR_JMP_EQ_I";
12044 	case INSTR_JMP_NEQ: return "INSTR_JMP_NEQ";
12045 	case INSTR_JMP_NEQ_MH: return "INSTR_JMP_NEQ_MH";
12046 	case INSTR_JMP_NEQ_HM: return "INSTR_JMP_NEQ_HM";
12047 	case INSTR_JMP_NEQ_HH: return "INSTR_JMP_NEQ_HH";
12048 	case INSTR_JMP_NEQ_I: return "INSTR_JMP_NEQ_I";
12049 	case INSTR_JMP_LT: return "INSTR_JMP_LT";
12050 	case INSTR_JMP_LT_MH: return "INSTR_JMP_LT_MH";
12051 	case INSTR_JMP_LT_HM: return "INSTR_JMP_LT_HM";
12052 	case INSTR_JMP_LT_HH: return "INSTR_JMP_LT_HH";
12053 	case INSTR_JMP_LT_MI: return "INSTR_JMP_LT_MI";
12054 	case INSTR_JMP_LT_HI: return "INSTR_JMP_LT_HI";
12055 	case INSTR_JMP_GT: return "INSTR_JMP_GT";
12056 	case INSTR_JMP_GT_MH: return "INSTR_JMP_GT_MH";
12057 	case INSTR_JMP_GT_HM: return "INSTR_JMP_GT_HM";
12058 	case INSTR_JMP_GT_HH: return "INSTR_JMP_GT_HH";
12059 	case INSTR_JMP_GT_MI: return "INSTR_JMP_GT_MI";
12060 	case INSTR_JMP_GT_HI: return "INSTR_JMP_GT_HI";
12061 
12062 	case INSTR_RETURN: return "INSTR_RETURN";
12063 
12064 	default: return "INSTR_UNKNOWN";
12065 	}
12066 }
12067 
12068 typedef void
12069 (*instruction_export_t)(struct instruction *, FILE *);
12070 
12071 static void
instr_io_export(struct instruction * instr,FILE * f)12072 instr_io_export(struct instruction *instr, FILE *f)
12073 {
12074 	uint32_t n_io = 0, n_io_imm = 0, n_hdrs = 0, i;
12075 
12076 	/* n_io, n_io_imm, n_hdrs. */
12077 	if (instr->type == INSTR_RX ||
12078 	    instr->type == INSTR_TX ||
12079 	    instr->type == INSTR_HDR_EXTRACT_M ||
12080 	    (instr->type >= INSTR_HDR_EMIT_TX && instr->type <= INSTR_HDR_EMIT8_TX))
12081 		n_io = 1;
12082 
12083 	if (instr->type == INSTR_TX_I)
12084 		n_io_imm = 1;
12085 
12086 	if (instr->type >= INSTR_HDR_EXTRACT && instr->type <= INSTR_HDR_EXTRACT8)
12087 		n_hdrs = 1 + (instr->type - INSTR_HDR_EXTRACT);
12088 
12089 	if (instr->type == INSTR_HDR_EXTRACT_M ||
12090 	    instr->type == INSTR_HDR_LOOKAHEAD ||
12091 	    instr->type == INSTR_HDR_EMIT)
12092 		n_hdrs = 1;
12093 
12094 	if (instr->type >= INSTR_HDR_EMIT_TX && instr->type <= INSTR_HDR_EMIT8_TX)
12095 		n_hdrs = 1 + (instr->type - INSTR_HDR_EMIT_TX);
12096 
12097 	/* instr. */
12098 	fprintf(f,
12099 		"\t{\n"
12100 		"\t\t.type = %s,\n",
12101 		instr_type_to_name(instr));
12102 
12103 	/* instr.io. */
12104 	if (n_io || n_io_imm || n_hdrs)
12105 		fprintf(f,
12106 			"\t\t.io = {\n");
12107 
12108 	/* instr.io.io. */
12109 	if (n_io)
12110 		fprintf(f,
12111 			"\t\t\t.io = {\n"
12112 			"\t\t\t\t.offset = %u,\n"
12113 			"\t\t\t\t.n_bits = %u,\n"
12114 			"\t\t\t},\n",
12115 			instr->io.io.offset,
12116 			instr->io.io.n_bits);
12117 
12118 	if (n_io_imm)
12119 		fprintf(f,
12120 			"\t\t\t.io = {\n"
12121 			"\t\t\t\t.val = %u,\n"
12122 			"\t\t\t},\n",
12123 			instr->io.io.val);
12124 
12125 	/* instr.io.hdr. */
12126 	if (n_hdrs) {
12127 		fprintf(f,
12128 			"\t\t.hdr = {\n");
12129 
12130 		/* instr.io.hdr.header_id. */
12131 		fprintf(f,
12132 			"\t\t\t.header_id = {");
12133 
12134 		for (i = 0; i < n_hdrs; i++)
12135 			fprintf(f,
12136 				"%u, ",
12137 				instr->io.hdr.header_id[i]);
12138 
12139 		fprintf(f,
12140 			"},\n");
12141 
12142 		/* instr.io.hdr.struct_id. */
12143 		fprintf(f,
12144 			"\t\t\t.struct_id = {");
12145 
12146 		for (i = 0; i < n_hdrs; i++)
12147 			fprintf(f,
12148 				"%u, ",
12149 				instr->io.hdr.struct_id[i]);
12150 
12151 		fprintf(f,
12152 			"},\n");
12153 
12154 		/* instr.io.hdr.n_bytes. */
12155 		fprintf(f,
12156 			"\t\t\t.n_bytes = {");
12157 
12158 		for (i = 0; i < n_hdrs; i++)
12159 			fprintf(f,
12160 				"%u, ",
12161 				instr->io.hdr.n_bytes[i]);
12162 
12163 		fprintf(f,
12164 			"},\n");
12165 
12166 		/* instr.io.hdr - closing curly brace. */
12167 		fprintf(f,
12168 			"\t\t\t}\n,");
12169 	}
12170 
12171 	/* instr.io - closing curly brace. */
12172 	if (n_io || n_io_imm || n_hdrs)
12173 		fprintf(f,
12174 			"\t\t},\n");
12175 
12176 	/* instr - closing curly brace. */
12177 	fprintf(f,
12178 		"\t},\n");
12179 }
12180 
12181 static void
instr_mirror_export(struct instruction * instr,FILE * f)12182 instr_mirror_export(struct instruction *instr, FILE *f)
12183 {
12184 	fprintf(f,
12185 		"\t{\n"
12186 		"\t\t.type = %s,\n"
12187 		"\t\t.mirror = {\n"
12188 		"\t\t\t.dst = {\n"
12189 		"\t\t\t\t.struct_id = %u,\n"
12190 		"\t\t\t\t.n_bits = %u,\n"
12191 		"\t\t\t\t.offset = %u,\n"
12192 		"\t\t\t}\n,"
12193 		"\t\t\t.src = {\n"
12194 		"\t\t\t\t.struct_id = %u,\n"
12195 		"\t\t\t\t.n_bits = %u,\n"
12196 		"\t\t\t\t.offset = %u,\n"
12197 		"\t\t\t}\n,"
12198 		"\t\t},\n"
12199 		"\t},\n",
12200 		instr_type_to_name(instr),
12201 		instr->mirror.dst.struct_id,
12202 		instr->mirror.dst.n_bits,
12203 		instr->mirror.dst.offset,
12204 		instr->mirror.src.struct_id,
12205 		instr->mirror.src.n_bits,
12206 		instr->mirror.src.offset);
12207 }
12208 
12209 static void
instr_recirculate_export(struct instruction * instr,FILE * f)12210 instr_recirculate_export(struct instruction *instr, FILE *f)
12211 {
12212 	fprintf(f,
12213 		"\t{\n"
12214 		"\t\t.type = %s,\n"
12215 		"\t},\n",
12216 		instr_type_to_name(instr));
12217 }
12218 
12219 static void
instr_recircid_export(struct instruction * instr,FILE * f)12220 instr_recircid_export(struct instruction *instr, FILE *f)
12221 {
12222 	fprintf(f,
12223 		"\t{\n"
12224 		"\t\t.type = %s,\n"
12225 		"\t\t.io = {\n"
12226 		"\t\t\t.io = {\n"
12227 		"\t\t\t\t.offset = %u,\n"
12228 		"\t\t\t\t.n_bits = %u,\n"
12229 		"\t\t\t},\n"
12230 		"\t\t},\n"
12231 		"\t},\n",
12232 		instr_type_to_name(instr),
12233 		instr->io.io.offset,
12234 		instr->io.io.n_bits);
12235 }
12236 
12237 static void
instr_hdr_validate_export(struct instruction * instr,FILE * f)12238 instr_hdr_validate_export(struct instruction *instr, FILE *f)
12239 {
12240 	fprintf(f,
12241 		"\t{\n"
12242 		"\t\t.type = %s,\n"
12243 		"\t\t.valid = {\n"
12244 		"\t\t\t.header_id = %u,\n"
12245 		"\t\t\t.struct_id = %u,\n"
12246 		"\t\t},\n"
12247 		"\t},\n",
12248 		instr_type_to_name(instr),
12249 		instr->valid.header_id,
12250 		instr->valid.struct_id);
12251 }
12252 
12253 static void
instr_mov_export(struct instruction * instr,FILE * f)12254 instr_mov_export(struct instruction *instr, FILE *f)
12255 {
12256 	if (instr->type != INSTR_MOV_I)
12257 		fprintf(f,
12258 			"\t{\n"
12259 			"\t\t.type = %s,\n"
12260 			"\t\t.mov = {\n"
12261 			"\t\t\t.dst = {\n"
12262 			"\t\t\t\t.struct_id = %u,\n"
12263 			"\t\t\t\t.n_bits = %u,\n"
12264 			"\t\t\t\t.offset = %u,\n"
12265 			"\t\t\t},\n"
12266 			"\t\t\t.src = {\n"
12267 			"\t\t\t\t.struct_id = %u,\n"
12268 			"\t\t\t\t.n_bits = %u,\n"
12269 			"\t\t\t\t.offset = %u,\n"
12270 			"\t\t\t},\n"
12271 			"\t\t},\n"
12272 			"\t},\n",
12273 			instr_type_to_name(instr),
12274 			instr->mov.dst.struct_id,
12275 			instr->mov.dst.n_bits,
12276 			instr->mov.dst.offset,
12277 			instr->mov.src.struct_id,
12278 			instr->mov.src.n_bits,
12279 			instr->mov.src.offset);
12280 	else
12281 		fprintf(f,
12282 			"\t{\n"
12283 			"\t\t.type = %s,\n"
12284 			"\t\t.mov = {\n"
12285 			"\t\t\t.dst = {\n"
12286 			"\t\t\t\t.struct_id = %u,\n"
12287 			"\t\t\t\t.n_bits = %u,\n"
12288 			"\t\t\t\t.offset = %u,\n"
12289 			"\t\t\t}\n,"
12290 			"\t\t\t.src_val = %" PRIu64 ",\n"
12291 			"\t\t},\n"
12292 			"\t},\n",
12293 			instr_type_to_name(instr),
12294 			instr->mov.dst.struct_id,
12295 			instr->mov.dst.n_bits,
12296 			instr->mov.dst.offset,
12297 			instr->mov.src_val);
12298 }
12299 
12300 static void
instr_movh_export(struct instruction * instr,FILE * f)12301 instr_movh_export(struct instruction *instr, FILE *f)
12302 {
12303 	fprintf(f,
12304 		"\t{\n"
12305 		"\t\t.type = %s,\n"
12306 		"\t\t.mov = {\n"
12307 		"\t\t\t.dst = {\n"
12308 		"\t\t\t\t.struct_id = %u,\n"
12309 		"\t\t\t\t.n_bits = %u,\n"
12310 		"\t\t\t\t.offset = %u,\n"
12311 		"\t\t\t},\n"
12312 		"\t\t\t.src = {\n"
12313 		"\t\t\t\t.struct_id = %u,\n"
12314 		"\t\t\t\t.n_bits = %u,\n"
12315 		"\t\t\t\t.offset = %u,\n"
12316 		"\t\t\t},\n"
12317 		"\t\t},\n"
12318 		"\t},\n",
12319 		instr_type_to_name(instr),
12320 		instr->mov.dst.struct_id,
12321 		instr->mov.dst.n_bits,
12322 		instr->mov.dst.offset,
12323 		instr->mov.src.struct_id,
12324 		instr->mov.src.n_bits,
12325 		instr->mov.src.offset);
12326 }
12327 
12328 static void
instr_dma_ht_export(struct instruction * instr,FILE * f)12329 instr_dma_ht_export(struct instruction *instr, FILE *f)
12330 {
12331 	uint32_t n_dma = 0, i;
12332 
12333 	/* n_dma. */
12334 	n_dma = 1 + (instr->type - INSTR_DMA_HT);
12335 
12336 	/* instr. */
12337 	fprintf(f,
12338 		"\t{\n"
12339 		"\t\t.type = %s,\n",
12340 		instr_type_to_name(instr));
12341 
12342 	/* instr.dma. */
12343 	fprintf(f,
12344 		"\t\t.dma = {\n");
12345 
12346 	/* instr.dma.dst. */
12347 	fprintf(f,
12348 		"\t\t\t.dst = {\n");
12349 
12350 	/* instr.dma.dst.header_id. */
12351 	fprintf(f,
12352 		"\t\t\t\t.header_id = {");
12353 
12354 	for (i = 0; i < n_dma; i++)
12355 		fprintf(f,
12356 			"%u, ",
12357 			instr->dma.dst.header_id[i]);
12358 
12359 	fprintf(f,
12360 		"},\n");
12361 
12362 	/* instr.dma.dst.struct_id. */
12363 	fprintf(f,
12364 		"\t\t\t\t.struct_id = {");
12365 
12366 	for (i = 0; i < n_dma; i++)
12367 		fprintf(f,
12368 			"%u, ",
12369 			instr->dma.dst.struct_id[i]);
12370 
12371 	fprintf(f,
12372 		"},\n");
12373 
12374 	/* instr.dma.dst - closing curly brace. */
12375 	fprintf(f,
12376 		"\t\t\t},\n");
12377 
12378 	/* instr.dma.src. */
12379 	fprintf(f,
12380 		"\t\t\t.src = {\n");
12381 
12382 	/* instr.dma.src.offset. */
12383 	fprintf(f,
12384 		"\t\t\t\t.offset = {");
12385 
12386 	for (i = 0; i < n_dma; i++)
12387 		fprintf(f,
12388 			"%u, ",
12389 			instr->dma.src.offset[i]);
12390 
12391 	fprintf(f,
12392 		"},\n");
12393 
12394 	/* instr.dma.src - closing curly brace. */
12395 	fprintf(f,
12396 		"\t\t\t},\n");
12397 
12398 	/* instr.dma.n_bytes. */
12399 	fprintf(f,
12400 		"\t\t\t.n_bytes = {");
12401 
12402 	for (i = 0; i < n_dma; i++)
12403 		fprintf(f,
12404 			"%u, ",
12405 			instr->dma.n_bytes[i]);
12406 
12407 	fprintf(f,
12408 		"},\n");
12409 
12410 	/* instr.dma - closing curly brace. */
12411 	fprintf(f,
12412 		"\t\t},\n");
12413 
12414 	/* instr - closing curly brace. */
12415 	fprintf(f,
12416 		"\t},\n");
12417 }
12418 
12419 static void
instr_alu_export(struct instruction * instr,FILE * f)12420 instr_alu_export(struct instruction *instr, FILE *f)
12421 {
12422 	int imm = 0;
12423 
12424 	if (instr->type == INSTR_ALU_ADD_MI ||
12425 	    instr->type == INSTR_ALU_ADD_HI ||
12426 	    instr->type == INSTR_ALU_SUB_MI ||
12427 	    instr->type == INSTR_ALU_SUB_HI ||
12428 	    instr->type == INSTR_ALU_SHL_MI ||
12429 	    instr->type == INSTR_ALU_SHL_HI ||
12430 	    instr->type == INSTR_ALU_SHR_MI ||
12431 	    instr->type == INSTR_ALU_SHR_HI ||
12432 	    instr->type == INSTR_ALU_AND_I ||
12433 	    instr->type == INSTR_ALU_OR_I ||
12434 	    instr->type == INSTR_ALU_XOR_I)
12435 		imm = 1;
12436 
12437 	if (!imm)
12438 		fprintf(f,
12439 			"\t{\n"
12440 			"\t\t.type = %s,\n"
12441 			"\t\t.alu = {\n"
12442 			"\t\t\t.dst = {\n"
12443 			"\t\t\t\t.struct_id = %u,\n"
12444 			"\t\t\t\t.n_bits = %u,\n"
12445 			"\t\t\t\t.offset = %u,\n"
12446 			"\t\t\t},\n"
12447 			"\t\t\t.src = {\n"
12448 			"\t\t\t\t.struct_id = %u,\n"
12449 			"\t\t\t\t.n_bits = %u,\n"
12450 			"\t\t\t\t.offset = %u,\n"
12451 			"\t\t\t},\n"
12452 			"\t\t},\n"
12453 			"\t},\n",
12454 			instr_type_to_name(instr),
12455 			instr->alu.dst.struct_id,
12456 			instr->alu.dst.n_bits,
12457 			instr->alu.dst.offset,
12458 			instr->alu.src.struct_id,
12459 			instr->alu.src.n_bits,
12460 			instr->alu.src.offset);
12461 	else
12462 		fprintf(f,
12463 			"\t{\n"
12464 			"\t\t.type = %s,\n"
12465 			"\t\t.alu = {\n"
12466 			"\t\t\t.dst = {\n"
12467 			"\t\t\t\t.struct_id = %u,\n"
12468 			"\t\t\t\t.n_bits = %u,\n"
12469 			"\t\t\t\t.offset = %u,\n"
12470 			"\t\t\t}\n,"
12471 			"\t\t\t.src_val = %" PRIu64 ",\n"
12472 			"\t\t},\n"
12473 			"\t},\n",
12474 			instr_type_to_name(instr),
12475 			instr->alu.dst.struct_id,
12476 			instr->alu.dst.n_bits,
12477 			instr->alu.dst.offset,
12478 			instr->alu.src_val);
12479 }
12480 
12481 static void
instr_hash_export(struct instruction * instr,FILE * f)12482 instr_hash_export(struct instruction *instr, FILE *f)
12483 {
12484 	fprintf(f,
12485 		"\t{\n"
12486 		"\t\t.type = %s,\n"
12487 		"\t\t.hash_func = {\n"
12488 		"\t\t\t.hash_func_id = %u,\n"
12489 		"\t\t\t.dst = {\n"
12490 		"\t\t\t\t.offset = %u,\n"
12491 		"\t\t\t\t.n_bits = %u,\n"
12492 		"\t\t\t},\n"
12493 		"\t\t\t.src = {\n"
12494 		"\t\t\t\t.struct_id = %u,\n"
12495 		"\t\t\t\t.offset = %u,\n"
12496 		"\t\t\t\t.n_bytes = %u,\n"
12497 		"\t\t\t},\n"
12498 		"\t\t},\n"
12499 		"\t},\n",
12500 		instr_type_to_name(instr),
12501 		instr->hash_func.hash_func_id,
12502 		instr->hash_func.dst.offset,
12503 		instr->hash_func.dst.n_bits,
12504 		instr->hash_func.src.struct_id,
12505 		instr->hash_func.src.offset,
12506 		instr->hash_func.src.n_bytes);
12507 }
12508 
12509 static void
instr_rss_export(struct instruction * instr,FILE * f)12510 instr_rss_export(struct instruction *instr, FILE *f)
12511 {
12512 	fprintf(f,
12513 		"\t{\n"
12514 		"\t\t.type = %s,\n"
12515 		"\t\t.rss = {\n"
12516 		"\t\t\t.rss_obj_id = %u,\n"
12517 		"\t\t\t.dst = {\n"
12518 		"\t\t\t\t.offset = %u,\n"
12519 		"\t\t\t\t.n_bits = %u,\n"
12520 		"\t\t\t},\n"
12521 		"\t\t\t.src = {\n"
12522 		"\t\t\t\t.struct_id = %u,\n"
12523 		"\t\t\t\t.offset = %u,\n"
12524 		"\t\t\t\t.n_bytes = %u,\n"
12525 		"\t\t\t},\n"
12526 		"\t\t},\n"
12527 		"\t},\n",
12528 		instr_type_to_name(instr),
12529 		instr->rss.rss_obj_id,
12530 		instr->rss.dst.offset,
12531 		instr->rss.dst.n_bits,
12532 		instr->rss.src.struct_id,
12533 		instr->rss.src.offset,
12534 		instr->rss.src.n_bytes);
12535 }
12536 
12537 static void
instr_reg_export(struct instruction * instr __rte_unused,FILE * f __rte_unused)12538 instr_reg_export(struct instruction *instr __rte_unused, FILE *f __rte_unused)
12539 {
12540 	int prefetch  = 0, idx_imm = 0, src_imm = 0;
12541 
12542 	if (instr->type == INSTR_REGPREFETCH_RH ||
12543 	    instr->type == INSTR_REGPREFETCH_RM ||
12544 	    instr->type == INSTR_REGPREFETCH_RI)
12545 		prefetch = 1;
12546 
12547 	/* index is the 3rd operand for the regrd instruction and the 2nd
12548 	 * operand for the regwr and regadd instructions.
12549 	 */
12550 	if (instr->type == INSTR_REGPREFETCH_RI ||
12551 	    instr->type == INSTR_REGRD_HRI ||
12552 	    instr->type == INSTR_REGRD_MRI ||
12553 	    instr->type == INSTR_REGWR_RIH ||
12554 	    instr->type == INSTR_REGWR_RIM ||
12555 	    instr->type == INSTR_REGWR_RII ||
12556 	    instr->type == INSTR_REGADD_RIH ||
12557 	    instr->type == INSTR_REGADD_RIM ||
12558 	    instr->type == INSTR_REGADD_RII)
12559 		idx_imm = 1;
12560 
12561 	/* src is the 3rd operand for the regwr and regadd instructions. */
12562 	if (instr->type == INSTR_REGWR_RHI ||
12563 	    instr->type == INSTR_REGWR_RMI ||
12564 	    instr->type == INSTR_REGWR_RII ||
12565 	    instr->type == INSTR_REGADD_RHI ||
12566 	    instr->type == INSTR_REGADD_RMI ||
12567 	    instr->type == INSTR_REGADD_RII)
12568 		src_imm = 1;
12569 
12570 	/* instr.regarray.regarray_id. */
12571 	fprintf(f,
12572 		"\t{\n"
12573 		"\t\t.type = %s,\n"
12574 		"\t\t.regarray = {\n"
12575 		"\t\t\t.regarray_id = %u,\n",
12576 		instr_type_to_name(instr),
12577 		instr->regarray.regarray_id);
12578 
12579 	/* instr.regarray.idx / instr.regarray.idx_val. */
12580 	if (!idx_imm)
12581 		fprintf(f,
12582 			"\t\t\t\t.idx = {\n"
12583 			"\t\t\t\t\t.struct_id = %u,\n"
12584 			"\t\t\t\t\t.n_bits = %u,\n"
12585 			"\t\t\t\t\t.offset = %u,\n"
12586 			"\t\t\t\t},\n",
12587 			instr->regarray.idx.struct_id,
12588 			instr->regarray.idx.n_bits,
12589 			instr->regarray.idx.offset);
12590 	else
12591 		fprintf(f,
12592 			"\t\t\t\t.idx_val = %u,\n",
12593 			instr->regarray.idx_val);
12594 
12595 	/* instr.regarray.dstsrc / instr.regarray.dstsrc_val. */
12596 	if (!prefetch) {
12597 		if (!src_imm)
12598 			fprintf(f,
12599 				"\t\t\t\t.dstsrc = {\n"
12600 				"\t\t\t\t\t.struct_id = %u,\n"
12601 				"\t\t\t\t\t.n_bits = %u,\n"
12602 				"\t\t\t\t\t.offset = %u,\n"
12603 				"\t\t\t\t},\n",
12604 				instr->regarray.dstsrc.struct_id,
12605 				instr->regarray.dstsrc.n_bits,
12606 				instr->regarray.dstsrc.offset);
12607 		else
12608 			fprintf(f,
12609 				"\t\t\t\t.dstsrc_val = %" PRIu64 ",\n",
12610 				instr->regarray.dstsrc_val);
12611 	}
12612 
12613 	/* instr.regarray and instr - closing curly braces. */
12614 	fprintf(f,
12615 		"\t\t},\n"
12616 		"\t},\n");
12617 }
12618 
12619 static void
instr_meter_export(struct instruction * instr __rte_unused,FILE * f __rte_unused)12620 instr_meter_export(struct instruction *instr __rte_unused, FILE *f __rte_unused)
12621 {
12622 	int prefetch  = 0, idx_imm = 0, color_in_imm = 0;
12623 
12624 	if (instr->type == INSTR_METPREFETCH_H ||
12625 	    instr->type == INSTR_METPREFETCH_M ||
12626 	    instr->type == INSTR_METPREFETCH_I)
12627 		prefetch = 1;
12628 
12629 	/* idx_imm. */
12630 	if (instr->type == INSTR_METPREFETCH_I ||
12631 	    instr->type == INSTR_METER_IHM ||
12632 	    instr->type == INSTR_METER_IHI ||
12633 	    instr->type == INSTR_METER_IMM ||
12634 	    instr->type == INSTR_METER_IMI)
12635 		idx_imm = 1;
12636 
12637 	/* color_in_imm. */
12638 	if (instr->type == INSTR_METER_HHI ||
12639 	    instr->type == INSTR_METER_HMI ||
12640 	    instr->type == INSTR_METER_MHI ||
12641 	    instr->type == INSTR_METER_MMI ||
12642 	    instr->type == INSTR_METER_IHI ||
12643 	    instr->type == INSTR_METER_IMI)
12644 		color_in_imm = 1;
12645 
12646 	/* instr.meter.metarray_id. */
12647 	fprintf(f,
12648 		"\t{\n"
12649 		"\t\t.type = %s,\n"
12650 		"\t\t.meter = {\n"
12651 		"\t\t\t.metarray_id = %u,\n",
12652 		instr_type_to_name(instr),
12653 		instr->meter.metarray_id);
12654 
12655 	/* instr.meter.idx / instr.meter.idx_val. */
12656 	if (!idx_imm)
12657 		fprintf(f,
12658 			"\t\t\t.idx = {\n"
12659 			"\t\t\t\t.struct_id = %u,\n"
12660 			"\t\t\t\t.n_bits = %u,\n"
12661 			"\t\t\t\t.offset = %u,\n"
12662 			"\t\t\t},\n",
12663 			instr->meter.idx.struct_id,
12664 			instr->meter.idx.n_bits,
12665 			instr->meter.idx.offset);
12666 	else
12667 		fprintf(f,
12668 			"\t\t\t.idx_val = %u,\n",
12669 			instr->meter.idx_val);
12670 
12671 	if (!prefetch) {
12672 		/* instr.meter.length. */
12673 		fprintf(f,
12674 			"\t\t\t.length = {\n"
12675 			"\t\t\t\t.struct_id = %u,\n"
12676 			"\t\t\t\t.n_bits = %u,\n"
12677 			"\t\t\t\t.offset = %u,\n"
12678 			"\t\t\t},\n",
12679 			instr->meter.length.struct_id,
12680 			instr->meter.length.n_bits,
12681 			instr->meter.length.offset);
12682 
12683 		/* instr.meter.color_in / instr.meter.color_in_val. */
12684 		if (!color_in_imm)
12685 			fprintf(f,
12686 				"\t\t\t.color_in = {\n"
12687 				"\t\t\t\t.struct_id = %u,\n"
12688 				"\t\t\t\t.n_bits = %u,\n"
12689 				"\t\t\t\t.offset = %u,\n"
12690 				"\t\t\t},\n",
12691 				instr->meter.color_in.struct_id,
12692 				instr->meter.color_in.n_bits,
12693 				instr->meter.color_in.offset);
12694 		else
12695 			fprintf(f,
12696 				"\t\t\t.color_in_val = %u,\n",
12697 				(uint32_t)instr->meter.color_in_val);
12698 
12699 		/* instr.meter.color_out. */
12700 		fprintf(f,
12701 			"\t\t\t.color_out = {\n"
12702 			"\t\t\t\t.struct_id = %u,\n"
12703 			"\t\t\t\t.n_bits = %u,\n"
12704 			"\t\t\t\t.offset = %u,\n"
12705 			"\t\t\t},\n",
12706 			instr->meter.color_out.struct_id,
12707 			instr->meter.color_out.n_bits,
12708 			instr->meter.color_out.offset);
12709 	}
12710 
12711 	/* instr.meter and instr - closing curly braces. */
12712 	fprintf(f,
12713 		"\t\t},\n"
12714 		"\t},\n");
12715 }
12716 
12717 static void
instr_table_export(struct instruction * instr,FILE * f)12718 instr_table_export(struct instruction *instr,
12719 		FILE *f)
12720 {
12721 	fprintf(f,
12722 		"\t{\n"
12723 		"\t\t.type = %s,\n"
12724 		"\t\t.table = {\n"
12725 		"\t\t\t.table_id = %u,\n"
12726 		"\t\t},\n"
12727 		"\t},\n",
12728 		instr_type_to_name(instr),
12729 		instr->table.table_id);
12730 }
12731 
12732 static void
instr_learn_export(struct instruction * instr,FILE * f)12733 instr_learn_export(struct instruction *instr, FILE *f)
12734 {
12735 	fprintf(f,
12736 		"\t{\n"
12737 		"\t\t.type = %s,\n"
12738 		"\t\t.learn = {\n"
12739 		"\t\t\t.action_id = %u,\n"
12740 		"\t\t\t.mf_first_arg_offset = %u,\n"
12741 		"\t\t\t.mf_timeout_id_offset = %u,\n"
12742 		"\t\t\t.mf_timeout_id_n_bits = %u,\n"
12743 		"\t\t},\n"
12744 		"\t},\n",
12745 		instr_type_to_name(instr),
12746 		instr->learn.action_id,
12747 		instr->learn.mf_first_arg_offset,
12748 		instr->learn.mf_timeout_id_offset,
12749 		instr->learn.mf_timeout_id_n_bits);
12750 }
12751 
12752 static void
instr_rearm_export(struct instruction * instr,FILE * f)12753 instr_rearm_export(struct instruction *instr, FILE *f)
12754 {
12755 	if (instr->type == INSTR_LEARNER_REARM)
12756 		fprintf(f,
12757 			"\t{\n"
12758 			"\t\t.type = %s,\n"
12759 			"\t},\n",
12760 			instr_type_to_name(instr));
12761 	else
12762 		fprintf(f,
12763 			"\t{\n"
12764 			"\t\t.type = %s,\n"
12765 			"\t\t.learn = {\n"
12766 			"\t\t\t.mf_timeout_id_offset = %u,\n"
12767 			"\t\t\t.mf_timeout_id_n_bits = %u,\n"
12768 			"\t\t},\n"
12769 			"\t},\n",
12770 			instr_type_to_name(instr),
12771 			instr->learn.mf_timeout_id_offset,
12772 			instr->learn.mf_timeout_id_n_bits);
12773 }
12774 
12775 static void
instr_forget_export(struct instruction * instr,FILE * f)12776 instr_forget_export(struct instruction *instr, FILE *f)
12777 {
12778 	fprintf(f,
12779 		"\t{\n"
12780 		"\t\t.type = %s,\n"
12781 		"\t},\n",
12782 		instr_type_to_name(instr));
12783 }
12784 
12785 static void
instr_entryid_export(struct instruction * instr,FILE * f)12786 instr_entryid_export(struct instruction *instr, FILE *f)
12787 {
12788 	fprintf(f,
12789 		"\t{\n"
12790 		"\t\t.type = %s,\n"
12791 		"\t\t.mov = {\n"
12792 		"\t\t\t.dst = {\n"
12793 		"\t\t\t\t.n_bits = %u,\n"
12794 		"\t\t\t\t.offset = %u,\n"
12795 		"\t\t\t},\n"
12796 		"\t\t},\n"
12797 		"\t},\n",
12798 		instr_type_to_name(instr),
12799 		instr->mov.dst.n_bits,
12800 		instr->mov.dst.offset);
12801 }
12802 
12803 static void
instr_extern_export(struct instruction * instr,FILE * f)12804 instr_extern_export(struct instruction *instr, FILE *f)
12805 {
12806 	if (instr->type == INSTR_EXTERN_OBJ)
12807 		fprintf(f,
12808 			"\t{\n"
12809 			"\t\t.type = %s,\n"
12810 			"\t\t.ext_obj = {\n"
12811 			"\t\t\t.ext_obj_id = %u,\n"
12812 			"\t\t\t.func_id = %u,\n"
12813 			"\t\t},\n"
12814 			"\t},\n",
12815 			instr_type_to_name(instr),
12816 			instr->ext_obj.ext_obj_id,
12817 			instr->ext_obj.func_id);
12818 	else
12819 		fprintf(f,
12820 			"\t{\n"
12821 			"\t\t.type = %s,\n"
12822 			"\t\t.ext_func = {\n"
12823 			"\t\t\t.ext_func_id = %u,\n"
12824 			"\t\t},\n"
12825 			"\t},\n",
12826 			instr_type_to_name(instr),
12827 			instr->ext_func.ext_func_id);
12828 }
12829 
12830 static void
instr_jmp_export(struct instruction * instr,FILE * f __rte_unused)12831 instr_jmp_export(struct instruction *instr, FILE *f __rte_unused)
12832 {
12833 	fprintf(f,
12834 		"\t{\n"
12835 		"\t\t.type = %s,\n"
12836 		"\t\t.jmp = {\n"
12837 		"\t\t\t.ip = NULL,\n",
12838 		instr_type_to_name(instr));
12839 
12840 	switch (instr->type) {
12841 	case INSTR_JMP_VALID:
12842 	case INSTR_JMP_INVALID:
12843 		fprintf(f,
12844 			"\t\t\t.header_id = %u,\n",
12845 			instr->jmp.header_id);
12846 		break;
12847 
12848 	case INSTR_JMP_ACTION_HIT:
12849 	case INSTR_JMP_ACTION_MISS:
12850 		fprintf(f,
12851 			"\t\t\t.action_id = %u,\n",
12852 			instr->jmp.action_id);
12853 		break;
12854 
12855 	case INSTR_JMP_EQ:
12856 	case INSTR_JMP_EQ_MH:
12857 	case INSTR_JMP_EQ_HM:
12858 	case INSTR_JMP_EQ_HH:
12859 	case INSTR_JMP_NEQ:
12860 	case INSTR_JMP_NEQ_MH:
12861 	case INSTR_JMP_NEQ_HM:
12862 	case INSTR_JMP_NEQ_HH:
12863 	case INSTR_JMP_LT:
12864 	case INSTR_JMP_LT_MH:
12865 	case INSTR_JMP_LT_HM:
12866 	case INSTR_JMP_LT_HH:
12867 	case INSTR_JMP_GT:
12868 	case INSTR_JMP_GT_MH:
12869 	case INSTR_JMP_GT_HM:
12870 	case INSTR_JMP_GT_HH:
12871 		fprintf(f,
12872 			"\t\t\t.a = {\n"
12873 			"\t\t\t\t.struct_id = %u,\n"
12874 			"\t\t\t\t.n_bits = %u,\n"
12875 			"\t\t\t\t.offset = %u,\n"
12876 			"\t\t\t},\n"
12877 			"\t\t\t.b = {\n"
12878 			"\t\t\t\t.struct_id = %u,\n"
12879 			"\t\t\t\t.n_bits = %u,\n"
12880 			"\t\t\t\t.offset = %u,\n"
12881 			"\t\t\t},\n",
12882 			instr->jmp.a.struct_id,
12883 			instr->jmp.a.n_bits,
12884 			instr->jmp.a.offset,
12885 			instr->jmp.b.struct_id,
12886 			instr->jmp.b.n_bits,
12887 			instr->jmp.b.offset);
12888 		break;
12889 
12890 	case INSTR_JMP_EQ_I:
12891 	case INSTR_JMP_NEQ_I:
12892 	case INSTR_JMP_LT_MI:
12893 	case INSTR_JMP_LT_HI:
12894 	case INSTR_JMP_GT_MI:
12895 	case INSTR_JMP_GT_HI:
12896 		fprintf(f,
12897 			"\t\t\t.a = {\n"
12898 			"\t\t\t\t.struct_id = %u,\n"
12899 			"\t\t\t\t.n_bits = %u,\n"
12900 			"\t\t\t\t.offset = %u,\n"
12901 			"\t\t\t}\n,"
12902 			"\t\t\t.b_val = %" PRIu64 ",\n",
12903 			instr->jmp.a.struct_id,
12904 			instr->jmp.a.n_bits,
12905 			instr->jmp.a.offset,
12906 			instr->jmp.b_val);
12907 		break;
12908 
12909 	default:
12910 		break;
12911 	}
12912 
12913 	fprintf(f,
12914 		"\t\t},\n"
12915 		"\t},\n");
12916 }
12917 
12918 static void
instr_return_export(struct instruction * instr,FILE * f)12919 instr_return_export(struct instruction *instr,
12920 		FILE *f)
12921 {
12922 	fprintf(f,
12923 		"\t{\n"
12924 		"\t\t.type = %s,\n",
12925 		instr_type_to_name(instr));
12926 
12927 	fprintf(f,
12928 		"\t},\n");
12929 }
12930 
12931 static instruction_export_t export_table[] = {
12932 	[INSTR_RX] = instr_io_export,
12933 
12934 	[INSTR_TX] = instr_io_export,
12935 	[INSTR_TX_I] = instr_io_export,
12936 	[INSTR_DROP] = instr_io_export,
12937 	[INSTR_MIRROR] = instr_mirror_export,
12938 	[INSTR_RECIRCULATE] = instr_recirculate_export,
12939 	[INSTR_RECIRCID] = instr_recircid_export,
12940 
12941 	[INSTR_HDR_EXTRACT] = instr_io_export,
12942 	[INSTR_HDR_EXTRACT2] = instr_io_export,
12943 	[INSTR_HDR_EXTRACT3] = instr_io_export,
12944 	[INSTR_HDR_EXTRACT4] = instr_io_export,
12945 	[INSTR_HDR_EXTRACT5] = instr_io_export,
12946 	[INSTR_HDR_EXTRACT6] = instr_io_export,
12947 	[INSTR_HDR_EXTRACT7] = instr_io_export,
12948 	[INSTR_HDR_EXTRACT8] = instr_io_export,
12949 
12950 	[INSTR_HDR_EXTRACT_M] = instr_io_export,
12951 
12952 	[INSTR_HDR_LOOKAHEAD] = instr_io_export,
12953 
12954 	[INSTR_HDR_EMIT] = instr_io_export,
12955 	[INSTR_HDR_EMIT_TX] = instr_io_export,
12956 	[INSTR_HDR_EMIT2_TX] = instr_io_export,
12957 	[INSTR_HDR_EMIT3_TX] = instr_io_export,
12958 	[INSTR_HDR_EMIT4_TX] = instr_io_export,
12959 	[INSTR_HDR_EMIT5_TX] = instr_io_export,
12960 	[INSTR_HDR_EMIT6_TX] = instr_io_export,
12961 	[INSTR_HDR_EMIT7_TX] = instr_io_export,
12962 	[INSTR_HDR_EMIT8_TX] = instr_io_export,
12963 
12964 	[INSTR_HDR_VALIDATE] = instr_hdr_validate_export,
12965 	[INSTR_HDR_INVALIDATE] = instr_hdr_validate_export,
12966 
12967 	[INSTR_MOV] = instr_mov_export,
12968 	[INSTR_MOV_MH] = instr_mov_export,
12969 	[INSTR_MOV_HM] = instr_mov_export,
12970 	[INSTR_MOV_HH] = instr_mov_export,
12971 	[INSTR_MOV_DMA] = instr_mov_export,
12972 	[INSTR_MOV_128] = instr_mov_export,
12973 	[INSTR_MOV_128_64] = instr_mov_export,
12974 	[INSTR_MOV_64_128] = instr_mov_export,
12975 	[INSTR_MOV_128_32] = instr_mov_export,
12976 	[INSTR_MOV_32_128] = instr_mov_export,
12977 	[INSTR_MOV_I] = instr_mov_export,
12978 
12979 	[INSTR_MOVH] = instr_movh_export,
12980 
12981 	[INSTR_DMA_HT]  = instr_dma_ht_export,
12982 	[INSTR_DMA_HT2] = instr_dma_ht_export,
12983 	[INSTR_DMA_HT3] = instr_dma_ht_export,
12984 	[INSTR_DMA_HT4] = instr_dma_ht_export,
12985 	[INSTR_DMA_HT5] = instr_dma_ht_export,
12986 	[INSTR_DMA_HT6] = instr_dma_ht_export,
12987 	[INSTR_DMA_HT7] = instr_dma_ht_export,
12988 	[INSTR_DMA_HT8] = instr_dma_ht_export,
12989 
12990 	[INSTR_ALU_ADD] = instr_alu_export,
12991 	[INSTR_ALU_ADD_MH] = instr_alu_export,
12992 	[INSTR_ALU_ADD_HM] = instr_alu_export,
12993 	[INSTR_ALU_ADD_HH] = instr_alu_export,
12994 	[INSTR_ALU_ADD_MI] = instr_alu_export,
12995 	[INSTR_ALU_ADD_HI] = instr_alu_export,
12996 
12997 	[INSTR_ALU_SUB] = instr_alu_export,
12998 	[INSTR_ALU_SUB_MH] = instr_alu_export,
12999 	[INSTR_ALU_SUB_HM] = instr_alu_export,
13000 	[INSTR_ALU_SUB_HH] = instr_alu_export,
13001 	[INSTR_ALU_SUB_MI] = instr_alu_export,
13002 	[INSTR_ALU_SUB_HI] = instr_alu_export,
13003 
13004 	[INSTR_ALU_CKADD_FIELD] = instr_alu_export,
13005 	[INSTR_ALU_CKADD_STRUCT] = instr_alu_export,
13006 	[INSTR_ALU_CKADD_STRUCT20] = instr_alu_export,
13007 	[INSTR_ALU_CKSUB_FIELD] = instr_alu_export,
13008 
13009 	[INSTR_ALU_AND] = instr_alu_export,
13010 	[INSTR_ALU_AND_MH] = instr_alu_export,
13011 	[INSTR_ALU_AND_HM] = instr_alu_export,
13012 	[INSTR_ALU_AND_HH] = instr_alu_export,
13013 	[INSTR_ALU_AND_I] = instr_alu_export,
13014 
13015 	[INSTR_ALU_OR] = instr_alu_export,
13016 	[INSTR_ALU_OR_MH] = instr_alu_export,
13017 	[INSTR_ALU_OR_HM] = instr_alu_export,
13018 	[INSTR_ALU_OR_HH] = instr_alu_export,
13019 	[INSTR_ALU_OR_I] = instr_alu_export,
13020 
13021 	[INSTR_ALU_XOR] = instr_alu_export,
13022 	[INSTR_ALU_XOR_MH] = instr_alu_export,
13023 	[INSTR_ALU_XOR_HM] = instr_alu_export,
13024 	[INSTR_ALU_XOR_HH] = instr_alu_export,
13025 	[INSTR_ALU_XOR_I] = instr_alu_export,
13026 
13027 	[INSTR_ALU_SHL] = instr_alu_export,
13028 	[INSTR_ALU_SHL_MH] = instr_alu_export,
13029 	[INSTR_ALU_SHL_HM] = instr_alu_export,
13030 	[INSTR_ALU_SHL_HH] = instr_alu_export,
13031 	[INSTR_ALU_SHL_MI] = instr_alu_export,
13032 	[INSTR_ALU_SHL_HI] = instr_alu_export,
13033 
13034 	[INSTR_ALU_SHR] = instr_alu_export,
13035 	[INSTR_ALU_SHR_MH] = instr_alu_export,
13036 	[INSTR_ALU_SHR_HM] = instr_alu_export,
13037 	[INSTR_ALU_SHR_HH] = instr_alu_export,
13038 	[INSTR_ALU_SHR_MI] = instr_alu_export,
13039 	[INSTR_ALU_SHR_HI] = instr_alu_export,
13040 
13041 	[INSTR_REGPREFETCH_RH] = instr_reg_export,
13042 	[INSTR_REGPREFETCH_RM] = instr_reg_export,
13043 	[INSTR_REGPREFETCH_RI] = instr_reg_export,
13044 
13045 	[INSTR_REGRD_HRH] = instr_reg_export,
13046 	[INSTR_REGRD_HRM] = instr_reg_export,
13047 	[INSTR_REGRD_MRH] = instr_reg_export,
13048 	[INSTR_REGRD_MRM] = instr_reg_export,
13049 	[INSTR_REGRD_HRI] = instr_reg_export,
13050 	[INSTR_REGRD_MRI] = instr_reg_export,
13051 
13052 	[INSTR_REGWR_RHH] = instr_reg_export,
13053 	[INSTR_REGWR_RHM] = instr_reg_export,
13054 	[INSTR_REGWR_RMH] = instr_reg_export,
13055 	[INSTR_REGWR_RMM] = instr_reg_export,
13056 	[INSTR_REGWR_RHI] = instr_reg_export,
13057 	[INSTR_REGWR_RMI] = instr_reg_export,
13058 	[INSTR_REGWR_RIH] = instr_reg_export,
13059 	[INSTR_REGWR_RIM] = instr_reg_export,
13060 	[INSTR_REGWR_RII] = instr_reg_export,
13061 
13062 	[INSTR_REGADD_RHH] = instr_reg_export,
13063 	[INSTR_REGADD_RHM] = instr_reg_export,
13064 	[INSTR_REGADD_RMH] = instr_reg_export,
13065 	[INSTR_REGADD_RMM] = instr_reg_export,
13066 	[INSTR_REGADD_RHI] = instr_reg_export,
13067 	[INSTR_REGADD_RMI] = instr_reg_export,
13068 	[INSTR_REGADD_RIH] = instr_reg_export,
13069 	[INSTR_REGADD_RIM] = instr_reg_export,
13070 	[INSTR_REGADD_RII] = instr_reg_export,
13071 
13072 	[INSTR_METPREFETCH_H] = instr_meter_export,
13073 	[INSTR_METPREFETCH_M] = instr_meter_export,
13074 	[INSTR_METPREFETCH_I] = instr_meter_export,
13075 
13076 	[INSTR_METER_HHM] = instr_meter_export,
13077 	[INSTR_METER_HHI] = instr_meter_export,
13078 	[INSTR_METER_HMM] = instr_meter_export,
13079 	[INSTR_METER_HMI] = instr_meter_export,
13080 	[INSTR_METER_MHM] = instr_meter_export,
13081 	[INSTR_METER_MHI] = instr_meter_export,
13082 	[INSTR_METER_MMM] = instr_meter_export,
13083 	[INSTR_METER_MMI] = instr_meter_export,
13084 	[INSTR_METER_IHM] = instr_meter_export,
13085 	[INSTR_METER_IHI] = instr_meter_export,
13086 	[INSTR_METER_IMM] = instr_meter_export,
13087 	[INSTR_METER_IMI] = instr_meter_export,
13088 
13089 	[INSTR_TABLE] = instr_table_export,
13090 	[INSTR_TABLE_AF] = instr_table_export,
13091 	[INSTR_SELECTOR] = instr_table_export,
13092 	[INSTR_LEARNER] = instr_table_export,
13093 	[INSTR_LEARNER_AF] = instr_table_export,
13094 
13095 	[INSTR_LEARNER_LEARN] = instr_learn_export,
13096 	[INSTR_LEARNER_REARM] = instr_rearm_export,
13097 	[INSTR_LEARNER_REARM_NEW] = instr_rearm_export,
13098 	[INSTR_LEARNER_FORGET] = instr_forget_export,
13099 	[INSTR_ENTRYID] = instr_entryid_export,
13100 
13101 	[INSTR_EXTERN_OBJ] = instr_extern_export,
13102 	[INSTR_EXTERN_FUNC] = instr_extern_export,
13103 	[INSTR_HASH_FUNC] = instr_hash_export,
13104 	[INSTR_RSS] = instr_rss_export,
13105 
13106 	[INSTR_JMP] = instr_jmp_export,
13107 	[INSTR_JMP_VALID] = instr_jmp_export,
13108 	[INSTR_JMP_INVALID] = instr_jmp_export,
13109 	[INSTR_JMP_HIT] = instr_jmp_export,
13110 	[INSTR_JMP_MISS] = instr_jmp_export,
13111 	[INSTR_JMP_ACTION_HIT] = instr_jmp_export,
13112 	[INSTR_JMP_ACTION_MISS] = instr_jmp_export,
13113 
13114 	[INSTR_JMP_EQ] = instr_jmp_export,
13115 	[INSTR_JMP_EQ_MH] = instr_jmp_export,
13116 	[INSTR_JMP_EQ_HM] = instr_jmp_export,
13117 	[INSTR_JMP_EQ_HH] = instr_jmp_export,
13118 	[INSTR_JMP_EQ_I] = instr_jmp_export,
13119 
13120 	[INSTR_JMP_NEQ] = instr_jmp_export,
13121 	[INSTR_JMP_NEQ_MH] = instr_jmp_export,
13122 	[INSTR_JMP_NEQ_HM] = instr_jmp_export,
13123 	[INSTR_JMP_NEQ_HH] = instr_jmp_export,
13124 	[INSTR_JMP_NEQ_I] = instr_jmp_export,
13125 
13126 	[INSTR_JMP_LT] = instr_jmp_export,
13127 	[INSTR_JMP_LT_MH] = instr_jmp_export,
13128 	[INSTR_JMP_LT_HM] = instr_jmp_export,
13129 	[INSTR_JMP_LT_HH] = instr_jmp_export,
13130 	[INSTR_JMP_LT_MI] = instr_jmp_export,
13131 	[INSTR_JMP_LT_HI] = instr_jmp_export,
13132 
13133 	[INSTR_JMP_GT] = instr_jmp_export,
13134 	[INSTR_JMP_GT_MH] = instr_jmp_export,
13135 	[INSTR_JMP_GT_HM] = instr_jmp_export,
13136 	[INSTR_JMP_GT_HH] = instr_jmp_export,
13137 	[INSTR_JMP_GT_MI] = instr_jmp_export,
13138 	[INSTR_JMP_GT_HI] = instr_jmp_export,
13139 
13140 	[INSTR_RETURN] = instr_return_export,
13141 };
13142 
13143 static void
action_data_codegen(struct action * a,FILE * f)13144 action_data_codegen(struct action *a, FILE *f)
13145 {
13146 	uint32_t i;
13147 
13148 	fprintf(f,
13149 		"static const struct instruction action_%s_instructions[] = {\n",
13150 		a->name);
13151 
13152 	for (i = 0; i < a->n_instructions; i++) {
13153 		struct instruction *instr = &a->instructions[i];
13154 		instruction_export_t func = export_table[instr->type];
13155 
13156 		func(instr, f);
13157 	}
13158 
13159 	fprintf(f, "};\n");
13160 }
13161 
13162 static const char *
instr_type_to_func(struct instruction * instr)13163 instr_type_to_func(struct instruction *instr)
13164 {
13165 	switch (instr->type) {
13166 	case INSTR_RX: return NULL;
13167 
13168 	case INSTR_TX: return "__instr_tx_exec";
13169 	case INSTR_TX_I: return "__instr_tx_i_exec";
13170 	case INSTR_DROP: return "__instr_drop_exec";
13171 	case INSTR_MIRROR: return "__instr_mirror_exec";
13172 	case INSTR_RECIRCULATE: return "__instr_recirculate_exec";
13173 	case INSTR_RECIRCID: return "__instr_recircid_exec";
13174 
13175 	case INSTR_HDR_EXTRACT: return "__instr_hdr_extract_exec";
13176 	case INSTR_HDR_EXTRACT2: return "__instr_hdr_extract2_exec";
13177 	case INSTR_HDR_EXTRACT3: return "__instr_hdr_extract3_exec";
13178 	case INSTR_HDR_EXTRACT4: return "__instr_hdr_extract4_exec";
13179 	case INSTR_HDR_EXTRACT5: return "__instr_hdr_extract5_exec";
13180 	case INSTR_HDR_EXTRACT6: return "__instr_hdr_extract6_exec";
13181 	case INSTR_HDR_EXTRACT7: return "__instr_hdr_extract7_exec";
13182 	case INSTR_HDR_EXTRACT8: return "__instr_hdr_extract8_exec";
13183 
13184 	case INSTR_HDR_EXTRACT_M: return "__instr_hdr_extract_m_exec";
13185 
13186 	case INSTR_HDR_LOOKAHEAD: return "__instr_hdr_lookahead_exec";
13187 
13188 	case INSTR_HDR_EMIT: return "__instr_hdr_emit_exec";
13189 	case INSTR_HDR_EMIT_TX: return "__instr_hdr_emit_tx_exec";
13190 	case INSTR_HDR_EMIT2_TX: return "__instr_hdr_emit2_tx_exec";
13191 	case INSTR_HDR_EMIT3_TX: return "__instr_hdr_emit3_tx_exec";
13192 	case INSTR_HDR_EMIT4_TX: return "__instr_hdr_emit4_tx_exec";
13193 	case INSTR_HDR_EMIT5_TX: return "__instr_hdr_emit5_tx_exec";
13194 	case INSTR_HDR_EMIT6_TX: return "__instr_hdr_emit6_tx_exec";
13195 	case INSTR_HDR_EMIT7_TX: return "__instr_hdr_emit7_tx_exec";
13196 	case INSTR_HDR_EMIT8_TX: return "__instr_hdr_emit8_tx_exec";
13197 
13198 	case INSTR_HDR_VALIDATE: return "__instr_hdr_validate_exec";
13199 	case INSTR_HDR_INVALIDATE: return "__instr_hdr_invalidate_exec";
13200 
13201 	case INSTR_MOV: return "__instr_mov_exec";
13202 	case INSTR_MOV_MH: return "__instr_mov_mh_exec";
13203 	case INSTR_MOV_HM: return "__instr_mov_hm_exec";
13204 	case INSTR_MOV_HH: return "__instr_mov_hh_exec";
13205 	case INSTR_MOV_DMA: return "__instr_mov_dma_exec";
13206 	case INSTR_MOV_128: return "__instr_mov_128_exec";
13207 	case INSTR_MOV_128_64: return "__instr_mov_128_64_exec";
13208 	case INSTR_MOV_64_128: return "__instr_mov_64_128_exec";
13209 	case INSTR_MOV_128_32: return "__instr_mov_128_32_exec";
13210 	case INSTR_MOV_32_128: return "__instr_mov_32_128_exec";
13211 	case INSTR_MOV_I: return "__instr_mov_i_exec";
13212 
13213 	case INSTR_MOVH: return "__instr_movh_exec";
13214 
13215 	case INSTR_DMA_HT: return "__instr_dma_ht_exec";
13216 	case INSTR_DMA_HT2: return "__instr_dma_ht2_exec";
13217 	case INSTR_DMA_HT3: return "__instr_dma_ht3_exec";
13218 	case INSTR_DMA_HT4: return "__instr_dma_ht4_exec";
13219 	case INSTR_DMA_HT5: return "__instr_dma_ht5_exec";
13220 	case INSTR_DMA_HT6: return "__instr_dma_ht6_exec";
13221 	case INSTR_DMA_HT7: return "__instr_dma_ht7_exec";
13222 	case INSTR_DMA_HT8: return "__instr_dma_ht8_exec";
13223 
13224 	case INSTR_ALU_ADD: return "__instr_alu_add_exec";
13225 	case INSTR_ALU_ADD_MH: return "__instr_alu_add_mh_exec";
13226 	case INSTR_ALU_ADD_HM: return "__instr_alu_add_hm_exec";
13227 	case INSTR_ALU_ADD_HH: return "__instr_alu_add_hh_exec";
13228 	case INSTR_ALU_ADD_MI: return "__instr_alu_add_mi_exec";
13229 	case INSTR_ALU_ADD_HI: return "__instr_alu_add_hi_exec";
13230 
13231 	case INSTR_ALU_SUB: return "__instr_alu_sub_exec";
13232 	case INSTR_ALU_SUB_MH: return "__instr_alu_sub_mh_exec";
13233 	case INSTR_ALU_SUB_HM: return "__instr_alu_sub_hm_exec";
13234 	case INSTR_ALU_SUB_HH: return "__instr_alu_sub_hh_exec";
13235 	case INSTR_ALU_SUB_MI: return "__instr_alu_sub_mi_exec";
13236 	case INSTR_ALU_SUB_HI: return "__instr_alu_sub_hi_exec";
13237 
13238 	case INSTR_ALU_CKADD_FIELD: return "__instr_alu_ckadd_field_exec";
13239 	case INSTR_ALU_CKADD_STRUCT20: return "__instr_alu_ckadd_struct20_exec";
13240 	case INSTR_ALU_CKADD_STRUCT: return "__instr_alu_ckadd_struct_exec";
13241 	case INSTR_ALU_CKSUB_FIELD: return "__instr_alu_cksub_field_exec";
13242 
13243 	case INSTR_ALU_AND: return "__instr_alu_and_exec";
13244 	case INSTR_ALU_AND_MH: return "__instr_alu_and_mh_exec";
13245 	case INSTR_ALU_AND_HM: return "__instr_alu_and_hm_exec";
13246 	case INSTR_ALU_AND_HH: return "__instr_alu_and_hh_exec";
13247 	case INSTR_ALU_AND_I: return "__instr_alu_and_i_exec";
13248 
13249 	case INSTR_ALU_OR: return "__instr_alu_or_exec";
13250 	case INSTR_ALU_OR_MH: return "__instr_alu_or_mh_exec";
13251 	case INSTR_ALU_OR_HM: return "__instr_alu_or_hm_exec";
13252 	case INSTR_ALU_OR_HH: return "__instr_alu_or_hh_exec";
13253 	case INSTR_ALU_OR_I: return "__instr_alu_or_i_exec";
13254 
13255 	case INSTR_ALU_XOR: return "__instr_alu_xor_exec";
13256 	case INSTR_ALU_XOR_MH: return "__instr_alu_xor_mh_exec";
13257 	case INSTR_ALU_XOR_HM: return "__instr_alu_xor_hm_exec";
13258 	case INSTR_ALU_XOR_HH: return "__instr_alu_xor_hh_exec";
13259 	case INSTR_ALU_XOR_I: return "__instr_alu_xor_i_exec";
13260 
13261 	case INSTR_ALU_SHL: return "__instr_alu_shl_exec";
13262 	case INSTR_ALU_SHL_MH: return "__instr_alu_shl_mh_exec";
13263 	case INSTR_ALU_SHL_HM: return "__instr_alu_shl_hm_exec";
13264 	case INSTR_ALU_SHL_HH: return "__instr_alu_shl_hh_exec";
13265 	case INSTR_ALU_SHL_MI: return "__instr_alu_shl_mi_exec";
13266 	case INSTR_ALU_SHL_HI: return "__instr_alu_shl_hi_exec";
13267 
13268 	case INSTR_ALU_SHR: return "__instr_alu_shr_exec";
13269 	case INSTR_ALU_SHR_MH: return "__instr_alu_shr_mh_exec";
13270 	case INSTR_ALU_SHR_HM: return "__instr_alu_shr_hm_exec";
13271 	case INSTR_ALU_SHR_HH: return "__instr_alu_shr_hh_exec";
13272 	case INSTR_ALU_SHR_MI: return "__instr_alu_shr_mi_exec";
13273 	case INSTR_ALU_SHR_HI: return "__instr_alu_shr_hi_exec";
13274 
13275 	case INSTR_REGPREFETCH_RH: return "__instr_regprefetch_rh_exec";
13276 	case INSTR_REGPREFETCH_RM: return "__instr_regprefetch_rm_exec";
13277 	case INSTR_REGPREFETCH_RI: return "__instr_regprefetch_ri_exec";
13278 
13279 	case INSTR_REGRD_HRH: return "__instr_regrd_hrh_exec";
13280 	case INSTR_REGRD_HRM: return "__instr_regrd_hrm_exec";
13281 	case INSTR_REGRD_HRI: return "__instr_regrd_hri_exec";
13282 	case INSTR_REGRD_MRH: return "__instr_regrd_mrh_exec";
13283 	case INSTR_REGRD_MRM: return "__instr_regrd_mrm_exec";
13284 	case INSTR_REGRD_MRI: return "__instr_regrd_mri_exec";
13285 
13286 	case INSTR_REGWR_RHH: return "__instr_regwr_rhh_exec";
13287 	case INSTR_REGWR_RHM: return "__instr_regwr_rhm_exec";
13288 	case INSTR_REGWR_RHI: return "__instr_regwr_rhi_exec";
13289 	case INSTR_REGWR_RMH: return "__instr_regwr_rmh_exec";
13290 	case INSTR_REGWR_RMM: return "__instr_regwr_rmm_exec";
13291 	case INSTR_REGWR_RMI: return "__instr_regwr_rmi_exec";
13292 	case INSTR_REGWR_RIH: return "__instr_regwr_rih_exec";
13293 	case INSTR_REGWR_RIM: return "__instr_regwr_rim_exec";
13294 	case INSTR_REGWR_RII: return "__instr_regwr_rii_exec";
13295 
13296 	case INSTR_REGADD_RHH: return "__instr_regadd_rhh_exec";
13297 	case INSTR_REGADD_RHM: return "__instr_regadd_rhm_exec";
13298 	case INSTR_REGADD_RHI: return "__instr_regadd_rhi_exec";
13299 	case INSTR_REGADD_RMH: return "__instr_regadd_rmh_exec";
13300 	case INSTR_REGADD_RMM: return "__instr_regadd_rmm_exec";
13301 	case INSTR_REGADD_RMI: return "__instr_regadd_rmi_exec";
13302 	case INSTR_REGADD_RIH: return "__instr_regadd_rih_exec";
13303 	case INSTR_REGADD_RIM: return "__instr_regadd_rim_exec";
13304 	case INSTR_REGADD_RII: return "__instr_regadd_rii_exec";
13305 
13306 	case INSTR_METPREFETCH_H: return "__instr_metprefetch_h_exec";
13307 	case INSTR_METPREFETCH_M: return "__instr_metprefetch_m_exec";
13308 	case INSTR_METPREFETCH_I: return "__instr_metprefetch_i_exec";
13309 
13310 	case INSTR_METER_HHM: return "__instr_meter_hhm_exec";
13311 	case INSTR_METER_HHI: return "__instr_meter_hhi_exec";
13312 	case INSTR_METER_HMM: return "__instr_meter_hmm_exec";
13313 	case INSTR_METER_HMI: return "__instr_meter_hmi_exec";
13314 	case INSTR_METER_MHM: return "__instr_meter_mhm_exec";
13315 	case INSTR_METER_MHI: return "__instr_meter_mhi_exec";
13316 	case INSTR_METER_MMM: return "__instr_meter_mmm_exec";
13317 	case INSTR_METER_MMI: return "__instr_meter_mmi_exec";
13318 	case INSTR_METER_IHM: return "__instr_meter_ihm_exec";
13319 	case INSTR_METER_IHI: return "__instr_meter_ihi_exec";
13320 	case INSTR_METER_IMM: return "__instr_meter_imm_exec";
13321 	case INSTR_METER_IMI: return "__instr_meter_imi_exec";
13322 
13323 	case INSTR_TABLE: return NULL;
13324 	case INSTR_TABLE_AF: return NULL;
13325 	case INSTR_SELECTOR: return NULL;
13326 	case INSTR_LEARNER: return NULL;
13327 	case INSTR_LEARNER_AF: return NULL;
13328 
13329 	case INSTR_LEARNER_LEARN: return "__instr_learn_exec";
13330 	case INSTR_LEARNER_REARM: return "__instr_rearm_exec";
13331 	case INSTR_LEARNER_REARM_NEW: return "__instr_rearm_new_exec";
13332 	case INSTR_LEARNER_FORGET: return "__instr_forget_exec";
13333 	case INSTR_ENTRYID: return "__instr_entryid_exec";
13334 
13335 	case INSTR_EXTERN_OBJ: return NULL;
13336 	case INSTR_EXTERN_FUNC: return NULL;
13337 	case INSTR_HASH_FUNC: return "__instr_hash_func_exec";
13338 	case INSTR_RSS: return "__instr_rss_exec";
13339 
13340 	case INSTR_JMP: return NULL;
13341 	case INSTR_JMP_VALID: return NULL;
13342 	case INSTR_JMP_INVALID: return NULL;
13343 	case INSTR_JMP_HIT: return NULL;
13344 	case INSTR_JMP_MISS: return NULL;
13345 	case INSTR_JMP_ACTION_HIT: return NULL;
13346 	case INSTR_JMP_ACTION_MISS: return NULL;
13347 	case INSTR_JMP_EQ: return NULL;
13348 	case INSTR_JMP_EQ_MH: return NULL;
13349 	case INSTR_JMP_EQ_HM: return NULL;
13350 	case INSTR_JMP_EQ_HH: return NULL;
13351 	case INSTR_JMP_EQ_I: return NULL;
13352 	case INSTR_JMP_NEQ: return NULL;
13353 	case INSTR_JMP_NEQ_MH: return NULL;
13354 	case INSTR_JMP_NEQ_HM: return NULL;
13355 	case INSTR_JMP_NEQ_HH: return NULL;
13356 	case INSTR_JMP_NEQ_I: return NULL;
13357 	case INSTR_JMP_LT: return NULL;
13358 	case INSTR_JMP_LT_MH: return NULL;
13359 	case INSTR_JMP_LT_HM: return NULL;
13360 	case INSTR_JMP_LT_HH: return NULL;
13361 	case INSTR_JMP_LT_MI: return NULL;
13362 	case INSTR_JMP_LT_HI: return NULL;
13363 	case INSTR_JMP_GT: return NULL;
13364 	case INSTR_JMP_GT_MH: return NULL;
13365 	case INSTR_JMP_GT_HM: return NULL;
13366 	case INSTR_JMP_GT_HH: return NULL;
13367 	case INSTR_JMP_GT_MI: return NULL;
13368 	case INSTR_JMP_GT_HI: return NULL;
13369 
13370 	case INSTR_RETURN: return NULL;
13371 
13372 	default: return NULL;
13373 	}
13374 }
13375 
13376 static void
action_instr_does_tx_codegen(struct action * a,uint32_t instr_pos,struct instruction * instr,FILE * f)13377 action_instr_does_tx_codegen(struct action *a,
13378 			uint32_t instr_pos,
13379 			struct instruction *instr,
13380 			FILE *f)
13381 {
13382 	fprintf(f,
13383 		"%s(p, t, &action_%s_instructions[%u]);\n"
13384 		"\tthread_ip_reset(p, t);\n"
13385 		"\tinstr_rx_exec(p);\n"
13386 		"\treturn;\n",
13387 		instr_type_to_func(instr),
13388 		a->name,
13389 		instr_pos);
13390 }
13391 
13392 static void
action_instr_extern_obj_codegen(struct action * a,uint32_t instr_pos,FILE * f)13393 action_instr_extern_obj_codegen(struct action *a,
13394 				uint32_t instr_pos,
13395 				FILE *f)
13396 {
13397 	fprintf(f,
13398 		"while (!__instr_extern_obj_exec(p, t, &action_%s_instructions[%u]));\n",
13399 		a->name,
13400 		instr_pos);
13401 }
13402 
13403 static void
action_instr_extern_func_codegen(struct action * a,uint32_t instr_pos,FILE * f)13404 action_instr_extern_func_codegen(struct action *a,
13405 				 uint32_t instr_pos,
13406 				 FILE *f)
13407 {
13408 	fprintf(f,
13409 		"while (!__instr_extern_func_exec(p, t, &action_%s_instructions[%u]));\n",
13410 		a->name,
13411 		instr_pos);
13412 }
13413 
13414 static void
action_instr_jmp_codegen(struct action * a,uint32_t instr_pos,struct instruction * instr,struct instruction_data * data,FILE * f)13415 action_instr_jmp_codegen(struct action *a,
13416 			 uint32_t instr_pos,
13417 			 struct instruction *instr,
13418 			 struct instruction_data *data,
13419 			 FILE *f)
13420 {
13421 	switch (instr->type) {
13422 	case INSTR_JMP:
13423 		fprintf(f,
13424 			"goto %s;\n",
13425 			data->jmp_label);
13426 		return;
13427 
13428 	case INSTR_JMP_VALID:
13429 		fprintf(f,
13430 			"if (HEADER_VALID(t, action_%s_instructions[%u].jmp.header_id))\n"
13431 			"\t\tgoto %s;\n",
13432 			a->name,
13433 			instr_pos,
13434 			data->jmp_label);
13435 		return;
13436 
13437 	case INSTR_JMP_INVALID:
13438 		fprintf(f,
13439 			"if (!HEADER_VALID(t, action_%s_instructions[%u].jmp.header_id))\n"
13440 			"\t\tgoto %s;\n",
13441 			a->name,
13442 			instr_pos,
13443 			data->jmp_label);
13444 		return;
13445 
13446 	case INSTR_JMP_HIT:
13447 		fprintf(f,
13448 			"if (t->hit)\n"
13449 			"\t\tgoto %s;\n",
13450 			data->jmp_label);
13451 		return;
13452 
13453 	case INSTR_JMP_MISS:
13454 		fprintf(f,
13455 			"if (!t->hit)\n"
13456 			"\t\tgoto %s;\n",
13457 			data->jmp_label);
13458 		return;
13459 
13460 	case INSTR_JMP_ACTION_HIT:
13461 		fprintf(f,
13462 			"if (t->action_id == action_%s_instructions[%u].jmp.action_id)\n"
13463 			"\t\tgoto %s;\n",
13464 			a->name,
13465 			instr_pos,
13466 			data->jmp_label);
13467 		return;
13468 
13469 	case INSTR_JMP_ACTION_MISS:
13470 		fprintf(f,
13471 			"if (t->action_id != action_%s_instructions[%u].jmp.action_id)\n"
13472 			"\t\tgoto %s;\n",
13473 			a->name,
13474 			instr_pos,
13475 			data->jmp_label);
13476 		return;
13477 
13478 	case INSTR_JMP_EQ:
13479 		fprintf(f,
13480 			"if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) == "
13481 			"instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
13482 			"\t\tgoto %s;\n",
13483 			a->name,
13484 			instr_pos,
13485 			a->name,
13486 			instr_pos,
13487 			data->jmp_label);
13488 		return;
13489 
13490 	case INSTR_JMP_EQ_MH:
13491 		fprintf(f,
13492 			"if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) == "
13493 			"instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
13494 			"\t\tgoto %s;\n",
13495 			a->name,
13496 			instr_pos,
13497 			a->name,
13498 			instr_pos,
13499 			data->jmp_label);
13500 		return;
13501 
13502 	case INSTR_JMP_EQ_HM:
13503 		fprintf(f,
13504 			"if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) == "
13505 			"instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
13506 			"\t\tgoto %s;\n",
13507 			a->name,
13508 			instr_pos,
13509 			a->name,
13510 			instr_pos,
13511 			data->jmp_label);
13512 		return;
13513 
13514 	case INSTR_JMP_EQ_HH:
13515 		fprintf(f,
13516 			"if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) == "
13517 			"instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
13518 			"\t\tgoto %s;\n",
13519 			a->name,
13520 			instr_pos,
13521 			a->name,
13522 			instr_pos,
13523 			data->jmp_label);
13524 		return;
13525 
13526 	case INSTR_JMP_EQ_I:
13527 		fprintf(f,
13528 			"if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) == "
13529 			"action_%s_instructions[%u].jmp.b_val)\n"
13530 			"\t\tgoto %s;\n",
13531 			a->name,
13532 			instr_pos,
13533 			a->name,
13534 			instr_pos,
13535 			data->jmp_label);
13536 		return;
13537 
13538 	case INSTR_JMP_NEQ:
13539 		fprintf(f,
13540 			"if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) != "
13541 			"instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
13542 			"\t\tgoto %s;\n",
13543 			a->name,
13544 			instr_pos,
13545 			a->name,
13546 			instr_pos,
13547 			data->jmp_label);
13548 		return;
13549 
13550 	case INSTR_JMP_NEQ_MH:
13551 		fprintf(f,
13552 			"if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) != "
13553 			"instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
13554 			"\t\tgoto %s;\n",
13555 			a->name,
13556 			instr_pos,
13557 			a->name,
13558 			instr_pos,
13559 			data->jmp_label);
13560 		return;
13561 
13562 	case INSTR_JMP_NEQ_HM:
13563 		fprintf(f,
13564 			"if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) != "
13565 			"instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
13566 			"\t\tgoto %s;\n",
13567 			a->name,
13568 			instr_pos,
13569 			a->name,
13570 			instr_pos,
13571 			data->jmp_label);
13572 		return;
13573 
13574 	case INSTR_JMP_NEQ_HH:
13575 		fprintf(f,
13576 			"if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) != "
13577 			"instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
13578 			"\t\tgoto %s;\n",
13579 			a->name,
13580 			instr_pos,
13581 			a->name,
13582 			instr_pos,
13583 			data->jmp_label);
13584 		return;
13585 
13586 	case INSTR_JMP_NEQ_I:
13587 		fprintf(f,
13588 			"if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) != "
13589 			"action_%s_instructions[%u].jmp.b_val)\n"
13590 			"\t\tgoto %s;\n",
13591 			a->name,
13592 			instr_pos,
13593 			a->name,
13594 			instr_pos,
13595 			data->jmp_label);
13596 		return;
13597 
13598 	case INSTR_JMP_LT:
13599 		fprintf(f,
13600 			"if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) < "
13601 			"instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
13602 			"\t\tgoto %s;\n",
13603 			a->name,
13604 			instr_pos,
13605 			a->name,
13606 			instr_pos,
13607 			data->jmp_label);
13608 		return;
13609 
13610 	case INSTR_JMP_LT_MH:
13611 		fprintf(f,
13612 			"if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) < "
13613 			"instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
13614 			"\t\tgoto %s;\n",
13615 			a->name,
13616 			instr_pos,
13617 			a->name,
13618 			instr_pos,
13619 			data->jmp_label);
13620 		return;
13621 
13622 	case INSTR_JMP_LT_HM:
13623 		fprintf(f,
13624 			"if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) < "
13625 			"instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
13626 			"\t\tgoto %s;\n",
13627 			a->name,
13628 			instr_pos,
13629 			a->name,
13630 			instr_pos,
13631 			data->jmp_label);
13632 		return;
13633 
13634 	case INSTR_JMP_LT_HH:
13635 		fprintf(f,
13636 			"if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) < "
13637 			"instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
13638 			"\t\tgoto %s;\n",
13639 			a->name,
13640 			instr_pos,
13641 			a->name,
13642 			instr_pos,
13643 			data->jmp_label);
13644 		return;
13645 
13646 	case INSTR_JMP_LT_MI:
13647 		fprintf(f,
13648 			"if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) < "
13649 			"action_%s_instructions[%u].jmp.b_val)\n"
13650 			"\t\tgoto %s;\n",
13651 			a->name,
13652 			instr_pos,
13653 			a->name,
13654 			instr_pos,
13655 			data->jmp_label);
13656 		return;
13657 
13658 	case INSTR_JMP_LT_HI:
13659 		fprintf(f,
13660 			"if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) < "
13661 			"action_%s_instructions[%u].jmp.b_val)\n"
13662 			"\t\tgoto %s;\n",
13663 			a->name,
13664 			instr_pos,
13665 			a->name,
13666 			instr_pos,
13667 			data->jmp_label);
13668 		return;
13669 
13670 	case INSTR_JMP_GT:
13671 		fprintf(f,
13672 			"if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) > "
13673 			"instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
13674 			"\t\tgoto %s;\n",
13675 			a->name,
13676 			instr_pos,
13677 			a->name,
13678 			instr_pos,
13679 			data->jmp_label);
13680 		return;
13681 
13682 	case INSTR_JMP_GT_MH:
13683 		fprintf(f,
13684 			"if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) > "
13685 			"instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
13686 			"\t\tgoto %s;\n",
13687 			a->name,
13688 			instr_pos,
13689 			a->name,
13690 			instr_pos,
13691 			data->jmp_label);
13692 		return;
13693 
13694 	case INSTR_JMP_GT_HM:
13695 		fprintf(f,
13696 			"if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) > "
13697 			"instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
13698 			"\t\tgoto %s;\n",
13699 			a->name,
13700 			instr_pos,
13701 			a->name,
13702 			instr_pos,
13703 			data->jmp_label);
13704 		return;
13705 
13706 	case INSTR_JMP_GT_HH:
13707 		fprintf(f,
13708 			"if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) > "
13709 			"instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
13710 			"\t\tgoto %s;\n",
13711 			a->name,
13712 			instr_pos,
13713 			a->name,
13714 			instr_pos,
13715 			data->jmp_label);
13716 		return;
13717 
13718 	case INSTR_JMP_GT_MI:
13719 		fprintf(f,
13720 			"if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) > "
13721 			"action_%s_instructions[%u].jmp.b_val)\n"
13722 			"\t\tgoto %s;\n",
13723 			a->name,
13724 			instr_pos,
13725 			a->name,
13726 			instr_pos,
13727 			data->jmp_label);
13728 		return;
13729 
13730 	case INSTR_JMP_GT_HI:
13731 		fprintf(f,
13732 			"if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) > "
13733 			"action_%s_instructions[%u].jmp.b_val)\n"
13734 			"\t\tgoto %s;\n",
13735 			a->name,
13736 			instr_pos,
13737 			a->name,
13738 			instr_pos,
13739 			data->jmp_label);
13740 		return;
13741 
13742 	default:
13743 		return;
13744 	}
13745 }
13746 
13747 static void
action_instr_return_codegen(FILE * f)13748 action_instr_return_codegen(FILE *f)
13749 {
13750 	fprintf(f,
13751 		"return;\n");
13752 }
13753 
13754 static void
action_instr_codegen(struct action * a,FILE * f)13755 action_instr_codegen(struct action *a, FILE *f)
13756 {
13757 	uint32_t i;
13758 
13759 	fprintf(f,
13760 		"void\n"
13761 		"action_%s_run(struct rte_swx_pipeline *p)\n"
13762 		"{\n"
13763 		"\tstruct thread *t = &p->threads[p->thread_id];\n"
13764 		"\n",
13765 		a->name);
13766 
13767 	for (i = 0; i < a->n_instructions; i++) {
13768 		struct instruction *instr = &a->instructions[i];
13769 		struct instruction_data *data = &a->instruction_data[i];
13770 
13771 		/* Label, if present. */
13772 		if (data->label[0])
13773 			fprintf(f, "\n%s : ", data->label);
13774 		else
13775 			fprintf(f, "\n\t");
13776 
13777 		/* TX instruction type. */
13778 		if (instruction_does_tx(instr)) {
13779 			action_instr_does_tx_codegen(a, i, instr, f);
13780 			continue;
13781 		}
13782 
13783 		/* Extern object/function instruction type. */
13784 		if (instr->type == INSTR_EXTERN_OBJ) {
13785 			action_instr_extern_obj_codegen(a, i, f);
13786 			continue;
13787 		}
13788 
13789 		if (instr->type == INSTR_EXTERN_FUNC) {
13790 			action_instr_extern_func_codegen(a, i, f);
13791 			continue;
13792 		}
13793 
13794 		/* Jump instruction type. */
13795 		if (instruction_is_jmp(instr)) {
13796 			action_instr_jmp_codegen(a, i, instr, data, f);
13797 			continue;
13798 		}
13799 
13800 		/* Return instruction type. */
13801 		if (instr->type == INSTR_RETURN) {
13802 			action_instr_return_codegen(f);
13803 			continue;
13804 		}
13805 
13806 		/* Any other instruction type. */
13807 		fprintf(f,
13808 			"%s(p, t, &action_%s_instructions[%u]);\n",
13809 			instr_type_to_func(instr),
13810 			a->name,
13811 			i);
13812 	}
13813 
13814 	fprintf(f, "}\n\n");
13815 }
13816 
13817 struct instruction_group {
13818 	TAILQ_ENTRY(instruction_group) node;
13819 
13820 	uint32_t group_id;
13821 
13822 	uint32_t first_instr_id;
13823 
13824 	uint32_t last_instr_id;
13825 
13826 	instr_exec_t func;
13827 };
13828 
13829 TAILQ_HEAD(instruction_group_list, instruction_group);
13830 
13831 static struct instruction_group *
instruction_group_list_group_find(struct instruction_group_list * igl,uint32_t instruction_id)13832 instruction_group_list_group_find(struct instruction_group_list *igl, uint32_t instruction_id)
13833 {
13834 	struct instruction_group *g;
13835 
13836 	TAILQ_FOREACH(g, igl, node)
13837 		if ((g->first_instr_id <= instruction_id) && (instruction_id <= g->last_instr_id))
13838 			return g;
13839 
13840 	return NULL;
13841 }
13842 
13843 static void
instruction_group_list_free(struct instruction_group_list * igl)13844 instruction_group_list_free(struct instruction_group_list *igl)
13845 {
13846 	if (!igl)
13847 		return;
13848 
13849 	for ( ; ; ) {
13850 		struct instruction_group *g;
13851 
13852 		g = TAILQ_FIRST(igl);
13853 		if (!g)
13854 			break;
13855 
13856 		TAILQ_REMOVE(igl, g, node);
13857 		free(g);
13858 	}
13859 
13860 	free(igl);
13861 }
13862 
13863 static struct instruction_group_list *
instruction_group_list_create(struct rte_swx_pipeline * p)13864 instruction_group_list_create(struct rte_swx_pipeline *p)
13865 {
13866 	struct instruction_group_list *igl = NULL;
13867 	struct instruction_group *g = NULL;
13868 	uint32_t n_groups = 0, i;
13869 
13870 	if (!p || !p->instructions || !p->instruction_data || !p->n_instructions)
13871 		goto error;
13872 
13873 	/* List init. */
13874 	igl = calloc(1, sizeof(struct instruction_group_list));
13875 	if (!igl)
13876 		goto error;
13877 
13878 	TAILQ_INIT(igl);
13879 
13880 	/* Allocate the first group. */
13881 	g = calloc(1, sizeof(struct instruction_group));
13882 	if (!g)
13883 		goto error;
13884 
13885 	/* Iteration 1: Separate the instructions into groups based on the thread yield
13886 	 * instructions. Do not worry about the jump instructions at this point.
13887 	 */
13888 	for (i = 0; i < p->n_instructions; i++) {
13889 		struct instruction *instr = &p->instructions[i];
13890 
13891 		/* Check for thread yield instructions. */
13892 		if (!instruction_does_thread_yield(instr))
13893 			continue;
13894 
13895 		/* If the current group contains at least one instruction, then finalize it (with
13896 		 * the previous instruction), add it to the list and allocate a new group (that
13897 		 * starts with the current instruction).
13898 		 */
13899 		if (i - g->first_instr_id) {
13900 			/* Finalize the group. */
13901 			g->last_instr_id = i - 1;
13902 
13903 			/* Add the group to the list. Advance the number of groups. */
13904 			TAILQ_INSERT_TAIL(igl, g, node);
13905 			n_groups++;
13906 
13907 			/* Allocate a new group. */
13908 			g = calloc(1, sizeof(struct instruction_group));
13909 			if (!g)
13910 				goto error;
13911 
13912 			/* Initialize the new group. */
13913 			g->group_id = n_groups;
13914 			g->first_instr_id = i;
13915 		}
13916 
13917 		/* Finalize the current group (with the current instruction, therefore this group
13918 		 * contains just the current thread yield instruction), add it to the list and
13919 		 * allocate a new group (that starts with the next instruction).
13920 		 */
13921 
13922 		/* Finalize the group. */
13923 		g->last_instr_id = i;
13924 
13925 		/* Add the group to the list. Advance the number of groups. */
13926 		TAILQ_INSERT_TAIL(igl, g, node);
13927 		n_groups++;
13928 
13929 		/* Allocate a new group. */
13930 		g = calloc(1, sizeof(struct instruction_group));
13931 		if (!g)
13932 			goto error;
13933 
13934 		/* Initialize the new group. */
13935 		g->group_id = n_groups;
13936 		g->first_instr_id = i + 1;
13937 	}
13938 
13939 	/* Handle the last group. */
13940 	if (i - g->first_instr_id) {
13941 		/* Finalize the group. */
13942 		g->last_instr_id = i - 1;
13943 
13944 		/* Add the group to the list. Advance the number of groups. */
13945 		TAILQ_INSERT_TAIL(igl, g, node);
13946 		n_groups++;
13947 	} else
13948 		free(g);
13949 
13950 	g = NULL;
13951 
13952 	/* Iteration 2: Handle jumps. If the current group contains an instruction which represents
13953 	 * the destination of a jump instruction located in a different group ("far jump"), then the
13954 	 * current group has to be split, so that the instruction representing the far jump
13955 	 * destination is at the start of its group.
13956 	 */
13957 	for ( ; ; ) {
13958 		int is_modified = 0;
13959 
13960 		for (i = 0; i < p->n_instructions; i++) {
13961 			struct instruction_data *data = &p->instruction_data[i];
13962 			struct instruction_group *g;
13963 			uint32_t j;
13964 
13965 			/* Continue when the current instruction is not a jump destination. */
13966 			if (!data->n_users)
13967 				continue;
13968 
13969 			g = instruction_group_list_group_find(igl, i);
13970 			if (!g)
13971 				goto error;
13972 
13973 			/* Find out all the jump instructions with this destination. */
13974 			for (j = 0; j < p->n_instructions; j++) {
13975 				struct instruction *jmp_instr = &p->instructions[j];
13976 				struct instruction_data *jmp_data = &p->instruction_data[j];
13977 				struct instruction_group *jmp_g, *new_g;
13978 
13979 				/* Continue when not a jump instruction. Even when jump instruction,
13980 				 * continue when the jump destination is not this instruction.
13981 				 */
13982 				if (!instruction_is_jmp(jmp_instr) ||
13983 				    strcmp(jmp_data->jmp_label, data->label))
13984 					continue;
13985 
13986 				jmp_g = instruction_group_list_group_find(igl, j);
13987 				if (!jmp_g)
13988 					goto error;
13989 
13990 				/* Continue when both the jump instruction and the jump destination
13991 				 * instruction are in the same group. Even when in different groups,
13992 				 * still continue if the jump destination instruction is already the
13993 				 * first instruction of its group.
13994 				 */
13995 				if ((jmp_g->group_id == g->group_id) || (g->first_instr_id == i))
13996 					continue;
13997 
13998 				/* Split the group of the current jump destination instruction to
13999 				 * make this instruction the first instruction of a new group.
14000 				 */
14001 				new_g = calloc(1, sizeof(struct instruction_group));
14002 				if (!new_g)
14003 					goto error;
14004 
14005 				new_g->group_id = n_groups;
14006 				new_g->first_instr_id = i;
14007 				new_g->last_instr_id = g->last_instr_id;
14008 
14009 				g->last_instr_id = i - 1;
14010 
14011 				TAILQ_INSERT_AFTER(igl, g, new_g, node);
14012 				n_groups++;
14013 				is_modified = 1;
14014 
14015 				/* The decision to split this group (to make the current instruction
14016 				 * the first instruction of a new group) is already taken and fully
14017 				 * implemented, so no need to search for more reasons to do it.
14018 				 */
14019 				break;
14020 			}
14021 		}
14022 
14023 		/* Re-evaluate everything, as at least one group got split, so some jumps that were
14024 		 * previously considered local (i.e. the jump destination is in the same group as
14025 		 * the jump instruction) can now be "far jumps" (i.e. the jump destination is in a
14026 		 * different group than the jump instruction). Wost case scenario: each instruction
14027 		 * that is a jump destination ends up as the first instruction of its group.
14028 		 */
14029 		if (!is_modified)
14030 			break;
14031 	}
14032 
14033 	/* Re-assign the group IDs to be in incremental order. */
14034 	i = 0;
14035 	TAILQ_FOREACH(g, igl, node) {
14036 		g->group_id = i;
14037 
14038 		i++;
14039 	}
14040 
14041 	return igl;
14042 
14043 error:
14044 	instruction_group_list_free(igl);
14045 
14046 	free(g);
14047 
14048 	return NULL;
14049 }
14050 
14051 static void
pipeline_instr_does_tx_codegen(struct rte_swx_pipeline * p __rte_unused,uint32_t instr_pos,struct instruction * instr,FILE * f)14052 pipeline_instr_does_tx_codegen(struct rte_swx_pipeline *p __rte_unused,
14053 			       uint32_t instr_pos,
14054 			       struct instruction *instr,
14055 			       FILE *f)
14056 {
14057 	fprintf(f,
14058 		"%s(p, t, &pipeline_instructions[%u]);\n"
14059 		"\tthread_ip_reset(p, t);\n"
14060 		"\tinstr_rx_exec(p);\n"
14061 		"\treturn;\n",
14062 		instr_type_to_func(instr),
14063 		instr_pos);
14064 }
14065 
14066 static int
pipeline_instr_jmp_codegen(struct rte_swx_pipeline * p,struct instruction_group_list * igl,uint32_t jmp_instr_id,struct instruction * jmp_instr,struct instruction_data * jmp_data,FILE * f)14067 pipeline_instr_jmp_codegen(struct rte_swx_pipeline *p,
14068 			   struct instruction_group_list *igl,
14069 			   uint32_t jmp_instr_id,
14070 			   struct instruction *jmp_instr,
14071 			   struct instruction_data *jmp_data,
14072 			   FILE *f)
14073 {
14074 	struct instruction_group *jmp_g, *g;
14075 	struct instruction_data *data;
14076 	uint32_t instr_id;
14077 
14078 	switch (jmp_instr->type) {
14079 	case INSTR_JMP:
14080 		break;
14081 
14082 	case INSTR_JMP_VALID:
14083 		fprintf(f,
14084 			"if (HEADER_VALID(t, pipeline_instructions[%u].jmp.header_id))",
14085 			jmp_instr_id);
14086 		break;
14087 
14088 	case INSTR_JMP_INVALID:
14089 		fprintf(f,
14090 			"if (!HEADER_VALID(t, pipeline_instructions[%u].jmp.header_id))",
14091 			jmp_instr_id);
14092 		break;
14093 
14094 	case INSTR_JMP_HIT:
14095 		fprintf(f,
14096 			"if (t->hit)\n");
14097 		break;
14098 
14099 	case INSTR_JMP_MISS:
14100 		fprintf(f,
14101 			"if (!t->hit)\n");
14102 		break;
14103 
14104 	case INSTR_JMP_ACTION_HIT:
14105 		fprintf(f,
14106 			"if (t->action_id == pipeline_instructions[%u].jmp.action_id)",
14107 			jmp_instr_id);
14108 		break;
14109 
14110 	case INSTR_JMP_ACTION_MISS:
14111 		fprintf(f,
14112 			"if (t->action_id != pipeline_instructions[%u].jmp.action_id)",
14113 			jmp_instr_id);
14114 		break;
14115 
14116 	case INSTR_JMP_EQ:
14117 		fprintf(f,
14118 			"if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) == "
14119 			"instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
14120 			jmp_instr_id,
14121 			jmp_instr_id);
14122 		break;
14123 
14124 	case INSTR_JMP_EQ_MH:
14125 		fprintf(f,
14126 			"if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) == "
14127 			"instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
14128 			jmp_instr_id,
14129 			jmp_instr_id);
14130 		break;
14131 
14132 	case INSTR_JMP_EQ_HM:
14133 		fprintf(f,
14134 			"if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) == "
14135 			"instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
14136 			jmp_instr_id,
14137 			jmp_instr_id);
14138 		break;
14139 
14140 	case INSTR_JMP_EQ_HH:
14141 		fprintf(f,
14142 			"if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) == "
14143 			"instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
14144 			jmp_instr_id,
14145 			jmp_instr_id);
14146 		break;
14147 
14148 	case INSTR_JMP_EQ_I:
14149 		fprintf(f,
14150 			"if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) == "
14151 			"pipeline_instructions[%u].jmp.b_val)",
14152 			jmp_instr_id,
14153 			jmp_instr_id);
14154 		break;
14155 
14156 	case INSTR_JMP_NEQ:
14157 		fprintf(f,
14158 			"if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) != "
14159 			"instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
14160 			jmp_instr_id,
14161 			jmp_instr_id);
14162 		break;
14163 
14164 	case INSTR_JMP_NEQ_MH:
14165 		fprintf(f,
14166 			"if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) != "
14167 			"instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
14168 			jmp_instr_id,
14169 			jmp_instr_id);
14170 		break;
14171 
14172 	case INSTR_JMP_NEQ_HM:
14173 		fprintf(f,
14174 			"if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) != "
14175 			"instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
14176 			jmp_instr_id,
14177 			jmp_instr_id);
14178 		break;
14179 
14180 	case INSTR_JMP_NEQ_HH:
14181 		fprintf(f,
14182 			"if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) != "
14183 			"instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
14184 			jmp_instr_id,
14185 			jmp_instr_id);
14186 		break;
14187 
14188 	case INSTR_JMP_NEQ_I:
14189 		fprintf(f,
14190 			"if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) != "
14191 			"pipeline_instructions[%u].jmp.b_val)",
14192 			jmp_instr_id,
14193 			jmp_instr_id);
14194 		break;
14195 
14196 	case INSTR_JMP_LT:
14197 		fprintf(f,
14198 			"if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) < "
14199 			"instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
14200 			jmp_instr_id,
14201 			jmp_instr_id);
14202 		break;
14203 
14204 	case INSTR_JMP_LT_MH:
14205 		fprintf(f,
14206 			"if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) < "
14207 			"instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
14208 			jmp_instr_id,
14209 			jmp_instr_id);
14210 		break;
14211 
14212 	case INSTR_JMP_LT_HM:
14213 		fprintf(f,
14214 			"if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) < "
14215 			"instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
14216 			jmp_instr_id,
14217 			jmp_instr_id);
14218 		break;
14219 
14220 	case INSTR_JMP_LT_HH:
14221 		fprintf(f,
14222 			"if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) < "
14223 			"instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
14224 			jmp_instr_id,
14225 			jmp_instr_id);
14226 		break;
14227 
14228 	case INSTR_JMP_LT_MI:
14229 		fprintf(f,
14230 			"if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) < "
14231 			"pipeline_instructions[%u].jmp.b_val)",
14232 			jmp_instr_id,
14233 			jmp_instr_id);
14234 		break;
14235 
14236 	case INSTR_JMP_LT_HI:
14237 		fprintf(f,
14238 			"if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) < "
14239 			"pipeline_instructions[%u].jmp.b_val)",
14240 			jmp_instr_id,
14241 			jmp_instr_id);
14242 		break;
14243 
14244 	case INSTR_JMP_GT:
14245 		fprintf(f,
14246 			"if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) > "
14247 			"instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
14248 			jmp_instr_id,
14249 			jmp_instr_id);
14250 		break;
14251 
14252 	case INSTR_JMP_GT_MH:
14253 		fprintf(f,
14254 			"if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) > "
14255 			"instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
14256 			jmp_instr_id,
14257 			jmp_instr_id);
14258 		break;
14259 
14260 	case INSTR_JMP_GT_HM:
14261 		fprintf(f,
14262 			"if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) > "
14263 			"instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
14264 			jmp_instr_id,
14265 			jmp_instr_id);
14266 		break;
14267 
14268 	case INSTR_JMP_GT_HH:
14269 		fprintf(f,
14270 			"if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) > "
14271 			"instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
14272 			jmp_instr_id,
14273 			jmp_instr_id);
14274 		break;
14275 
14276 	case INSTR_JMP_GT_MI:
14277 		fprintf(f,
14278 			"if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) > "
14279 			"pipeline_instructions[%u].jmp.b_val)",
14280 			jmp_instr_id,
14281 			jmp_instr_id);
14282 		break;
14283 
14284 	case INSTR_JMP_GT_HI:
14285 		fprintf(f,
14286 			"if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) > "
14287 			"pipeline_instructions[%u].jmp.b_val)",
14288 			jmp_instr_id,
14289 			jmp_instr_id);
14290 		break;
14291 
14292 	default:
14293 		break;
14294 	}
14295 
14296 	/* Find the instruction group of the jump instruction. */
14297 	jmp_g = instruction_group_list_group_find(igl, jmp_instr_id);
14298 	if (!jmp_g)
14299 		return -EINVAL;
14300 
14301 	/* Find the instruction group of the jump destination instruction. */
14302 	data = label_find(p->instruction_data, p->n_instructions, jmp_data->jmp_label);
14303 	if (!data)
14304 		return -EINVAL;
14305 
14306 	instr_id = data - p->instruction_data;
14307 
14308 	g = instruction_group_list_group_find(igl, instr_id);
14309 	if (!g)
14310 		return -EINVAL;
14311 
14312 	/* Code generation for "near" jump (same instruction group) or "far" jump (different
14313 	 * instruction group).
14314 	 */
14315 	if (g->group_id == jmp_g->group_id)
14316 		fprintf(f,
14317 			"\n\t\tgoto %s;\n",
14318 			jmp_data->jmp_label);
14319 	else
14320 		fprintf(f,
14321 			" {\n"
14322 			"\t\tthread_ip_set(t, &p->instructions[%u]);\n"
14323 			"\t\treturn;\n"
14324 			"\t}\n\n",
14325 			g->group_id);
14326 
14327 	return 0;
14328 }
14329 
14330 static void
instruction_group_list_codegen(struct instruction_group_list * igl,struct rte_swx_pipeline * p,FILE * f)14331 instruction_group_list_codegen(struct instruction_group_list *igl,
14332 			       struct rte_swx_pipeline *p,
14333 			       FILE *f)
14334 {
14335 	struct instruction_group *g;
14336 	uint32_t i;
14337 	int is_required = 0;
14338 
14339 	/* Check if code generation is required. */
14340 	TAILQ_FOREACH(g, igl, node)
14341 		if (g->first_instr_id < g->last_instr_id)
14342 			is_required = 1;
14343 
14344 	if (!is_required)
14345 		return;
14346 
14347 	/* Generate the code for the pipeline instruction array. */
14348 	fprintf(f,
14349 		"static const struct instruction pipeline_instructions[] = {\n");
14350 
14351 	for (i = 0; i < p->n_instructions; i++) {
14352 		struct instruction *instr = &p->instructions[i];
14353 		instruction_export_t func = export_table[instr->type];
14354 
14355 		func(instr, f);
14356 	}
14357 
14358 	fprintf(f, "};\n\n");
14359 
14360 	/* Generate the code for the pipeline functions: one function for each instruction group
14361 	 * that contains more than one instruction.
14362 	 */
14363 	TAILQ_FOREACH(g, igl, node) {
14364 		struct instruction *last_instr;
14365 		uint32_t j;
14366 
14367 		/* Skip if group contains a single instruction. */
14368 		if (g->last_instr_id == g->first_instr_id)
14369 			continue;
14370 
14371 		/* Generate new pipeline function. */
14372 		fprintf(f,
14373 			"void\n"
14374 			"pipeline_func_%u(struct rte_swx_pipeline *p)\n"
14375 			"{\n"
14376 			"\tstruct thread *t = &p->threads[p->thread_id];\n"
14377 			"\n",
14378 			g->group_id);
14379 
14380 		/* Generate the code for each pipeline instruction. */
14381 		for (j = g->first_instr_id; j <= g->last_instr_id; j++) {
14382 			struct instruction *instr = &p->instructions[j];
14383 			struct instruction_data *data = &p->instruction_data[j];
14384 
14385 			/* Label, if present. */
14386 			if (data->label[0])
14387 				fprintf(f, "\n%s : ", data->label);
14388 			else
14389 				fprintf(f, "\n\t");
14390 
14391 			/* TX instruction type. */
14392 			if (instruction_does_tx(instr)) {
14393 				pipeline_instr_does_tx_codegen(p, j, instr, f);
14394 				continue;
14395 			}
14396 
14397 			/* Jump instruction type. */
14398 			if (instruction_is_jmp(instr)) {
14399 				pipeline_instr_jmp_codegen(p, igl, j, instr, data, f);
14400 				continue;
14401 			}
14402 
14403 			/* Any other instruction type. */
14404 			fprintf(f,
14405 				"%s(p, t, &pipeline_instructions[%u]);\n",
14406 				instr_type_to_func(instr),
14407 				j);
14408 		}
14409 
14410 		/* Finalize the generated pipeline function. For some instructions such as TX,
14411 		 * emit-many-and-TX and unconditional jump, the next instruction has been already
14412 		 * decided unconditionally and the instruction pointer of the current thread set
14413 		 * accordingly; for all the other instructions, the instruction pointer must be
14414 		 * incremented now.
14415 		 */
14416 		last_instr = &p->instructions[g->last_instr_id];
14417 
14418 		if (!instruction_does_tx(last_instr) && (last_instr->type != INSTR_JMP))
14419 			fprintf(f,
14420 				"thread_ip_inc(p);\n");
14421 
14422 		fprintf(f,
14423 			"}\n"
14424 			"\n");
14425 	}
14426 }
14427 
14428 static uint32_t
instruction_group_list_custom_instructions_count(struct instruction_group_list * igl)14429 instruction_group_list_custom_instructions_count(struct instruction_group_list *igl)
14430 {
14431 	struct instruction_group *g;
14432 	uint32_t n_custom_instr = 0;
14433 
14434 	/* Groups with a single instruction: no function is generated for this group, the group
14435 	 * keeps its current instruction. Groups with more than two instructions: one function and
14436 	 * the associated custom instruction get generated for each such group.
14437 	 */
14438 	TAILQ_FOREACH(g, igl, node) {
14439 		if (g->first_instr_id == g->last_instr_id)
14440 			continue;
14441 
14442 		n_custom_instr++;
14443 	}
14444 
14445 	return n_custom_instr;
14446 }
14447 
14448 static int
pipeline_adjust_check(struct rte_swx_pipeline * p __rte_unused,struct instruction_group_list * igl)14449 pipeline_adjust_check(struct rte_swx_pipeline *p __rte_unused,
14450 		      struct instruction_group_list *igl)
14451 {
14452 	uint32_t n_custom_instr = instruction_group_list_custom_instructions_count(igl);
14453 
14454 	/* Check that enough space is available within the pipeline instruction table to store all
14455 	 * the custom instructions.
14456 	 */
14457 	if (INSTR_CUSTOM_0 + n_custom_instr > RTE_SWX_PIPELINE_INSTRUCTION_TABLE_SIZE_MAX)
14458 		return -ENOSPC;
14459 
14460 	return 0;
14461 }
14462 
14463 static void
pipeline_adjust(struct rte_swx_pipeline * p,struct instruction_group_list * igl)14464 pipeline_adjust(struct rte_swx_pipeline *p, struct instruction_group_list *igl)
14465 {
14466 	struct instruction_group *g;
14467 	uint32_t i;
14468 
14469 	/* Pipeline table instructions. */
14470 	for (i = 0; i < p->n_instructions; i++) {
14471 		struct instruction *instr = &p->instructions[i];
14472 
14473 		if (instr->type == INSTR_TABLE)
14474 			instr->type = INSTR_TABLE_AF;
14475 
14476 		if (instr->type == INSTR_LEARNER)
14477 			instr->type = INSTR_LEARNER_AF;
14478 	}
14479 
14480 	/* Pipeline custom instructions. */
14481 	i = 0;
14482 	TAILQ_FOREACH(g, igl, node) {
14483 		struct instruction *instr = &p->instructions[g->first_instr_id];
14484 		uint32_t j;
14485 
14486 		if (g->first_instr_id == g->last_instr_id)
14487 			continue;
14488 
14489 		/* Install a new custom instruction. */
14490 		p->instruction_table[INSTR_CUSTOM_0 + i] = g->func;
14491 
14492 		/* First instruction of the group: change its type to the new custom instruction. */
14493 		instr->type = INSTR_CUSTOM_0 + i;
14494 
14495 		/* All the subsequent instructions of the group: invalidate. */
14496 		for (j = g->first_instr_id + 1; j <= g->last_instr_id; j++) {
14497 			struct instruction_data *data = &p->instruction_data[j];
14498 
14499 			data->invalid = 1;
14500 		}
14501 
14502 		i++;
14503 	}
14504 
14505 	/* Remove the invalidated instructions. */
14506 	p->n_instructions = instr_compact(p->instructions, p->instruction_data, p->n_instructions);
14507 
14508 	/* Resolve the jump destination for any "standalone" jump instructions (i.e. those jump
14509 	 * instructions that are the only instruction within their group, so they were left
14510 	 * unmodified).
14511 	 */
14512 	instr_jmp_resolve(p->instructions, p->instruction_data, p->n_instructions);
14513 }
14514 
14515 int
rte_swx_pipeline_codegen(FILE * spec_file,FILE * code_file,uint32_t * err_line,const char ** err_msg)14516 rte_swx_pipeline_codegen(FILE *spec_file,
14517 			 FILE *code_file,
14518 			 uint32_t *err_line,
14519 			 const char **err_msg)
14520 
14521 {
14522 	struct rte_swx_pipeline *p = NULL;
14523 	struct pipeline_spec *s = NULL;
14524 	struct instruction_group_list *igl = NULL;
14525 	struct action *a;
14526 	int status = 0;
14527 
14528 	/* Check input arguments. */
14529 	if (!spec_file || !code_file) {
14530 		if (err_line)
14531 			*err_line = 0;
14532 		if (err_msg)
14533 			*err_msg = "Invalid input argument.";
14534 		status = -EINVAL;
14535 		goto free;
14536 	}
14537 
14538 	/* Pipeline configuration. */
14539 	s = pipeline_spec_parse(spec_file, err_line, err_msg);
14540 	if (!s) {
14541 		status = -EINVAL;
14542 		goto free;
14543 	}
14544 
14545 	status = rte_swx_pipeline_config(&p, NULL, 0);
14546 	if (status) {
14547 		if (err_line)
14548 			*err_line = 0;
14549 		if (err_msg)
14550 			*err_msg = "Pipeline configuration error.";
14551 		goto free;
14552 	}
14553 
14554 	status = pipeline_spec_configure(p, s, err_msg);
14555 	if (status) {
14556 		if (err_line)
14557 			*err_line = 0;
14558 		goto free;
14559 	}
14560 
14561 	/*
14562 	 * Pipeline code generation.
14563 	 */
14564 
14565 	/* Instruction Group List (IGL) computation: the pipeline configuration must be done first,
14566 	 * but there is no need for the pipeline build to be done as well.
14567 	 */
14568 	igl = instruction_group_list_create(p);
14569 	if (!igl) {
14570 		if (err_line)
14571 			*err_line = 0;
14572 		if (err_msg)
14573 			*err_msg = "Memory allocation failed.";
14574 		status = -ENOMEM;
14575 		goto free;
14576 	}
14577 
14578 	/* Header file inclusion. */
14579 	fprintf(code_file, "#include \"rte_swx_pipeline_internal.h\"\n");
14580 	fprintf(code_file, "#include \"rte_swx_pipeline_spec.h\"\n\n");
14581 
14582 	/* Code generation for the pipeline specification. */
14583 	pipeline_spec_codegen(code_file, s);
14584 	fprintf(code_file, "\n");
14585 
14586 	/* Code generation for the action instructions. */
14587 	TAILQ_FOREACH(a, &p->actions, node) {
14588 		fprintf(code_file, "/**\n * Action %s\n */\n\n", a->name);
14589 
14590 		action_data_codegen(a, code_file);
14591 		fprintf(code_file, "\n");
14592 
14593 		action_instr_codegen(a, code_file);
14594 		fprintf(code_file, "\n");
14595 	}
14596 
14597 	/* Code generation for the pipeline instructions. */
14598 	instruction_group_list_codegen(igl, p, code_file);
14599 
14600 free:
14601 	instruction_group_list_free(igl);
14602 	rte_swx_pipeline_free(p);
14603 	pipeline_spec_free(s);
14604 
14605 	return status;
14606 }
14607 
14608 int
rte_swx_pipeline_build_from_lib(struct rte_swx_pipeline ** pipeline,const char * name,const char * lib_file_name,FILE * iospec_file,int numa_node)14609 rte_swx_pipeline_build_from_lib(struct rte_swx_pipeline **pipeline,
14610 				const char *name,
14611 				const char *lib_file_name,
14612 				FILE *iospec_file,
14613 				int numa_node)
14614 {
14615 	struct rte_swx_pipeline *p = NULL;
14616 	void *lib = NULL;
14617 	struct pipeline_iospec *sio = NULL;
14618 	struct pipeline_spec *s = NULL;
14619 	struct instruction_group_list *igl = NULL;
14620 	struct action *a;
14621 	struct instruction_group *g;
14622 	int status = 0;
14623 
14624 	/* Check input arguments. */
14625 	if (!pipeline ||
14626 	    !name ||
14627 	    !name[0] ||
14628 	    !lib_file_name ||
14629 	    !lib_file_name[0] ||
14630 	    !iospec_file) {
14631 		status = -EINVAL;
14632 		goto free;
14633 	}
14634 
14635 	/* Open the library. */
14636 	lib = dlopen(lib_file_name, RTLD_LAZY);
14637 	if (!lib) {
14638 		status = -EIO;
14639 		goto free;
14640 	}
14641 
14642 	/* Get the pipeline specification structures. */
14643 	s = dlsym(lib, "pipeline_spec");
14644 	if (!s) {
14645 		status = -EINVAL;
14646 		goto free;
14647 	}
14648 
14649 	sio = pipeline_iospec_parse(iospec_file, NULL, NULL);
14650 	if (!sio) {
14651 		status = -EINVAL;
14652 		goto free;
14653 	}
14654 
14655 	/* Pipeline configuration based on the specification structures. */
14656 	status = rte_swx_pipeline_config(&p, name, numa_node);
14657 	if (status)
14658 		goto free;
14659 
14660 	status = pipeline_iospec_configure(p, sio, NULL);
14661 	if (status)
14662 		goto free;
14663 
14664 	status = pipeline_spec_configure(p, s, NULL);
14665 	if (status)
14666 		goto free;
14667 
14668 	/* Pipeline build. */
14669 	status = rte_swx_pipeline_build(p);
14670 	if (status)
14671 		goto free;
14672 
14673 	/* Action instructions. */
14674 	TAILQ_FOREACH(a, &p->actions, node) {
14675 		char name[RTE_SWX_NAME_SIZE * 2];
14676 
14677 		snprintf(name, sizeof(name), "action_%s_run", a->name);
14678 
14679 		p->action_funcs[a->id] = dlsym(lib, name);
14680 		if (!p->action_funcs[a->id]) {
14681 			status = -EINVAL;
14682 			goto free;
14683 		}
14684 	}
14685 
14686 	/* Pipeline instructions. */
14687 	igl = instruction_group_list_create(p);
14688 	if (!igl) {
14689 		status = -ENOMEM;
14690 		goto free;
14691 	}
14692 
14693 	TAILQ_FOREACH(g, igl, node) {
14694 		char name[RTE_SWX_NAME_SIZE * 2];
14695 
14696 		if (g->first_instr_id == g->last_instr_id)
14697 			continue;
14698 
14699 		snprintf(name, sizeof(name), "pipeline_func_%u", g->group_id);
14700 
14701 		g->func = dlsym(lib, name);
14702 		if (!g->func) {
14703 			status = -EINVAL;
14704 			goto free;
14705 		}
14706 	}
14707 
14708 	status = pipeline_adjust_check(p, igl);
14709 	if (status)
14710 		goto free;
14711 
14712 	pipeline_adjust(p, igl);
14713 
14714 	p->lib = lib;
14715 
14716 	*pipeline = p;
14717 
14718 free:
14719 	instruction_group_list_free(igl);
14720 
14721 	pipeline_iospec_free(sio);
14722 
14723 	if (status) {
14724 		rte_swx_pipeline_free(p);
14725 
14726 		if (lib)
14727 			dlclose(lib);
14728 	}
14729 
14730 	return status;
14731 }
14732