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
kernel_tx_process_mbuf(struct rte_node * node,struct rte_mbuf ** mbufs,uint16_t cnt)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
kernel_tx_node_process(struct rte_graph * graph __rte_unused,struct rte_node * node,void ** objs,uint16_t nb_objs)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
kernel_tx_node_init(const struct rte_graph * graph __rte_unused,struct rte_node * node)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
kernel_tx_node_fini(const struct rte_graph * graph __rte_unused,struct rte_node * node)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 *
kernel_tx_node_get(void)117 kernel_tx_node_get(void)
118 {
119 return &kernel_tx_node_base;
120 }
121
122 RTE_NODE_REGISTER(kernel_tx_node_base);
123