Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2023 Marvell.
3 : : */
4 : :
5 : : #include <stdbool.h>
6 : : #include <stdio.h>
7 : : #include <stdlib.h>
8 : : #include <string.h>
9 : :
10 : : #include <cmdline_parse.h>
11 : : #include <cmdline_parse_num.h>
12 : : #include <cmdline_parse_string.h>
13 : : #include <cmdline_socket.h>
14 : : #include <rte_ethdev.h>
15 : : #include <rte_node_ip4_api.h>
16 : : #include <rte_node_ip6_api.h>
17 : :
18 : : #include "neigh_priv.h"
19 : : #include "module_api.h"
20 : :
21 : : static const char
22 : : cmd_neigh_v4_help[] = "neigh add ipv4 <ip> <mac>";
23 : :
24 : : static const char
25 : : cmd_neigh_v6_help[] = "neigh add ipv6 <ip> <mac>";
26 : :
27 : : struct neigh4_head neigh4 = TAILQ_HEAD_INITIALIZER(neigh4);
28 : : struct neigh6_head neigh6 = TAILQ_HEAD_INITIALIZER(neigh6);
29 : :
30 : : void
31 : 0 : neigh4_list_clean(void)
32 : : {
33 : : struct neigh_ipv4_config *v4_config;
34 : :
35 : 0 : while (!TAILQ_EMPTY(&neigh4)) {
36 : : v4_config = TAILQ_FIRST(&neigh4);
37 : 0 : TAILQ_REMOVE(&neigh4, v4_config, next);
38 : : }
39 : 0 : }
40 : :
41 : : void
42 : 0 : neigh6_list_clean(void)
43 : : {
44 : : struct neigh_ipv6_config *v6_config;
45 : :
46 : 0 : while (!TAILQ_EMPTY(&neigh6)) {
47 : : v6_config = TAILQ_FIRST(&neigh6);
48 : 0 : TAILQ_REMOVE(&neigh6, v6_config, next);
49 : : }
50 : 0 : }
51 : :
52 : : static struct neigh_ipv4_config *
53 : : find_neigh4_entry(uint32_t ip, uint64_t mac)
54 : : {
55 : : struct neigh_ipv4_config *v4_config;
56 : :
57 : 0 : TAILQ_FOREACH(v4_config, &neigh4, next) {
58 : 0 : if ((v4_config->ip == ip) && (v4_config->mac == mac))
59 : : return v4_config;
60 : : }
61 : : return NULL;
62 : : }
63 : :
64 : : static struct neigh_ipv6_config *
65 : 0 : find_neigh6_entry(uint8_t *ip, uint64_t mac)
66 : : {
67 : : struct neigh_ipv6_config *v6_config;
68 : :
69 : 0 : TAILQ_FOREACH(v6_config, &neigh6, next) {
70 : 0 : if (!(memcmp(v6_config->ip, ip, 16)) && (v6_config->mac == mac))
71 : 0 : return v6_config;
72 : : }
73 : : return NULL;
74 : : }
75 : :
76 : : static int
77 : 0 : ip6_rewrite_node_add(struct neigh_ipv6_config *v6_config)
78 : : {
79 : : uint8_t data[2 * RTE_ETHER_ADDR_LEN];
80 : : uint8_t len = 2 * RTE_ETHER_ADDR_LEN;
81 : : struct rte_ether_addr smac;
82 : : int16_t portid = 0;
83 : : int rc;
84 : :
85 : 0 : portid = ethdev_portid_by_ip6(v6_config->ip, NULL);
86 : 0 : if (portid < 0) {
87 : : printf("Invalid portid found to add neigh\n");
88 : 0 : return -EINVAL;
89 : : }
90 : :
91 : : memset(data, 0, len);
92 : :
93 : : /* Copy dst mac */
94 : 0 : rte_memcpy((void *)&data[0], (void *)&v6_config->mac, RTE_ETHER_ADDR_LEN);
95 : :
96 : : /* Copy src mac */
97 : 0 : rc = rte_eth_macaddr_get(portid, &smac);
98 : 0 : if (rc < 0)
99 : : return rc;
100 : :
101 : : rte_memcpy(&data[RTE_ETHER_ADDR_LEN], smac.addr_bytes, RTE_ETHER_ADDR_LEN);
102 : :
103 : 0 : return rte_node_ip6_rewrite_add(portid, data, len, portid);
104 : : }
105 : :
106 : : static int
107 : 0 : ip4_rewrite_node_add(struct neigh_ipv4_config *v4_config)
108 : : {
109 : : uint8_t data[2 * RTE_ETHER_ADDR_LEN];
110 : : uint8_t len = 2 * RTE_ETHER_ADDR_LEN;
111 : : struct rte_ether_addr smac;
112 : : int16_t portid = 0;
113 : : int rc;
114 : :
115 : 0 : portid = ethdev_portid_by_ip4(v4_config->ip, 0);
116 : 0 : if (portid < 0) {
117 : : printf("Invalid portid found to add neigh\n");
118 : 0 : return -EINVAL;
119 : : }
120 : :
121 : : memset(data, 0, len);
122 : :
123 : : /* Copy dst mac */
124 : 0 : rte_memcpy((void *)&data[0], (void *)&v4_config->mac, RTE_ETHER_ADDR_LEN);
125 : :
126 : : /* Copy src mac */
127 : 0 : rc = rte_eth_macaddr_get(portid, &smac);
128 : 0 : if (rc < 0) {
129 : 0 : printf("Cannot get MAC address: err=%d, port=%d\n", rc, portid);
130 : 0 : return rc;
131 : : }
132 : :
133 : : rte_memcpy(&data[RTE_ETHER_ADDR_LEN], smac.addr_bytes, RTE_ETHER_ADDR_LEN);
134 : :
135 : 0 : return rte_node_ip4_rewrite_add(portid, data, len, portid);
136 : : }
137 : :
138 : :
139 : : static int
140 : 0 : neigh_ip4_add(uint32_t ip, uint64_t mac)
141 : : {
142 : : struct neigh_ipv4_config *v4_config;
143 : : int rc = -EINVAL;
144 : :
145 : : v4_config = find_neigh4_entry(ip, mac);
146 : :
147 : 0 : if (!v4_config) {
148 : 0 : v4_config = malloc(sizeof(struct neigh_ipv4_config));
149 : 0 : if (!v4_config)
150 : : return -ENOMEM;
151 : : }
152 : :
153 : 0 : v4_config->ip = ip;
154 : 0 : v4_config->mac = mac;
155 : 0 : v4_config->is_used = true;
156 : :
157 : 0 : if (!graph_status_get())
158 : 0 : goto exit;
159 : :
160 : 0 : rc = ip4_rewrite_node_add(v4_config);
161 : 0 : if (rc)
162 : 0 : goto free;
163 : :
164 : 0 : exit:
165 : 0 : TAILQ_INSERT_TAIL(&neigh4, v4_config, next);
166 : 0 : return 0;
167 : : free:
168 : 0 : free(v4_config);
169 : 0 : return rc;
170 : : }
171 : :
172 : : static int
173 : 0 : neigh_ip6_add(uint8_t *ip, uint64_t mac)
174 : : {
175 : : struct neigh_ipv6_config *v6_config;
176 : : int rc = -EINVAL;
177 : : int j;
178 : :
179 : 0 : v6_config = find_neigh6_entry(ip, mac);
180 : :
181 : 0 : if (!v6_config) {
182 : 0 : v6_config = malloc(sizeof(struct neigh_ipv6_config));
183 : 0 : if (!v6_config)
184 : : return -ENOMEM;
185 : : }
186 : :
187 : 0 : for (j = 0; j < ETHDEV_IPV6_ADDR_LEN; j++)
188 : 0 : v6_config->ip[j] = ip[j];
189 : :
190 : 0 : v6_config->mac = mac;
191 : 0 : v6_config->is_used = true;
192 : :
193 : 0 : if (!graph_status_get())
194 : 0 : goto exit;
195 : :
196 : 0 : rc = ip6_rewrite_node_add(v6_config);
197 : 0 : if (rc)
198 : 0 : goto free;
199 : :
200 : 0 : exit:
201 : 0 : TAILQ_INSERT_TAIL(&neigh6, v6_config, next);
202 : 0 : return 0;
203 : : free:
204 : 0 : free(v6_config);
205 : 0 : return rc;
206 : : }
207 : :
208 : : int
209 : 0 : neigh_ip4_add_to_rewrite(void)
210 : : {
211 : : struct neigh_ipv4_config *neigh;
212 : : int rc;
213 : :
214 : 0 : TAILQ_FOREACH(neigh, &neigh4, next) {
215 : 0 : rc = ip4_rewrite_node_add(neigh);
216 : 0 : if (rc)
217 : 0 : return rc;
218 : : }
219 : : return 0;
220 : : }
221 : :
222 : : int
223 : 0 : neigh_ip6_add_to_rewrite(void)
224 : : {
225 : : struct neigh_ipv6_config *neigh;
226 : : int rc;
227 : :
228 : :
229 : 0 : TAILQ_FOREACH(neigh, &neigh6, next) {
230 : 0 : rc = ip6_rewrite_node_add(neigh);
231 : 0 : if (rc < 0)
232 : 0 : return rc;
233 : : }
234 : :
235 : : return 0;
236 : : }
237 : :
238 : : static void
239 : 0 : cli_neigh_v4(void *parsed_result, __rte_unused struct cmdline *cl, void *data __rte_unused)
240 : : {
241 : : struct neigh_v4_cmd_tokens *res = parsed_result;
242 : : int rc = -EINVAL;
243 : : uint64_t mac;
244 : : uint32_t ip;
245 : :
246 : 0 : if (parser_ip4_read(&ip, res->ip)) {
247 : : printf(MSG_ARG_INVALID, "ip");
248 : 0 : return;
249 : : }
250 : :
251 : 0 : if (parser_mac_read(&mac, res->mac)) {
252 : : printf(MSG_ARG_INVALID, "mac");
253 : 0 : return;
254 : : }
255 : :
256 : 0 : rc = neigh_ip4_add(ip, mac);
257 : 0 : if (rc < 0)
258 : 0 : printf(MSG_CMD_FAIL, res->cmd);
259 : : }
260 : :
261 : : static void
262 : 0 : cli_neigh_v6(void *parsed_result, __rte_unused struct cmdline *cl, void *data __rte_unused)
263 : : {
264 : : struct neigh_v6_cmd_tokens *res = parsed_result;
265 : : uint8_t ip[ETHDEV_IPV6_ADDR_LEN];
266 : : int rc = -EINVAL;
267 : : uint64_t mac;
268 : :
269 : 0 : if (parser_ip6_read(ip, res->ip)) {
270 : : printf(MSG_ARG_INVALID, "ip");
271 : 0 : return;
272 : : }
273 : :
274 : 0 : if (parser_mac_read(&mac, res->mac)) {
275 : : printf(MSG_ARG_INVALID, "mac");
276 : 0 : return;
277 : : }
278 : :
279 : 0 : rc = neigh_ip6_add(ip, mac);
280 : 0 : if (rc < 0)
281 : 0 : printf(MSG_CMD_FAIL, res->cmd);
282 : : }
283 : :
284 : : static void
285 : 0 : cli_neigh_help(__rte_unused void *parsed_result, __rte_unused struct cmdline *cl,
286 : : __rte_unused void *data)
287 : : {
288 : : size_t len;
289 : :
290 : 0 : len = strlen(conn->msg_out);
291 : 0 : conn->msg_out += len;
292 : 0 : snprintf(conn->msg_out, conn->msg_out_len_max, "\n%s\n%s\n%s\n",
293 : : "--------------------------- neigh command help ---------------------------",
294 : : cmd_neigh_v4_help, cmd_neigh_v6_help);
295 : :
296 : 0 : len = strlen(conn->msg_out);
297 : 0 : conn->msg_out_len_max -= len;
298 : 0 : }
299 : :
300 : : cmdline_parse_token_string_t neigh_v4_cmd =
301 : : TOKEN_STRING_INITIALIZER(struct neigh_v4_cmd_tokens, cmd, "neigh");
302 : : cmdline_parse_token_string_t neigh_v4_add =
303 : : TOKEN_STRING_INITIALIZER(struct neigh_v4_cmd_tokens, add, "add");
304 : : cmdline_parse_token_string_t neigh_v4_ip4 =
305 : : TOKEN_STRING_INITIALIZER(struct neigh_v4_cmd_tokens, ip4, "ipv4");
306 : : cmdline_parse_token_string_t neigh_v4_ip =
307 : : TOKEN_STRING_INITIALIZER(struct neigh_v4_cmd_tokens, ip, NULL);
308 : : cmdline_parse_token_string_t neigh_v4_mac =
309 : : TOKEN_STRING_INITIALIZER(struct neigh_v4_cmd_tokens, mac, NULL);
310 : :
311 : : cmdline_parse_inst_t neigh_v4_cmd_ctx = {
312 : : .f = cli_neigh_v4,
313 : : .data = NULL,
314 : : .help_str = cmd_neigh_v4_help,
315 : : .tokens = {
316 : : (void *)&neigh_v4_cmd,
317 : : (void *)&neigh_v4_add,
318 : : (void *)&neigh_v4_ip4,
319 : : (void *)&neigh_v4_ip,
320 : : (void *)&neigh_v4_mac,
321 : : NULL,
322 : : },
323 : : };
324 : :
325 : : cmdline_parse_token_string_t neigh_v6_cmd =
326 : : TOKEN_STRING_INITIALIZER(struct neigh_v6_cmd_tokens, cmd, "neigh");
327 : : cmdline_parse_token_string_t neigh_v6_add =
328 : : TOKEN_STRING_INITIALIZER(struct neigh_v6_cmd_tokens, add, "add");
329 : : cmdline_parse_token_string_t neigh_v6_ip6 =
330 : : TOKEN_STRING_INITIALIZER(struct neigh_v6_cmd_tokens, ip6, "ipv6");
331 : : cmdline_parse_token_string_t neigh_v6_ip =
332 : : TOKEN_STRING_INITIALIZER(struct neigh_v6_cmd_tokens, ip, NULL);
333 : : cmdline_parse_token_string_t neigh_v6_mac =
334 : : TOKEN_STRING_INITIALIZER(struct neigh_v6_cmd_tokens, mac, NULL);
335 : :
336 : : cmdline_parse_inst_t neigh_v6_cmd_ctx = {
337 : : .f = cli_neigh_v6,
338 : : .data = NULL,
339 : : .help_str = cmd_neigh_v6_help,
340 : : .tokens = {
341 : : (void *)&neigh_v6_cmd,
342 : : (void *)&neigh_v6_add,
343 : : (void *)&neigh_v6_ip6,
344 : : (void *)&neigh_v6_ip,
345 : : (void *)&neigh_v6_mac,
346 : : NULL,
347 : : },
348 : : };
349 : :
350 : : cmdline_parse_token_string_t neigh_help_cmd =
351 : : TOKEN_STRING_INITIALIZER(struct neigh_help_cmd_tokens, cmd, "help");
352 : : cmdline_parse_token_string_t neigh_help_module =
353 : : TOKEN_STRING_INITIALIZER(struct neigh_help_cmd_tokens, module, "neigh");
354 : :
355 : : cmdline_parse_inst_t neigh_help_cmd_ctx = {
356 : : .f = cli_neigh_help,
357 : : .data = NULL,
358 : : .help_str = "",
359 : : .tokens = {
360 : : (void *)&neigh_help_cmd,
361 : : (void *)&neigh_help_module,
362 : : NULL,
363 : : },
364 : : };
|