l3.c (14866B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * File: l3.c 8 * Purpose: BCMX L3 commands 9 */ 10 11 #include <sal/appl/io.h> 12 #include <shared/bsl.h> 13 #include <bcm/error.h> 14 15 #include <bcmx/bcmx.h> 16 #include <bcmx/l3.h> 17 18 #include <appl/diag/shell.h> 19 #include <appl/diag/system.h> 20 #include <appl/diag/parse.h> 21 22 #ifdef INCLUDE_BCMX 23 24 #include "bcmx.h" 25 #include <appl/diag/diag.h> 26 27 #ifdef INCLUDE_L3 28 29 STATIC int 30 _bcmx_l3_intf_show(bcmx_l3_intf_t *intf) 31 { 32 char if_mac_str[SAL_MACADDR_STR_LEN]; 33 34 cli_out("%-5s %-5s %-5s %-4s %-18s %-4s %-4s %-5s %-5s\n", 35 "INTF", "VRF", "Group", "VLAN", "Source Mac", "MTU", "TTL", 36 "Tunnel", "InnerVlan"); 37 38 format_macaddr(if_mac_str, intf->l3a_mac_addr); 39 cli_out("%-5d %-5d %-5d %-4d %-18s %-4d %-4d %-5d %-5d\n", 40 intf->l3a_intf_id, intf->l3a_vrf, intf->l3a_group, 41 intf->l3a_vid, if_mac_str, intf->l3a_mtu, intf->l3a_ttl, 42 intf->l3a_tunnel_idx, intf->l3a_inner_vlan); 43 44 return BCM_E_NONE; 45 } 46 47 48 STATIC int 49 _bcmx_l3_ip_show(bcmx_l3_host_t *info) 50 { 51 char ip_str[IP6ADDR_STR_LEN]; 52 char if_mac_str[SAL_MACADDR_STR_LEN]; 53 char *hit; 54 char *trunk = " "; 55 bcmx_lport_t port; 56 57 if (info->l3a_flags & BCM_L3_IP6) { 58 cli_out("%-4s %-42s %-18s %-4s %-11s %6s %3s\n", 59 "VRF", "IP address", "Mac Address", "INTF", 60 "LPORT", "CLASS", "HIT"); 61 } else { 62 cli_out("%-4s %-16s %-18s %-4s %-11s %6s %3s\n", 63 "VRF", "IP address", "Mac Address", "INTF", 64 "LPORT", "CLASS", "HIT"); 65 } 66 67 hit = (info->l3a_flags & BCM_L3_HIT) ? "y" : "n"; 68 69 format_macaddr(if_mac_str, info->l3a_nexthop_mac); 70 if (BCM_GPORT_IS_SET(info->l3a_lport)) { 71 if (BCM_GPORT_IS_TRUNK(info->l3a_lport)) { 72 trunk = "t"; 73 } 74 port = info->l3a_lport; 75 76 } else { 77 if (info->l3a_flags & BCM_L3_TGID) { 78 trunk = "t" ; 79 port = info->l3a_trunk; 80 } else { 81 port = info->l3a_lport; 82 } 83 } 84 85 if (info->l3a_flags & BCM_L3_IP6) { 86 format_ip6addr(ip_str, info->l3a_ip6_addr); 87 cli_out("%-4d %-42s %-18s %-4d 0x%8.8x%1s %-6d %-3s\n", 88 info->l3a_vrf, ip_str, if_mac_str, info->l3a_intf, 89 port, trunk, info->l3a_lookup_class, hit); 90 } else { 91 format_ipaddr(ip_str, info->l3a_ip_addr); 92 cli_out("%-4d %-16s %-18s %-4d 0x%8.8x%1s %-6d %-3s\n", 93 info->l3a_vrf, ip_str, if_mac_str, info->l3a_intf, 94 port, trunk, info->l3a_lookup_class, hit); 95 } 96 97 return BCM_E_NONE; 98 } 99 100 101 102 char bcmx_cmd_l3_usage[] = 103 "Usages:\n" 104 #ifdef COMPILER_STRING_CONST_LIMIT 105 " l3 intf create | delete | show ...\n" 106 " l3 ip add | del | show\n" 107 " l3 defip add | del | show\n" 108 #else 109 " l3 intf create Mac=<mac> Vlan=<vid> [INtf=<n>]\n" 110 " - Create an L3 interface\n" 111 " Interface index may be optionally specified\n" 112 " l3 intf delete <intf> - Destroy an L3 interface\n" 113 " l3 intf show INtf=<n> - Show L3 interface\n" 114 115 " l3 ip add IP=<ipaddr> Mac=<nexthop_mac> Port=<uport> INt=<intf>\n" 116 " - Add L3 cache entry\n" 117 " l3 ip del IP=<ipaddr> - Remove L3 cache entry\n" 118 " l3 ip show IP=<ipaddr> - Display L3 cache entry\n" 119 120 " l3 defip add IP=<ipaddr> MaSk=<mask>\n" 121 " Mac=<nexthop_mac> Port=<uport> INt=<intf>\n" 122 " - Add L3 route\n" 123 " l3 defip del IP=<ipaddr> MaSk=<mask>\n" 124 " - Delete L3 route\n" 125 " l3 defip show - Show L3 routes\n" 126 #endif 127 ; 128 129 cmd_result_t 130 bcmx_cmd_l3(int unit, args_t *args) 131 { 132 parse_table_t pt; 133 char *table, *subcmd, *ch; 134 sal_mac_addr_t mac; 135 int vid; /* not a bcm_vlan_t due to parsing uint16 vs uint32 */ 136 int intf; 137 int rv = BCM_E_NONE; 138 cmd_result_t cmd_rv; 139 140 if ((table = ARG_GET(args)) == NULL) { 141 sal_printf("Table required\n"); 142 return CMD_USAGE; 143 } 144 145 if ((subcmd = ARG_GET(args)) == NULL) { 146 sal_printf("Subcommand required\n"); 147 return CMD_USAGE; 148 } 149 150 /* 151 * L3 interface table 152 */ 153 if (sal_strcasecmp(table, "intf") == 0 || 154 sal_strcasecmp(table, "if") == 0 || 155 sal_strcasecmp(table, "interface") == 0) { 156 157 /* l3 intf create Mac=<mac> Vlan=<vid> */ 158 if (sal_strcasecmp(subcmd, "create") == 0 || 159 sal_strcasecmp(subcmd, "add") == 0) { 160 bcmx_l3_intf_t intrf; 161 int intf_idx = -1; 162 163 parse_table_init(0, &pt); 164 parse_table_add(&pt, "Mac", PQ_DFL | PQ_MAC, 0, &mac, 0); 165 parse_table_add(&pt, "Vlan", PQ_DFL | PQ_INT, 0, &vid, 0); 166 parse_table_add(&pt, "INtf", PQ_DFL | PQ_INT, 0, &intf_idx, 0); 167 if (!parseEndOk(args, &pt, &cmd_rv)) { 168 return cmd_rv; 169 } 170 171 bcmx_l3_intf_t_init(&intrf); 172 sal_memcpy(intrf.l3a_mac_addr, mac, sizeof(bcm_mac_t)); 173 intrf.l3a_vid = vid; 174 intrf.l3a_intf_id = intf_idx; 175 intrf.l3a_flags |= BCM_L3_ADD_TO_ARL; 176 intrf.l3a_flags |= BCM_L3_WITH_ID; 177 if (intf_idx < 0) { /* Not specified */ 178 rv = bcmx_l3_intf_create(&intrf); 179 if (rv == BCM_E_NONE) { 180 intf_idx = rv; 181 } 182 } else { 183 rv = bcmx_l3_intf_create(&intrf); 184 } 185 186 if (rv < 0) { 187 sal_printf("ERROR: l3 interface create %sfailed: %s\n", 188 intf_idx < 0 ? "" : "with id ", bcm_errmsg(rv)); 189 return CMD_FAIL; 190 } 191 sal_printf("l3 interface %d created\n", intf_idx); 192 return CMD_OK; 193 } 194 195 /* l3 intf delete <intf> */ 196 if (sal_strcasecmp(subcmd, "delete") == 0 || 197 sal_strcasecmp(subcmd, "del") == 0 || 198 sal_strcasecmp(subcmd, "destroy") == 0) { 199 bcmx_l3_intf_t intrf; 200 if ((ch = ARG_GET(args)) == NULL) { 201 return CMD_USAGE; 202 } 203 intf = parse_integer(ch); 204 205 bcmx_l3_intf_t_init(&intrf); 206 intrf.l3a_intf_id = intf; 207 208 rv = bcmx_l3_intf_delete(&intrf); 209 if (rv < 0) { 210 sal_printf("ERROR: l3 interface destroy failed: %s\n", 211 bcm_errmsg(rv)); 212 return CMD_FAIL; 213 } 214 return CMD_OK; 215 } 216 217 /* l3 intf show INtf=<intf> */ 218 if (sal_strcasecmp(subcmd, "show") == 0) { 219 bcmx_l3_intf_t intf; 220 int intf_id; 221 222 parse_table_init(0, &pt); 223 parse_table_add(&pt, "INtf", PQ_DFL | PQ_INT, 0, (void*)&intf_id, 0); 224 225 if (!parse_arg_eq(args, &pt)) { 226 sal_printf("%s: Unknown options: %s\n", 227 ARG_CMD(args), ARG_CUR(args)); 228 parse_arg_eq_done(&pt); 229 return(CMD_FAIL); 230 } 231 232 parse_arg_eq_done(&pt); /* No longer needed */ 233 234 bcmx_l3_intf_t_init(&intf); 235 intf.l3a_intf_id = intf_id; 236 237 rv = bcmx_l3_intf_get(&intf); 238 if (rv < 0) { 239 sal_printf("BCMX L3 intf get failed: %s\n", bcm_errmsg(rv)); 240 return CMD_FAIL; 241 } 242 243 _bcmx_l3_intf_show(&intf); 244 return CMD_OK; 245 } 246 247 sal_printf("%s: unknown %s subcommand %s\n", 248 ARG_CMD(args), table, subcmd); 249 return CMD_USAGE; 250 } 251 252 /* 253 * L3 IP cache table 254 */ 255 if (sal_strcasecmp(table, "ip") == 0) { 256 ip_addr_t ipaddr; 257 char *lpstr; 258 bcmx_uport_t uport; 259 bcmx_lport_t lport; 260 261 /* l3 ip add IP=<ipaddr> Mac=<nexthop_mac> Port=<uport> INt=<intf> */ 262 if (sal_strcasecmp(subcmd, "add") == 0 || 263 sal_strcasecmp(subcmd, "create") == 0) { 264 bcmx_l3_host_t l3ip; 265 int tid; 266 267 parse_table_init(0, &pt); 268 parse_table_add(&pt, "IP", PQ_DFL | PQ_IP, 0, (void *)&ipaddr, NULL); 269 parse_table_add(&pt, "Mac", PQ_DFL | PQ_MAC, 0, &mac, NULL); 270 parse_table_add(&pt, "Port", PQ_STRING, 0, &lpstr, NULL); 271 parse_table_add(&pt, "INtf", PQ_DFL | PQ_INT, 0, (void *)&intf, NULL); 272 tid = -1; 273 parse_table_add(&pt, "Trunk", PQ_DFL | PQ_INT, 0, (void *)&tid, NULL); 274 if (!parse_arg_eq(args, &pt)) { 275 sal_printf("%s: Unknown options: %s\n", 276 ARG_CMD(args), ARG_CUR(args)); 277 parse_arg_eq_done(&pt); 278 return(CMD_FAIL); 279 } 280 281 uport = bcmx_uport_parse(lpstr, NULL); 282 lport = BCMX_UPORT_TO_LPORT(uport); 283 if (lport == BCMX_NO_SUCH_LPORT) { 284 sal_printf("%s: bad uport given: %s\n", ARG_CMD(args), lpstr); 285 parse_arg_eq_done(&pt); 286 return CMD_FAIL; 287 } 288 289 290 bcmx_l3_host_t_init(&l3ip); 291 l3ip.l3a_ip_addr = ipaddr; 292 l3ip.l3a_intf = intf; 293 sal_memcpy(l3ip.l3a_nexthop_mac, mac, sizeof(mac)); 294 l3ip.l3a_lport = lport; 295 l3ip.l3a_flags = 0; 296 if (tid != -1) { 297 l3ip.l3a_trunk = tid; 298 l3ip.l3a_flags |= BCM_L3_TGID; 299 } 300 301 rv = bcmx_l3_host_add(&l3ip); 302 if (rv < 0) { 303 sal_printf("BCMX L3 add failed: %s\n", bcm_errmsg(rv)); 304 parse_arg_eq_done(&pt); 305 return CMD_FAIL; 306 } 307 parse_arg_eq_done(&pt); 308 return CMD_OK; 309 } 310 311 /* l3 ip del IP=<ipaddr> */ 312 if (sal_strcasecmp(subcmd, "delete") == 0 || 313 sal_strcasecmp(subcmd, "del") == 0 || 314 sal_strcasecmp(subcmd, "destroy") == 0) { 315 bcmx_l3_host_t l3ip; 316 parse_table_init(0, &pt); 317 parse_table_add(&pt, "IP", PQ_DFL | PQ_IP, 0, (void *)&ipaddr, 0); 318 if (!parseEndOk(args, &pt, &cmd_rv)) { 319 return cmd_rv; 320 } 321 bcmx_l3_host_t_init(&l3ip); 322 l3ip.l3a_ip_addr = ipaddr; 323 l3ip.l3a_flags = 0; 324 325 rv = bcmx_l3_host_delete(&l3ip); 326 if (rv < 0) { 327 sal_printf("BCMX L3 delete failed: %s\n", bcm_errmsg(rv)); 328 return CMD_FAIL; 329 } 330 return CMD_OK; 331 } 332 333 /* l3 ip show IP=<ipaddr> */ 334 if (sal_strcasecmp(subcmd, "show") == 0) { 335 bcmx_l3_host_t l3ip; 336 337 parse_table_init(0, &pt); 338 parse_table_add(&pt, "IP", PQ_DFL | PQ_IP, 0, (void *)&ipaddr, NULL); 339 340 if (!parse_arg_eq(args, &pt)) { 341 sal_printf("%s: Unknown options: %s\n", 342 ARG_CMD(args), ARG_CUR(args)); 343 parse_arg_eq_done(&pt); 344 return(CMD_FAIL); 345 } 346 347 parse_arg_eq_done(&pt); /* No longer needed */ 348 349 bcmx_l3_host_t_init(&l3ip); 350 l3ip.l3a_ip_addr = ipaddr; 351 l3ip.l3a_flags = 0; 352 353 rv = bcmx_l3_host_find(&l3ip); 354 if (rv < 0) { 355 sal_printf("BCMX L3 find failed: %s\n", bcm_errmsg(rv)); 356 return CMD_FAIL; 357 } 358 359 _bcmx_l3_ip_show(&l3ip); 360 return CMD_OK; 361 } 362 363 sal_printf("%s: unknown %s subcommand %s\n", 364 ARG_CMD(args), table, subcmd); 365 return CMD_USAGE; 366 } 367 368 /* 369 * L3 DEFIP route table 370 */ 371 if (sal_strcasecmp(table, "defip") == 0) { 372 bcmx_l3_route_t l3route; 373 ip_addr_t ipaddr, mask; 374 char *lpstr; 375 bcmx_lport_t lport; 376 bcmx_uport_t uport; 377 378 /* 379 * l3 defip add IP=<ipaddr> MaSk=<mask> 380 * Mac=<nexthop_mac> Port=<uport> INt=<intf> 381 */ 382 if (sal_strcasecmp(subcmd, "add") == 0 || 383 sal_strcasecmp(subcmd, "create") == 0) { 384 parse_table_init(0, &pt); 385 parse_table_add(&pt, "IP", PQ_DFL | PQ_IP, 0, &ipaddr, NULL); 386 parse_table_add(&pt, "MaSk", PQ_DFL | PQ_IP, 0, &mask, NULL); 387 parse_table_add(&pt, "Mac", PQ_DFL | PQ_MAC, 0, &mac, NULL); 388 parse_table_add(&pt, "Port", PQ_STRING, 0, &lpstr, NULL); 389 parse_table_add(&pt, "INtf", PQ_DFL | PQ_INT, 0, &intf, NULL); 390 if (!parse_arg_eq(args, &pt)) { 391 sal_printf("%s: Unknown options: %s\n", 392 ARG_CMD(args), ARG_CUR(args)); 393 parse_arg_eq_done(&pt); 394 return(CMD_FAIL); 395 } 396 397 uport = bcmx_uport_parse(lpstr, NULL); 398 lport = BCMX_UPORT_TO_LPORT(uport); 399 if (lport == BCMX_NO_SUCH_LPORT) { 400 sal_printf("%s: bad uport given: %s\n", ARG_CMD(args), lpstr); 401 parse_arg_eq_done(&pt); 402 return CMD_FAIL; 403 } 404 405 sal_memset(&l3route, 0, sizeof(l3route)); 406 l3route.l3a_subnet = ipaddr; 407 l3route.l3a_ip_mask = mask; 408 l3route.l3a_intf = intf; 409 sal_memcpy(l3route.l3a_nexthop_mac, mac, sizeof(mac)); 410 l3route.l3a_lport = lport; 411 l3route.l3a_flags = 0; 412 413 rv = bcmx_l3_route_add(&l3route); 414 if (rv < 0) { 415 sal_printf("BCMX L3 defip add failed: %s\n", bcm_errmsg(rv)); 416 parse_arg_eq_done(&pt); 417 return CMD_FAIL; 418 } 419 parse_arg_eq_done(&pt); 420 return CMD_OK; 421 } 422 423 /* l3 defip del IP=<ipaddr> MaSk=<mask> */ 424 if (sal_strcasecmp(subcmd, "delete") == 0 || 425 sal_strcasecmp(subcmd, "del") == 0 || 426 sal_strcasecmp(subcmd, "destroy") == 0) { 427 parse_table_init(0, &pt); 428 parse_table_add(&pt, "IP", PQ_DFL | PQ_IP, 0, &ipaddr, NULL); 429 parse_table_add(&pt, "MaSk", PQ_DFL | PQ_IP, 0, &mask, NULL); 430 if (!parseEndOk(args, &pt, &cmd_rv)) { 431 return cmd_rv; 432 } 433 434 sal_memset(&l3route, 0, sizeof(l3route)); 435 l3route.l3a_subnet = ipaddr; 436 l3route.l3a_ip_mask = mask; 437 438 rv = bcmx_l3_route_delete(&l3route); 439 if (rv < 0) { 440 sal_printf("BCMX L3 defip delete failed: %s\n", 441 bcm_errmsg(rv)); 442 return CMD_FAIL; 443 } 444 return CMD_OK; 445 } 446 447 /* l3 defip show */ 448 if (sal_strcasecmp(subcmd, "show") == 0) { 449 sal_printf("To be implemented\n"); 450 return CMD_FAIL; 451 } 452 453 sal_printf("%s: unknown %s subcommand %s\n", 454 ARG_CMD(args), table, subcmd); 455 return CMD_USAGE; 456 } 457 458 459 sal_printf("%s: unknown table %s\n", ARG_CMD(args), table); 460 return CMD_USAGE; 461 } 462 463 #endif /* INCLUDE_L3 */ 464 #endif /* INCLUDE_BCMX */