// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2025 Robin Jarry

#include "graph.h"
#include "mbuf.h"
#include "port.h"
#include "rxtx.h"

#include <rte_malloc.h>

#include <stdint.h>

static uint16_t
port_output_process(struct rte_graph *graph, struct rte_node *node, void **objs, uint16_t nb_objs) {
	const struct port_output_edges *ctx = node->ctx_ptr;
	const struct iface_info_port *port;
	const struct iface *iface;
	rte_edge_t edge;

	for (unsigned i = 0; i < nb_objs; i++) {
		struct rte_mbuf *mbuf = objs[i];
		iface = mbuf_data(mbuf)->iface;
		port = iface_info_port(iface);

		if (gr_mbuf_is_traced(mbuf))
			gr_mbuf_trace_add(mbuf, node, 0);

		edge = ctx->edges[port->port_id];
		rte_node_enqueue_x1(graph, node, edge, mbuf);
	}

	return nb_objs;
}

static void port_output_fini(const struct rte_graph *, struct rte_node *node) {
	rte_free(node->ctx_ptr);
}

static struct rte_node_register node = {
	.name = "port_output",
	.process = port_output_process,
	.fini = port_output_fini,
	.nb_edges = 2,
	.next_nodes = {
		"port_tx", // will be overridden at runtime
		"port_output_invalid",
	},
};

static void port_output_register(void) {
	iface_output_type_register(GR_IFACE_TYPE_PORT, "port_output");
}

static struct gr_node_info info = {
	.node = &node,
	.type = GR_NODE_T_L1,
	.register_callback = port_output_register,
};

GR_NODE_REGISTER(info);

GR_DROP_REGISTER(port_output_invalid);
