xref: /dpdk/app/graph/neigh.c (revision 2cfebc3f1046e4166e13b4f906e3ddc1c26c7eeb)
19a3a41ebSSunil Kumar Kori /* SPDX-License-Identifier: BSD-3-Clause
29a3a41ebSSunil Kumar Kori  * Copyright(c) 2023 Marvell.
39a3a41ebSSunil Kumar Kori  */
49a3a41ebSSunil Kumar Kori 
59a3a41ebSSunil Kumar Kori #include <stdbool.h>
69a3a41ebSSunil Kumar Kori #include <stdio.h>
79a3a41ebSSunil Kumar Kori #include <stdlib.h>
89a3a41ebSSunil Kumar Kori #include <string.h>
99a3a41ebSSunil Kumar Kori 
109a3a41ebSSunil Kumar Kori #include <cmdline_parse.h>
119a3a41ebSSunil Kumar Kori #include <cmdline_parse_num.h>
129a3a41ebSSunil Kumar Kori #include <cmdline_parse_string.h>
139a3a41ebSSunil Kumar Kori #include <cmdline_socket.h>
149a3a41ebSSunil Kumar Kori #include <rte_ethdev.h>
159a3a41ebSSunil Kumar Kori #include <rte_node_ip4_api.h>
169a3a41ebSSunil Kumar Kori #include <rte_node_ip6_api.h>
179a3a41ebSSunil Kumar Kori 
189a3a41ebSSunil Kumar Kori #include "neigh_priv.h"
199a3a41ebSSunil Kumar Kori #include "module_api.h"
209a3a41ebSSunil Kumar Kori 
219a3a41ebSSunil Kumar Kori static const char
229a3a41ebSSunil Kumar Kori cmd_neigh_v4_help[] = "neigh add ipv4 <ip> <mac>";
239a3a41ebSSunil Kumar Kori 
249a3a41ebSSunil Kumar Kori static const char
259a3a41ebSSunil Kumar Kori cmd_neigh_v6_help[] = "neigh add ipv6 <ip> <mac>";
269a3a41ebSSunil Kumar Kori 
279a3a41ebSSunil Kumar Kori struct neigh4_head neigh4 = TAILQ_HEAD_INITIALIZER(neigh4);
289a3a41ebSSunil Kumar Kori struct neigh6_head neigh6 = TAILQ_HEAD_INITIALIZER(neigh6);
299a3a41ebSSunil Kumar Kori 
309a3a41ebSSunil Kumar Kori void
319a3a41ebSSunil Kumar Kori neigh4_list_clean(void)
329a3a41ebSSunil Kumar Kori {
339a3a41ebSSunil Kumar Kori 	struct neigh_ipv4_config *v4_config;
349a3a41ebSSunil Kumar Kori 
359a3a41ebSSunil Kumar Kori 	while (!TAILQ_EMPTY(&neigh4)) {
369a3a41ebSSunil Kumar Kori 		v4_config = TAILQ_FIRST(&neigh4);
379a3a41ebSSunil Kumar Kori 		TAILQ_REMOVE(&neigh4, v4_config, next);
389a3a41ebSSunil Kumar Kori 	}
399a3a41ebSSunil Kumar Kori }
409a3a41ebSSunil Kumar Kori 
419a3a41ebSSunil Kumar Kori void
429a3a41ebSSunil Kumar Kori neigh6_list_clean(void)
439a3a41ebSSunil Kumar Kori {
449a3a41ebSSunil Kumar Kori 	struct neigh_ipv6_config *v6_config;
459a3a41ebSSunil Kumar Kori 
469a3a41ebSSunil Kumar Kori 	while (!TAILQ_EMPTY(&neigh6)) {
479a3a41ebSSunil Kumar Kori 		v6_config = TAILQ_FIRST(&neigh6);
489a3a41ebSSunil Kumar Kori 		TAILQ_REMOVE(&neigh6, v6_config, next);
499a3a41ebSSunil Kumar Kori 	}
509a3a41ebSSunil Kumar Kori }
519a3a41ebSSunil Kumar Kori 
529a3a41ebSSunil Kumar Kori static struct neigh_ipv4_config *
539a3a41ebSSunil Kumar Kori find_neigh4_entry(uint32_t ip, uint64_t mac)
549a3a41ebSSunil Kumar Kori {
559a3a41ebSSunil Kumar Kori 	struct neigh_ipv4_config *v4_config;
569a3a41ebSSunil Kumar Kori 
579a3a41ebSSunil Kumar Kori 	TAILQ_FOREACH(v4_config, &neigh4, next) {
589a3a41ebSSunil Kumar Kori 		if ((v4_config->ip == ip) && (v4_config->mac == mac))
599a3a41ebSSunil Kumar Kori 			return v4_config;
609a3a41ebSSunil Kumar Kori 	}
619a3a41ebSSunil Kumar Kori 	return NULL;
629a3a41ebSSunil Kumar Kori }
639a3a41ebSSunil Kumar Kori 
649a3a41ebSSunil Kumar Kori static struct neigh_ipv6_config *
65*2cfebc3fSRobin Jarry find_neigh6_entry(struct rte_ipv6_addr *ip, uint64_t mac)
669a3a41ebSSunil Kumar Kori {
679a3a41ebSSunil Kumar Kori 	struct neigh_ipv6_config *v6_config;
689a3a41ebSSunil Kumar Kori 
699a3a41ebSSunil Kumar Kori 	TAILQ_FOREACH(v6_config, &neigh6, next) {
70*2cfebc3fSRobin Jarry 		if (rte_ipv6_addr_eq(&v6_config->ip, ip) && v6_config->mac == mac)
719a3a41ebSSunil Kumar Kori 			return v6_config;
729a3a41ebSSunil Kumar Kori 	}
739a3a41ebSSunil Kumar Kori 	return NULL;
749a3a41ebSSunil Kumar Kori }
759a3a41ebSSunil Kumar Kori 
769a3a41ebSSunil Kumar Kori static int
779a3a41ebSSunil Kumar Kori ip6_rewrite_node_add(struct neigh_ipv6_config *v6_config)
789a3a41ebSSunil Kumar Kori {
799a3a41ebSSunil Kumar Kori 	uint8_t data[2 * RTE_ETHER_ADDR_LEN];
809a3a41ebSSunil Kumar Kori 	uint8_t len = 2 * RTE_ETHER_ADDR_LEN;
819a3a41ebSSunil Kumar Kori 	struct rte_ether_addr smac;
829a3a41ebSSunil Kumar Kori 	int16_t portid = 0;
839a3a41ebSSunil Kumar Kori 	int rc;
849a3a41ebSSunil Kumar Kori 
85*2cfebc3fSRobin Jarry 	portid = ethdev_portid_by_ip6(&v6_config->ip, NULL);
869a3a41ebSSunil Kumar Kori 	if (portid < 0) {
879a3a41ebSSunil Kumar Kori 		printf("Invalid portid found to add neigh\n");
889a3a41ebSSunil Kumar Kori 		return -EINVAL;
899a3a41ebSSunil Kumar Kori 	}
909a3a41ebSSunil Kumar Kori 
919a3a41ebSSunil Kumar Kori 	memset(data, 0, len);
929a3a41ebSSunil Kumar Kori 
939a3a41ebSSunil Kumar Kori 	/* Copy dst mac */
949a3a41ebSSunil Kumar Kori 	rte_memcpy((void *)&data[0], (void *)&v6_config->mac, RTE_ETHER_ADDR_LEN);
959a3a41ebSSunil Kumar Kori 
969a3a41ebSSunil Kumar Kori 	/* Copy src mac */
979a3a41ebSSunil Kumar Kori 	rc = rte_eth_macaddr_get(portid, &smac);
989a3a41ebSSunil Kumar Kori 	if (rc < 0)
999a3a41ebSSunil Kumar Kori 		return rc;
1009a3a41ebSSunil Kumar Kori 
1019a3a41ebSSunil Kumar Kori 	rte_memcpy(&data[RTE_ETHER_ADDR_LEN], smac.addr_bytes, RTE_ETHER_ADDR_LEN);
1029a3a41ebSSunil Kumar Kori 
1039a3a41ebSSunil Kumar Kori 	return rte_node_ip6_rewrite_add(portid, data, len, portid);
1049a3a41ebSSunil Kumar Kori }
1059a3a41ebSSunil Kumar Kori 
1069a3a41ebSSunil Kumar Kori static int
1079a3a41ebSSunil Kumar Kori ip4_rewrite_node_add(struct neigh_ipv4_config *v4_config)
1089a3a41ebSSunil Kumar Kori {
1099a3a41ebSSunil Kumar Kori 	uint8_t data[2 * RTE_ETHER_ADDR_LEN];
1109a3a41ebSSunil Kumar Kori 	uint8_t len = 2 * RTE_ETHER_ADDR_LEN;
1119a3a41ebSSunil Kumar Kori 	struct rte_ether_addr smac;
1129a3a41ebSSunil Kumar Kori 	int16_t portid = 0;
1139a3a41ebSSunil Kumar Kori 	int rc;
1149a3a41ebSSunil Kumar Kori 
1159a3a41ebSSunil Kumar Kori 	portid = ethdev_portid_by_ip4(v4_config->ip, 0);
1169a3a41ebSSunil Kumar Kori 	if (portid < 0) {
1179a3a41ebSSunil Kumar Kori 		printf("Invalid portid found to add  neigh\n");
1189a3a41ebSSunil Kumar Kori 		return -EINVAL;
1199a3a41ebSSunil Kumar Kori 	}
1209a3a41ebSSunil Kumar Kori 
1219a3a41ebSSunil Kumar Kori 	memset(data, 0, len);
1229a3a41ebSSunil Kumar Kori 
1239a3a41ebSSunil Kumar Kori 	/* Copy dst mac */
1249a3a41ebSSunil Kumar Kori 	rte_memcpy((void *)&data[0], (void *)&v4_config->mac, RTE_ETHER_ADDR_LEN);
1259a3a41ebSSunil Kumar Kori 
1269a3a41ebSSunil Kumar Kori 	/* Copy src mac */
1279a3a41ebSSunil Kumar Kori 	rc = rte_eth_macaddr_get(portid, &smac);
1289a3a41ebSSunil Kumar Kori 	if (rc < 0) {
1299a3a41ebSSunil Kumar Kori 		printf("Cannot get MAC address: err=%d, port=%d\n", rc, portid);
1309a3a41ebSSunil Kumar Kori 		return rc;
1319a3a41ebSSunil Kumar Kori 	}
1329a3a41ebSSunil Kumar Kori 
1339a3a41ebSSunil Kumar Kori 	rte_memcpy(&data[RTE_ETHER_ADDR_LEN], smac.addr_bytes, RTE_ETHER_ADDR_LEN);
1349a3a41ebSSunil Kumar Kori 
1359a3a41ebSSunil Kumar Kori 	return rte_node_ip4_rewrite_add(portid, data, len, portid);
1369a3a41ebSSunil Kumar Kori }
1379a3a41ebSSunil Kumar Kori 
1389a3a41ebSSunil Kumar Kori 
1399a3a41ebSSunil Kumar Kori static int
1409a3a41ebSSunil Kumar Kori neigh_ip4_add(uint32_t ip, uint64_t mac)
1419a3a41ebSSunil Kumar Kori {
1429a3a41ebSSunil Kumar Kori 	struct neigh_ipv4_config *v4_config;
1439a3a41ebSSunil Kumar Kori 	int rc = -EINVAL;
1449a3a41ebSSunil Kumar Kori 
1459a3a41ebSSunil Kumar Kori 	v4_config = find_neigh4_entry(ip, mac);
1469a3a41ebSSunil Kumar Kori 
1479a3a41ebSSunil Kumar Kori 	if (!v4_config) {
1489a3a41ebSSunil Kumar Kori 		v4_config = malloc(sizeof(struct neigh_ipv4_config));
1499a3a41ebSSunil Kumar Kori 		if (!v4_config)
1509a3a41ebSSunil Kumar Kori 			return -ENOMEM;
1519a3a41ebSSunil Kumar Kori 	}
1529a3a41ebSSunil Kumar Kori 
1539a3a41ebSSunil Kumar Kori 	v4_config->ip = ip;
1549a3a41ebSSunil Kumar Kori 	v4_config->mac = mac;
1559a3a41ebSSunil Kumar Kori 	v4_config->is_used = true;
1569a3a41ebSSunil Kumar Kori 
1575c59002aSRakesh Kudurumalla 	if (!graph_status_get())
1585c59002aSRakesh Kudurumalla 		goto exit;
1595c59002aSRakesh Kudurumalla 
1609a3a41ebSSunil Kumar Kori 	rc = ip4_rewrite_node_add(v4_config);
1619a3a41ebSSunil Kumar Kori 	if (rc)
1629a3a41ebSSunil Kumar Kori 		goto free;
1639a3a41ebSSunil Kumar Kori 
1645c59002aSRakesh Kudurumalla exit:
1659a3a41ebSSunil Kumar Kori 	TAILQ_INSERT_TAIL(&neigh4, v4_config, next);
1669a3a41ebSSunil Kumar Kori 	return 0;
1679a3a41ebSSunil Kumar Kori free:
1689a3a41ebSSunil Kumar Kori 	free(v4_config);
1699a3a41ebSSunil Kumar Kori 	return rc;
1709a3a41ebSSunil Kumar Kori }
1719a3a41ebSSunil Kumar Kori 
1729a3a41ebSSunil Kumar Kori static int
173*2cfebc3fSRobin Jarry neigh_ip6_add(struct rte_ipv6_addr *ip, uint64_t mac)
1749a3a41ebSSunil Kumar Kori {
1759a3a41ebSSunil Kumar Kori 	struct neigh_ipv6_config *v6_config;
1769a3a41ebSSunil Kumar Kori 	int rc = -EINVAL;
1779a3a41ebSSunil Kumar Kori 
1789a3a41ebSSunil Kumar Kori 	v6_config = find_neigh6_entry(ip, mac);
1799a3a41ebSSunil Kumar Kori 
1809a3a41ebSSunil Kumar Kori 	if (!v6_config) {
1819a3a41ebSSunil Kumar Kori 		v6_config = malloc(sizeof(struct neigh_ipv6_config));
1829a3a41ebSSunil Kumar Kori 		if (!v6_config)
1839a3a41ebSSunil Kumar Kori 			return -ENOMEM;
1849a3a41ebSSunil Kumar Kori 	}
1859a3a41ebSSunil Kumar Kori 
186*2cfebc3fSRobin Jarry 	v6_config->ip = *ip;
1879a3a41ebSSunil Kumar Kori 	v6_config->mac = mac;
1889a3a41ebSSunil Kumar Kori 	v6_config->is_used = true;
1899a3a41ebSSunil Kumar Kori 
1905c59002aSRakesh Kudurumalla 	if (!graph_status_get())
1915c59002aSRakesh Kudurumalla 		goto exit;
1925c59002aSRakesh Kudurumalla 
1939a3a41ebSSunil Kumar Kori 	rc =  ip6_rewrite_node_add(v6_config);
1949a3a41ebSSunil Kumar Kori 	if (rc)
1959a3a41ebSSunil Kumar Kori 		goto free;
1969a3a41ebSSunil Kumar Kori 
1975c59002aSRakesh Kudurumalla exit:
1989a3a41ebSSunil Kumar Kori 	TAILQ_INSERT_TAIL(&neigh6, v6_config, next);
1999a3a41ebSSunil Kumar Kori 	return 0;
2009a3a41ebSSunil Kumar Kori free:
2019a3a41ebSSunil Kumar Kori 	free(v6_config);
2029a3a41ebSSunil Kumar Kori 	return rc;
2039a3a41ebSSunil Kumar Kori }
2049a3a41ebSSunil Kumar Kori 
2059a3a41ebSSunil Kumar Kori int
2069a3a41ebSSunil Kumar Kori neigh_ip4_add_to_rewrite(void)
2079a3a41ebSSunil Kumar Kori {
2089a3a41ebSSunil Kumar Kori 	struct neigh_ipv4_config *neigh;
2099a3a41ebSSunil Kumar Kori 	int rc;
2109a3a41ebSSunil Kumar Kori 
2119a3a41ebSSunil Kumar Kori 	TAILQ_FOREACH(neigh, &neigh4, next) {
2129a3a41ebSSunil Kumar Kori 		rc = ip4_rewrite_node_add(neigh);
2139a3a41ebSSunil Kumar Kori 		if (rc)
2149a3a41ebSSunil Kumar Kori 			return rc;
2159a3a41ebSSunil Kumar Kori 	}
2169a3a41ebSSunil Kumar Kori 	return 0;
2179a3a41ebSSunil Kumar Kori }
2189a3a41ebSSunil Kumar Kori 
2199a3a41ebSSunil Kumar Kori int
2209a3a41ebSSunil Kumar Kori neigh_ip6_add_to_rewrite(void)
2219a3a41ebSSunil Kumar Kori {
2229a3a41ebSSunil Kumar Kori 	struct neigh_ipv6_config *neigh;
2239a3a41ebSSunil Kumar Kori 	int rc;
2249a3a41ebSSunil Kumar Kori 
2259a3a41ebSSunil Kumar Kori 
2269a3a41ebSSunil Kumar Kori 	TAILQ_FOREACH(neigh, &neigh6, next) {
2279a3a41ebSSunil Kumar Kori 		rc = ip6_rewrite_node_add(neigh);
2289a3a41ebSSunil Kumar Kori 		if (rc < 0)
2299a3a41ebSSunil Kumar Kori 			return rc;
2309a3a41ebSSunil Kumar Kori 	}
2319a3a41ebSSunil Kumar Kori 
2329a3a41ebSSunil Kumar Kori 	return 0;
2339a3a41ebSSunil Kumar Kori }
2349a3a41ebSSunil Kumar Kori 
2350f32dac4SSunil Kumar Kori void
2360f32dac4SSunil Kumar Kori cmd_neigh_add_ipv4_parsed(void *parsed_result, __rte_unused struct cmdline *cl,
2370f32dac4SSunil Kumar Kori 			  void *data __rte_unused)
2389a3a41ebSSunil Kumar Kori {
2390f32dac4SSunil Kumar Kori 	struct cmd_neigh_add_ipv4_result *res = parsed_result;
2409a3a41ebSSunil Kumar Kori 	int rc = -EINVAL;
2419a3a41ebSSunil Kumar Kori 	uint64_t mac;
2429a3a41ebSSunil Kumar Kori 	uint32_t ip;
2439a3a41ebSSunil Kumar Kori 
2440f32dac4SSunil Kumar Kori 	ip = rte_be_to_cpu_32(res->ip.addr.ipv4.s_addr);
2459a3a41ebSSunil Kumar Kori 
2469a3a41ebSSunil Kumar Kori 	if (parser_mac_read(&mac, res->mac)) {
2479a3a41ebSSunil Kumar Kori 		printf(MSG_ARG_INVALID, "mac");
2489a3a41ebSSunil Kumar Kori 		return;
2499a3a41ebSSunil Kumar Kori 	}
2509a3a41ebSSunil Kumar Kori 
2519a3a41ebSSunil Kumar Kori 	rc = neigh_ip4_add(ip, mac);
2529a3a41ebSSunil Kumar Kori 	if (rc < 0)
2530f32dac4SSunil Kumar Kori 		printf(MSG_CMD_FAIL, res->neigh);
2549a3a41ebSSunil Kumar Kori }
2559a3a41ebSSunil Kumar Kori 
2560f32dac4SSunil Kumar Kori void
2570f32dac4SSunil Kumar Kori cmd_neigh_add_ipv6_parsed(void *parsed_result, __rte_unused struct cmdline *cl,
2580f32dac4SSunil Kumar Kori 			  void *data __rte_unused)
2599a3a41ebSSunil Kumar Kori {
2600f32dac4SSunil Kumar Kori 	struct cmd_neigh_add_ipv6_result *res = parsed_result;
261*2cfebc3fSRobin Jarry 	int rc = -EINVAL;
2629a3a41ebSSunil Kumar Kori 	uint64_t mac;
2639a3a41ebSSunil Kumar Kori 
2649a3a41ebSSunil Kumar Kori 	if (parser_mac_read(&mac, res->mac)) {
2659a3a41ebSSunil Kumar Kori 		printf(MSG_ARG_INVALID, "mac");
2669a3a41ebSSunil Kumar Kori 		return;
2679a3a41ebSSunil Kumar Kori 	}
2689a3a41ebSSunil Kumar Kori 
269*2cfebc3fSRobin Jarry 	rc = neigh_ip6_add(&res->ip.addr.ipv6, mac);
2709a3a41ebSSunil Kumar Kori 	if (rc < 0)
2710f32dac4SSunil Kumar Kori 		printf(MSG_CMD_FAIL, res->neigh);
2729a3a41ebSSunil Kumar Kori }
2739a3a41ebSSunil Kumar Kori 
2740f32dac4SSunil Kumar Kori void
2750f32dac4SSunil Kumar Kori cmd_help_neigh_parsed(__rte_unused void *parsed_result, __rte_unused struct cmdline *cl,
2769a3a41ebSSunil Kumar Kori 		      __rte_unused void *data)
2779a3a41ebSSunil Kumar Kori {
2789a3a41ebSSunil Kumar Kori 	size_t len;
2799a3a41ebSSunil Kumar Kori 
2809a3a41ebSSunil Kumar Kori 	len = strlen(conn->msg_out);
2819a3a41ebSSunil Kumar Kori 	conn->msg_out += len;
2829a3a41ebSSunil Kumar Kori 	snprintf(conn->msg_out, conn->msg_out_len_max, "\n%s\n%s\n%s\n",
2839a3a41ebSSunil Kumar Kori 		 "--------------------------- neigh command help ---------------------------",
2849a3a41ebSSunil Kumar Kori 		 cmd_neigh_v4_help, cmd_neigh_v6_help);
2859a3a41ebSSunil Kumar Kori 
2869a3a41ebSSunil Kumar Kori 	len = strlen(conn->msg_out);
2879a3a41ebSSunil Kumar Kori 	conn->msg_out_len_max -= len;
2889a3a41ebSSunil Kumar Kori }
289