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