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