Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2023 Marvell International Ltd.
3 : : */
4 : :
5 : : #include <arpa/inet.h>
6 : : #include <sys/socket.h>
7 : :
8 : : #include <eal_export.h>
9 : : #include <rte_ethdev.h>
10 : : #include <rte_ether.h>
11 : : #include <rte_graph.h>
12 : : #include <rte_graph_worker.h>
13 : : #include <rte_ip.h>
14 : : #include <rte_lpm.h>
15 : : #include <rte_hash.h>
16 : : #include <rte_fbk_hash.h>
17 : : #include <rte_jhash.h>
18 : : #include <rte_hash_crc.h>
19 : :
20 : : #include "rte_node_udp4_input_api.h"
21 : :
22 : : #include "node_private.h"
23 : :
24 : : #define UDP4_INPUT_HASH_TBL_SIZE 1024
25 : :
26 : : #define UDP4_INPUT_NODE_HASH(ctx) \
27 : : (((struct udp4_input_node_ctx *)ctx)->hash)
28 : :
29 : : #define UDP4_INPUT_NODE_NEXT_INDEX(ctx) \
30 : : (((struct udp4_input_node_ctx *)ctx)->next_index)
31 : :
32 : :
33 : : /* UDP4 input global data struct */
34 : : struct udp4_input_node_main {
35 : : struct rte_hash *hash_tbl[RTE_MAX_NUMA_NODES];
36 : : };
37 : :
38 : : static struct udp4_input_node_main udp4_input_nm;
39 : :
40 : : struct udp4_input_node_ctx {
41 : : /* Socket's Hash table */
42 : : struct rte_hash *hash;
43 : : /* Cached next index */
44 : : uint16_t next_index;
45 : : };
46 : :
47 : : struct flow_key {
48 : : uint32_t prt_dst;
49 : : };
50 : :
51 : : static struct rte_hash_parameters udp4_params = {
52 : : .entries = UDP4_INPUT_HASH_TBL_SIZE,
53 : : .key_len = sizeof(uint32_t),
54 : : .hash_func = rte_jhash,
55 : : .hash_func_init_val = 0,
56 : : .socket_id = 0,
57 : : };
58 : :
59 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_node_udp4_dst_port_add, 23.11)
60 : : int
61 : 0 : rte_node_udp4_dst_port_add(uint32_t dst_port, rte_edge_t next_node)
62 : : {
63 : : uint8_t socket;
64 : : int rc;
65 : :
66 [ # # ]: 0 : for (socket = 0; socket < RTE_MAX_NUMA_NODES; socket++) {
67 [ # # ]: 0 : if (!udp4_input_nm.hash_tbl[socket])
68 : 0 : continue;
69 : :
70 : 0 : rc = rte_hash_add_key_data(udp4_input_nm.hash_tbl[socket],
71 : 0 : &dst_port, (void *)(uintptr_t)next_node);
72 [ # # ]: 0 : if (rc < 0) {
73 : 0 : node_err("udp4_lookup", "Failed to add key for sock %u, rc=%d",
74 : : socket, rc);
75 : 0 : return rc;
76 : : }
77 : : }
78 : : return 0;
79 : : }
80 : :
81 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_node_udp4_usr_node_add, 23.11)
82 : : int
83 : 0 : rte_node_udp4_usr_node_add(const char *usr_node)
84 : : {
85 : 0 : const char *next_nodes = usr_node;
86 : : rte_node_t udp4_input_node_id, count;
87 : :
88 : 0 : udp4_input_node_id = rte_node_from_name("udp4_input");
89 : 0 : count = rte_node_edge_update(udp4_input_node_id, RTE_EDGE_ID_INVALID,
90 : : &next_nodes, 1);
91 [ # # ]: 0 : if (count == 0) {
92 : 0 : node_dbg("udp4_input", "Adding usr node as edge to udp4_input failed");
93 : 0 : return count;
94 : : }
95 : 0 : count = rte_node_edge_count(udp4_input_node_id) - 1;
96 : 0 : return count;
97 : : }
98 : :
99 : : static int
100 : 0 : setup_udp4_dstprt_hash(struct udp4_input_node_main *nm, int socket)
101 : : {
102 : : struct rte_hash_parameters *hash_udp4 = &udp4_params;
103 : : char s[RTE_HASH_NAMESIZE];
104 : :
105 : : /* One Hash table per socket */
106 [ # # ]: 0 : if (nm->hash_tbl[socket])
107 : : return 0;
108 : :
109 : : /* create Hash table */
110 : : snprintf(s, sizeof(s), "UDP4_INPUT_HASH_%d", socket);
111 : 0 : hash_udp4->name = s;
112 : 0 : hash_udp4->socket_id = socket;
113 : 0 : nm->hash_tbl[socket] = rte_hash_create(hash_udp4);
114 [ # # ]: 0 : if (nm->hash_tbl[socket] == NULL)
115 : 0 : return -rte_errno;
116 : :
117 : : return 0;
118 : : }
119 : :
120 : : static int
121 : 0 : udp4_input_node_init(const struct rte_graph *graph, struct rte_node *node)
122 : : {
123 : : uint16_t socket, lcore_id;
124 : : static uint8_t init_once;
125 : : int rc;
126 : :
127 : : RTE_SET_USED(graph);
128 : : RTE_BUILD_BUG_ON(sizeof(struct udp4_input_node_ctx) > RTE_NODE_CTX_SZ);
129 : :
130 [ # # ]: 0 : if (!init_once) {
131 : :
132 : : /* Setup HASH tables for all sockets */
133 [ # # ]: 0 : RTE_LCORE_FOREACH(lcore_id)
134 : : {
135 : 0 : socket = rte_lcore_to_socket_id(lcore_id);
136 : 0 : rc = setup_udp4_dstprt_hash(&udp4_input_nm, socket);
137 [ # # ]: 0 : if (rc) {
138 : 0 : node_err("udp4_lookup",
139 : : "Failed to setup hash tbl for sock %u, rc=%d",
140 : : socket, rc);
141 : 0 : return rc;
142 : : }
143 : : }
144 : 0 : init_once = 1;
145 : : }
146 : :
147 : 0 : UDP4_INPUT_NODE_HASH(node->ctx) = udp4_input_nm.hash_tbl[graph->socket];
148 : :
149 : 0 : node_dbg("udp4_input", "Initialized udp4_input node");
150 : 0 : return 0;
151 : : }
152 : :
153 : : static uint16_t
154 : 0 : udp4_input_node_process_scalar(struct rte_graph *graph, struct rte_node *node,
155 : : void **objs, uint16_t nb_objs)
156 : : {
157 : 0 : struct rte_hash *hash_tbl_handle = UDP4_INPUT_NODE_HASH(node->ctx);
158 : : rte_edge_t next_index, udplookup_node;
159 : : struct rte_udp_hdr *pkt_udp_hdr;
160 : : uint16_t last_spec = 0;
161 : : void **to_next, **from;
162 : : struct rte_mbuf *mbuf;
163 : : uint16_t held = 0;
164 : : uint16_t next = 0;
165 : : int i, rc;
166 : :
167 : : /* Speculative next */
168 : 0 : next_index = UDP4_INPUT_NODE_NEXT_INDEX(node->ctx);
169 : :
170 : : from = objs;
171 : :
172 : 0 : to_next = rte_node_next_stream_get(graph, node, next_index, nb_objs);
173 [ # # ]: 0 : for (i = 0; i < nb_objs; i++) {
174 : : struct flow_key key_port;
175 : :
176 : 0 : mbuf = (struct rte_mbuf *)objs[i];
177 : 0 : pkt_udp_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_udp_hdr *,
178 : : sizeof(struct rte_ether_hdr) +
179 : : sizeof(struct rte_ipv4_hdr));
180 : :
181 [ # # ]: 0 : key_port.prt_dst = rte_cpu_to_be_16(pkt_udp_hdr->dst_port);
182 : 0 : rc = rte_hash_lookup_data(hash_tbl_handle,
183 : : &key_port.prt_dst,
184 : : (void **)&udplookup_node);
185 [ # # ]: 0 : next = (rc < 0) ? RTE_NODE_UDP4_INPUT_NEXT_PKT_DROP
186 : : : udplookup_node;
187 : :
188 [ # # ]: 0 : if (unlikely(next_index != next)) {
189 : : /* Copy things successfully speculated till now */
190 [ # # ]: 0 : rte_memcpy(to_next, from, last_spec * sizeof(from[0]));
191 : 0 : from += last_spec;
192 : 0 : to_next += last_spec;
193 : 0 : held += last_spec;
194 : : last_spec = 0;
195 : :
196 : 0 : rte_node_enqueue_x1(graph, node, next, from[0]);
197 : 0 : from += 1;
198 : : } else {
199 : 0 : last_spec += 1;
200 : : }
201 : : }
202 : : /* !!! Home run !!! */
203 [ # # ]: 0 : if (likely(last_spec == nb_objs)) {
204 : 0 : rte_node_next_stream_move(graph, node, next_index);
205 : 0 : return nb_objs;
206 : : }
207 : 0 : held += last_spec;
208 [ # # ]: 0 : rte_memcpy(to_next, from, last_spec * sizeof(from[0]));
209 : : rte_node_next_stream_put(graph, node, next_index, held);
210 : : /* Save the last next used */
211 : 0 : UDP4_INPUT_NODE_NEXT_INDEX(node->ctx) = next;
212 : :
213 : 0 : return nb_objs;
214 : : }
215 : :
216 : : static struct rte_node_register udp4_input_node = {
217 : : .process = udp4_input_node_process_scalar,
218 : : .name = "udp4_input",
219 : :
220 : : .init = udp4_input_node_init,
221 : :
222 : : .nb_edges = RTE_NODE_UDP4_INPUT_NEXT_PKT_DROP + 1,
223 : : .next_nodes = {
224 : : [RTE_NODE_UDP4_INPUT_NEXT_PKT_DROP] = "pkt_drop",
225 : : },
226 : : };
227 : :
228 : 252 : RTE_NODE_REGISTER(udp4_input_node);
|