xref: /dpdk/app/graph/neigh.c (revision 2cfebc3f1046e4166e13b4f906e3ddc1c26c7eeb)
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(struct rte_ipv6_addr *ip, uint64_t mac)
66 {
67 	struct neigh_ipv6_config *v6_config;
68 
69 	TAILQ_FOREACH(v6_config, &neigh6, next) {
70 		if (rte_ipv6_addr_eq(&v6_config->ip, ip) && 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(struct rte_ipv6_addr *ip, uint64_t mac)
174 {
175 	struct neigh_ipv6_config *v6_config;
176 	int rc = -EINVAL;
177 
178 	v6_config = find_neigh6_entry(ip, mac);
179 
180 	if (!v6_config) {
181 		v6_config = malloc(sizeof(struct neigh_ipv6_config));
182 		if (!v6_config)
183 			return -ENOMEM;
184 	}
185 
186 	v6_config->ip = *ip;
187 	v6_config->mac = mac;
188 	v6_config->is_used = true;
189 
190 	if (!graph_status_get())
191 		goto exit;
192 
193 	rc =  ip6_rewrite_node_add(v6_config);
194 	if (rc)
195 		goto free;
196 
197 exit:
198 	TAILQ_INSERT_TAIL(&neigh6, v6_config, next);
199 	return 0;
200 free:
201 	free(v6_config);
202 	return rc;
203 }
204 
205 int
206 neigh_ip4_add_to_rewrite(void)
207 {
208 	struct neigh_ipv4_config *neigh;
209 	int rc;
210 
211 	TAILQ_FOREACH(neigh, &neigh4, next) {
212 		rc = ip4_rewrite_node_add(neigh);
213 		if (rc)
214 			return rc;
215 	}
216 	return 0;
217 }
218 
219 int
220 neigh_ip6_add_to_rewrite(void)
221 {
222 	struct neigh_ipv6_config *neigh;
223 	int rc;
224 
225 
226 	TAILQ_FOREACH(neigh, &neigh6, next) {
227 		rc = ip6_rewrite_node_add(neigh);
228 		if (rc < 0)
229 			return rc;
230 	}
231 
232 	return 0;
233 }
234 
235 void
236 cmd_neigh_add_ipv4_parsed(void *parsed_result, __rte_unused struct cmdline *cl,
237 			  void *data __rte_unused)
238 {
239 	struct cmd_neigh_add_ipv4_result *res = parsed_result;
240 	int rc = -EINVAL;
241 	uint64_t mac;
242 	uint32_t ip;
243 
244 	ip = rte_be_to_cpu_32(res->ip.addr.ipv4.s_addr);
245 
246 	if (parser_mac_read(&mac, res->mac)) {
247 		printf(MSG_ARG_INVALID, "mac");
248 		return;
249 	}
250 
251 	rc = neigh_ip4_add(ip, mac);
252 	if (rc < 0)
253 		printf(MSG_CMD_FAIL, res->neigh);
254 }
255 
256 void
257 cmd_neigh_add_ipv6_parsed(void *parsed_result, __rte_unused struct cmdline *cl,
258 			  void *data __rte_unused)
259 {
260 	struct cmd_neigh_add_ipv6_result *res = parsed_result;
261 	int rc = -EINVAL;
262 	uint64_t mac;
263 
264 	if (parser_mac_read(&mac, res->mac)) {
265 		printf(MSG_ARG_INVALID, "mac");
266 		return;
267 	}
268 
269 	rc = neigh_ip6_add(&res->ip.addr.ipv6, mac);
270 	if (rc < 0)
271 		printf(MSG_CMD_FAIL, res->neigh);
272 }
273 
274 void
275 cmd_help_neigh_parsed(__rte_unused void *parsed_result, __rte_unused struct cmdline *cl,
276 		      __rte_unused void *data)
277 {
278 	size_t len;
279 
280 	len = strlen(conn->msg_out);
281 	conn->msg_out += len;
282 	snprintf(conn->msg_out, conn->msg_out_len_max, "\n%s\n%s\n%s\n",
283 		 "--------------------------- neigh command help ---------------------------",
284 		 cmd_neigh_v4_help, cmd_neigh_v6_help);
285 
286 	len = strlen(conn->msg_out);
287 	conn->msg_out_len_max -= len;
288 }
289