xref: /dpdk/app/graph/neigh.c (revision 7917b0d38e92e8b9ec5a870415b791420e10f11a)
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 neigh4_list_clean(void)
32 {
33 	struct neigh_ipv4_config *v4_config;
34 
35 	while (!TAILQ_EMPTY(&neigh4)) {
36 		v4_config = TAILQ_FIRST(&neigh4);
37 		TAILQ_REMOVE(&neigh4, v4_config, next);
38 	}
39 }
40 
41 void
42 neigh6_list_clean(void)
43 {
44 	struct neigh_ipv6_config *v6_config;
45 
46 	while (!TAILQ_EMPTY(&neigh6)) {
47 		v6_config = TAILQ_FIRST(&neigh6);
48 		TAILQ_REMOVE(&neigh6, v6_config, next);
49 	}
50 }
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 	TAILQ_FOREACH(v4_config, &neigh4, next) {
58 		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 find_neigh6_entry(uint8_t *ip, uint64_t mac)
66 {
67 	struct neigh_ipv6_config *v6_config;
68 
69 	TAILQ_FOREACH(v6_config, &neigh6, next) {
70 		if (!(memcmp(v6_config->ip, ip, 16)) && (v6_config->mac == mac))
71 			return v6_config;
72 	}
73 	return NULL;
74 }
75 
76 static int
77 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 	portid = ethdev_portid_by_ip6(v6_config->ip, NULL);
86 	if (portid < 0) {
87 		printf("Invalid portid found to add neigh\n");
88 		return -EINVAL;
89 	}
90 
91 	memset(data, 0, len);
92 
93 	/* Copy dst mac */
94 	rte_memcpy((void *)&data[0], (void *)&v6_config->mac, RTE_ETHER_ADDR_LEN);
95 
96 	/* Copy src mac */
97 	rc = rte_eth_macaddr_get(portid, &smac);
98 	if (rc < 0)
99 		return rc;
100 
101 	rte_memcpy(&data[RTE_ETHER_ADDR_LEN], smac.addr_bytes, RTE_ETHER_ADDR_LEN);
102 
103 	return rte_node_ip6_rewrite_add(portid, data, len, portid);
104 }
105 
106 static int
107 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 	portid = ethdev_portid_by_ip4(v4_config->ip, 0);
116 	if (portid < 0) {
117 		printf("Invalid portid found to add  neigh\n");
118 		return -EINVAL;
119 	}
120 
121 	memset(data, 0, len);
122 
123 	/* Copy dst mac */
124 	rte_memcpy((void *)&data[0], (void *)&v4_config->mac, RTE_ETHER_ADDR_LEN);
125 
126 	/* Copy src mac */
127 	rc = rte_eth_macaddr_get(portid, &smac);
128 	if (rc < 0) {
129 		printf("Cannot get MAC address: err=%d, port=%d\n", rc, portid);
130 		return rc;
131 	}
132 
133 	rte_memcpy(&data[RTE_ETHER_ADDR_LEN], smac.addr_bytes, RTE_ETHER_ADDR_LEN);
134 
135 	return rte_node_ip4_rewrite_add(portid, data, len, portid);
136 }
137 
138 
139 static int
140 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 	if (!v4_config) {
148 		v4_config = malloc(sizeof(struct neigh_ipv4_config));
149 		if (!v4_config)
150 			return -ENOMEM;
151 	}
152 
153 	v4_config->ip = ip;
154 	v4_config->mac = mac;
155 	v4_config->is_used = true;
156 
157 	if (!graph_status_get())
158 		goto exit;
159 
160 	rc = ip4_rewrite_node_add(v4_config);
161 	if (rc)
162 		goto free;
163 
164 exit:
165 	TAILQ_INSERT_TAIL(&neigh4, v4_config, next);
166 	return 0;
167 free:
168 	free(v4_config);
169 	return rc;
170 }
171 
172 static int
173 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 	v6_config = find_neigh6_entry(ip, mac);
180 
181 	if (!v6_config) {
182 		v6_config = malloc(sizeof(struct neigh_ipv6_config));
183 		if (!v6_config)
184 			return -ENOMEM;
185 	}
186 
187 	for (j = 0; j < ETHDEV_IPV6_ADDR_LEN; j++)
188 		v6_config->ip[j] = ip[j];
189 
190 	v6_config->mac = mac;
191 	v6_config->is_used = true;
192 
193 	if (!graph_status_get())
194 		goto exit;
195 
196 	rc =  ip6_rewrite_node_add(v6_config);
197 	if (rc)
198 		goto free;
199 
200 exit:
201 	TAILQ_INSERT_TAIL(&neigh6, v6_config, next);
202 	return 0;
203 free:
204 	free(v6_config);
205 	return rc;
206 }
207 
208 int
209 neigh_ip4_add_to_rewrite(void)
210 {
211 	struct neigh_ipv4_config *neigh;
212 	int rc;
213 
214 	TAILQ_FOREACH(neigh, &neigh4, next) {
215 		rc = ip4_rewrite_node_add(neigh);
216 		if (rc)
217 			return rc;
218 	}
219 	return 0;
220 }
221 
222 int
223 neigh_ip6_add_to_rewrite(void)
224 {
225 	struct neigh_ipv6_config *neigh;
226 	int rc;
227 
228 
229 	TAILQ_FOREACH(neigh, &neigh6, next) {
230 		rc = ip6_rewrite_node_add(neigh);
231 		if (rc < 0)
232 			return rc;
233 	}
234 
235 	return 0;
236 }
237 
238 void
239 cmd_neigh_add_ipv4_parsed(void *parsed_result, __rte_unused struct cmdline *cl,
240 			  void *data __rte_unused)
241 {
242 	struct cmd_neigh_add_ipv4_result *res = parsed_result;
243 	int rc = -EINVAL;
244 	uint64_t mac;
245 	uint32_t ip;
246 
247 	ip = rte_be_to_cpu_32(res->ip.addr.ipv4.s_addr);
248 
249 	if (parser_mac_read(&mac, res->mac)) {
250 		printf(MSG_ARG_INVALID, "mac");
251 		return;
252 	}
253 
254 	rc = neigh_ip4_add(ip, mac);
255 	if (rc < 0)
256 		printf(MSG_CMD_FAIL, res->neigh);
257 }
258 
259 void
260 cmd_neigh_add_ipv6_parsed(void *parsed_result, __rte_unused struct cmdline *cl,
261 			  void *data __rte_unused)
262 {
263 	struct cmd_neigh_add_ipv6_result *res = parsed_result;
264 	uint8_t ip[ETHDEV_IPV6_ADDR_LEN];
265 	int rc = -EINVAL, i;
266 	uint64_t mac;
267 
268 	for (i = 0; i < ETHDEV_IPV6_ADDR_LEN; i++)
269 		ip[i] = res->ip.addr.ipv6.s6_addr[i];
270 
271 	if (parser_mac_read(&mac, res->mac)) {
272 		printf(MSG_ARG_INVALID, "mac");
273 		return;
274 	}
275 
276 	rc = neigh_ip6_add(ip, mac);
277 	if (rc < 0)
278 		printf(MSG_CMD_FAIL, res->neigh);
279 }
280 
281 void
282 cmd_help_neigh_parsed(__rte_unused void *parsed_result, __rte_unused struct cmdline *cl,
283 		      __rte_unused void *data)
284 {
285 	size_t len;
286 
287 	len = strlen(conn->msg_out);
288 	conn->msg_out += len;
289 	snprintf(conn->msg_out, conn->msg_out_len_max, "\n%s\n%s\n%s\n",
290 		 "--------------------------- neigh command help ---------------------------",
291 		 cmd_neigh_v4_help, cmd_neigh_v6_help);
292 
293 	len = strlen(conn->msg_out);
294 	conn->msg_out_len_max -= len;
295 }
296