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(struct rte_ipv6_addr *ip, uint64_t mac)
66 : : {
67 : : struct neigh_ipv6_config *v6_config;
68 : :
69 : 0 : TAILQ_FOREACH(v6_config, &neigh6, next) {
70 : 0 : if (rte_ipv6_addr_eq(&v6_config->ip, ip) && 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(struct rte_ipv6_addr *ip, uint64_t mac)
174 : : {
175 : : struct neigh_ipv6_config *v6_config;
176 : : int rc = -EINVAL;
177 : :
178 : 0 : v6_config = find_neigh6_entry(ip, mac);
179 : :
180 : 0 : if (!v6_config) {
181 : 0 : v6_config = malloc(sizeof(struct neigh_ipv6_config));
182 : 0 : if (!v6_config)
183 : : return -ENOMEM;
184 : : }
185 : :
186 : 0 : v6_config->ip = *ip;
187 : 0 : v6_config->mac = mac;
188 : 0 : v6_config->is_used = true;
189 : :
190 : 0 : if (!graph_status_get())
191 : 0 : goto exit;
192 : :
193 : 0 : rc = ip6_rewrite_node_add(v6_config);
194 : 0 : if (rc)
195 : 0 : goto free;
196 : :
197 : 0 : exit:
198 : 0 : TAILQ_INSERT_TAIL(&neigh6, v6_config, next);
199 : 0 : return 0;
200 : : free:
201 : 0 : free(v6_config);
202 : 0 : return rc;
203 : : }
204 : :
205 : : int
206 : 0 : neigh_ip4_add_to_rewrite(void)
207 : : {
208 : : struct neigh_ipv4_config *neigh;
209 : : int rc;
210 : :
211 : 0 : TAILQ_FOREACH(neigh, &neigh4, next) {
212 : 0 : rc = ip4_rewrite_node_add(neigh);
213 : 0 : if (rc)
214 : 0 : return rc;
215 : : }
216 : : return 0;
217 : : }
218 : :
219 : : int
220 : 0 : neigh_ip6_add_to_rewrite(void)
221 : : {
222 : : struct neigh_ipv6_config *neigh;
223 : : int rc;
224 : :
225 : :
226 : 0 : TAILQ_FOREACH(neigh, &neigh6, next) {
227 : 0 : rc = ip6_rewrite_node_add(neigh);
228 : 0 : if (rc < 0)
229 : 0 : return rc;
230 : : }
231 : :
232 : : return 0;
233 : : }
234 : :
235 : : void
236 : 0 : 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 : 0 : ip = rte_be_to_cpu_32(res->ip.addr.ipv4.s_addr);
245 : :
246 : 0 : if (parser_mac_read(&mac, res->mac)) {
247 : : printf(MSG_ARG_INVALID, "mac");
248 : 0 : return;
249 : : }
250 : :
251 : 0 : rc = neigh_ip4_add(ip, mac);
252 : 0 : if (rc < 0)
253 : 0 : printf(MSG_CMD_FAIL, res->neigh);
254 : : }
255 : :
256 : : void
257 : 0 : 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 : 0 : if (parser_mac_read(&mac, res->mac)) {
265 : : printf(MSG_ARG_INVALID, "mac");
266 : 0 : return;
267 : : }
268 : :
269 : 0 : rc = neigh_ip6_add(&res->ip.addr.ipv6, mac);
270 : 0 : if (rc < 0)
271 : 0 : printf(MSG_CMD_FAIL, res->neigh);
272 : : }
273 : :
274 : : void
275 : 0 : 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 : 0 : len = strlen(conn->msg_out);
281 : 0 : conn->msg_out += len;
282 : 0 : 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 : 0 : len = strlen(conn->msg_out);
287 : 0 : conn->msg_out_len_max -= len;
288 : 0 : }
|