xref: /dpdk/lib/node/kernel_tx.c (revision 1e472b5746aeb6189fa254ab82ce4cd27999f868)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2023 Marvell International Ltd.
3  */
4 
5 #include <fcntl.h>
6 #include <sys/ioctl.h>
7 #include <sys/socket.h>
8 #include <unistd.h>
9 
10 #include <rte_debug.h>
11 #include <rte_ethdev.h>
12 #include <rte_graph.h>
13 #include <rte_graph_worker.h>
14 #include <rte_ip.h>
15 
16 #include "kernel_tx_priv.h"
17 #include "node_private.h"
18 
19 static __rte_always_inline void
20 kernel_tx_process_mbuf(struct rte_node *node, struct rte_mbuf **mbufs, uint16_t cnt)
21 {
22 	kernel_tx_node_ctx_t *ctx = (kernel_tx_node_ctx_t *)node->ctx;
23 	struct sockaddr_in sin = {0};
24 	struct rte_ipv4_hdr *ip4;
25 	size_t len;
26 	char *buf;
27 	int i;
28 
29 	for (i = 0; i < cnt; i++) {
30 		ip4 = rte_pktmbuf_mtod(mbufs[i], struct rte_ipv4_hdr *);
31 		len = rte_pktmbuf_data_len(mbufs[i]);
32 		buf = (char *)ip4;
33 
34 		sin.sin_family = AF_INET;
35 		sin.sin_port = 0;
36 		sin.sin_addr.s_addr = ip4->dst_addr;
37 
38 		if (sendto(ctx->sock, buf, len, 0, (struct sockaddr *)&sin, sizeof(sin)) < 0)
39 			node_err("kernel_tx", "Unable to send packets: %s", strerror(errno));
40 	}
41 }
42 
43 static uint16_t
44 kernel_tx_node_process(struct rte_graph *graph __rte_unused, struct rte_node *node, void **objs,
45 			 uint16_t nb_objs)
46 {
47 	struct rte_mbuf **pkts = (struct rte_mbuf **)objs;
48 	uint16_t obj_left = nb_objs;
49 
50 #define PREFETCH_CNT 4
51 
52 	while (obj_left >= 12) {
53 		/* Prefetch next-next mbufs */
54 		rte_prefetch0(pkts[8]);
55 		rte_prefetch0(pkts[9]);
56 		rte_prefetch0(pkts[10]);
57 		rte_prefetch0(pkts[11]);
58 
59 		/* Prefetch next mbuf data */
60 		rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[4], void *, pkts[4]->l2_len));
61 		rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[5], void *, pkts[5]->l2_len));
62 		rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[6], void *, pkts[6]->l2_len));
63 		rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[7], void *, pkts[7]->l2_len));
64 
65 		kernel_tx_process_mbuf(node, pkts, PREFETCH_CNT);
66 
67 		obj_left -= PREFETCH_CNT;
68 		pkts += PREFETCH_CNT;
69 	}
70 
71 	while (obj_left > 0) {
72 		kernel_tx_process_mbuf(node, pkts, 1);
73 
74 		obj_left--;
75 		pkts++;
76 	}
77 
78 	rte_pktmbuf_free_bulk((struct rte_mbuf **)objs, nb_objs);
79 
80 	return nb_objs;
81 }
82 
83 static int
84 kernel_tx_node_init(const struct rte_graph *graph __rte_unused, struct rte_node *node)
85 {
86 	kernel_tx_node_ctx_t *ctx = (kernel_tx_node_ctx_t *)node->ctx;
87 
88 	ctx->sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
89 	if (ctx->sock < 0)
90 		node_err("kernel_tx", "Unable to open RAW socket");
91 
92 	return 0;
93 }
94 
95 static void
96 kernel_tx_node_fini(const struct rte_graph *graph __rte_unused, struct rte_node *node)
97 {
98 	kernel_tx_node_ctx_t *ctx = (kernel_tx_node_ctx_t *)node->ctx;
99 
100 	if (ctx->sock >= 0) {
101 		close(ctx->sock);
102 		ctx->sock = -1;
103 	}
104 }
105 
106 static struct rte_node_register kernel_tx_node_base = {
107 	.process = kernel_tx_node_process,
108 	.name = "kernel_tx",
109 
110 	.init = kernel_tx_node_init,
111 	.fini = kernel_tx_node_fini,
112 
113 	.nb_edges = 0,
114 };
115 
116 struct rte_node_register *
117 kernel_tx_node_get(void)
118 {
119 	return &kernel_tx_node_base;
120 }
121 
122 RTE_NODE_REGISTER(kernel_tx_node_base);
123