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