12a0ae651SVamsi Attunuru /* SPDX-License-Identifier: BSD-3-Clause
22a0ae651SVamsi Attunuru * Copyright(C) 2023 Marvell International Ltd.
32a0ae651SVamsi Attunuru */
42a0ae651SVamsi Attunuru
52a0ae651SVamsi Attunuru #include <fcntl.h>
62a0ae651SVamsi Attunuru #include <sys/ioctl.h>
72a0ae651SVamsi Attunuru #include <sys/socket.h>
82a0ae651SVamsi Attunuru #include <unistd.h>
92a0ae651SVamsi Attunuru
102a0ae651SVamsi Attunuru #include <rte_debug.h>
112a0ae651SVamsi Attunuru #include <rte_ethdev.h>
122a0ae651SVamsi Attunuru #include <rte_graph.h>
13a2bc0584SZhirun Yan #include <rte_graph_worker.h>
142a0ae651SVamsi Attunuru #include <rte_ip.h>
152a0ae651SVamsi Attunuru
162a0ae651SVamsi Attunuru #include "kernel_tx_priv.h"
172a0ae651SVamsi Attunuru #include "node_private.h"
182a0ae651SVamsi Attunuru
192a0ae651SVamsi Attunuru static __rte_always_inline void
kernel_tx_process_mbuf(struct rte_node * node,struct rte_mbuf ** mbufs,uint16_t cnt)202a0ae651SVamsi Attunuru kernel_tx_process_mbuf(struct rte_node *node, struct rte_mbuf **mbufs, uint16_t cnt)
212a0ae651SVamsi Attunuru {
222a0ae651SVamsi Attunuru kernel_tx_node_ctx_t *ctx = (kernel_tx_node_ctx_t *)node->ctx;
232a0ae651SVamsi Attunuru struct sockaddr_in sin = {0};
242a0ae651SVamsi Attunuru struct rte_ipv4_hdr *ip4;
252a0ae651SVamsi Attunuru size_t len;
262a0ae651SVamsi Attunuru char *buf;
272a0ae651SVamsi Attunuru int i;
282a0ae651SVamsi Attunuru
292a0ae651SVamsi Attunuru for (i = 0; i < cnt; i++) {
302a0ae651SVamsi Attunuru ip4 = rte_pktmbuf_mtod(mbufs[i], struct rte_ipv4_hdr *);
312a0ae651SVamsi Attunuru len = rte_pktmbuf_data_len(mbufs[i]);
322a0ae651SVamsi Attunuru buf = (char *)ip4;
332a0ae651SVamsi Attunuru
342a0ae651SVamsi Attunuru sin.sin_family = AF_INET;
352a0ae651SVamsi Attunuru sin.sin_port = 0;
362a0ae651SVamsi Attunuru sin.sin_addr.s_addr = ip4->dst_addr;
372a0ae651SVamsi Attunuru
382a0ae651SVamsi Attunuru if (sendto(ctx->sock, buf, len, 0, (struct sockaddr *)&sin, sizeof(sin)) < 0)
39*ae282b06SDavid Marchand node_err("kernel_tx", "Unable to send packets: %s", strerror(errno));
402a0ae651SVamsi Attunuru }
412a0ae651SVamsi Attunuru }
422a0ae651SVamsi Attunuru
432a0ae651SVamsi Attunuru static uint16_t
kernel_tx_node_process(struct rte_graph * graph __rte_unused,struct rte_node * node,void ** objs,uint16_t nb_objs)442a0ae651SVamsi Attunuru kernel_tx_node_process(struct rte_graph *graph __rte_unused, struct rte_node *node, void **objs,
452a0ae651SVamsi Attunuru uint16_t nb_objs)
462a0ae651SVamsi Attunuru {
472a0ae651SVamsi Attunuru struct rte_mbuf **pkts = (struct rte_mbuf **)objs;
482a0ae651SVamsi Attunuru uint16_t obj_left = nb_objs;
492a0ae651SVamsi Attunuru
502a0ae651SVamsi Attunuru #define PREFETCH_CNT 4
512a0ae651SVamsi Attunuru
522a0ae651SVamsi Attunuru while (obj_left >= 12) {
532a0ae651SVamsi Attunuru /* Prefetch next-next mbufs */
542a0ae651SVamsi Attunuru rte_prefetch0(pkts[8]);
552a0ae651SVamsi Attunuru rte_prefetch0(pkts[9]);
562a0ae651SVamsi Attunuru rte_prefetch0(pkts[10]);
572a0ae651SVamsi Attunuru rte_prefetch0(pkts[11]);
582a0ae651SVamsi Attunuru
592a0ae651SVamsi Attunuru /* Prefetch next mbuf data */
602a0ae651SVamsi Attunuru rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[4], void *, pkts[4]->l2_len));
612a0ae651SVamsi Attunuru rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[5], void *, pkts[5]->l2_len));
622a0ae651SVamsi Attunuru rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[6], void *, pkts[6]->l2_len));
632a0ae651SVamsi Attunuru rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[7], void *, pkts[7]->l2_len));
642a0ae651SVamsi Attunuru
652a0ae651SVamsi Attunuru kernel_tx_process_mbuf(node, pkts, PREFETCH_CNT);
662a0ae651SVamsi Attunuru
672a0ae651SVamsi Attunuru obj_left -= PREFETCH_CNT;
682a0ae651SVamsi Attunuru pkts += PREFETCH_CNT;
692a0ae651SVamsi Attunuru }
702a0ae651SVamsi Attunuru
712a0ae651SVamsi Attunuru while (obj_left > 0) {
722a0ae651SVamsi Attunuru kernel_tx_process_mbuf(node, pkts, 1);
732a0ae651SVamsi Attunuru
742a0ae651SVamsi Attunuru obj_left--;
752a0ae651SVamsi Attunuru pkts++;
762a0ae651SVamsi Attunuru }
772a0ae651SVamsi Attunuru
782a0ae651SVamsi Attunuru rte_pktmbuf_free_bulk((struct rte_mbuf **)objs, nb_objs);
792a0ae651SVamsi Attunuru
802a0ae651SVamsi Attunuru return nb_objs;
812a0ae651SVamsi Attunuru }
822a0ae651SVamsi Attunuru
832a0ae651SVamsi Attunuru static int
kernel_tx_node_init(const struct rte_graph * graph __rte_unused,struct rte_node * node)842a0ae651SVamsi Attunuru kernel_tx_node_init(const struct rte_graph *graph __rte_unused, struct rte_node *node)
852a0ae651SVamsi Attunuru {
862a0ae651SVamsi Attunuru kernel_tx_node_ctx_t *ctx = (kernel_tx_node_ctx_t *)node->ctx;
872a0ae651SVamsi Attunuru
882a0ae651SVamsi Attunuru ctx->sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
892a0ae651SVamsi Attunuru if (ctx->sock < 0)
90*ae282b06SDavid Marchand node_err("kernel_tx", "Unable to open RAW socket");
912a0ae651SVamsi Attunuru
922a0ae651SVamsi Attunuru return 0;
932a0ae651SVamsi Attunuru }
942a0ae651SVamsi Attunuru
952a0ae651SVamsi Attunuru static void
kernel_tx_node_fini(const struct rte_graph * graph __rte_unused,struct rte_node * node)962a0ae651SVamsi Attunuru kernel_tx_node_fini(const struct rte_graph *graph __rte_unused, struct rte_node *node)
972a0ae651SVamsi Attunuru {
982a0ae651SVamsi Attunuru kernel_tx_node_ctx_t *ctx = (kernel_tx_node_ctx_t *)node->ctx;
992a0ae651SVamsi Attunuru
1002a0ae651SVamsi Attunuru if (ctx->sock >= 0) {
1012a0ae651SVamsi Attunuru close(ctx->sock);
1022a0ae651SVamsi Attunuru ctx->sock = -1;
1032a0ae651SVamsi Attunuru }
1042a0ae651SVamsi Attunuru }
1052a0ae651SVamsi Attunuru
1062a0ae651SVamsi Attunuru static struct rte_node_register kernel_tx_node_base = {
1072a0ae651SVamsi Attunuru .process = kernel_tx_node_process,
1082a0ae651SVamsi Attunuru .name = "kernel_tx",
1092a0ae651SVamsi Attunuru
1102a0ae651SVamsi Attunuru .init = kernel_tx_node_init,
1112a0ae651SVamsi Attunuru .fini = kernel_tx_node_fini,
1122a0ae651SVamsi Attunuru
1132a0ae651SVamsi Attunuru .nb_edges = 0,
1142a0ae651SVamsi Attunuru };
1152a0ae651SVamsi Attunuru
1162a0ae651SVamsi Attunuru struct rte_node_register *
kernel_tx_node_get(void)1172a0ae651SVamsi Attunuru kernel_tx_node_get(void)
1182a0ae651SVamsi Attunuru {
1192a0ae651SVamsi Attunuru return &kernel_tx_node_base;
1202a0ae651SVamsi Attunuru }
1212a0ae651SVamsi Attunuru
1222a0ae651SVamsi Attunuru RTE_NODE_REGISTER(kernel_tx_node_base);
123