l3.c (276820B)
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 * L3 CLI commands 8 */ 9 10 #include <shared/bsl.h> 11 12 #include <appl/diag/system.h> 13 #include <appl/diag/parse.h> 14 #include <appl/diag/dport.h> 15 #include <appl/diag/shell.h> 16 #include <appl/diag/bslcons.h> 17 #include <shared/bsl.h> 18 #include <soc/debug.h> 19 #include <soc/hash.h> 20 #if defined(BCM_TRIDENT2_SUPPORT) 21 #include <soc/trident2.h> 22 #endif /* BCM_TRIDENT2_SUPPORT */ 23 24 #ifdef ALPM_ENABLE 25 #include <soc/alpm.h> 26 #endif 27 28 #include <bcm/error.h> 29 #include <bcm/l3.h> 30 #include <bcm/tunnel.h> 31 #include <bcm/ipmc.h> 32 #include <bcm/debug.h> 33 #include <bcm/nat.h> 34 35 #include <bcm_int/esw/l3.h> 36 #include <bcm_int/esw/nat.h> 37 #include <bcm_int/esw/katana.h> 38 #include <bcm_int/common/multicast.h> 39 #include <bcm_int/esw/port.h> 40 41 #if defined(BCM_TRX_SUPPORT) 42 #include <bcm_int/esw/trx.h> 43 #include <bcm_int/esw/virtual.h> 44 #endif /* BCM_TRX_SUPPORT */ 45 #if defined(BCM_TOMAHAWK3_SUPPORT) 46 #include <bcm_int/esw/tomahawk3.h> 47 #endif /* BCM_TOMAHAWK3_SUPPORT */ 48 49 #ifdef ALPM_ENABLE 50 #include <bcm_int/esw/alpm.h> 51 #include <bcm_int/esw/alpm_util.h> 52 53 #endif 54 55 #ifdef INCLUDE_L3 56 #define ENV_EGRESS_OBJECT_ID "egr_object_id" 57 58 #define L3X_MAX_BUCKET_SIZE 16 59 #define L3X_BUCKET_SIZE(_u) ((SOC_IS_RAVEN(_u) || SOC_IS_TR_VL(_u)) ? 16 : 8) 60 #define L3X_IP_MULTICAST(_i) (((uint32)(_i) & 0xf0000000) == 0xe0000000) 61 62 /* 63 * Function: 64 * _ipmc_cmd_entry_print 65 * Description: 66 * Internal function to print out ipmc entry info 67 * Parameters: 68 * unit - device number. 69 * info - Pointer to bcm_ipmc_addr_t data structure. 70 * cookie - user cookie 71 */ 72 STATIC int 73 _ipmc_cmd_entry_print(int unit, bcm_ipmc_addr_t *info, void *cookie) 74 { 75 char s_ip_str[IP6ADDR_STR_LEN]; 76 char mc_ip_str[IP6ADDR_STR_LEN]; 77 78 /* Input parameters check. */ 79 if (NULL == info) { 80 return (BCM_E_PARAM); 81 } 82 83 /* Print IPMC entry. */ 84 if (info->flags & BCM_IPMC_IP6) { 85 format_ip6addr(s_ip_str, info->s_ip6_addr); 86 format_ip6addr(mc_ip_str, info->mc_ip6_addr); 87 cli_out("SRC IP ADDRESS: %s\n", s_ip_str); 88 cli_out("MC IP ADDRESS: %s\n", mc_ip_str); 89 cli_out("VLAN MOD PORT V COS TS "); 90 cli_out("%s %s %s %s %s\n", "Group", "GroupL2", "VRF", "CLASS", "HIT"); 91 cli_out("%3d %4d %5d %2d %3d %3d 0x%x 0x%x %2d,%5d,%4s %6d\n", 92 info->vid, info->mod_id, info->port_tgid, 93 info->v, info->cos, 94 info->ts, info->group, info->group_l2, 95 info->vrf, info->lookup_class, 96 (info->flags & BCM_IPMC_HIT) ? "y" :"no", info->l3a_intf); 97 } else { 98 format_ipaddr(s_ip_str, info->s_ip_addr); 99 format_ipaddr(mc_ip_str, info->mc_ip_addr); 100 cli_out("%-16s%-16s%4d %3d %4d %3d %3d %2d 0x%x %3d\n", 101 s_ip_str, mc_ip_str, info->vid, 102 info->mod_id, info->port_tgid, 103 info->v, info->cos, info->ts, info->group, 104 info->vrf); 105 cli_out("0x%x %d %6s %6d\n", 106 info->group_l2, info->lookup_class, (info->flags & BCM_IPMC_HIT) ? "y" :"no", info->l3a_intf); 107 108 } 109 return (BCM_E_NONE); 110 } 111 #if defined(BCM_XGS_SWITCH_SUPPORT) 112 char if_ipmc_usage[] = 113 "Usages:\n\t" 114 #ifdef COMPILER_STRING_CONST_LIMIT 115 " ipmc <options> [arg...]\n" 116 #else 117 " ipmc init - Init ipmc function.\n\t" 118 " ipmc detach - Detach ipmc function.\n\t" 119 " ipmc config [Enable=<bool>] [CheckSrcPort=<bool>] " 120 "[CheckSrcIp=<bool>]\n\t" 121 " ipmc table add Src_IP=<ipaddr> Mc_IP=<grpaddr> VlanID=<vid>\n\t" 122 " Group=<val> [GroupL2=<val>] [src_Port=<port>] [COS=<cosl>]\n\t" 123 " [TS=<tsl>] [Valid=<bool>] [NoCHECK=<bool>]\n\t" 124 " [Replace=<bool>] [VRF=<vrf>] [LookupClass=<val>]\n\t" 125 " - Add an entry into ipmc table\n\t" 126 " ipmc table del Src_IP=<ipaddr> Mc_IP=<macaddr> VlanID=<vid>\n\t" 127 " - Destroy an entry in ipmc table\n\t" 128 " ipmc table clear\n\t" 129 " - Delete all ipmc table\n\t" 130 " ipmc table show [entry]\n\t" 131 " - Display all ipmc table or a single one\n\t" 132 " ipmc egr set Port=<port> Mac=<macaddr> Vlan=<vid>\n\t" 133 " Untag=<untag> Ttl_thresh=<ttl threshold>\n\t" 134 " - set egress IP Multicast configuration regs for a port\n\t" 135 " ipmc egr show [<port>]\n\t" 136 " - Display egress IP Multicast configuration regs for\n\t" 137 " all ports or a single port\n\t" 138 " ipmc counter show [<port>]\n\t" 139 " - Display IP Multicast counter information\n\t" 140 " ipmc ip6table add Src_IP=<ipaddr> Mc_IP=<grpaddr> VlanID=<vid>\n\t" 141 " Group=<val> [src_Port=<port>] [COS=<cosl>]\n\t" 142 " [NoCHECK=<bool>] [TS=<tsl>]\n\t" 143 " [Valid=<bool>] [LookupClass=<val>]\n\t" 144 " - Add an entry into ipmc table\n\t" 145 " ipmc ip6table del Src_IP=<ipaddr> Mc_IP=<macaddr> VlanID=<vid>\n\t" 146 " - Destroy an entry in ipmc table\n\t" 147 " ipmc ip6table clear\n\t" 148 " - Delete all ipmc table\n\t" 149 " ipmc ip6table show [entry]\n\t" 150 " - Display all ipmc table or a single one\n" 151 #endif 152 ; 153 154 cmd_result_t 155 if_ipmc(int unit, args_t *a) 156 { 157 char *table, *subcmd_s, *argstr; 158 int subcmd = 0; 159 parse_table_t pt; 160 cmd_result_t retCode; 161 bcm_mac_t mac; 162 vlan_id_t vid; 163 int vlan = 0; 164 int r, i, entry = 0, one_entry_only = 0; 165 int dport, port = 0, ttl_th = 1, untag = 1; 166 char mac_str[SAL_MACADDR_STR_LEN]; 167 bcm_ipmc_counters_t counters; 168 bcm_ip_t s_ip_addr = 0, mc_ip_addr = 0; 169 bcm_ipmc_addr_t ipmc_data; 170 bcm_pbmp_t pbmp; 171 bcm_port_config_t pcfg; 172 int valid = 1, cos = 0, ts = 0, nocheck = 0, replace = 0, group = 0, group_l2 = 0; 173 int lookup_class = 0; 174 int cfg_enable = 1, cfg_check_src_port = 1, cfg_check_src_ip = 1; 175 #if defined(BCM_XGS3_SWITCH_SUPPORT) 176 int vrf = 0; 177 bcm_ip6_t ip6_addr, sip6_addr; 178 #endif 179 180 #define IPMC_ADD 1 181 #define IPMC_DEL 2 182 #define IPMC_CLEAR 3 183 #define IPMC_SHOW 4 184 #define IPMC_SET 5 185 186 sal_memset(mac, 0x10, 6); 187 sal_memset(&ipmc_data, 0, sizeof(ipmc_data)); 188 189 /* Check valid device to operation on ...*/ 190 if (! sh_check_attached(ARG_CMD(a), unit)) { 191 return CMD_FAIL; 192 } 193 194 if (bcm_port_config_get(unit, &pcfg) != BCM_E_NONE) { 195 cli_out("%s: Error: bcm ports not initialized\n", ARG_CMD(a)); 196 return CMD_FAIL; 197 } 198 199 if ((table = ARG_GET(a)) == NULL) { 200 return CMD_USAGE; 201 } 202 203 if (sal_strcasecmp(table, "init") == 0) { 204 if ((r = bcm_ipmc_init(unit)) < 0) { 205 cli_out("%s: error initializing: %s\n", ARG_CMD(a), bcm_errmsg(r)); 206 } 207 return CMD_OK; 208 } 209 if (sal_strcasecmp(table, "detach") == 0) { 210 if ((r = bcm_ipmc_detach(unit)) < 0) { 211 cli_out("%s: error detaching: %s\n", ARG_CMD(a), bcm_errmsg(r)); 212 } 213 return CMD_OK; 214 } 215 216 if (sal_strcasecmp(table, "config") == 0) { 217 parse_table_init(unit, &pt); 218 parse_table_add(&pt, "Enable", PQ_DFL|PQ_BOOL, 0, 219 (void *)&cfg_enable, 0); 220 parse_table_add(&pt, "CheckSrcPort", PQ_DFL|PQ_BOOL, 0, 221 (void *)&cfg_check_src_port, 0); 222 parse_table_add(&pt, "CheckSrcIp", PQ_DFL|PQ_BOOL, 0, 223 (void *)&cfg_check_src_ip, 0); 224 if (parse_arg_eq(a, &pt) < 0) { 225 cli_out("%s: Error: Unknown option: %s\n", 226 ARG_CMD(a), ARG_CUR(a)); 227 parse_arg_eq_done(&pt); 228 return CMD_FAIL; 229 } 230 i = CMD_OK; 231 if (pt.pt_entries[0].pq_type & PQ_PARSED) { 232 r = bcm_ipmc_enable(unit, cfg_enable); 233 if (r < 0) { 234 cli_out("%s: Error: Enable failed: %s\n", 235 ARG_CMD(a), bcm_errmsg(r)); 236 i = CMD_FAIL; 237 } 238 } 239 if (pt.pt_entries[1].pq_type & PQ_PARSED) { 240 /* bcm_ipmc_source_port_check is deprecated */ 241 r = BCM_E_UNAVAIL; 242 if (r < 0) { 243 cli_out("%s: Error: check_source_port failed: %s\n", 244 ARG_CMD(a), bcm_errmsg(r)); 245 i = CMD_FAIL; 246 } 247 } 248 if (pt.pt_entries[2].pq_type & PQ_PARSED) { 249 /* bcm_ipmc_source_ip_search is deprecated */ 250 r = BCM_E_UNAVAIL; 251 if (r < 0) { 252 cli_out("%s: Error: check_source_ip failed: %s\n", 253 ARG_CMD(a), bcm_errmsg(r)); 254 i = CMD_FAIL; 255 } 256 } 257 parse_arg_eq_done(&pt); 258 return (i); 259 } 260 261 if ((subcmd_s = ARG_GET(a)) == NULL) { 262 return CMD_USAGE; 263 } 264 265 if (sal_strcasecmp(subcmd_s, "add") == 0) { 266 subcmd = IPMC_ADD; 267 } 268 269 if (sal_strcasecmp(subcmd_s, "del") == 0) { 270 subcmd = IPMC_DEL; 271 } 272 273 if (sal_strcasecmp(subcmd_s, "clear") == 0) { 274 subcmd = IPMC_CLEAR; 275 } 276 277 if (sal_strcasecmp(subcmd_s, "show") == 0) { 278 subcmd = IPMC_SHOW; 279 } 280 281 if (sal_strcasecmp(subcmd_s, "set") == 0) { 282 subcmd = IPMC_SET; 283 } 284 285 /* coverity[equality_cond : FALSE] */ 286 if (!subcmd) { 287 return CMD_USAGE; 288 } 289 290 if (sal_strcasecmp(table, "table") == 0) { 291 switch (subcmd) { 292 case IPMC_ADD: 293 parse_table_init(unit, &pt); 294 parse_table_add(&pt, "Src_IP", PQ_DFL|PQ_IP, 0, 295 (void *)&s_ip_addr, 0); 296 parse_table_add(&pt, "Mc_IP", PQ_DFL|PQ_IP, 0, 297 (void *)&mc_ip_addr, 0); 298 parse_table_add(&pt, "VlanID", PQ_DFL|PQ_INT, 0, (void *)&vlan, 0); 299 parse_table_add(&pt, "COS", PQ_DFL|PQ_INT, 0, (void *)&cos, 0); 300 #if defined(BCM_XGS3_SWITCH_SUPPORT) 301 parse_table_add(&pt, "VRF", PQ_DFL|PQ_INT, 0, 302 (void *)&vrf, 0); 303 #endif 304 parse_table_add(&pt, "Valid", PQ_DFL|PQ_BOOL, 0, 305 (void *)&valid, 0); 306 parse_table_add(&pt, "src_Port", PQ_INT, 0, (void *)&port, 0); 307 parse_table_add(&pt, "TS", PQ_INT, 0, (void *)&ts, 0); 308 parse_table_add(&pt, "NoCHECK", PQ_DFL|PQ_BOOL, 0, 309 (void *)&nocheck, 0); 310 parse_table_add(&pt, "Replace", PQ_DFL|PQ_BOOL, 0, 311 (void *)&replace, 0); 312 parse_table_add(&pt, "LookupClass", PQ_DFL|PQ_INT, 0, 313 (void *)&lookup_class, 0); 314 parse_table_add(&pt, "Group", PQ_DFL|PQ_INT, 0, 315 (void *)&group, 0); 316 parse_table_add(&pt, "GroupL2", PQ_DFL|PQ_INT, 0, 317 (void *)&group_l2, 0); 318 if (parse_arg_eq(a, &pt) < 0) { 319 cli_out("%s: Error: Unknown option: %s\n", 320 ARG_CMD(a), ARG_CUR(a)); 321 parse_arg_eq_done(&pt); 322 return CMD_FAIL; 323 } 324 bcm_ipmc_addr_t_init(&ipmc_data); 325 if (pt.pt_entries[3].pq_type & PQ_PARSED) { 326 ipmc_data.flags |= BCM_IPMC_SETPRI; 327 } 328 parse_arg_eq_done(&pt); 329 vid = vlan; 330 ipmc_data.s_ip_addr = s_ip_addr; 331 ipmc_data.mc_ip_addr = mc_ip_addr; 332 ipmc_data.vid = vid; 333 #if defined(BCM_XGS3_SWITCH_SUPPORT) 334 ipmc_data.vrf = vrf; 335 #endif 336 ipmc_data.cos = cos; 337 ipmc_data.ts = ts; 338 ipmc_data.port_tgid = port; 339 ipmc_data.v = valid; 340 if (nocheck) { 341 ipmc_data.flags |= BCM_IPMC_SOURCE_PORT_NOCHECK; 342 } 343 if (replace) { 344 ipmc_data.flags |= BCM_IPMC_REPLACE; 345 } 346 ipmc_data.lookup_class = lookup_class; 347 if (group) { 348 ipmc_data.group = group; 349 } 350 if (group_l2) { 351 ipmc_data.group_l2 = group_l2; 352 } 353 r = bcm_ipmc_add(unit, &ipmc_data); 354 if (r < 0) { 355 cli_out("%s: Error Add to ipmc table %s\n", ARG_CMD(a), 356 bcm_errmsg(r)); 357 return CMD_FAIL; 358 } 359 return CMD_OK; 360 break; 361 case IPMC_DEL: 362 parse_table_init(unit, &pt); 363 parse_table_add(&pt, "Src_IP", PQ_DFL|PQ_IP, 0, 364 (void *)&s_ip_addr, 0); 365 parse_table_add(&pt, "Mc_IP", PQ_DFL|PQ_IP, 0, 366 (void *)&mc_ip_addr, 0); 367 parse_table_add(&pt, "VlanID", PQ_DFL|PQ_INT, 0, (void *)&vlan, 0); 368 #if defined(BCM_XGS3_SWITCH_SUPPORT) 369 parse_table_add(&pt, "VRF", PQ_DFL|PQ_INT, 0, 370 (void *)&vrf, 0); 371 #endif 372 if (!parseEndOk( a, &pt, &retCode)) 373 return retCode; 374 bcm_ipmc_addr_t_init(&ipmc_data); 375 ipmc_data.s_ip_addr = s_ip_addr; 376 ipmc_data.mc_ip_addr = mc_ip_addr; 377 ipmc_data.vid = vlan; 378 #if defined(BCM_XGS3_SWITCH_SUPPORT) 379 ipmc_data.vrf = vrf; 380 #endif 381 r = bcm_ipmc_remove(unit, &ipmc_data); 382 if (r < 0) { 383 cli_out("%s: Error delete from ipmc table %s\n", ARG_CMD(a), 384 bcm_errmsg(r)); 385 return CMD_FAIL; 386 } 387 return CMD_OK; 388 break; 389 case IPMC_CLEAR: 390 r = bcm_ipmc_remove_all(unit); 391 if (r < 0) { 392 cli_out("%s: %s\n", 393 ARG_CMD(a), bcm_errmsg(r)); 394 return CMD_FAIL; 395 } 396 return (CMD_OK); 397 break; 398 case IPMC_SHOW: 399 if (ARG_CNT(a)) { 400 if (!isint(ARG_CUR(a))) { 401 cli_out("%s: Invalid entry number: %s\n", ARG_CMD(a), 402 ARG_CUR(a)); 403 return (CMD_FAIL); 404 } 405 entry = parse_integer(ARG_GET(a)); 406 if (entry == 0) 407 return (CMD_OK); 408 if (_BCM_MULTICAST_IS_SET(entry) && _BCM_MULTICAST_IS_L3(entry)) { 409 entry = _BCM_MULTICAST_ID_GET(entry); 410 } 411 if (entry < soc_mem_index_min(unit, L3_IPMCm) || 412 entry > soc_mem_index_max(unit, L3_IPMCm)) { 413 cli_out("%s: ERROR: Entry # too high, only permitted %d\n", 414 ARG_CMD(a), soc_mem_index_max(unit, L3_IPMCm)); 415 return(CMD_FAIL); 416 } 417 one_entry_only = 1; 418 } 419 420 cli_out("SRC IP ADDRESS MC IP ADDRESS VLAN MOD PORT V COS "); 421 cli_out("TS GROUP %s\n", 422 "VRF"); 423 cli_out("%s %s %s %s\n", 424 "GROUP-L2 ", "CLASS", "HIT", "L3_IIF"); 425 if (one_entry_only) { 426 /* bcm_ipmc_get_by_index is deprecated */ 427 r = BCM_E_UNAVAIL; 428 return CMD_OK; 429 } 430 bcm_ipmc_traverse(unit, 0, _ipmc_cmd_entry_print, NULL); 431 return (CMD_OK); 432 break; 433 default: 434 return CMD_USAGE; 435 break; 436 } 437 return CMD_OK; 438 } 439 440 if (sal_strcasecmp(table, "egr") == 0) { 441 switch (subcmd) { 442 case IPMC_SET: 443 parse_table_init(unit, &pt); 444 parse_table_add(&pt, "Port", PQ_PORT, 0, (void *)&port, 0); 445 parse_table_add(&pt, "MAC", PQ_DFL|PQ_MAC, 0, (void *)mac, 0); 446 parse_table_add(&pt, "Vlan", PQ_INT, 0, (void *)&vlan, 0); 447 parse_table_add(&pt, "Untag", PQ_DFL|PQ_BOOL, 0, (void *)&untag, 448 0); 449 parse_table_add(&pt, "Ttl_thresh", PQ_DFL|PQ_INT, 0, 450 (void *)&ttl_th, 0); 451 if (!parseEndOk( a, &pt, &retCode)) 452 return retCode; 453 vid = vlan; 454 r = bcm_ipmc_egress_port_set(unit, port, mac, untag, vid, 455 ttl_th); 456 if (r < 0) { 457 cli_out("%s: Egress IP Multicast Configuration registers: %s\n", 458 ARG_CMD(a), bcm_errmsg(r)); 459 return CMD_FAIL; 460 } 461 break; 462 463 case IPMC_SHOW: 464 if ((argstr = ARG_GET(a)) == NULL) { 465 pbmp = pcfg.e; 466 } else { 467 if (parse_bcm_port(unit, argstr, &port) < 0) { 468 cli_out("%s: Invalid port string: %s\n", ARG_CMD(a), 469 argstr); 470 return CMD_FAIL; 471 } 472 if (!BCM_PBMP_MEMBER(pcfg.e, port)) { 473 cli_out("port %d is not a valid Ethernet port\n", port); 474 return CMD_FAIL; 475 } 476 BCM_PBMP_CLEAR(pbmp); 477 BCM_PBMP_PORT_ADD(pbmp, port); 478 } 479 cli_out("Egress IP Multicast Configuration Register information\n"); 480 cli_out("Port Mac Address Vlan Untag TTL_THRESH\n"); 481 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) { 482 r = bcm_ipmc_egress_port_get(unit, port, mac, &untag, &vid, 483 &ttl_th); 484 if (r == BCM_E_NONE) { 485 format_macaddr(mac_str, mac); 486 cli_out("%-4s %-18s %4d %s %5d\n", 487 BCM_PORT_NAME(unit, port), mac_str, 488 vid, untag ? "Y" : "N", ttl_th); 489 } 490 } 491 return CMD_OK; 492 break; 493 default: 494 return CMD_USAGE; 495 break; 496 } 497 498 return CMD_OK; 499 } 500 501 if (sal_strcasecmp(table, "counter") == 0) { 502 if ((argstr = ARG_GET(a)) == NULL) { 503 pbmp = pcfg.e; 504 } else { 505 if (parse_bcm_port(unit, argstr, &port) < 0) { 506 cli_out("%s: Invalid port string: %s\n", ARG_CMD(a), 507 argstr); 508 return CMD_FAIL; 509 } 510 if (!BCM_PBMP_MEMBER(pcfg.e, port)) { 511 cli_out("port %d is not a valid Ethernet port\n", port); 512 return CMD_FAIL; 513 } 514 BCM_PBMP_CLEAR(pbmp); 515 BCM_PBMP_PORT_ADD(pbmp, port); 516 } 517 cli_out("PORT RMCA TMCA IMBP IMRP RIMDR TIMDR\n"); 518 /* coverity[overrun-local] */ 519 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) { 520 r = bcm_ipmc_counters_get(unit, port, &counters); 521 if (r == BCM_E_NONE) { 522 cli_out("%4d %8d %8d %8d %8d %8d %8d\n", 523 port, 524 COMPILER_64_LO(counters.rmca), 525 COMPILER_64_LO(counters.tmca), 526 COMPILER_64_LO(counters.imbp), 527 COMPILER_64_LO(counters.imrp), 528 COMPILER_64_LO(counters.rimdr), 529 COMPILER_64_LO(counters.timdr)); 530 } 531 } 532 return CMD_OK; 533 } 534 535 #if defined(BCM_XGS3_SWITCH_SUPPORT) 536 if (sal_strcasecmp(table, "ip6table") == 0) { 537 switch (subcmd) { 538 /* ipmc ip6table add */ 539 case IPMC_ADD: 540 parse_table_init(unit, &pt); 541 parse_table_add(&pt, "Src_IP", PQ_DFL|PQ_IP6, 0, 542 (void *)&sip6_addr, 0); 543 parse_table_add(&pt, "Mc_IP", PQ_DFL|PQ_IP6, 0, 544 (void *)&ip6_addr, 0); 545 parse_table_add(&pt, "VlanID", PQ_DFL|PQ_INT, 0, (void *)&vlan, 0); 546 parse_table_add(&pt, "Valid", PQ_DFL|PQ_BOOL, 0, 547 (void *)&valid, 0); 548 parse_table_add(&pt, "COS", PQ_DFL|PQ_INT, 0, (void *)&cos, 0); 549 parse_table_add(&pt, "src_Port", PQ_INT, 0, (void *)&port, 0); 550 parse_table_add(&pt, "TS", PQ_INT, 0, (void *)&ts, 0); 551 parse_table_add(&pt, "NoCHECK", PQ_DFL|PQ_BOOL, 0, 552 (void *)&nocheck, 0); 553 parse_table_add(&pt, "LookupClass", PQ_DFL|PQ_INT, 0, 554 (void *)&lookup_class, 0); 555 parse_table_add(&pt, "Group", PQ_DFL|PQ_INT, 0, 556 (void *)&group, 0); 557 parse_table_add(&pt, "GroupL2", PQ_DFL|PQ_INT, 0, 558 (void *)&group_l2, 0); 559 if (parse_arg_eq(a, &pt) < 0) { 560 cli_out("%s: Error: Unknown option: %s\n", 561 ARG_CMD(a), ARG_CUR(a)); 562 parse_arg_eq_done(&pt); 563 return CMD_FAIL; 564 } 565 bcm_ipmc_addr_t_init(&ipmc_data); 566 if (pt.pt_entries[4].pq_type & PQ_PARSED) { 567 ipmc_data.flags |= BCM_IPMC_SETPRI; 568 } 569 parse_arg_eq_done(&pt); 570 sal_memcpy(ipmc_data.mc_ip6_addr, ip6_addr, BCM_IP6_ADDRLEN); 571 sal_memcpy(ipmc_data.s_ip6_addr, sip6_addr, BCM_IP6_ADDRLEN); 572 ipmc_data.cos = cos; 573 ipmc_data.vid = vlan; 574 ipmc_data.flags |= BCM_IPMC_IP6; 575 ipmc_data.ts = ts; 576 ipmc_data.port_tgid = port; 577 ipmc_data.v = valid; 578 if (nocheck) { 579 ipmc_data.flags |= BCM_IPMC_SOURCE_PORT_NOCHECK; 580 } 581 ipmc_data.lookup_class = lookup_class; 582 if (group) { 583 ipmc_data.group = group; 584 } 585 if (group_l2) { 586 ipmc_data.group_l2 = group_l2; 587 } 588 r = bcm_ipmc_add(unit, &ipmc_data); 589 if (r < 0) { 590 cli_out("%s: Error Add to ipmc table %s\n", ARG_CMD(a), 591 bcm_errmsg(r)); 592 return CMD_FAIL; 593 } 594 return CMD_OK; 595 break; 596 case IPMC_DEL: 597 /* ipmc ip6table del */ 598 parse_table_init(unit, &pt); 599 parse_table_add(&pt, "Src_IP", PQ_DFL|PQ_IP6, 0, 600 (void *)&sip6_addr, 0); 601 parse_table_add(&pt, "Mc_IP", PQ_DFL|PQ_IP6, 0, 602 (void *)&ip6_addr, 0); 603 parse_table_add(&pt, "VlanID", PQ_DFL|PQ_INT, 0, (void *)&vlan, 0); 604 if (!parseEndOk( a, &pt, &retCode)) 605 return retCode; 606 bcm_ipmc_addr_t_init(&ipmc_data); 607 sal_memcpy(ipmc_data.mc_ip6_addr, ip6_addr, BCM_IP6_ADDRLEN); 608 sal_memcpy(ipmc_data.s_ip6_addr, sip6_addr, BCM_IP6_ADDRLEN); 609 ipmc_data.vid=vlan; 610 ipmc_data.flags = BCM_IPMC_IP6; 611 r = bcm_ipmc_remove(unit, &ipmc_data); 612 if (r < 0) { 613 cli_out("%s: Error delete from ipmc table %s\n", ARG_CMD(a), 614 bcm_errmsg(r)); 615 return CMD_FAIL; 616 } 617 return CMD_OK; 618 break; 619 case IPMC_CLEAR: 620 /* ipmc ip6table clear */ 621 r = bcm_ipmc_remove_all(unit); 622 if (r < 0) { 623 cli_out("%s: %s\n", 624 ARG_CMD(a), bcm_errmsg(r)); 625 return CMD_FAIL; 626 } 627 return (CMD_OK); 628 break; 629 case IPMC_SHOW: 630 /* ipmc ip6table show */ 631 if (ARG_CNT(a)) { 632 if (!isint(ARG_CUR(a))) { 633 cli_out("%s: Invalid entry number: %s\n", ARG_CMD(a), 634 ARG_CUR(a)); 635 return (CMD_FAIL); 636 } 637 entry = parse_integer(ARG_GET(a)); 638 if (entry == 0) 639 return (CMD_OK); 640 if (entry < soc_mem_index_min(unit, L3_IPMCm) || 641 entry > soc_mem_index_max(unit, L3_IPMCm)) { 642 cli_out("%s: ERROR: Entry # too high, only permitted %d\n", 643 ARG_CMD(a), soc_mem_index_max(unit, L3_IPMCm)); 644 return(CMD_FAIL); 645 } 646 one_entry_only = 1; 647 } 648 649 if (one_entry_only) { 650 /* bcm_ipmc_get_by_index is deprecated */ 651 r = BCM_E_UNAVAIL; 652 cli_out("%s: bcm_ipmc_get_by_index is deprecated %s\n", 653 ARG_CMD(a), bcm_errmsg(r)); 654 } 655 bcm_ipmc_traverse(unit, BCM_IPMC_IP6, _ipmc_cmd_entry_print, NULL); 656 657 return (CMD_OK); 658 break; 659 default: 660 return CMD_USAGE; 661 break; 662 } 663 return CMD_OK; 664 } 665 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 666 667 return CMD_USAGE; 668 } 669 #endif /* BCM_XGS_SWITCH_SUPPORT */ 670 #endif /* INCLUDE_L3 */ 671 672 #ifdef INCLUDE_L3 673 char if_l3_usage[] = 674 "Usages:\n\t" 675 #ifdef COMPILER_STRING_CONST_LIMIT 676 " l3 <option> [args...]\n" 677 #else 678 " l3 init - Init L3 function.\n\t" 679 " l3 detach - Detach L3 function.\n\n\t" 680 681 " l3 intf add <Vlan>=<val> <Mac>=<val> [<INtf>=<val>] [<VRF>=<val>]\n\t" 682 " [<Mtu>=<val>] [<Group>=<val>]\n\t" 683 " - Add an entry into l3 interface table\n\t" 684 " l3 intf destroy <INtf>=<val>\n\t" 685 " - Destroy an entry in l3 interface table\n\t" 686 " l3 intf clear - Destroy all intf\n\t" 687 " l3 intf show - [<INtf>=<val>]\n\t" 688 " Display all Intfs or a single one\n\n\t" 689 690 " l3 egress add <Mac>=<val> <INtf>=<val> [<Trunk>=<val>]\n\t" 691 " <Port>=<val> [<MOdule>=<val>] [<L2tocpu>=<val>]\n\t" 692 " [<L3MC>=<val>] [<MplsLabel>=<val>] [<Drop>=<val>]\n\t" 693 " [<CopyToCpu>=<val>]\n\t" 694 " - Create egress object entry\n\t" 695 " l3 egress update <EgrId>=<val> <Mac>=<val> <INtf>=<val>\n\t" 696 " [<Trunk>=<val>] <Port>=<val> [<MOdule>=<val>]\n\t" 697 " [<L2tocpu>=<val>] [<L3MC>=<val>] [<MplsLabel>=<val>]\n\t" 698 " - Update egress object entry\n\t" 699 " l3 egress delete <entry>\n\t" 700 " - Delete egress object entry\n\t" 701 " l3 egress show [entry]\n\t" 702 " -Show egress object entry\n\t" 703 " l3 egress find <Mac>=<val> <INtf>=<val> [<Trunk>=<val>]\n\t" 704 " <Port>=<val> [<MOdule>=<val>] [<L2tocpu>=<val>]\n\t" 705 " [<L3MC>=<val>] [<MplsLabel>=<val>]\n\t" 706 " - Find egress object entry\n\t" 707 " l3 multipath add <Size>=<val> [<INtf0>=<val>] [<INtf1>=<val>]\n\t" 708 " [<INtf2>=<val>] [<INtf3>=<val>]\n\t" 709 " - Create multipath egress object entry\n\t" 710 " l3 multipath maxadd <Size>=<val> [<MaxGrpSize>=<val>] [<INtf0>=<val>] [<INtf1>=<val>]\n\t" 711 " [<INtf2>=<val>] [<INtf3>=<val>]\n\t" 712 " - Create multipath egress object entry(dynamic grp size)\n\t" 713 " l3 multipath update <EgrId>=<val> <Size>=<val> [<INtf0>=<val>]\n\t" 714 " [<INtf1>=<val>] [<INtf2>=<val>] [<INtf3>=<val>]\n\t" 715 " - Update multipath egress object entry\n\t" 716 " l3 multipath delete <entry>\n\t" 717 " - Delete multipath egress object entry\n\t" 718 " l3 multipath show [entry]\n\t" 719 " -Show multipath egress object entry\n\t" 720 " l3 multipath insert <EgrId>=<val> <Intf>=<val>\n\t" 721 " -Add interface to multipath egress object entry\n\t" 722 " l3 multipath remove <EgrId>=<val> <Intf>\n\t" 723 " -Remove interface from multipath egress object entry\n\t" 724 " l3 multipath find <Size>=<val> [<INtf0>=<val>] [<INtf1>=<val>]\n\t" 725 " [<INtf2>=<val>] [<INtf3>=<val>]\n\t" 726 " - Find multipath egress object entry\n\t" 727 " l3 ecmp egress add <Size>=<val> [<INtf0>=<val>] [<INtf1>=<val>]\n\t" 728 " [<INtf2>=<val>] [<INtf3>=<val>]\n\t" 729 " - Create ecmp egress object entry\n\t" 730 " l3 ecmp egress maxadd <Size>=<val> [<MaxGrpSize>=<val>] [<INtf0>=<val>] [<INtf1>=<val>]\n\t" 731 " [<INtf2>=<val>] [<INtf3>=<val>]\n\t" 732 " - Create ecmp egress object entry(dynamic grp size)\n\t" 733 " l3 ecmp egress update <EgrId>=<val> <Size>=<val> [<INtf0>=<val>]\n\t" 734 " [<INtf1>=<val>] [<INtf2>=<val>] [<INtf3>=<val>]\n\t" 735 " - Update ecmp egress object entry\n\t" 736 " l3 ecmp egress delete <entry>\n\t" 737 " - Delete ecmp egress object entry\n\t" 738 " l3 ecmp egress show [entry]\n\t" 739 " -Show ecmp egress object entry\n\t" 740 " l3 ecmp egress insert <EgrId>=<val> <Intf>=<val>\n\t" 741 " -Add interface to ecmp egress object entry\n\t" 742 " l3 ecmp egress remove <EgrId>=<val> <Intf>\n\t" 743 " -Remove interface from ecmp egress object entry\n\t" 744 " l3 ecmp egress find <Size>=<val> [<INtf0>=<val>] [<INtf1>=<val>]\n\t" 745 " [<INtf2>=<val>] [<INtf3>=<val>]\n\t" 746 " - Find ecmp egress object entry\n\t" 747 " l3 l3table add <VRF>=<val> <IP>=<val> <Mac>=<val> <INtf>=<val>\n\t" 748 " [<Hit>=<val>] [<Trunk>=<val>] [MOdule=<val>] <Port>=<val>\n\t" 749 " <PRI>=<val> <RPE>=<val> [<Untag>=<val>] [<L2tocpu>=<val>]\n\t" 750 " [<HOST_AS_ROUTE>=<val>] [Replace=<bool>] <LookupClass>=<val>\n\t" 751 " l3 l3table destroy <VRF>=<val> <IP>=<val>\n\t" 752 " - Destroy an entry in l3 table\n\t" 753 " l3 l3table clear - Destroy all l3 table\n\t" 754 " l3 l3table show - Display all l3 table or a single one\n\t" 755 " l3 l3table age - Age L3 table\n\t" 756 " l3 l3table sanity <Start=<index> End=<index>\n\t" 757 " - Check l3x tables for (san)ity in the given range\n\t" 758 " l3 l3table hash <VRF>=<val> <IP>=<val> [<SrcIP>=<val>] [<SipKey>=<val>]\n\t" 759 " [<VID>=<val>] [<Hash>=<hash_type>]\n\t" 760 " - Calculate l3 hash index\n\t" 761 " l3 l3table ip6hash <IP>=<val> [<SrcIP>=<val>] [<SipKey>=<val>]\n\t" 762 " [<VID>=<val>] [<Hash>=<hash_type>]\n\t" 763 " - Calculate l3 hash index for IPv6 entry\n\t" 764 " l3 l3table untag - Recalculate untagged bits for L3\n\n\t" 765 " l3 l3table conflict <VRF>=<val> <DIP>=<val> <DIP6>=<val>\n\t" 766 " <SIP>=<val> <SIP6>=<val> <IP6>=<val> <IPMC>=<val>\n\t" 767 " <VLAN>=<val> \n\t" 768 " - Get conflicting l3 entries.\n\n\t" 769 770 " l3 defip add <VRF>=<val> <IP>=<val> <MaSk>=<val> <Mac>=<val>\n\t" 771 " <INtf>=<val> <Gateway>=<next hop Ip address> <Port>=<val>\n\t" 772 " [MOdule=<val>] [<Untag>=<val>] [<Local>=<val>] [<ECMP>=<1/0>]\n\t" 773 " [<Hit>=<val>] [<VLAN>=<val>](BCM5695 def route 0.0.0.0/0 only)\n\t" 774 " [<DstDiscard>=<val>] <PRI>=<val> <RPE>=<val> [Replace=<bool>]\n\t" 775 " [<MplsLabel>=<val>] <TunnelOpt>=<val> <LookupClass>=<val>\n\t" 776 " - Add an IPv4 entry into DEFIP table\n\t" 777 " l3 defip destroy <VRF>=<val> <IP>=<val> <MaSk>=<val>\n\t" 778 " [<ECMP=<1/0> <Mac>=<val> <Gateway>=<next hop Ip address>\n\t" 779 " <INtf>=<val> <Port>=<val> [MOdule=<val>]\n\t" 780 " [<VLAN>=<val>](BCM5695 def route 0.0.0.0/0 only)\n\t" 781 " - Destroy an IPv4 entry in def IP table\n\t" 782 " l3 defip clear - Destroy all IPv4 DEFIP table\n\t" 783 " l3 defip age - Age DEFIP(LPM) table(XGS Switch only)\n\t" 784 " l3 defip show [<START> [<COUNT>]]\n\t" 785 " - Display all IPv4 DEFIP table or\n\t" 786 " the entires in a specified range\n\t" 787 " l3 defip ecmp <max>=<val> - Set MAX number of ECMP paths allowed\n\t" 788 " l3 defip ecmphash <DIP>=<val> <SIP>=<val> <SIP6>=val <DIP6>=val\n\t" 789 " <COUNT>=<val> <IP6>=val <L4_SRC_PORT>=val\n\t" 790 " <L4_DST_PORT>=val [<EHash>=<ECMP hash Sel>] \n\t" 791 " [<Hash>=<L3 hash type>]\n\t" 792 " - Calculate ECMP hash index (COUNT is zero based)\n\t" 793 #ifdef FB_LPM_DEBUG 794 " l3 defip sanity - Check L3 lpm states in scaling mode\n\n\t" 795 #endif 796 797 #ifdef ALPM_ENABLE 798 " l3 alpm show [all] [<VRF>=<val>] [<Global-vrf>=<bool>] \n\t" 799 " [<Pivot>=<bool>] [<Bucket>=<bool>] [<Counter>=<bool>]\n\t" 800 " [BucketuSage=<bool>] [InternelDebug=<bool>\n\t" 801 " - Show ALPM debug info\n\n\t" 802 803 " l3 alpm show brief [<Bucket>=<val>] [<Index>=<val>] \n\t" 804 " - Show ALPM brief debug info\n\n\t" 805 806 " l3 alpm find [<VRF>=<val>] <IP4>=<val> <IP6>=<val> [<Length>=<val>]\n\t" 807 " - Find hit longest prefix match route\n\n\t" 808 809 " l3 alpm sanity [<memory>=<val>] [<index>=<val>] [<sw>=<0/1>]\n\t" 810 " - Process sanity check for ALPM tables\n\n\t" 811 812 #endif 813 814 " l3 ip6host add <VRF>=<val> <IP>=<val> <Mac>=<val> [MOdule=<val>]\n\t" 815 " <Port>=<val> [<Trunk>=<val>] <INtf>=<val> [<Hit>=<val>]\n\t" 816 " <PRI>=<val> <RPE>=<val> [<Replace>=<bool>]\n\t" 817 " [<HOST_AS_ROUTE>=<bool>] <LookupClass>=<val>\n\t" 818 " - Add/Update an IPv6 entry\n\t" 819 " l3 ip6host delete <VRF>=<val> <IP>=<val>\n\t" 820 " - Delete an IPv6 entry\n\t" 821 " l3 ip6host clear - Delete all IPv6 host entries\n\t" 822 " l3 ip6host age - Age IPv6 host entries\n\t" 823 " l3 ip6host show - Show all IPv6 host entries\n\n\t" 824 825 " l3 ip6route add <VRF>=<val> <IP>=<val> <MaskLen>=<val> <Mac>=<val>\n\t" 826 " [MOdule=<val>] <Port>=<val> [<Trunk>=<val>]\n\t" 827 " <INtf>=<val> <VLan>=<val> [<Hit>=<val>]\n\t" 828 " [<ECMP>=<1/0>] [<DstDiscard>=<val>] <PRI>=<val>\n\t" 829 " <RPE>=<val> [Replace=<bool>] [<MplsLabel>=<val>]\n\t" 830 " <TunnelOpt>=<val> <LookupClass>=<val>\n\t" 831 " - Add IPv6 route\n\t" 832 " l3 ip6route delete <VRF>=<val> <IP>=<val> <MaskLen>=<val>\n\t" 833 " [<ECMP=<1/0> <Mac>=<val> <INtf>=<val> <Port>=<val> [MOdule=<val>]\n\t" 834 " - Delete an IPv6 route\n\t" 835 " l3 ip6route clear - Delete all IPv6 routes\n\t" 836 " l3 ip6route age - Clear all IPv6 route HIT bits\n\t" 837 " l3 ip6route show [<START> [<COUNT>]]\n\t" 838 " - Display all IPv6 routes or\n\t" 839 " the routes in a specified range\n\t" 840 841 " l3 tunnel_init set <INtf>=<val> <TYpe>=<val> <TTL>=<val>\n\t" 842 " <Mac>=<val> <DIP>=<val> <SIP>=<val> <DSCPSel>=<val> <DSCPV>=<val>\n\t" 843 " <DFSEL4>=<val> <DFSEL6>=<val> <SIP6>=<val> <DIP6>=<val>\n\t" 844 " l3 tunnel_init show <INtf>=<val>\n\t" 845 " l3 tunnel_init clear <INtf>=<val>\n\t" 846 847 " l3 tunnel_term add <TYPE>=<val> <VRF>=<val> <DIP>=<val> <SIP>=<val>\n\t" 848 " <DipMaskLen>=<val> <SipMaskLen>=<val> <DIP6>=<val> <SIP6>=<val>\n\t" 849 " <L4DstPort>=<val> <L4SrcPort>=<val> <OuterTTL>=<bool> \n\t" 850 " <OuterDSCP>=<val> <InnerDSCP>=<val> <TrustDSCP>=<val> \n\t" 851 " <VLanid>=<val> <PBMP>=<val> <AllowIPv6Payload>=<bool> \n\t" 852 " <AllowIPv4Payload>=<bool> <Replace>=<bool>\n\t" 853 " l3 tunnel_term delete <TYPE>=<val> <VRF>=<val> <DIP>=<val> <SIP>=<val>\n\t" 854 " <DipMaskLen>=<val> <SipMaskLen>=<val> <DIP6>=<val> <SIP6>=<val>\n\t" 855 " <L4DstPort>=<val> <L4SrcPort>=<val> \n\t" 856 " l3 tunnel_term show <TYPE>=<val> <VRF>=<val> <DIP>=<val> <SIP>=<val>\n\t" 857 " <DipMaskLen>=<val> <SipMaskLen>=<val> <DIP6>=<val> <SIP6>=<val>\n\t" 858 " <L4DstPort>=<val> <L4SrcPort>=<val> \n\t" 859 860 " l3 dscp_map add\n\t" 861 " l3 dscp_map destroy <DscpMapId>=<val>\n\t" 862 " l3 dscp_map set <DscpMapId>=<val> <Priority>=<val> <Color>=<val>\n\t" 863 " <DSCPValue>=<val>\n\t" 864 " l3 dscp_map show <DscpMapId>=<val>\n\t" 865 " l3 dscp_map_port set <Port>=<val> <Priority>=<val> <Color>=<val>\n\t" 866 " <DSCPValue>=<val>\n\t" 867 " l3 dscp_map_port show <Port>=<val>\n\t" 868 " l3 prefix_map add <IP>=<val>\n\t" 869 " l3 prefix_map delete <IP>=<val>\n\t" 870 " - Destroy ip6 prefix map to IPv4 entry\n\t" 871 " l3 prefix_map clear\n\t" 872 " - Flush ip6 prefix map to IPv4 entry\n\t" 873 " l3 prefix_map show [entry]\n\t" 874 " - Show ip6 prefix map to IPv4 entry\n\t" 875 " l3 nat_ingress show\n\t" 876 " - Show all NAT Ingress Rules\n\t" 877 " l3 nat_egress add <DNAT=0/1> <DIP=new_ip> <SIP=new_ip> <DIPMASK=mask>\n\t" 878 " <SIPMASK=mask> <SRCPORT=new_port> <DSTPORT=new_port>\n\t" 879 " - Add a new Egress Translation Rule\n\t" 880 " l3 nat_egress show\n\t" 881 " - Show all NAT Egress Translation Rules\n\t" 882 " l3 route test perf\n\t" 883 " - Run IPv4/IPv6 route performance test\n\t" 884 "\n" 885 #endif 886 ; 887 888 889 /* 890 * Function: 891 * _nat_ingress_traverse_cb 892 * Description: 893 * Internal function to print out ingress nat info. 894 * Parameters: 895 * unit - (IN) Device number. 896 * index - (IN) Ingress NAT index. 897 * nat_info - (IN) Ingress NAT structure. 898 * ign - (IN) Ingress NAT user data. 899 */ 900 int 901 _nat_ingress_traverse_cb(int unit, int index, 902 bcm_l3_nat_ingress_t *nat_info, void *ign) 903 { 904 char ip_str[IP6ADDR_STR_LEN]; 905 906 format_ipaddr(ip_str, nat_info->ip_addr); 907 cli_out("%-5d %-5d %-16s %-5d %-5d %-5d %-5d\n", 908 index, nat_info->nat_id, ip_str, nat_info->vrf, nat_info->l4_port, 909 nat_info->ip_proto, nat_info->nexthop); 910 return BCM_E_NONE; 911 } 912 913 /* 914 * Function: 915 * _nat_ingress_traverse_cb 916 * Description: 917 * Internal function to print out ingress nat info. 918 * Parameters: 919 * unit - (IN) Device number. 920 * index - (IN) Engress NAT index. 921 * nat_info - (IN) Engress NAT structure. 922 * ign - (IN) Engress NAT user data. 923 */ 924 int 925 _nat_egress_traverse_cb(int unit, int index, 926 bcm_l3_nat_egress_t *nat_info, void *ign) 927 { 928 char ip_str[IP6ADDR_STR_LEN]; 929 char ip_mask_str[IP6ADDR_STR_LEN]; 930 uint32 flags = nat_info->flags; 931 uint32 ref_count = 0; 932 933 _bcm_esw_l3_nat_egress_reference_get(unit, nat_info->nat_id, 934 &ref_count); 935 if(flags & BCM_L3_NAT_EGRESS_SNAT) 936 { 937 format_ipaddr(ip_str, nat_info->sip_addr); 938 format_ipaddr(ip_mask_str, nat_info->sip_addr_mask); 939 cli_out("%-5d %-5s %-5d %-16s %-16s %-6d %-8d\n", 940 index, "SNAT", nat_info->nat_id, ip_str, 941 ip_mask_str, nat_info->src_port, ref_count); 942 } 943 if(flags & BCM_L3_NAT_EGRESS_DNAT) 944 { 945 format_ipaddr(ip_str, nat_info->dip_addr); 946 format_ipaddr(ip_mask_str, nat_info->dip_addr_mask); 947 cli_out("%-5d %-5s %-5d %-16s %-16s %-6d %-8d\n", 948 index, "DNAT", nat_info->nat_id, ip_str, 949 ip_mask_str, nat_info->dst_port, ref_count); 950 } 951 return BCM_E_NONE; 952 } 953 954 /* 955 * Function: 956 * _l3_cmd_nat_ingress_show 957 * Description: 958 * Service routine used to show net entries. 959 * Parameters: 960 * unit - (IN) Device number. 961 * a - (IN) Command arguments. 962 * Returns: 963 * CMD_XXX 964 */ 965 STATIC int 966 _l3_cmd_nat_ingress_show(int unit, args_t *a) 967 { 968 int rv; 969 970 uint32 flags = 0; 971 972 /* -1 is special value to say all entries */ 973 cli_out("%-5s %-5s %-16s %-5s %-6s %-5s %-5s\n", "IDX", 974 "ID", "IP", "VRF", "L4Port", "IPProto", "NextHop"); 975 cli_out("*****SNAT Entries*****\n"); 976 rv = bcm_l3_nat_ingress_traverse( unit, flags, 0, -1, _nat_ingress_traverse_cb, NULL ); 977 if( BCM_FAILURE( rv ) ) { 978 cli_out("Failed in ingress_traverse: %s\n", bcm_errmsg(rv)); 979 return rv; 980 } 981 982 flags = BCM_L3_NAT_INGRESS_TYPE_NAPT; 983 rv = bcm_l3_nat_ingress_traverse( unit, flags, 0, -1, _nat_ingress_traverse_cb, NULL ); 984 if( BCM_FAILURE( rv ) ) { 985 cli_out("Failed in ingress_traverse: %s\n", bcm_errmsg(rv)); 986 return rv; 987 } 988 989 cli_out("*****DNAT Entries*****\n"); 990 flags = BCM_L3_NAT_INGRESS_DNAT; 991 rv = bcm_l3_nat_ingress_traverse( unit, flags, 0, -1, _nat_ingress_traverse_cb, NULL ); 992 if( BCM_FAILURE( rv ) ) { 993 cli_out("Failed in ingress_traverse: %s\n", bcm_errmsg(rv)); 994 return rv; 995 } 996 flags = BCM_L3_NAT_INGRESS_DNAT | BCM_L3_NAT_INGRESS_TYPE_NAPT; 997 rv = bcm_l3_nat_ingress_traverse( unit, flags, 0, -1, _nat_ingress_traverse_cb, NULL ); 998 if( BCM_FAILURE( rv ) ) { 999 cli_out("Failed in ingress_traverse: %s\n", bcm_errmsg(rv)); 1000 return rv; 1001 } 1002 1003 cli_out("*****DNAT Pool Entries*****\n"); 1004 flags = BCM_L3_NAT_INGRESS_DNAT | BCM_L3_NAT_INGRESS_DNAT_POOL; 1005 rv = bcm_l3_nat_ingress_traverse( unit, flags, 0, -1, _nat_ingress_traverse_cb, NULL ); 1006 if( BCM_FAILURE( rv ) ) { 1007 cli_out("Failed in ingress_traverse: %s\n", bcm_errmsg(rv)); 1008 return rv; 1009 } 1010 flags = BCM_L3_NAT_INGRESS_DNAT 1011 | BCM_L3_NAT_INGRESS_DNAT_POOL 1012 | BCM_L3_NAT_INGRESS_TYPE_NAPT; 1013 rv = bcm_l3_nat_ingress_traverse( unit, flags, 0, -1, _nat_ingress_traverse_cb, NULL ); 1014 if( BCM_FAILURE( rv ) ) { 1015 cli_out("Failed in ingress_traverse: %s\n", bcm_errmsg(rv)); 1016 return rv; 1017 } 1018 1019 return CMD_OK; 1020 } 1021 1022 /* 1023 * Function: 1024 * _l3_cmd_nat_egress_add 1025 * Description: 1026 * Service routine used to add net entry. 1027 * Parameters: 1028 * unit - (IN) Device number. 1029 * a - (IN) Command arguments. 1030 * Returns: 1031 * CMD_XXX 1032 */ 1033 STATIC int 1034 _l3_cmd_nat_egress_add(int unit, args_t *a) 1035 { 1036 parse_table_t pt; 1037 cmd_result_t retCode; 1038 bcm_ip_t sip_addr = 0; 1039 bcm_ip_t dip_addr = 0; 1040 bcm_ip_t sip_mask = 0; 1041 bcm_ip_t dip_mask = 0; 1042 int src_port = 0; 1043 int dst_port = 0; 1044 int dnat = 0; 1045 int rv; 1046 bcm_l3_nat_egress_t nat_info; 1047 1048 1049 parse_table_init(unit, &pt); 1050 parse_table_add(&pt, "DIP", PQ_DFL | PQ_IP, 0, (void *)&dip_addr, 0); 1051 parse_table_add(&pt, "SIP", PQ_DFL | PQ_IP, 0, (void *)&sip_addr, 0); 1052 parse_table_add(&pt, "DIPMASK", PQ_DFL | PQ_IP, 0, (void *)&dip_mask, 0); 1053 parse_table_add(&pt, "SIPMASK", PQ_DFL | PQ_IP, 0, (void *)&sip_mask, 0); 1054 parse_table_add(&pt, "SRCPORT", PQ_DFL | PQ_INT, 0, (void *)&src_port, 0); 1055 parse_table_add(&pt, "SRCPORT", PQ_DFL | PQ_INT, 0, (void *)&dst_port, 0); 1056 parse_table_add(&pt, "DNAT", PQ_DFL | PQ_INT, 0, (void *)&dnat, 0); 1057 if (!parseEndOk(a, &pt, &retCode)) { 1058 return retCode; 1059 } 1060 1061 bcm_l3_nat_egress_t_init( &nat_info ); 1062 if( dnat ) { 1063 nat_info.flags = BCM_L3_NAT_EGRESS_DNAT; 1064 } 1065 else { 1066 nat_info.flags = BCM_L3_NAT_EGRESS_SNAT; 1067 } 1068 nat_info.sip_addr = sip_addr; 1069 nat_info.dip_addr = dip_addr; 1070 nat_info.sip_addr_mask = sip_mask; 1071 nat_info.dip_addr_mask = dip_mask; 1072 nat_info.src_port = src_port; 1073 nat_info.dst_port = dst_port; 1074 1075 rv = bcm_l3_nat_egress_add(unit, &nat_info); 1076 if (BCM_FAILURE(rv)) { 1077 cli_out("Egress Add failed: %s\n", bcm_errmsg(rv)); 1078 return rv; 1079 } 1080 cli_out("NAT ID: %d\n", nat_info.nat_id); 1081 1082 return CMD_OK; 1083 } 1084 1085 /* 1086 * Function: 1087 * _l3_cmd_nat_egress_show 1088 * Description: 1089 * Service routine used to show net egress info. 1090 * Parameters: 1091 * unit - (IN) Device number. 1092 * a - (IN) Command arguments. 1093 * Returns: 1094 * CMD_XXX 1095 */ 1096 STATIC int 1097 _l3_cmd_nat_egress_show(int unit, args_t *a) 1098 { 1099 int rv; 1100 1101 uint32 flags = 0; 1102 1103 cli_out("%-5s %-5s %-5s %-16s %-16s %-6s %-8s\n", "IDX", 1104 "TYPE", "ID", "IP", "MASK", "L4Port", "RefCount"); 1105 /* -1 is special value to say all entries */ 1106 rv = bcm_l3_nat_egress_traverse( unit, flags, 0, -1, _nat_egress_traverse_cb, NULL ); 1107 if( BCM_FAILURE( rv ) ) { 1108 cli_out("Failed in egress_traverse: %s\n", bcm_errmsg(rv)); 1109 return rv; 1110 } 1111 1112 return CMD_OK; 1113 } 1114 1115 1116 1117 /* 1118 * Function: 1119 * _l3_cmd_route_print 1120 * Description: 1121 * Internal function to print out route info 1122 * Parameters: 1123 * unit - device number. 1124 * index - Traversal index number 1125 * info - Pointer to bcm_l3_route_t data structure. 1126 * cookie - user cookie 1127 */ 1128 STATIC int 1129 _l3_cmd_route_print(int unit, int index, bcm_l3_route_t *info, void *cookie) 1130 { 1131 char ip_str[IP6ADDR_STR_LEN + 3]; 1132 char if_mac_str[SAL_MACADDR_STR_LEN]; 1133 char vrf_str[20]; 1134 char *hit; 1135 char *trunk; 1136 int masklen; 1137 int priority; 1138 1139 hit = (info->l3a_flags & BCM_L3_HIT) ? "y" : "n"; 1140 trunk = (info->l3a_flags & BCM_L3_TGID) ? "t" : " "; 1141 priority = info->l3a_pri; 1142 1143 switch (info->l3a_vrf){ 1144 case BCM_L3_VRF_GLOBAL: 1145 /* coverity[secure_coding : FALSE] */ 1146 sal_strcpy(vrf_str,"Global"); 1147 break; 1148 case BCM_L3_VRF_OVERRIDE: 1149 /* coverity[secure_coding : FALSE] */ 1150 sal_strcpy(vrf_str,"Override"); 1151 break; 1152 default: 1153 sal_sprintf(vrf_str,"%d",info->l3a_vrf); 1154 } 1155 1156 format_macaddr(if_mac_str, info->l3a_nexthop_mac); 1157 1158 if (info->l3a_flags & BCM_L3_IP6) { 1159 format_ip6addr(ip_str, info->l3a_ip6_net); 1160 masklen = bcm_ip6_mask_length(info->l3a_ip6_mask); 1161 cli_out("%-5d %-8s %-s/%d %18s %4d %4d %5d%1s %4d %4d %s", index, vrf_str, 1162 ip_str, masklen, if_mac_str, info->l3a_intf, 1163 info->l3a_modid, info->l3a_port_tgid, trunk, priority, 1164 info->l3a_lookup_class, hit); 1165 } else { 1166 format_ipaddr_mask(ip_str, info->l3a_subnet, info->l3a_ip_mask); 1167 cli_out("%-5d %-8s %-19s %18s %4d %4d %5d%1s %4d %4d %s", index, vrf_str, 1168 ip_str, if_mac_str, info->l3a_intf, 1169 info->l3a_modid, info->l3a_port_tgid, trunk, priority, 1170 info->l3a_lookup_class, hit); 1171 1172 if (SOC_CHIP_GROUP(unit) == SOC_CHIP_BCM5695 && 1173 info->l3a_subnet == 0) { 1174 cli_out(" %d (Per VLAN)", info->l3a_vid); 1175 } 1176 } 1177 1178 if (info->l3a_flags & BCM_L3_MULTIPATH) { 1179 cli_out(" (ECMP)"); 1180 } else if (info->l3a_flags & BCM_L3_DEFIP_LOCAL) { 1181 cli_out(" (LOCAL ROUTE)"); 1182 } 1183 1184 if (info->l3a_flags & BCM_L3_ROUTE_LABEL) { 1185 cli_out(" (MPLS)%d", info->l3a_mpls_label); 1186 } else if (info->l3a_tunnel_option) { 1187 cli_out(" (UDP tunnel) %d", info->l3a_tunnel_option); 1188 } 1189 cli_out("\n"); 1190 1191 1192 return BCM_E_NONE; 1193 } 1194 1195 1196 /* 1197 * Function: 1198 * _l3_cmd_egress_intf_print 1199 * Description: 1200 * Internal function to print out egress l3 interface info. 1201 * Parameters: 1202 * unit - (IN) Device number. 1203 * print_hdr - (IN) Print header indicator. 1204 * intf - (IN) Pointer to bcm_l3_intf_t data structure. 1205 */ 1206 STATIC int 1207 _l3_cmd_egress_intf_print(int unit, int print_hdr, bcm_l3_intf_t *intf) 1208 { 1209 char if_mac_str[SAL_MACADDR_STR_LEN]; 1210 1211 if (NULL == intf) { 1212 return (BCM_E_PARAM); 1213 } 1214 1215 if (print_hdr) { 1216 cli_out("Unit Intf VRF Group VLAN Source Mac MTU TTL Tunnel InnerVlan NATRealm\n"); 1217 cli_out("------------------------------------------------------------------\n"); 1218 } 1219 1220 format_macaddr(if_mac_str, intf->l3a_mac_addr); 1221 cli_out("%-5d %-5d %-5d %-5d %-4d %-18s %-4d %-4d %-5d %-5d %-5d\n", unit, 1222 intf->l3a_intf_id, intf->l3a_vrf, intf->l3a_group, 1223 intf->l3a_vid, if_mac_str, intf->l3a_mtu, intf->l3a_ttl, 1224 intf->l3a_tunnel_idx, intf->l3a_inner_vlan, intf->l3a_nat_realm_id); 1225 return (CMD_OK); 1226 } 1227 1228 1229 /* 1230 * Function: 1231 * _l3_cmd_tunnel_init_print 1232 * Description: 1233 * Internal function to print out tunnel initiator info. 1234 * Parameters: 1235 * unit - (IN) Device number. 1236 * interface - (IN) L3 egress interface. 1237 * info - (IN) Pointer to bcm_tunnel_initiator_t data structure. 1238 */ 1239 STATIC int 1240 _l3_cmd_tunnel_init_print (int unit, bcm_if_t interface, bcm_tunnel_initiator_t *info) 1241 { 1242 char ip_str[IP6ADDR_STR_LEN + 3]; 1243 char if_mac_str[SAL_MACADDR_STR_LEN]; 1244 1245 cli_out("Tunnel initiator:\n"); 1246 cli_out("\tUnit = %d\n", unit); 1247 cli_out("\tInterface = %d\n", interface); 1248 cli_out("\tTUNNEL_TYPE = %d\n", info->type); 1249 cli_out("\tTTL = %d\n", info->ttl); 1250 format_macaddr(if_mac_str, info->dmac); 1251 cli_out("\tMAC_ADDR = %-18s\n", if_mac_str); 1252 if (_BCM_TUNNEL_OUTER_HEADER_IPV6(info->type)) { 1253 format_ip6addr(ip_str, info->dip6); 1254 cli_out("\tDIP = 0x%-s\n", ip_str); 1255 format_ip6addr(ip_str, info->sip6); 1256 cli_out("\tSIP = 0x%-s\n", ip_str); 1257 } else { 1258 cli_out("\tDIP = 0x%08x\n", info->dip); 1259 cli_out("\tSIP = 0x%08x\n", info->sip); 1260 if (info->flags & BCM_TUNNEL_INIT_USE_INNER_DF) { 1261 cli_out("\tCopy DF from inner header.\n"); 1262 } else if (info->flags & BCM_TUNNEL_INIT_IPV4_SET_DF) { 1263 cli_out("\tForce DF to 1 for ipv4 payload.\n"); 1264 } 1265 if (info->flags & BCM_TUNNEL_INIT_IPV6_SET_DF) { 1266 cli_out("\tForce DF to 1 for ipv6 payload.\n"); 1267 } 1268 } 1269 cli_out("\tDSCP_SEL = 0x%x\n", info->dscp_sel); 1270 cli_out("\tDSCP = 0x%x\n", info->dscp); 1271 cli_out("\tDSCP_MAP = 0x%x\n", info->dscp_map); 1272 return CMD_OK; 1273 } 1274 1275 /* 1276 * Function: 1277 * _l3_cmd_tunnel_term_print 1278 * Description: 1279 * Internal function to print out tunnel terminator info. 1280 * Parameters: 1281 * unit - (IN) Device number. 1282 * info - (IN) Pointer to bcm_tunnel_terminator_t data structure. 1283 */ 1284 STATIC int 1285 _l3_cmd_tunnel_term_print (int unit, bcm_tunnel_terminator_t *info) 1286 { 1287 char ip_str[IP6ADDR_STR_LEN + 3]; 1288 char buf_pbmp[SOC_PBMP_FMT_LEN]; 1289 1290 cli_out("Tunnel terminator:\n"); 1291 cli_out("\tUnit = %d\n", unit); 1292 cli_out("\tTUNNEL_TYPE = %d\n", info->type); 1293 cli_out("\tVRF = %d\n", info->vrf); 1294 if (_BCM_TUNNEL_OUTER_HEADER_IPV6(info->type)) { 1295 format_ip6addr(ip_str, info->dip6); 1296 cli_out("\tDIP = 0x%-s\n", ip_str); 1297 format_ip6addr(ip_str, info->dip6_mask); 1298 cli_out("\tDIP MASK = 0x%-s\n", ip_str); 1299 format_ip6addr(ip_str, info->sip6); 1300 cli_out("\tSIP = 0x%-s\n", ip_str); 1301 format_ip6addr(ip_str, info->sip6_mask); 1302 cli_out("\tSIP MASK = 0x%-s\n", ip_str); 1303 } else { 1304 cli_out("\tDIP = 0x%08x\n", info->dip); 1305 cli_out("\tDIP_MASK = 0x%08x\n", info->dip_mask); 1306 cli_out("\tSIP = 0x%08x\n", info->sip); 1307 cli_out("\tSIP_MASK = 0x%08x\n", info->sip_mask); 1308 } 1309 1310 1311 cli_out("\tL4 Destination Port = 0x%08x\n", info->udp_dst_port); 1312 cli_out("\tL4 Source Port = 0x%08x\n", info->udp_src_port); 1313 cli_out("\tVlan id = 0x%08x\n", info->vlan); 1314 format_pbmp(unit, buf_pbmp, sizeof(buf_pbmp), info->pbmp); 1315 cli_out("\tPbmp = 0x%s\n", buf_pbmp); 1316 1317 if (info->flags & BCM_TUNNEL_TERM_USE_OUTER_DSCP) { 1318 cli_out("\tCopy DSCP from outer ip header.\n"); 1319 } else if (info->flags & BCM_TUNNEL_TERM_KEEP_INNER_DSCP) { 1320 cli_out("\tCopy DSCP from inner ip header.\n"); 1321 } 1322 1323 1324 if (info->flags & BCM_TUNNEL_TERM_DSCP_TRUST) { 1325 cli_out("\tTrust incming DSCP based on inner/outer selection.\n"); 1326 } 1327 1328 if (info->flags & BCM_TUNNEL_TERM_USE_OUTER_TTL) { 1329 cli_out("\tCopy TTL from outer ip header.\n"); 1330 } 1331 return CMD_OK; 1332 } 1333 1334 1335 /* 1336 * Function: 1337 * _l3_cmd_egress_mpath_obj_print 1338 * Description: 1339 * Internal function to print out multipath egress object info 1340 * Parameters: 1341 * unit - device number. 1342 * index - Egress object id. 1343 * intf_count - Interface count. 1344 * info - Pointer to interfaces array. 1345 * user_data - User cookie. 1346 */ 1347 STATIC int 1348 _l3_cmd_egress_mpath_obj_print(int unit, int index, int intf_count, bcm_if_t 1349 *info, void *user_data) 1350 { 1351 int idx; 1352 uint32 ref_count; 1353 1354 cli_out("Multipath Egress Object %d\n", index); 1355 1356 cli_out("Interfaces:"); 1357 1358 for (idx = 0; idx < intf_count; idx++) { 1359 cli_out(" %d", info[idx]); 1360 if (idx && (!(idx % 10))) { 1361 cli_out("\n "); 1362 } 1363 } 1364 1365 /* 1366 * Get the reference count for the multipath object. This ref count 1367 * indicates the number of route references for this egress object. This is 1368 * a read only object and used for debugging purposes. Hence, this is not 1369 * exposed in the form of an API and retrieved internally 1370 */ 1371 _bcm_esw_l3_egress_reference_get(unit, index, 1, &ref_count); 1372 1373 cli_out("\nReference count: %d", ref_count); 1374 cli_out("\n"); 1375 return BCM_E_NONE; 1376 } 1377 1378 /* 1379 * Function: 1380 * _l3_cmd_egress_ecmp_obj_print 1381 * Description: 1382 * Internal function to print out ecmp egress object info 1383 * Parameters: 1384 * unit - device number. 1385 * ecmp - ECMP group info. 1386 * intf_count - Interface count. 1387 * intf_array - Array of Egress forwarding objects. 1388 * user_data - User cookie. 1389 */ 1390 STATIC int 1391 _l3_cmd_egress_ecmp_obj_print(int unit, bcm_l3_egress_ecmp_t *ecmp, 1392 int intf_count, bcm_if_t *intf_array, 1393 void *user_data) 1394 { 1395 int idx; 1396 uint32 ref_count; 1397 1398 cli_out("ECMP Egress Object %d\n", ecmp->ecmp_intf); 1399 1400 cli_out("Interfaces:"); 1401 1402 for (idx = 0; idx < intf_count; idx++) { 1403 cli_out(" %d", *intf_array); 1404 if (idx && (!(idx % 10))) { 1405 cli_out("\n "); 1406 } 1407 intf_array++; 1408 } 1409 1410 /* 1411 * Get the reference count for the ecmp object. This ref count 1412 * indicates the number of route references for this egress object. This is 1413 * a read only object and used for debugging purposes. Hence, this is not 1414 * exposed in the form of an API and retrieved internally 1415 */ 1416 _bcm_esw_l3_egress_reference_get(unit, ecmp->ecmp_intf, 1, &ref_count); 1417 1418 cli_out("\nReference count: %d", ref_count); 1419 cli_out("\n"); 1420 return BCM_E_NONE; 1421 } 1422 1423 /* 1424 * Function: 1425 * _l3_cmd_egress_obj_print 1426 * Description: 1427 * Internal function to print out egress object info 1428 * Parameters: 1429 * unit - device number. 1430 * index - Egress object id. 1431 * info - Pointer to bcm_l3_egres_t data structure. 1432 * cookie - user cookie 1433 */ 1434 STATIC int 1435 _l3_cmd_egress_obj_print(int unit, int index, bcm_l3_egress_t *info, void *cookie) 1436 { 1437 char if_mac_str[SAL_MACADDR_STR_LEN]; 1438 char *trunk; 1439 int port, tgid, module, id; 1440 uint32 ref_count = 0; 1441 1442 trunk = (info->flags & BCM_L3_TGID) ? "t" : " "; 1443 1444 format_macaddr(if_mac_str, info->mac_addr); 1445 if (BCM_GPORT_IS_SET(info->port)) { 1446 BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, info->port, &module, &port, &tgid, &id)); 1447 if (id != -1) { 1448 port = id; 1449 } 1450 } else { 1451 port = info->port; 1452 module = info->module; 1453 tgid = info->trunk; 1454 } 1455 1456 /* 1457 * Get the reference count for the egress object. This ref count indicates 1458 * the number of route references for this egress object. This is a read 1459 * only object and used for debugging purposes. Hence, this is not exposed 1460 * in the form of an API and retrieved internally 1461 */ 1462 _bcm_esw_l3_egress_reference_get(unit, index, 0, &ref_count); 1463 1464 BCM_IF_ERROR_RETURN(_bcm_esw_l3_egress_ref_dlb_update 1465 (unit, index, &ref_count)); 1466 1467 cli_out("%d %18s %4d %4d %5d%1s %3d %9d %4s %4s %4u %4s\n", index, 1468 if_mac_str, info->vlan, info->intf, 1469 ((info->flags & BCM_L3_TGID) ? tgid : port), 1470 trunk, module, info->mpls_label, 1471 (info->flags & BCM_L3_COPY_TO_CPU) ? "yes" : "no" , 1472 (info->flags & BCM_L3_DST_DISCARD) ? "yes" : "no" , 1473 ref_count, 1474 (info->flags & BCM_L3_IPMC) ? "yes" : "no"); 1475 1476 return BCM_E_NONE; 1477 } 1478 1479 /* 1480 * Function: 1481 * _l3_cmd_host_print 1482 * Description: 1483 * Internal function to print out host entry info 1484 * Parameters: 1485 * unit - device number. 1486 * index - Traversal index number 1487 * info - Pointer to bcm_l3_host_t data structure. 1488 * cookie - user cookie 1489 */ 1490 STATIC int 1491 _l3_cmd_host_print(int unit, int index, bcm_l3_host_t *info, void *cookie) 1492 { 1493 char ip_str[IP6ADDR_STR_LEN]; 1494 char if_mac_str[SAL_MACADDR_STR_LEN]; 1495 char *hit; 1496 char *trunk = " "; 1497 int tgid=0, port, module, id; 1498 1499 hit = (info->l3a_flags & BCM_L3_HIT) ? "y" : "n"; 1500 1501 format_macaddr(if_mac_str, info->l3a_nexthop_mac); 1502 if (BCM_GPORT_IS_SET(info->l3a_port_tgid)) { 1503 BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, info->l3a_port_tgid, &module, 1504 &port, &tgid, &id)); 1505 #ifdef BCM_RIOT_SUPPORT 1506 /* VFI type virtual port */ 1507 if (_bcm_vp_is_vfi_type(unit, info->l3a_port_tgid)) { 1508 port = id; 1509 } else 1510 #endif 1511 { 1512 if (!BCM_L3_BK_FLAG_GET(unit, BCM_L3_BK_ENABLE_MACDA_OUI_PROFILE)) { 1513 /* For Tomahawk L3/NIV/PE extended view,ignore id = -1 check 1514 * as id > 0 is returned for VPs in extended view 1515 */ 1516 if (id != -1) { 1517 return CMD_USAGE; 1518 } 1519 } 1520 } 1521 if (tgid != -1) { 1522 trunk = "t"; 1523 } 1524 } else { 1525 if (info->l3a_flags & BCM_L3_TGID) { 1526 trunk = "t" ; 1527 tgid = info->l3a_port_tgid; 1528 port = -1; 1529 } else { 1530 port = info->l3a_port_tgid; 1531 } 1532 module = info->l3a_modid; 1533 } 1534 1535 if (info->l3a_flags & BCM_L3_IP6) { 1536 format_ip6addr(ip_str, info->l3a_ip6_addr); 1537 cli_out("%-5d %-4d %-42s %18s %4d %4d %5d%1s %6d %s %-5d\n", 1538 index, info->l3a_vrf, ip_str, if_mac_str, info->l3a_intf, 1539 module, (port == -1) ? tgid : port, trunk, 1540 info->l3a_lookup_class, hit, *(int *)cookie); 1541 } else { 1542 format_ipaddr(ip_str, info->l3a_ip_addr); 1543 cli_out("%-5d %-4d %-16s %-18s %4d %4d %4d%1s %6d %s %-5d", 1544 index, info->l3a_vrf, ip_str, if_mac_str, info->l3a_intf, 1545 module, (port == -1) ? tgid : port, trunk, 1546 info->l3a_lookup_class, hit, *(int *)cookie); 1547 } 1548 1549 if (info->l3a_flags & BCM_L3_MULTIPATH) { 1550 cli_out(" (ECMP)\n"); 1551 } else if (info->l3a_flags & BCM_L3_HOST_LOCAL) { 1552 cli_out(" (LOCAL ROUTE)\n"); 1553 } else { 1554 cli_out("\n"); 1555 } 1556 1557 return BCM_E_NONE; 1558 } 1559 1560 1561 /* 1562 * Function: 1563 * _l3_cmd_l3_key_print 1564 * Description: 1565 * Internal function to print out host entry info 1566 * Parameters: 1567 * unit - device number. 1568 * index - Traversal index number 1569 */ 1570 STATIC int 1571 _l3_cmd_l3_key_print(int unit, int index, bcm_l3_key_t *info) 1572 { 1573 char dip_str[IP6ADDR_STR_LEN]; 1574 char sip_str[IP6ADDR_STR_LEN]; 1575 1576 if (info->l3k_flags & BCM_L3_IPMC) { 1577 if (info->l3k_flags & BCM_L3_IP6) { 1578 format_ip6addr(dip_str, info->l3k_ip6_addr); 1579 format_ip6addr(sip_str, info->l3k_sip6_addr); 1580 cli_out("%-5d Group %-42s\n", index, dip_str); 1581 cli_out(" Src %-42s\n", sip_str); 1582 cli_out(" Vrf %-4d VLAN %-4d\n", info->l3k_vrf, info->l3k_vid); 1583 } else { 1584 format_ipaddr(dip_str, info->l3k_ip_addr); 1585 format_ipaddr(sip_str, info->l3k_sip_addr); 1586 cli_out("%-5d Group %-18s Src %-18s Vrf %-4d Vlan %-4d\n", 1587 index, dip_str, sip_str, info->l3k_vrf, info->l3k_vid); 1588 } 1589 } else { 1590 if (info->l3k_flags & BCM_L3_IP6) { 1591 format_ip6addr(dip_str, info->l3k_ip6_addr); 1592 cli_out("%-5d VRF %-4d DIP %-18s\n", 1593 index, info->l3k_vrf, dip_str); 1594 } else { 1595 format_ipaddr(dip_str, info->l3k_ip_addr); 1596 cli_out("%-5d VRF %-4d DIP %-18s\n", 1597 index, info->l3k_vrf, dip_str); 1598 } 1599 } 1600 return CMD_OK; 1601 } 1602 1603 1604 /* 1605 * Function: 1606 * _l3_cmd_host_age_callback 1607 * Description: 1608 * Internal function to print out host entry being aged out 1609 * Parameters: 1610 * unit - device number. 1611 * index - Traversal index number 1612 * info - Pointer to bcm_l3_host_t data structure. 1613 * cookie - user cookie 1614 */ 1615 STATIC int 1616 _l3_cmd_host_age_callback(int unit, int index, bcm_l3_host_t *info, void *cookie) 1617 { 1618 if (info->l3a_flags & BCM_L3_IP6) { 1619 char ip_str[IP6ADDR_STR_LEN]; 1620 1621 format_ip6addr(ip_str, info->l3a_ip6_addr); 1622 cli_out("IPv6 Address %s age out\n", ip_str); 1623 } else { 1624 cli_out("IP Address 0x%x age out\n", info->l3a_ip_addr); 1625 } 1626 1627 return BCM_E_NONE; 1628 } 1629 1630 /* 1631 * Function: 1632 * _l3_cmd_route_age_callback 1633 * Description: 1634 * Internal function to print out route being aged (HIT bit cleared) 1635 * Parameters: 1636 * unit - device number. 1637 * index - Traversal index number 1638 * info - Pointer to bcm_l3_host_t data structure. 1639 * cookie - user cookie 1640 */ 1641 STATIC int 1642 _l3_cmd_route_age_callback(int unit, int index, bcm_l3_route_t *net, void *cookie) 1643 { 1644 if (net->l3a_flags & BCM_L3_IP6) { 1645 char ip_str[IP6ADDR_STR_LEN]; 1646 int masklen; 1647 1648 format_ip6addr(ip_str, net->l3a_ip6_net); 1649 masklen = bcm_ip6_mask_length(net->l3a_ip6_mask); 1650 cli_out("Deleted unused route %s/%d)\n", ip_str, masklen); 1651 } else { 1652 cli_out("Deleted unused route 0x%x(mask 0x%x)\n", 1653 net->l3a_subnet, net->l3a_ip_mask); 1654 } 1655 1656 return BCM_E_NONE; 1657 } 1658 1659 /* 1660 * L3 command catagory 1661 */ 1662 enum _l3_cmd_t { 1663 L3_ADD = 1, 1664 L3_DESTROY, 1665 L3_SET, 1666 L3_CLEAR, 1667 L3_SHOW, 1668 L3_AGE, 1669 L3_UPDATE, 1670 L3_HASH, 1671 L3_IP6HASH, 1672 L3_SANITY, 1673 L3_ECMP, 1674 L3_ECMP_HASH, 1675 L3_INSERT, 1676 L3_REMOVE, 1677 L3_FIND, 1678 L3_CONFLICT, 1679 L3_TEST, 1680 L3_MAXADD 1681 }; 1682 1683 const char *cmd_tunnel_term_parse_type[] = { 1684 "6to4", 1685 "6to4-unchecked", 1686 "isatap", 1687 "ipip", 1688 NULL 1689 }; 1690 1691 1692 #if defined(BCM_XGS_SWITCH_SUPPORT) 1693 /* 1694 * Function: 1695 * _l3_cmd_l3_conflict_show 1696 * Description: 1697 * Service routine used to show l3 table conflicting entries. 1698 * Parameters: 1699 * unit - (IN) Device number. 1700 * a - (IN) Command arguments. 1701 * Returns: 1702 * CMD_XXX 1703 */ 1704 1705 STATIC cmd_result_t 1706 _l3_cmd_l3_conflict_show(int unit, args_t *a) 1707 { 1708 parse_table_t pt; 1709 cmd_result_t retCode; 1710 bcm_ip6_t sip6_addr; 1711 bcm_ip6_t ip6_addr; 1712 bcm_ip_t sip_addr = 0; 1713 bcm_ip_t ip_addr = 0; 1714 int vlan = 0; 1715 int ipmc = 0; 1716 int ip6 = 0; 1717 bcm_vrf_t vrf = BCM_L3_VRF_DEFAULT; 1718 bcm_l3_key_t ipkey; 1719 bcm_l3_key_t result[L3X_MAX_BUCKET_SIZE]; 1720 int count; 1721 int idx; 1722 int rv; 1723 1724 /* Stack variables initialization. */ 1725 sal_memset(sip6_addr, 0, sizeof(bcm_ip6_t)); 1726 sal_memset(ip6_addr, 0, sizeof(bcm_ip6_t)); 1727 sal_memset(result, 0, L3X_MAX_BUCKET_SIZE * sizeof(bcm_l3_key_t)); 1728 1729 parse_table_init(unit, &pt); 1730 parse_table_add(&pt, "DIP", PQ_DFL | PQ_IP, 0, (void *)&ip_addr, 0); 1731 parse_table_add(&pt, "SIP", PQ_DFL | PQ_IP, 0, (void *)&sip_addr, 0); 1732 parse_table_add(&pt, "DIP6", PQ_DFL | PQ_IP6, 0, (void *)&ip6_addr, 0); 1733 parse_table_add(&pt, "SIP6", PQ_DFL | PQ_IP6, 0, (void *)&sip6_addr, 0); 1734 parse_table_add(&pt, "VRF", PQ_DFL | PQ_INT, 0, (void *)&vrf, 0); 1735 parse_table_add(&pt, "VLAN", PQ_DFL | PQ_INT, 0, (void *)&vlan, 0); 1736 parse_table_add(&pt, "IPMC", PQ_DFL | PQ_INT, 0, (void *)&ipmc, 0); 1737 parse_table_add(&pt, "IP6", PQ_DFL | PQ_INT, 0, (void *)&ip6, 0); 1738 if (!parseEndOk(a, &pt, &retCode)) { 1739 return retCode; 1740 } 1741 1742 /* Initialize data structures. */ 1743 sal_memset(&ipkey, 0, sizeof(bcm_l3_key_t)); 1744 1745 /* Fill tunnel info. */ 1746 if (ip6) { 1747 ipkey.l3k_flags |= BCM_L3_IP6; 1748 sal_memcpy(ipkey.l3k_ip6_addr, ip6_addr, sizeof(bcm_ip6_t)); 1749 sal_memcpy(ipkey.l3k_sip6_addr, sip6_addr, sizeof(bcm_ip6_t)); 1750 } else { 1751 ipkey.l3k_ip_addr = ip_addr; 1752 ipkey.l3k_sip_addr = sip_addr; 1753 } 1754 1755 if (ipmc) { 1756 ipkey.l3k_flags |= BCM_L3_IPMC; 1757 } 1758 ipkey.l3k_vrf = vrf; 1759 ipkey.l3k_vid = vlan & 0xfff; 1760 1761 if ((rv = bcm_l3_host_conflict_get(unit, &ipkey, result, 1762 L3X_MAX_BUCKET_SIZE, &count)) < 0) { 1763 cli_out("ERROR %s: getting l3 conflicts %s\n", 1764 ARG_CMD(a), bcm_errmsg(rv)); 1765 return CMD_FAIL; 1766 } 1767 1768 for (idx = 0; idx < count; idx++) { 1769 _l3_cmd_l3_key_print(unit, idx, result + idx); 1770 } 1771 return CMD_OK; 1772 } 1773 1774 /* 1775 * Function: 1776 * _l3_cmd_defip_ecmp_hash 1777 * Description: 1778 * Service routine used to calculate route ecmp hash 1779 * Parameters: 1780 * unit - (IN) Device number. 1781 * a - (IN) Command arguments. 1782 * Returns: 1783 * CMD_XXX 1784 */ 1785 STATIC cmd_result_t 1786 _l3_cmd_defip_ecmp_hash(int unit, args_t *a) 1787 { 1788 uint32 l4_dst_port = 0; 1789 uint32 l4_src_port = 0; 1790 int ecmp_count = 0; 1791 bcm_ip6_t dip6_addr; 1792 bcm_ip6_t sip6_addr; 1793 bcm_ip_t dip_addr = 0; 1794 bcm_ip_t sip_addr = 0; 1795 cmd_result_t retCode; 1796 parse_table_t pt; 1797 int rv; 1798 int ip6 = 0; 1799 int hash_select = XGS_HASH_COUNT; 1800 int ecmp_hash_sel = 2; 1801 #ifdef BCM_XGS3_SWITCH_SUPPORT 1802 soc_xgs3_ecmp_hash_t data; 1803 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 1804 1805 if (!SOC_IS_XGS_SWITCH(unit)) { 1806 cli_out("Command only valid for XGS switches\n"); 1807 return CMD_FAIL; 1808 } 1809 1810 sal_memset(dip6_addr, 0, sizeof (bcm_ip6_t)); 1811 sal_memset(sip6_addr, 0, sizeof (bcm_ip6_t)); 1812 1813 parse_table_init(unit, &pt); 1814 parse_table_add(&pt, "DIP", PQ_DFL | PQ_IP, 0, (void *)&dip_addr, 0); 1815 parse_table_add(&pt, "SIP", PQ_DFL | PQ_IP, 0, (void *)&sip_addr, 0); 1816 parse_table_add(&pt, "DIP6", PQ_DFL | PQ_IP6, 0, (void *)dip6_addr, 0); 1817 parse_table_add(&pt, "SIP6", PQ_DFL | PQ_IP6, 0, (void *)sip6_addr, 0); 1818 parse_table_add(&pt, "IP6", PQ_DFL | PQ_INT, 0, (void *)&ip6, 0); 1819 parse_table_add(&pt, "L4_SRC_PORT", PQ_DFL | PQ_INT, 0, 1820 (void *)&l4_dst_port, 0); 1821 parse_table_add(&pt, "L4_DST_PORT", PQ_DFL | PQ_INT, 0, 1822 (void *)&l4_src_port, 0); 1823 parse_table_add(&pt, "COUNT", PQ_DFL | PQ_INT, 0, 1824 (void *)&ecmp_count, 0); 1825 parse_table_add(&pt, "EHash", PQ_DFL | PQ_INT, 0, 1826 (void *)&ecmp_hash_sel, 0); 1827 parse_table_add(&pt, "Hash", PQ_DFL | PQ_INT, 0, 1828 (void *)&hash_select, 0); 1829 if (!parseEndOk(a, &pt, &retCode)) { 1830 return retCode; 1831 } 1832 1833 #ifdef BCM_XGS3_SWITCH_SUPPORT 1834 if (SOC_IS_XGS3_SWITCH(unit)) { /* FBX || ER */ 1835 sal_memset(&data, 0, sizeof (soc_xgs3_ecmp_hash_t)); 1836 /* Fill source/destination address. . */ 1837 if (ip6) { 1838 sal_memcpy(data.dip6, dip6_addr, sizeof(bcm_ip6_t)); 1839 sal_memcpy(data.sip6, sip6_addr, sizeof(bcm_ip6_t)); 1840 data.v6 = TRUE; 1841 } else { 1842 data.dip = dip_addr; 1843 data.sip = sip_addr; 1844 } 1845 data.l4_src_port = l4_src_port & 0xffff; /* TCP/UDP src port. */ 1846 data.l4_dst_port = l4_dst_port & 0xffff; /* TCP/UDP dst port. */ 1847 data.ecmp_count = ecmp_count; /* Zero based ecmp count. */ 1848 1849 rv = soc_xgs3_l3_ecmp_hash(unit, &data); 1850 if (rv < 0){ 1851 cli_out("Internal error\n"); 1852 return CMD_FAIL; 1853 } 1854 cli_out("ECMP hash is %d \n", rv); 1855 return CMD_OK; 1856 } else 1857 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 1858 if (ip6) { 1859 cli_out("IPv6 is not supported.\n"); 1860 return CMD_OK; 1861 } 1862 1863 cli_out("Command is not supported.\n"); 1864 return CMD_FAIL; 1865 } 1866 #endif /* BCM_XGS_SWITCH_SUPPORT*/ 1867 1868 /* 1869 * Function: 1870 * _l3_cmd_tunnel_init_add 1871 * Description: 1872 * Service routine used to add tunnel initiator to an interface. 1873 * Parameters: 1874 * unit - (IN) Device number. 1875 * a - (IN) Command arguments. 1876 * Returns: 1877 * CMD_XXX 1878 */ 1879 1880 STATIC cmd_result_t 1881 _l3_cmd_tunnel_init_add(int unit, args_t *a) 1882 { 1883 bcm_tunnel_initiator_t tunnel_init; 1884 bcm_l3_intf_t intf; 1885 bcm_tunnel_type_t type = 0; 1886 parse_table_t pt; 1887 cmd_result_t retCode; 1888 bcm_ip6_t sip6_addr; 1889 bcm_ip6_t ip6_addr; 1890 bcm_mac_t mac; 1891 bcm_if_t interface = 0; 1892 bcm_ip_t sip_addr = 0; 1893 bcm_ip_t ip_addr = 0; 1894 int ip4_df_sel = 0; 1895 int ip6_df_sel = 0; 1896 int dscp_val = 0; 1897 int dscp_sel = 0; 1898 int dscp_map = 0; 1899 int ttl = 0; 1900 int rv; 1901 1902 1903 /* Stack variables initialization. */ 1904 sal_memset(&intf, 0, sizeof(bcm_l3_intf_t)); 1905 sal_memset(sip6_addr, 0, sizeof(bcm_ip6_t)); 1906 sal_memset(ip6_addr, 0, sizeof(bcm_ip6_t)); 1907 sal_memset(mac, 0, sizeof(bcm_mac_t)); 1908 1909 parse_table_init(unit, &pt); 1910 parse_table_add(&pt, "INtf", PQ_DFL|PQ_INT, 0, (void*)&interface, 0); 1911 parse_table_add(&pt, "TYpe", PQ_DFL|PQ_INT, 0, (void*)&type, 0); 1912 parse_table_add(&pt, "TTL", PQ_DFL|PQ_INT, 0, (void*)&ttl, 0); 1913 parse_table_add(&pt, "Mac", PQ_DFL|PQ_MAC, 0, (void *)mac, 0); 1914 parse_table_add(&pt, "DIP", PQ_DFL|PQ_IP, 0, (void *)&ip_addr, 0); 1915 parse_table_add(&pt, "SIP", PQ_DFL|PQ_IP, 0, (void *)&sip_addr, 0); 1916 parse_table_add(&pt, "DIP6", PQ_DFL | PQ_IP6, 0, (void *)&ip6_addr, 0); 1917 parse_table_add(&pt, "SIP6", PQ_DFL | PQ_IP6, 0, (void *)&sip6_addr, 0); 1918 parse_table_add(&pt, "DSCPSel", PQ_DFL|PQ_INT, 0, (void *)&dscp_sel, 0); 1919 parse_table_add(&pt, "DSCPV", PQ_DFL|PQ_INT, 0, (void *)&dscp_val, 0); 1920 parse_table_add(&pt, "DFSEL4", PQ_DFL|PQ_INT, 0, (void *)&ip4_df_sel, 0); 1921 parse_table_add(&pt, "DFSEL6", PQ_DFL|PQ_BOOL, 0, (void *)&ip6_df_sel, 0); 1922 parse_table_add(&pt, "DSCPMap", PQ_DFL|PQ_INT, 0, (void *)&dscp_map, 0); 1923 if (!parseEndOk(a, &pt, &retCode)) { 1924 return retCode; 1925 } 1926 1927 /* Initialize data structures. */ 1928 bcm_l3_intf_t_init(&intf); 1929 bcm_tunnel_initiator_t_init(&tunnel_init); 1930 1931 /* Fill tunnel info. */ 1932 intf.l3a_intf_id = interface; 1933 tunnel_init.type = type; 1934 tunnel_init.ttl = ttl; 1935 1936 sal_memcpy(tunnel_init.dmac, mac, sizeof(mac)); 1937 1938 if (ip4_df_sel) { 1939 tunnel_init.flags |= (ip4_df_sel > 1) ? 1940 BCM_TUNNEL_INIT_USE_INNER_DF : BCM_TUNNEL_INIT_IPV4_SET_DF; 1941 } 1942 if (ip6_df_sel) { 1943 tunnel_init.flags |= BCM_TUNNEL_INIT_IPV6_SET_DF; 1944 } 1945 1946 sal_memcpy(tunnel_init.dip6, ip6_addr, sizeof(bcm_ip6_t)); 1947 sal_memcpy(tunnel_init.sip6, sip6_addr, sizeof(bcm_ip6_t)); 1948 tunnel_init.dip = ip_addr; 1949 tunnel_init.sip = sip_addr; 1950 tunnel_init.dscp_sel = dscp_sel; 1951 tunnel_init.dscp = dscp_val; 1952 tunnel_init.dscp_map = dscp_map; 1953 1954 if ((rv = bcm_tunnel_initiator_set(unit, &intf, &tunnel_init)) < 0) { 1955 cli_out("ERROR %s: setting tunnel initiator for %d %s\n", 1956 ARG_CMD(a), interface, bcm_errmsg(rv)); 1957 return CMD_FAIL; 1958 } 1959 return CMD_OK; 1960 } 1961 1962 /* 1963 * Function: 1964 * _l3_cmd_tunnel_init_show 1965 * Description: 1966 * Service routine used to get & show tunnel initiator info. 1967 * Parameters: 1968 * unit - (IN) Device number. 1969 * a - (IN) Command arguments. 1970 * Returns: 1971 * CMD_XXX 1972 */ 1973 STATIC cmd_result_t 1974 _l3_cmd_tunnel_init_show(int unit, args_t *a) 1975 { 1976 bcm_tunnel_initiator_t tunnel_init; 1977 bcm_l3_intf_t intf; 1978 parse_table_t pt; 1979 cmd_result_t retCode; 1980 bcm_if_t interface; 1981 int rv; 1982 1983 parse_table_init(unit, &pt); 1984 parse_table_add(&pt, "INtf", PQ_DFL|PQ_INT, 0, (void*)&interface, 0); 1985 if (!parseEndOk(a, &pt, &retCode)) { 1986 return retCode; 1987 } 1988 1989 bcm_tunnel_initiator_t_init(&tunnel_init); 1990 1991 bcm_l3_intf_t_init(&intf); 1992 intf.l3a_intf_id = interface; 1993 1994 if ((rv = bcm_tunnel_initiator_get(unit, &intf, &tunnel_init)) < 0) { 1995 cli_out("ERROR %s: getting tunnel initiator for %d %s\n", 1996 ARG_CMD(a), interface, bcm_errmsg(rv)); 1997 return CMD_FAIL; 1998 } 1999 2000 _l3_cmd_tunnel_init_print(unit, interface, &tunnel_init); 2001 return CMD_OK; 2002 } 2003 2004 /* 2005 * Function: 2006 * _l3_cmd_tunnel_init_clear 2007 * Description: 2008 * Service routine used to remove tunnel initiator from an interface. 2009 * Parameters: 2010 * unit - (IN) Device number. 2011 * a - (IN) Command arguments. 2012 * Returns: 2013 * CMD_XXX 2014 */ 2015 STATIC cmd_result_t 2016 _l3_cmd_tunnel_init_clear(int unit, args_t *a) 2017 { 2018 bcm_if_t interface; 2019 cmd_result_t retCode; 2020 bcm_l3_intf_t intf; 2021 parse_table_t pt; 2022 int rv; 2023 2024 parse_table_init(unit, &pt); 2025 parse_table_add(&pt, "INtf", PQ_DFL|PQ_INT, 0, (void*)&interface, 0); 2026 if (!parseEndOk(a, &pt, &retCode)) { 2027 return retCode; 2028 } 2029 2030 bcm_l3_intf_t_init(&intf); 2031 intf.l3a_intf_id = interface; 2032 2033 if ((rv = bcm_tunnel_initiator_clear(unit, &intf)) < 0) { 2034 cli_out("ERROR %s: clearing tunnel initiator for %d %s\n", 2035 ARG_CMD(a), interface, bcm_errmsg(rv)); 2036 return CMD_FAIL; 2037 } 2038 return CMD_OK; 2039 } 2040 2041 /* 2042 * Function: 2043 * _l3_cmd_tunnel_term_add 2044 * Description: 2045 * Service routine used to add tunnel terminator entry. 2046 * Parameters: 2047 * unit - (IN) Device number. 2048 * a - (IN) Command arguments. 2049 * Returns: 2050 * CMD_XXX 2051 */ 2052 STATIC cmd_result_t 2053 _l3_cmd_tunnel_term_add(int unit, args_t *a) 2054 { 2055 bcm_tunnel_terminator_t tunnel_term; 2056 cmd_result_t retCode; 2057 parse_table_t pt; 2058 int rv; 2059 bcm_pbmp_t pbmap; 2060 bcm_ip6_t sip6; 2061 bcm_ip6_t dip6; 2062 int vlan = 0; 2063 int dip = 0; 2064 int sip = 0; 2065 int sip_mask_len = 0; 2066 int dip_mask_len = 0; 2067 int dport = 0; 2068 int sport = 0; 2069 int tnl_type = 0; 2070 int outer_ttl = 0; 2071 int outer_dscp = 0; 2072 int inner_dscp = 0; 2073 int trust_dscp = 0; 2074 int allow_v4 = 0; 2075 int allow_v6 = 0; 2076 int vrf = 0; 2077 int replace=0; 2078 bcm_gport_t remote_port = BCM_GPORT_INVALID; 2079 bcm_gport_t tunnel_id = 0; 2080 2081 parse_table_init(unit, &pt); 2082 sal_memset(sip6, 0, sizeof(bcm_ip6_t)); 2083 sal_memset(dip6, 0, sizeof(bcm_ip6_t)); 2084 sal_memset(&pbmap, 0, sizeof(bcm_pbmp_t)); 2085 2086 parse_table_add(&pt, "VRF", PQ_DFL | PQ_INT, 0, (void *)&vrf, 0); 2087 parse_table_add(&pt, "DIP", PQ_DFL|PQ_IP, 0, (void*)&dip, 0); 2088 parse_table_add(&pt, "SIP", PQ_DFL|PQ_IP, 0, (void*)&sip, 0); 2089 parse_table_add(&pt, "DIP6", PQ_DFL|PQ_IP6, 0, (void*)&dip6, 0); 2090 parse_table_add(&pt, "SIP6", PQ_DFL|PQ_IP6, 0, (void*)&sip6, 0); 2091 parse_table_add(&pt, "DipMaskLen", PQ_DFL|PQ_INT, 0, (void*)&dip_mask_len, 0); 2092 parse_table_add(&pt, "SipMaskLen", PQ_DFL|PQ_INT, 0, (void*)&sip_mask_len, 0); 2093 parse_table_add(&pt, "L4DstPort", PQ_DFL|PQ_INT, 0, (void*)&dport, 0); 2094 parse_table_add(&pt, "L4SrcPort", PQ_DFL|PQ_INT, 0, (void*)&sport, 0); 2095 parse_table_add(&pt, "TYpe", PQ_DFL|PQ_INT, 0, (void*)&tnl_type, 0); 2096 parse_table_add(&pt, "OuterDSCP", PQ_DFL|PQ_BOOL, 0,(void *)&outer_dscp, 0); 2097 parse_table_add(&pt, "OuterTTL", PQ_DFL|PQ_BOOL, 0, (void *)&outer_ttl, 0); 2098 parse_table_add(&pt, "InnerDSCP", PQ_DFL|PQ_BOOL, 0,(void *)&inner_dscp, 0); 2099 parse_table_add(&pt, "TrustDSCP", PQ_DFL|PQ_BOOL, 0,(void *)&trust_dscp, 0); 2100 parse_table_add(&pt, "VLanid", PQ_DFL|PQ_INT, 0, (void*)&vlan, 0); 2101 parse_table_add(&pt, "AllowIPv6Payload", PQ_DFL|PQ_BOOL, 0, (void*)&allow_v4, 0); 2102 parse_table_add(&pt, "AllowIPv4Payload", PQ_DFL|PQ_BOOL, 0, (void*)&allow_v6, 0); 2103 parse_table_add(&pt, "PBMP", PQ_DFL|PQ_PBMP|PQ_BCM, 0, &pbmap, 0); 2104 parse_table_add(&pt, "Replace", PQ_DFL|PQ_BOOL, 0, &replace, 0); 2105 parse_table_add(&pt, "RemoteTerminate", PQ_DFL|PQ_INT, 0, &remote_port, 0); 2106 parse_table_add(&pt, "TunnelID", PQ_DFL|PQ_INT, 0, (void*)&tunnel_id, 0); 2107 2108 if (!parseEndOk(a, &pt, &retCode)) { 2109 return retCode; 2110 } 2111 2112 sal_memset(&tunnel_term, 0, sizeof (tunnel_term)); 2113 2114 if ((tnl_type == bcmTunnelTypeWlanWtpToAc) || 2115 (tnl_type == bcmTunnelTypeWlanAcToAc) || 2116 (tnl_type == bcmTunnelTypeWlanWtpToAc6) || 2117 (tnl_type == bcmTunnelTypeWlanAcToAc6)) { 2118 tunnel_term.flags |= BCM_TUNNEL_TERM_TUNNEL_WITH_ID; 2119 tunnel_term.tunnel_id = tunnel_id; 2120 if (remote_port != BCM_GPORT_INVALID) { 2121 tunnel_term.flags |= BCM_TUNNEL_TERM_WLAN_REMOTE_TERMINATE; 2122 tunnel_term.remote_port = remote_port; 2123 } 2124 } 2125 2126 if (_BCM_TUNNEL_OUTER_HEADER_IPV6(tnl_type)) { 2127 sal_memcpy(tunnel_term.sip6, sip6, sizeof(bcm_ip6_t)); 2128 sal_memcpy(tunnel_term.dip6, dip6, sizeof(bcm_ip6_t)); 2129 bcm_ip6_mask_create(tunnel_term.sip6_mask, sip_mask_len); 2130 bcm_ip6_mask_create(tunnel_term.dip6_mask, dip_mask_len); 2131 } else { 2132 tunnel_term.sip = sip; 2133 tunnel_term.dip = dip; 2134 tunnel_term.sip_mask = bcm_ip_mask_create(sip_mask_len); 2135 tunnel_term.dip_mask = bcm_ip_mask_create(dip_mask_len); 2136 } 2137 2138 tunnel_term.udp_dst_port = dport; 2139 tunnel_term.udp_src_port = sport; 2140 tunnel_term.type = tnl_type; 2141 tunnel_term.vrf = vrf; 2142 2143 if (outer_dscp) { 2144 tunnel_term.flags |= BCM_TUNNEL_TERM_USE_OUTER_DSCP; 2145 } 2146 2147 if (outer_ttl) { 2148 tunnel_term.flags |= BCM_TUNNEL_TERM_USE_OUTER_TTL; 2149 } 2150 if (inner_dscp) { 2151 tunnel_term.flags |= BCM_TUNNEL_TERM_KEEP_INNER_DSCP; 2152 } 2153 2154 if (trust_dscp) { 2155 tunnel_term.flags |= BCM_TUNNEL_TERM_DSCP_TRUST; 2156 } 2157 2158 if (replace) { 2159 tunnel_term.flags |= BCM_TUNNEL_REPLACE; 2160 } 2161 2162 tunnel_term.vlan = (bcm_vlan_t)vlan; 2163 tunnel_term.pbmp = pbmap; 2164 2165 if ((rv = bcm_tunnel_terminator_add(unit, &tunnel_term)) < 0) { 2166 cli_out("ERROR %s: adding tunnel term %s\n", 2167 ARG_CMD(a), bcm_errmsg(rv)); 2168 return CMD_FAIL; 2169 } 2170 return CMD_OK; 2171 } 2172 2173 /* 2174 * Function: 2175 * _l3_cmd_tunnel_term_delete 2176 * Description: 2177 * Service routine used to delete tunnel terminator entry. 2178 * Parameters: 2179 * unit - (IN) Device number. 2180 * a - (IN) Command arguments. 2181 * Returns: 2182 * CMD_XXX 2183 */ 2184 STATIC cmd_result_t 2185 _l3_cmd_tunnel_term_delete(int unit, args_t *a) 2186 { 2187 bcm_tunnel_terminator_t tunnel_term; 2188 cmd_result_t retCode; 2189 parse_table_t pt; 2190 int rv; 2191 bcm_ip6_t sip6; 2192 bcm_ip6_t dip6; 2193 int dip = 0; 2194 int sip = 0; 2195 int sip_mask_len = 0; 2196 int dip_mask_len = 0; 2197 int tnl_type = 0; 2198 int vrf = 0; 2199 int dport = 0; 2200 int sport = 0; 2201 2202 parse_table_init(unit, &pt); 2203 sal_memset(sip6, 0, sizeof(bcm_ip6_t)); 2204 sal_memset(dip6, 0, sizeof(bcm_ip6_t)); 2205 2206 parse_table_add(&pt, "VRF", PQ_DFL | PQ_INT, 0, (void *)&vrf, 0); 2207 parse_table_add(&pt, "DIP", PQ_DFL|PQ_IP, 0, (void*)&dip, 0); 2208 parse_table_add(&pt, "SIP", PQ_DFL|PQ_IP, 0, (void*)&sip, 0); 2209 parse_table_add(&pt, "DIP6", PQ_DFL|PQ_IP6, 0, (void*)&dip6, 0); 2210 parse_table_add(&pt, "SIP6", PQ_DFL|PQ_IP6, 0, (void*)&sip6, 0); 2211 parse_table_add(&pt, "DipMaskLen", PQ_DFL|PQ_INT, 0, (void*)&dip_mask_len, 0); 2212 parse_table_add(&pt, "SipMaskLen", PQ_DFL|PQ_INT, 0, (void*)&sip_mask_len, 0); 2213 parse_table_add(&pt, "TYpe", PQ_DFL|PQ_INT, 0, (void*)&tnl_type, 0); 2214 parse_table_add(&pt, "L4DstPort", PQ_DFL|PQ_INT, 0, (void*)&dport, 0); 2215 parse_table_add(&pt, "L4SrcPort", PQ_DFL|PQ_INT, 0, (void*)&sport, 0); 2216 2217 if (!parseEndOk(a, &pt, &retCode)) { 2218 return retCode; 2219 } 2220 2221 sal_memset(&tunnel_term, 0, sizeof (tunnel_term)); 2222 2223 2224 if (_BCM_TUNNEL_OUTER_HEADER_IPV6(tnl_type)) { 2225 sal_memcpy(tunnel_term.sip6, sip6, sizeof(bcm_ip6_t)); 2226 sal_memcpy(tunnel_term.dip6, dip6, sizeof(bcm_ip6_t)); 2227 bcm_ip6_mask_create(tunnel_term.sip6_mask, sip_mask_len); 2228 bcm_ip6_mask_create(tunnel_term.dip6_mask, dip_mask_len); 2229 } else { 2230 tunnel_term.sip = sip; 2231 tunnel_term.dip = dip; 2232 tunnel_term.sip_mask = bcm_ip_mask_create(sip_mask_len); 2233 tunnel_term.dip_mask = bcm_ip_mask_create(dip_mask_len); 2234 } 2235 2236 tunnel_term.udp_dst_port = dport; 2237 tunnel_term.udp_src_port = sport; 2238 tunnel_term.type = tnl_type; 2239 tunnel_term.vrf = vrf; 2240 2241 if ((rv = bcm_tunnel_terminator_delete(unit, &tunnel_term)) < 0) { 2242 cli_out("ERROR %s: adding tunnel term %s\n", 2243 ARG_CMD(a), bcm_errmsg(rv)); 2244 return CMD_FAIL; 2245 } 2246 return CMD_OK; 2247 } 2248 2249 /* 2250 * Function: 2251 * _l3_cmd_tunnel_term_get 2252 * Description: 2253 * Service routine used to read tunnel terminator entry. 2254 * Parameters: 2255 * unit - (IN) Device number. 2256 * a - (IN) Command arguments. 2257 * Returns: 2258 * CMD_XXX 2259 */ 2260 STATIC cmd_result_t 2261 _l3_cmd_tunnel_term_get(int unit, args_t *a) 2262 { 2263 bcm_tunnel_terminator_t tunnel_term; 2264 cmd_result_t retCode; 2265 parse_table_t pt; 2266 int rv; 2267 bcm_ip6_t sip6; 2268 bcm_ip6_t dip6; 2269 int vlan = 0; 2270 int dip = 0; 2271 int sip = 0; 2272 int sip_mask_len = 0; 2273 int dip_mask_len = 0; 2274 int tnl_type = 0; 2275 int vrf = 0; 2276 int dport = 0; 2277 int sport = 0; 2278 2279 parse_table_init(unit, &pt); 2280 sal_memset(sip6, 0, sizeof(bcm_ip6_t)); 2281 sal_memset(dip6, 0, sizeof(bcm_ip6_t)); 2282 sal_memset(&tunnel_term, 0, sizeof(bcm_tunnel_terminator_t)); 2283 2284 parse_table_add(&pt, "VRF", PQ_DFL | PQ_INT, 0, (void *)&vrf, 0); 2285 parse_table_add(&pt, "DIP", PQ_DFL|PQ_IP, 0, (void*)&dip, 0); 2286 parse_table_add(&pt, "SIP", PQ_DFL|PQ_IP, 0, (void*)&sip, 0); 2287 parse_table_add(&pt, "DIP6", PQ_DFL|PQ_IP6, 0, (void*)&dip6, 0); 2288 parse_table_add(&pt, "SIP6", PQ_DFL|PQ_IP6, 0, (void*)&sip6, 0); 2289 parse_table_add(&pt, "DipMaskLen", PQ_DFL|PQ_INT, 0, (void*)&dip_mask_len, 0); 2290 parse_table_add(&pt, "SipMaskLen", PQ_DFL|PQ_INT, 0, (void*)&sip_mask_len, 0); 2291 parse_table_add(&pt, "TYpe", PQ_DFL|PQ_INT, 0, (void*)&tnl_type, 0); 2292 parse_table_add(&pt, "L4DstPort", PQ_DFL|PQ_INT, 0, (void*)&dport, 0); 2293 parse_table_add(&pt, "L4SrcPort", PQ_DFL|PQ_INT, 0, (void*)&sport, 0); 2294 parse_table_add(&pt, "VLAN", PQ_DFL|PQ_INT, 0, (void*)&vlan, 0); 2295 2296 if (!parseEndOk(a, &pt, &retCode)) { 2297 return retCode; 2298 } 2299 2300 sal_memset(&tunnel_term, 0, sizeof (tunnel_term)); 2301 2302 2303 if (_BCM_TUNNEL_OUTER_HEADER_IPV6(tnl_type)) { 2304 sal_memcpy(tunnel_term.sip6, sip6, sizeof(bcm_ip6_t)); 2305 sal_memcpy(tunnel_term.dip6, dip6, sizeof(bcm_ip6_t)); 2306 bcm_ip6_mask_create(tunnel_term.sip6_mask, sip_mask_len); 2307 bcm_ip6_mask_create(tunnel_term.dip6_mask, dip_mask_len); 2308 } else { 2309 tunnel_term.sip = sip; 2310 tunnel_term.dip = dip; 2311 tunnel_term.sip_mask = bcm_ip_mask_create(sip_mask_len); 2312 tunnel_term.dip_mask = bcm_ip_mask_create(dip_mask_len); 2313 } 2314 2315 tunnel_term.udp_dst_port = dport; 2316 tunnel_term.udp_src_port = sport; 2317 tunnel_term.type = tnl_type; 2318 tunnel_term.vrf = vrf; 2319 tunnel_term.vlan = (bcm_vlan_t)vlan; 2320 2321 if ((rv = bcm_tunnel_terminator_get(unit, &tunnel_term)) < 0) { 2322 cli_out("ERROR %s: adding tunnel term %s\n", 2323 ARG_CMD(a), bcm_errmsg(rv)); 2324 return CMD_FAIL; 2325 } 2326 2327 _l3_cmd_tunnel_term_print(unit, &tunnel_term); 2328 return CMD_OK; 2329 } 2330 2331 /* 2332 * Function: 2333 * _l3_cmd_dscp_map_add 2334 * Description: 2335 * Service routine used to add dscp map object. 2336 * Parameters: 2337 * unit - (IN) Device number. 2338 * a - (IN) Command arguments. 2339 * Returns: 2340 * CMD_XXX 2341 */ 2342 STATIC cmd_result_t 2343 _l3_cmd_dscp_map_add(int unit, args_t *a) 2344 { 2345 int dscp_map_id = -1; 2346 int rv; 2347 2348 rv = bcm_tunnel_dscp_map_create(unit, 0, &dscp_map_id); 2349 if (BCM_FAILURE(rv)) { 2350 cli_out("%s: Failed to create egress dscp map id: %s\n", 2351 ARG_CMD(a), bcm_errmsg(rv)); 2352 return (CMD_FAIL); 2353 } else { 2354 cli_out("%s: Returned DSCP Map ID %d\n", ARG_CMD(a), dscp_map_id); 2355 } 2356 return (CMD_OK); 2357 } 2358 2359 /* 2360 * Function: 2361 * _l3_cmd_dscp_map_delete 2362 * Description: 2363 * Service routine used to delete dscp map object. 2364 * Parameters: 2365 * unit - (IN) Device number. 2366 * a - (IN) Command arguments. 2367 * Returns: 2368 * CMD_XXX 2369 */ 2370 STATIC cmd_result_t 2371 _l3_cmd_dscp_map_delete(int unit, args_t *a) 2372 { 2373 cmd_result_t retCode; 2374 parse_table_t pt; 2375 int dscp_map_id = -1; 2376 int rv; 2377 2378 parse_table_init(unit, &pt); 2379 parse_table_add(&pt, "DscpMapId", PQ_DFL|PQ_INT, 0, (void*)&dscp_map_id, 0); 2380 if (!parseEndOk(a, &pt, &retCode)) { 2381 return retCode; 2382 } 2383 2384 if (-1 == dscp_map_id) { 2385 return(CMD_USAGE); 2386 } 2387 2388 rv = bcm_tunnel_dscp_map_destroy(unit, dscp_map_id); 2389 if (BCM_FAILURE(rv)) { 2390 cli_out("%s: Error deleting entry from egress : %s\n", 2391 ARG_CMD(a), bcm_errmsg(rv)); 2392 return (CMD_FAIL); 2393 } 2394 return (CMD_OK); 2395 } 2396 /* 2397 * Function: 2398 * _l3_cmd_dscp_map_port_set 2399 * Description: 2400 * Service routine used to set dscp map priority, color -> dscp mapping. 2401 * Parameters: 2402 * unit - (IN) Device number. 2403 * a - (IN) Command arguments. 2404 * Returns: 2405 * CMD_XXX 2406 */ 2407 STATIC cmd_result_t 2408 _l3_cmd_dscp_map_port_set(int unit, args_t *a) 2409 { 2410 parse_table_t pt; 2411 bcm_tunnel_dscp_map_t dscp_map; 2412 int prio, color, dscp_val; 2413 cmd_result_t retCode; 2414 bcm_port_t port = -1; 2415 int rv; 2416 2417 parse_table_init(unit, &pt); 2418 parse_table_add(&pt, "Port", PQ_DFL|PQ_PORT, 0, (void*)&port, 0); 2419 parse_table_add(&pt, "Priority", PQ_DFL|PQ_INT, 0, (void*)&prio, 0); 2420 parse_table_add(&pt, "Color", PQ_DFL|PQ_INT, 0, (void*)&color, 0); 2421 parse_table_add(&pt, "DSCPValue", PQ_DFL|PQ_INT, 0, (void *)&dscp_val, 0); 2422 if (!parseEndOk(a, &pt, &retCode)) { 2423 return retCode; 2424 } 2425 2426 if (-1 == port) { 2427 return (CMD_USAGE); 2428 } 2429 2430 dscp_map.priority = prio; 2431 dscp_map.color = color; 2432 dscp_map.dscp = dscp_val; 2433 2434 rv = bcm_tunnel_dscp_map_port_set(unit, port, &dscp_map); 2435 2436 if (BCM_FAILURE(rv)) { 2437 cli_out("ERROR %s: setting tunnel DSCP Map for port %d %s\n", 2438 ARG_CMD(a), port, bcm_errmsg(rv)); 2439 return (CMD_FAIL); 2440 } 2441 return (CMD_OK); 2442 } 2443 2444 /* 2445 * Function: 2446 * _l3_cmd_dscp_map_port_show 2447 * Description: 2448 * Service routine used to show dscp map object. 2449 * Parameters: 2450 * unit - (IN) Device number. 2451 * a - (IN) Command arguments. 2452 * Returns: 2453 * CMD_XXX 2454 */ 2455 STATIC cmd_result_t 2456 _l3_cmd_dscp_map_port_show(int unit, args_t *a) 2457 { 2458 parse_table_t pt; 2459 bcm_tunnel_dscp_map_t dscp_map; 2460 int prio; 2461 cmd_result_t retCode; 2462 bcm_port_t port = -1; 2463 int rv; 2464 2465 parse_table_init(unit, &pt); 2466 parse_table_add(&pt, "Port", PQ_DFL | PQ_PORT, 0, 2467 (void *)&port, 0); 2468 if (!parseEndOk(a, &pt, &retCode)) 2469 return retCode; 2470 2471 if (-1 == port) { 2472 return(CMD_USAGE); 2473 } 2474 2475 cli_out("\nDSCP Map for port %d:\n", port); 2476 cli_out("\n-----------\n"); 2477 for (prio = 0; prio < 8; prio++) { 2478 dscp_map.priority = prio; 2479 dscp_map.color = bcmColorGreen; 2480 rv = bcm_tunnel_dscp_map_port_get(unit, port, &dscp_map); 2481 if (BCM_FAILURE(rv)) { 2482 cli_out("%s: Error L3 accessing: %s\n", ARG_CMD(a), bcm_errmsg(rv)); 2483 return CMD_FAIL; 2484 } 2485 cli_out(" Priority = %d, Color = Green, DSCP = %d\n", 2486 prio, dscp_map.dscp); 2487 2488 dscp_map.priority = prio; 2489 dscp_map.color = bcmColorYellow; 2490 rv = bcm_tunnel_dscp_map_port_get(unit, port, &dscp_map); 2491 if (BCM_FAILURE(rv)) { 2492 cli_out("%s: Error L3 accessing: %s\n", ARG_CMD(a), bcm_errmsg(rv)); 2493 return CMD_FAIL; 2494 } 2495 cli_out(" Priority = %d, Color = Yellow, DSCP = %d\n", 2496 prio, dscp_map.dscp); 2497 2498 dscp_map.priority = prio; 2499 dscp_map.color = bcmColorRed; 2500 rv = bcm_tunnel_dscp_map_port_get(unit, port, &dscp_map); 2501 if (BCM_FAILURE(rv)) { 2502 cli_out("%s: Error L3 accessing: %s\n", ARG_CMD(a), bcm_errmsg(rv)); 2503 return CMD_FAIL; 2504 } 2505 cli_out(" Priority = %d, Color = Red, DSCP = %d\n", 2506 prio, dscp_map.dscp); 2507 } 2508 return CMD_OK; 2509 } 2510 2511 2512 /* 2513 * Function: 2514 * _l3_cmd_dscp_map_show 2515 * Description: 2516 * Service routine used to set dscp map priority, color -> dscp mapping. 2517 * Parameters: 2518 * unit - (IN) Device number. 2519 * a - (IN) Command arguments. 2520 * Returns: 2521 * CMD_XXX 2522 */ 2523 STATIC cmd_result_t 2524 _l3_cmd_dscp_map_set(int unit, args_t *a) 2525 { 2526 parse_table_t pt; 2527 bcm_tunnel_dscp_map_t dscp_map; 2528 int prio, color, dscp_val; 2529 cmd_result_t retCode; 2530 int dscp_map_id = -1; 2531 int rv; 2532 2533 parse_table_init(unit, &pt); 2534 parse_table_add(&pt, "DscpMapId", PQ_DFL|PQ_INT, 0, 2535 (void*)&dscp_map_id, 0); 2536 parse_table_add(&pt, "Priority", PQ_DFL|PQ_INT, 0, (void*)&prio, 0); 2537 parse_table_add(&pt, "Color", PQ_DFL|PQ_INT, 0, (void*)&color, 0); 2538 parse_table_add(&pt, "DSCPValue", PQ_DFL|PQ_INT, 0, (void *)&dscp_val, 0); 2539 if (!parseEndOk(a, &pt, &retCode)) { 2540 return retCode; 2541 } 2542 2543 if (-1 == dscp_map_id) { 2544 return(CMD_USAGE); 2545 } 2546 2547 dscp_map.priority = prio; 2548 dscp_map.color = color; 2549 dscp_map.dscp = dscp_val; 2550 2551 rv = bcm_tunnel_dscp_map_set(unit, dscp_map_id, &dscp_map); 2552 2553 if (BCM_FAILURE(rv)) { 2554 cli_out("ERROR %s: setting tunnel DSCP Map for %d %s\n", 2555 ARG_CMD(a), dscp_map_id, bcm_errmsg(rv)); 2556 return (CMD_FAIL); 2557 } 2558 return (CMD_OK); 2559 } 2560 2561 /* 2562 * Function: 2563 * _l3_cmd_dscp_map_show 2564 * Description: 2565 * Service routine used to show dscp map object. 2566 * Parameters: 2567 * unit - (IN) Device number. 2568 * a - (IN) Command arguments. 2569 * Returns: 2570 * CMD_XXX 2571 */ 2572 STATIC cmd_result_t 2573 _l3_cmd_dscp_map_show(int unit, args_t *a) 2574 { 2575 parse_table_t pt; 2576 bcm_tunnel_dscp_map_t dscp_map; 2577 int prio; 2578 cmd_result_t retCode; 2579 int dscp_map_id = -1; 2580 int rv; 2581 2582 parse_table_init(unit, &pt); 2583 parse_table_add(&pt, "DscpMapId", PQ_DFL | PQ_INT, 0, 2584 (void *)&dscp_map_id, 0); 2585 if (!parseEndOk(a, &pt, &retCode)) 2586 return retCode; 2587 2588 if (-1 == dscp_map_id) { 2589 return(CMD_USAGE); 2590 } 2591 2592 cli_out("\nDSCP Map %d:\n", dscp_map_id); 2593 cli_out("\n-----------\n"); 2594 for (prio = 0; prio < 8; prio++) { 2595 dscp_map.priority = prio; 2596 dscp_map.color = bcmColorGreen; 2597 rv = bcm_tunnel_dscp_map_get(unit, dscp_map_id, &dscp_map); 2598 if (BCM_FAILURE(rv)) { 2599 cli_out("%s: Error L3 accessing: %s\n", ARG_CMD(a), bcm_errmsg(rv)); 2600 return CMD_FAIL; 2601 } 2602 cli_out(" Priority = %d, Color = Green, DSCP = %d\n", 2603 prio, dscp_map.dscp); 2604 2605 dscp_map.priority = prio; 2606 dscp_map.color = bcmColorYellow; 2607 rv = bcm_tunnel_dscp_map_get(unit, dscp_map_id, &dscp_map); 2608 if (BCM_FAILURE(rv)) { 2609 cli_out("%s: Error L3 accessing: %s\n", ARG_CMD(a), bcm_errmsg(rv)); 2610 return CMD_FAIL; 2611 } 2612 cli_out(" Priority = %d, Color = Yellow, DSCP = %d\n", 2613 prio, dscp_map.dscp); 2614 2615 dscp_map.priority = prio; 2616 dscp_map.color = bcmColorRed; 2617 rv = bcm_tunnel_dscp_map_get(unit, dscp_map_id, &dscp_map); 2618 if (BCM_FAILURE(rv)) { 2619 cli_out("%s: Error L3 accessing: %s\n", ARG_CMD(a), bcm_errmsg(rv)); 2620 return CMD_FAIL; 2621 } 2622 cli_out(" Priority = %d, Color = Red, DSCP = %d\n", 2623 prio, dscp_map.dscp); 2624 } 2625 return CMD_OK; 2626 } 2627 2628 /* 2629 * Function: 2630 * _l3_cmd_egress_intf_create 2631 * Description: 2632 * Service routine used to create/add egress l3 interface. 2633 * Parameters: 2634 * unit - (IN) Device number. 2635 * a - (IN) Command arguments. 2636 * Returns: 2637 * CMD_XXX 2638 */ 2639 STATIC cmd_result_t 2640 _l3_cmd_egress_intf_create(int unit, args_t *a) 2641 { 2642 cmd_result_t retCode; 2643 parse_table_t pt; 2644 int rv; 2645 bcm_mac_t mac; 2646 bcm_l3_intf_t intf; 2647 bcm_if_t interface = -1; 2648 int vid = 0; 2649 #if defined(BCM_XGS3_SWITCH_SUPPORT) 2650 int inner_vlan = 0; 2651 bcm_vrf_t vrf = 0; 2652 bcm_if_group_t group = 0; 2653 int mtu = 0; 2654 int nat_realm = 0; 2655 #endif /* BCM_XGS_SWITCH_SUPPORT */ 2656 2657 parse_table_init(unit, &pt); 2658 sal_memset(mac, 0, sizeof(bcm_mac_t)); 2659 bcm_l3_intf_t_init(&intf); 2660 2661 parse_table_init(unit, &pt); 2662 parse_table_add(&pt, "Vlan", PQ_DFL|PQ_INT, 0, &vid, NULL); 2663 parse_table_add(&pt, "Mac", PQ_DFL|PQ_MAC, 0, mac, NULL); 2664 parse_table_add(&pt, "INtf", PQ_DFL|PQ_INT, 0, (void*)&interface, 0); 2665 #if defined(BCM_XGS3_SWITCH_SUPPORT) 2666 parse_table_add(&pt, "InnerVlan", PQ_DFL|PQ_INT, 0, &inner_vlan, NULL); 2667 parse_table_add(&pt, "VRF", PQ_DFL | PQ_INT, 0, (void *)&vrf, 0); 2668 parse_table_add(&pt, "Group", PQ_DFL | PQ_INT, 0, (void *)&group, 0); 2669 parse_table_add(&pt, "MTU", PQ_DFL | PQ_INT, 0, (void *)&mtu, 0); 2670 parse_table_add(&pt, "NATrealm", PQ_DFL | PQ_INT, 0, (void *)&nat_realm, 0); 2671 #endif 2672 if (!parseEndOk(a, &pt, &retCode)) { 2673 return retCode; 2674 } 2675 2676 sal_memcpy(intf.l3a_mac_addr, mac, sizeof(bcm_mac_t)); 2677 intf.l3a_vid = (bcm_vlan_t) vid; 2678 intf.l3a_flags |= BCM_L3_ADD_TO_ARL; 2679 if (interface != -1) { 2680 intf.l3a_intf_id = interface; 2681 intf.l3a_flags |= BCM_L3_WITH_ID; 2682 } 2683 #if defined(BCM_XGS3_SWITCH_SUPPORT) 2684 intf.l3a_vrf = vrf; 2685 intf.l3a_group = group; 2686 intf.l3a_mtu = mtu; 2687 intf.l3a_inner_vlan = inner_vlan; 2688 intf.l3a_nat_realm_id = nat_realm; 2689 #endif 2690 rv = bcm_l3_intf_create(unit, &intf); 2691 if (BCM_FAILURE(rv)) { 2692 cli_out("%s: Error creating entry to L3 Intf table: %s\n", 2693 ARG_CMD(a), bcm_errmsg(rv)); 2694 return (CMD_FAIL); 2695 } 2696 return (CMD_OK); 2697 } 2698 /* 2699 * Function: 2700 * _l3_cmd_egress_intf_delete 2701 * Description: 2702 * Service routine used to remove egress l3 interface. 2703 * Parameters: 2704 * unit - (IN) Device number. 2705 * a - (IN) Command arguments. 2706 * Returns: 2707 * CMD_XXX 2708 */ 2709 STATIC cmd_result_t 2710 _l3_cmd_egress_intf_delete(int unit, args_t *a) 2711 { 2712 bcm_l3_intf_t intf; 2713 cmd_result_t retCode; 2714 parse_table_t pt; 2715 int rv; 2716 bcm_if_t interface = -1; 2717 2718 if (!ARG_CNT(a)) { 2719 cli_out("Expected command parameters: Intf=id\n"); 2720 return (CMD_FAIL); 2721 } 2722 2723 parse_table_init(unit, &pt); 2724 parse_table_add(&pt, "INtf", PQ_DFL|PQ_INT, 0, (void*)&interface, 0); 2725 if (!parseEndOk(a, &pt, &retCode)) { 2726 return retCode; 2727 } 2728 2729 bcm_l3_intf_t_init(&intf); 2730 intf.l3a_intf_id = interface; 2731 if (-1 == interface) { 2732 cli_out("Expected command parameters: Intf=id\n"); 2733 return (CMD_FAIL); 2734 } 2735 2736 if ((rv = bcm_l3_intf_delete(unit, &intf)) < 0) { 2737 cli_out("%s: Error (%s) destroy interface (%d)\n", 2738 ARG_CMD(a), bcm_errmsg(rv), interface); 2739 return (CMD_FAIL); 2740 } 2741 2742 return (CMD_OK); 2743 } 2744 2745 2746 /* 2747 * Function: 2748 * _l3_cmd_egress_intf_delete_all 2749 * Description: 2750 * Service routine used to flush all egress l3 interfaces. 2751 * Parameters: 2752 * unit - (IN) Device number. 2753 * a - (IN) Command arguments. 2754 * Returns: 2755 * CMD_XXX 2756 */ 2757 STATIC cmd_result_t 2758 _l3_cmd_egress_intf_delete_all(int unit, args_t *a) 2759 { 2760 int rv; 2761 int idx; 2762 bcm_l3_intf_t intf; 2763 bcm_l3_info_t l3_hw_status; 2764 2765 if ((rv = bcm_l3_info(unit, &l3_hw_status)) < 0) { 2766 cli_out("%s: Error L3 accessing: %s\n", ARG_CMD(a), bcm_errmsg(rv)); 2767 return CMD_FAIL; 2768 } 2769 2770 bcm_l3_intf_t_init(&intf); 2771 for (idx = 0; idx < l3_hw_status.l3info_max_intf; idx++) { 2772 intf.l3a_intf_id = idx; 2773 rv = bcm_l3_intf_delete(unit, &intf); 2774 2775 if (BCM_FAILURE(rv) && rv != BCM_E_NOT_FOUND) { 2776 cli_out("%s: Error destroy interface %d from L3 Intf" 2777 "table: %s\n", ARG_CMD(a), idx, bcm_errmsg(rv)); 2778 return (CMD_FAIL); 2779 } 2780 } 2781 return (CMD_OK); 2782 } 2783 2784 /* 2785 * Function: 2786 * _l3_cmd_egress_intf_show 2787 * Description: 2788 * Service routine used to show l3 egress interfaces. 2789 * Parameters: 2790 * unit - (IN) Device number. 2791 * a - (IN) Command arguments. 2792 * Returns: 2793 * CMD_XXX 2794 */ 2795 STATIC cmd_result_t 2796 _l3_cmd_egress_intf_show(int unit, args_t *a) 2797 { 2798 int rv; 2799 parse_table_t pt; 2800 bcm_l3_intf_t intf; 2801 cmd_result_t retCode; 2802 bcm_l3_info_t l3_hw_status; 2803 int free_l3intf; 2804 int print_hdr = TRUE; 2805 bcm_if_t interface = -1; 2806 int min_idx, max_idx; 2807 2808 if ((rv = bcm_l3_info(unit, &l3_hw_status)) < 0) { 2809 cli_out("Error in L3 info access: %s\n", bcm_errmsg(rv)); 2810 return CMD_FAIL; 2811 } 2812 2813 free_l3intf = l3_hw_status.l3info_max_intf - 2814 l3_hw_status.l3info_occupied_intf; 2815 2816 2817 if (ARG_CNT(a)) { 2818 parse_table_init(unit, &pt); 2819 parse_table_add(&pt, "INtf", PQ_DFL|PQ_INT, 0, (void*)&interface, 0); 2820 if (!parseEndOk(a, &pt, &retCode)) { 2821 return retCode; 2822 } 2823 } 2824 2825 /* Min index and max interfaces number depend on this soc feature. */ 2826 if (soc_feature(unit, soc_feature_l3_egr_intf_zero_invalid)) { 2827 min_idx = 1; 2828 } else { 2829 min_idx = 0; 2830 } 2831 max_idx = min_idx + (l3_hw_status.l3info_max_intf - 1); 2832 2833 if (interface != -1) { 2834 if ((interface < 0) || (interface > max_idx)) { 2835 cli_out("Invalid interface index: %d\n", interface); 2836 return (CMD_FAIL); 2837 } 2838 } 2839 2840 cli_out("Free L3INTF entries: %d\n", free_l3intf); 2841 2842 if (interface != -1) { 2843 sal_memset(&intf, 0, sizeof (bcm_l3_intf_t)); 2844 intf.l3a_intf_id = interface; 2845 rv = bcm_l3_intf_get(unit, &intf); 2846 if (BCM_SUCCESS(rv)) { 2847 _l3_cmd_egress_intf_print(unit, TRUE, &intf); 2848 return (CMD_OK); 2849 } else { 2850 cli_out("Error L3 interface %d: %s\n", interface, bcm_errmsg(rv)); 2851 return (CMD_FAIL); 2852 } 2853 } 2854 2855 /* Note: last interface id is reserved for Copy To Cpu purposes. */ 2856 for (interface = min_idx; interface < max_idx; interface++) { 2857 sal_memset(&intf, 0, sizeof (bcm_l3_intf_t)); 2858 intf.l3a_intf_id = interface; 2859 rv = bcm_l3_intf_get(unit, &intf); 2860 if (BCM_SUCCESS(rv)) { 2861 _l3_cmd_egress_intf_print(unit, print_hdr, &intf); 2862 print_hdr = FALSE; 2863 } else if (rv == BCM_E_NOT_FOUND) { 2864 continue; 2865 } else if (BCM_FAILURE(rv)) { 2866 cli_out("Error traverse l3 interfaces: %s\n", bcm_errmsg(rv)); 2867 } 2868 } 2869 return CMD_OK; 2870 } 2871 2872 #if defined(BCM_XGS3_SWITCH_SUPPORT) 2873 /* 2874 * Function: 2875 * _l3_cmd_egress_object_create 2876 * Description: 2877 * Service routine used to create/update l3 egress object. 2878 * Parameters: 2879 * unit - (IN) Device number. 2880 * a - (IN) Command arguments. 2881 * Returns: 2882 * CMD_XXX 2883 */ 2884 STATIC cmd_result_t 2885 _l3_cmd_egress_object_create(int unit, args_t *a) 2886 { 2887 cmd_result_t retCode; 2888 parse_table_t pt; 2889 int rv; 2890 bcm_mac_t mac; 2891 bcm_l3_egress_t egress_object; 2892 bcm_if_t interface = -1; 2893 bcm_port_t port = 0; 2894 bcm_module_t module = 0; 2895 bcm_trunk_t trunk = -1; 2896 int l2tocpu = 0; 2897 int copytocpu = 0; 2898 int drop = 0; 2899 int l3mc = 0; 2900 int mpls_label = BCM_MPLS_LABEL_INVALID; 2901 int object_id = -1; 2902 uint32 flags = 0; 2903 2904 bcm_l3_egress_t_init(&egress_object); 2905 sal_memset(mac, 0, sizeof(bcm_mac_t)); 2906 2907 parse_table_init(unit, &pt); 2908 parse_table_add(&pt, "Mac", PQ_DFL | PQ_MAC, 0, (void *)mac, 0); 2909 parse_table_add(&pt, "Port", PQ_DFL | PQ_PORT, 0, (void *)&port, 0); 2910 parse_table_add(&pt, "INtf", PQ_DFL | PQ_INT, 0, (void *)&interface, 0); 2911 parse_table_add(&pt, "MOdule", PQ_DFL | PQ_INT, 0, (void *)&module, 0); 2912 parse_table_add(&pt, "Trunk", PQ_DFL | PQ_INT, 0, (void *)&trunk, 0); 2913 parse_table_add(&pt, "L2tocpu", PQ_DFL | PQ_BOOL, 0, (void *)&l2tocpu, 0); 2914 parse_table_add(&pt, "CopyToCpu", PQ_DFL | PQ_BOOL, 0, (void *)©tocpu, 0); 2915 parse_table_add(&pt, "Drop", PQ_DFL | PQ_BOOL, 0, (void *)&drop, 0); 2916 parse_table_add(&pt, "L3MC", PQ_DFL | PQ_BOOL, 0, (void *)&l3mc, 0); 2917 parse_table_add(&pt, "MplsLabel", PQ_DFL | PQ_INT, 0, 2918 (void *)&mpls_label, 0); 2919 parse_table_add(&pt, "EgrId", PQ_DFL | PQ_INT, 0, (void *)&object_id, 0); 2920 if (!parseEndOk(a, &pt, &retCode)) 2921 return retCode; 2922 2923 egress_object.intf = interface; 2924 egress_object.mpls_label = mpls_label; 2925 sal_memcpy(egress_object.mac_addr, mac, sizeof(mac)); 2926 2927 if (BCM_GPORT_IS_SET(port)) { 2928 egress_object.port = port; 2929 } else { 2930 egress_object.module = module; 2931 if (trunk >= 0) { 2932 egress_object.flags |= BCM_L3_TGID; 2933 egress_object.trunk = trunk; 2934 } else { 2935 egress_object.port = port; 2936 } 2937 } 2938 2939 if (l2tocpu) { 2940 egress_object.flags |= BCM_L3_L2TOCPU; 2941 } 2942 2943 if (copytocpu) { 2944 egress_object.flags |= (BCM_L3_COPY_TO_CPU); 2945 } 2946 2947 if (drop) { 2948 egress_object.flags |= (BCM_L3_DST_DISCARD); 2949 } 2950 2951 if (l3mc) { 2952 egress_object.flags |= (BCM_L3_IPMC); 2953 if (MAC_ADDR_EQUAL(mac, _soc_mac_all_zeroes)){ 2954 /* Assert BCM_L3_KEEP_DSTMAC if no valid mac-da is assigned. */ 2955 egress_object.flags |= (BCM_L3_KEEP_DSTMAC); 2956 } 2957 } 2958 2959 if (object_id >= 0) { 2960 flags = (BCM_L3_WITH_ID | BCM_L3_REPLACE); 2961 } 2962 2963 2964 rv = bcm_l3_egress_create(unit, flags, &egress_object, &object_id); 2965 if (BCM_FAILURE(rv)) { 2966 cli_out("%s: Error creating egress object entry: %s\n", 2967 ARG_CMD(a), bcm_errmsg(rv)); 2968 return (CMD_FAIL); 2969 } 2970 2971 var_set_integer(ENV_EGRESS_OBJECT_ID, object_id, TRUE, FALSE); 2972 cli_out("New egress object index: %d\n", object_id); 2973 cli_out("Environment variable (%s) was set\n", ENV_EGRESS_OBJECT_ID); 2974 return (CMD_OK); 2975 } 2976 2977 /* 2978 * Function: 2979 * _l3_cmd_egress_object_find 2980 * Description: 2981 * Service routine used to locate id of l3 egress object. 2982 * Parameters: 2983 * unit - (IN) Device number. 2984 * a - (IN) Command arguments. 2985 * Returns: 2986 * CMD_XXX 2987 */ 2988 STATIC cmd_result_t 2989 _l3_cmd_egress_object_find(int unit, args_t *a) 2990 { 2991 cmd_result_t retCode; 2992 parse_table_t pt; 2993 int rv; 2994 bcm_mac_t mac; 2995 bcm_l3_egress_t egress_object; 2996 bcm_if_t interface = -1; 2997 bcm_port_t port = 0; 2998 bcm_module_t module = 0; 2999 bcm_trunk_t trunk = -1; 3000 int l2tocpu = 0; 3001 int l3mc = 0; 3002 int mpls_label = BCM_MPLS_LABEL_INVALID; 3003 int object_id = -1; 3004 3005 bcm_l3_egress_t_init(&egress_object); 3006 sal_memset(mac, 0, sizeof(bcm_mac_t)); 3007 3008 parse_table_init(unit, &pt); 3009 parse_table_add(&pt, "Mac", PQ_DFL | PQ_MAC, 0, (void *)mac, 0); 3010 parse_table_add(&pt, "Port", PQ_DFL | PQ_PORT, 0, (void *)&port, 0); 3011 parse_table_add(&pt, "INtf", PQ_DFL | PQ_INT, 0, (void *)&interface, 0); 3012 parse_table_add(&pt, "MOdule", PQ_DFL | PQ_INT, 0, (void *)&module, 0); 3013 parse_table_add(&pt, "Trunk", PQ_DFL | PQ_INT, 0, (void *)&trunk, 0); 3014 parse_table_add(&pt, "L2tocpu", PQ_DFL | PQ_BOOL, 0, (void *)&l2tocpu, 0); 3015 parse_table_add(&pt, "L3MC", PQ_DFL | PQ_BOOL, 0, (void *)&l3mc, 0); 3016 parse_table_add(&pt, "MplsLabel", PQ_DFL | PQ_INT, 0, 3017 (void *)&mpls_label, 0); 3018 if (!parseEndOk(a, &pt, &retCode)) 3019 return retCode; 3020 3021 egress_object.intf = interface; 3022 egress_object.mpls_label = mpls_label; 3023 sal_memcpy(egress_object.mac_addr, mac, sizeof(mac)); 3024 3025 if (BCM_GPORT_IS_SET(port)) { 3026 egress_object.port = port; 3027 } else { 3028 egress_object.module = module; 3029 if (trunk >= 0) { 3030 egress_object.flags |= BCM_L3_TGID; 3031 egress_object.trunk = trunk; 3032 } else { 3033 egress_object.port = port; 3034 } 3035 } 3036 3037 if (l2tocpu) { 3038 egress_object.flags |= BCM_L3_L2TOCPU; 3039 } 3040 3041 if (l3mc) { 3042 egress_object.flags |= BCM_L3_IPMC; 3043 if (MAC_ADDR_EQUAL(mac, _soc_mac_all_zeroes)){ 3044 /* Assert BCM_L3_KEEP_DSTMAC if no valid mac-da is assigned. */ 3045 egress_object.flags |= (BCM_L3_KEEP_DSTMAC); 3046 } 3047 } 3048 3049 rv = bcm_l3_egress_find(unit, &egress_object, &object_id); 3050 if (BCM_FAILURE(rv)) { 3051 if (rv != BCM_E_NOT_FOUND) { 3052 cli_out("%s: Error finding egress object entry: %s\n", 3053 ARG_CMD(a), bcm_errmsg(rv)); 3054 return (CMD_FAIL); 3055 } 3056 cli_out("%s: Couldn't find entry\n",ARG_CMD(a)); 3057 return (CMD_OK); 3058 } 3059 var_set_integer(ENV_EGRESS_OBJECT_ID, object_id, TRUE, FALSE); 3060 cli_out("Egress object interface id: %d\n", object_id); 3061 cli_out("Environment variable (%s) was set\n", ENV_EGRESS_OBJECT_ID); 3062 return (CMD_OK); 3063 } 3064 3065 3066 /* 3067 * Function: 3068 * _l3_cmd_egress_object_destroy 3069 * Description: 3070 * Service routine used to destroy l3 egress object by id. 3071 * Parameters: 3072 * unit - (IN) Device number. 3073 * a - (IN) Command arguments. 3074 * Returns: 3075 * CMD_XXX 3076 */ 3077 STATIC cmd_result_t 3078 _l3_cmd_egress_object_destroy(int unit, args_t *a) 3079 { 3080 int rv; 3081 int object_id = -1; 3082 3083 if (ARG_CNT(a)) { 3084 if (!isint(ARG_CUR(a))) { 3085 cli_out("%s: Invalid number: %s\n", ARG_CMD(a), ARG_CUR(a)); 3086 return (CMD_FAIL); 3087 } 3088 object_id = parse_integer(ARG_GET(a)); 3089 } else { 3090 cli_out("%s: Invalid arguments: %s\n", ARG_CMD(a), ARG_CUR(a)); 3091 return (CMD_FAIL); 3092 } 3093 3094 rv = bcm_l3_egress_destroy(unit, object_id); 3095 if (BCM_FAILURE(rv)) 3096 { 3097 cli_out("%s: Error deleting egress object entry: %s\n", ARG_CMD(a), 3098 bcm_errmsg(rv)); 3099 return (CMD_FAIL); 3100 } 3101 return (CMD_OK); 3102 } 3103 3104 /* 3105 * Function: 3106 * _l3_cmd_egress_object_show 3107 * Description: 3108 * Service routine used to display l3 egress object/s. 3109 * specific one or all of them. 3110 * Parameters: 3111 * unit - (IN) Device number. 3112 * a - (IN) Command arguments. 3113 * Returns: 3114 * CMD_XXX 3115 */ 3116 STATIC cmd_result_t 3117 _l3_cmd_egress_object_show(int unit, args_t *a) 3118 { 3119 int rv; 3120 int object_id = -1; 3121 int one_entry_only = 0; 3122 bcm_l3_egress_t egress_object; 3123 3124 bcm_l3_egress_t_init(&egress_object); 3125 3126 if (ARG_CNT(a)) { 3127 if (!isint(ARG_CUR(a))) { 3128 cli_out("%s: Invalid number: %s\n", ARG_CMD(a), ARG_CUR(a)); 3129 return (CMD_FAIL); 3130 } 3131 object_id = parse_integer(ARG_GET(a)); 3132 one_entry_only = 1; 3133 } 3134 3135 cli_out("Entry Mac Vlan INTF PORT MOD MPLS_LABEL ToCpu Drop" 3136 " RefCount L3MC\n"); 3137 3138 if (one_entry_only) { 3139 rv = bcm_l3_egress_get(unit, object_id, &egress_object); 3140 if (BCM_FAILURE(rv)) { 3141 cli_out("%s: Error reading egress object entry: %s\n", 3142 ARG_CMD(a), bcm_errmsg(rv)); 3143 return (CMD_FAIL); 3144 } 3145 _l3_cmd_egress_obj_print(unit, object_id, &egress_object, NULL); 3146 } else { 3147 rv = bcm_l3_egress_traverse(unit, _l3_cmd_egress_obj_print, NULL); 3148 if (BCM_FAILURE(rv)) { 3149 cli_out("%s: Error reading egress object entry: %s\n", 3150 ARG_CMD(a), bcm_errmsg(rv)); 3151 return (CMD_FAIL); 3152 } 3153 } 3154 return (CMD_OK); 3155 } 3156 3157 3158 /* 3159 * Function: 3160 * _l3_cmd_egress_mpath_object_create 3161 * Description: 3162 * Service routine used to create/update l3 multipath egress object. 3163 * Parameters: 3164 * unit - (IN) Device number. 3165 * a - (IN) Command arguments. 3166 * Returns: 3167 * CMD_XXX 3168 */ 3169 STATIC cmd_result_t 3170 _l3_cmd_egress_mpath_object_create(int unit, args_t *a) 3171 { 3172 int rv; 3173 parse_table_t pt; 3174 cmd_result_t retCode; 3175 bcm_if_t mpath_egr[32]; 3176 int intf_count = 0; 3177 int object_id = -1; 3178 int flags = 0; 3179 3180 3181 parse_table_init(unit, &pt); 3182 parse_table_add(&pt, "EgrId", PQ_DFL | PQ_INT, 0, (void *)&object_id, 0); 3183 parse_table_add(&pt, "Size", PQ_DFL | PQ_INT, 0, (void *)&intf_count, 0); 3184 parse_table_add(&pt, "Intf0", PQ_DFL | PQ_INT, 0, (void *)&mpath_egr[0], 0); 3185 parse_table_add(&pt, "Intf1", PQ_DFL | PQ_INT, 0, (void *)&mpath_egr[1], 0); 3186 parse_table_add(&pt, "Intf2", PQ_DFL | PQ_INT, 0, (void *)&mpath_egr[2], 0); 3187 parse_table_add(&pt, "Intf3", PQ_DFL | PQ_INT, 0, (void *)&mpath_egr[3], 0); 3188 3189 if (!parseEndOk(a, &pt, &retCode)) { 3190 return retCode; 3191 } 3192 3193 if (object_id >= 0) { 3194 flags = (BCM_L3_WITH_ID | BCM_L3_REPLACE); 3195 } 3196 3197 rv = bcm_l3_egress_multipath_create(unit, flags, intf_count, 3198 mpath_egr, &object_id); 3199 if (BCM_FAILURE(rv)) { 3200 cli_out("%s: Error creating mpath egress object entry: %s\n", 3201 ARG_CMD(a), bcm_errmsg(rv)); 3202 return (CMD_FAIL); 3203 } 3204 3205 var_set_integer(ENV_EGRESS_OBJECT_ID, object_id, TRUE, FALSE); 3206 cli_out("New multipath egress object index: %d\n", object_id); 3207 cli_out("Environment variable (%s) was set\n", ENV_EGRESS_OBJECT_ID); 3208 return (CMD_OK); 3209 } 3210 3211 /* 3212 * Function: 3213 * _l3_cmd_egress_mpath_object_max_create 3214 * Description: 3215 * Service routine used to create l3 multipath egress object 3216 * with dynamic ecmp group sizing. 3217 * Parameters: 3218 * unit - (IN) Device number. 3219 * a - (IN) Command arguments. 3220 * Returns: 3221 * CMD_XXX 3222 */ 3223 STATIC cmd_result_t 3224 _l3_cmd_egress_mpath_object_max_create(int unit, args_t *a) 3225 { 3226 int rv; 3227 parse_table_t pt; 3228 cmd_result_t retCode; 3229 bcm_if_t mpath_egr[32]; 3230 int max_paths = 0; 3231 int intf_count = 0; 3232 int object_id = -1; 3233 int flags = 0; 3234 3235 3236 parse_table_init(unit, &pt); 3237 parse_table_add(&pt, "EgrId", PQ_DFL | PQ_INT, 0, (void *)&object_id, 0); 3238 parse_table_add(&pt, "Size", PQ_DFL | PQ_INT, 0, (void *)&intf_count, 0); 3239 parse_table_add(&pt, "MaxGrpSize", PQ_DFL | PQ_INT, 0, (void *)&max_paths, 0); 3240 parse_table_add(&pt, "Intf0", PQ_DFL | PQ_INT, 0, (void *)&mpath_egr[0], 0); 3241 parse_table_add(&pt, "Intf1", PQ_DFL | PQ_INT, 0, (void *)&mpath_egr[1], 0); 3242 parse_table_add(&pt, "Intf2", PQ_DFL | PQ_INT, 0, (void *)&mpath_egr[2], 0); 3243 parse_table_add(&pt, "Intf3", PQ_DFL | PQ_INT, 0, (void *)&mpath_egr[3], 0); 3244 3245 if (!parseEndOk(a, &pt, &retCode)) { 3246 return retCode; 3247 } 3248 3249 if (object_id >= 0) { 3250 flags = (BCM_L3_WITH_ID | BCM_L3_REPLACE); 3251 } 3252 3253 rv = bcm_l3_egress_multipath_max_create(unit, flags, max_paths, intf_count, 3254 mpath_egr, &object_id); 3255 if (BCM_FAILURE(rv)) { 3256 cli_out("%s: Error creating mpath egress object entry: %s\n", 3257 ARG_CMD(a), bcm_errmsg(rv)); 3258 return (CMD_FAIL); 3259 } 3260 3261 var_set_integer(ENV_EGRESS_OBJECT_ID, object_id, TRUE, FALSE); 3262 cli_out("New multipath egress object index: %d\n", object_id); 3263 cli_out("Environment variable (%s) was set\n", ENV_EGRESS_OBJECT_ID); 3264 return (CMD_OK); 3265 } 3266 3267 /* 3268 * Function: 3269 * _l3_cmd_egress_mpath_object_lookup 3270 * Description: 3271 * Service routine used to search for matching l3 3272 * multipath egress object. 3273 * Parameters: 3274 * unit - (IN) Device number. 3275 * a - (IN) Command arguments. 3276 * Returns: 3277 * CMD_XXX 3278 */ 3279 STATIC cmd_result_t 3280 _l3_cmd_egress_mpath_object_lookup(int unit, args_t *a) 3281 { 3282 int rv; 3283 parse_table_t pt; 3284 cmd_result_t retCode; 3285 bcm_if_t mpath_egr[32]; 3286 int intf_count = 0; 3287 int object_id = -1; 3288 3289 parse_table_init(unit, &pt); 3290 parse_table_add(&pt, "Size", PQ_DFL | PQ_INT, 0, (void *)&intf_count, 0); 3291 parse_table_add(&pt, "Intf0", PQ_DFL | PQ_INT, 0, (void *)&mpath_egr[0], 0); 3292 parse_table_add(&pt, "Intf1", PQ_DFL | PQ_INT, 0, (void *)&mpath_egr[1], 0); 3293 parse_table_add(&pt, "Intf2", PQ_DFL | PQ_INT, 0, (void *)&mpath_egr[2], 0); 3294 parse_table_add(&pt, "Intf3", PQ_DFL | PQ_INT, 0, (void *)&mpath_egr[3], 0); 3295 if (!parseEndOk(a, &pt, &retCode)) { 3296 return retCode; 3297 } 3298 rv = bcm_l3_egress_multipath_find(unit, intf_count, mpath_egr, &object_id); 3299 3300 if (BCM_FAILURE(rv)) { 3301 if (rv != BCM_E_NOT_FOUND) { 3302 cli_out("%s: Error finding mpath egress object entry: %s\n", 3303 ARG_CMD(a), bcm_errmsg(rv)); 3304 return CMD_FAIL; 3305 } 3306 cli_out("%s: Couldn't find the entry\n",ARG_CMD(a)); 3307 return CMD_OK; 3308 } 3309 3310 var_set_integer(ENV_EGRESS_OBJECT_ID, object_id, TRUE, FALSE); 3311 cli_out("Egress mpath object interface id: %d\n", object_id); 3312 cli_out("Environment variable (%s) was set\n", ENV_EGRESS_OBJECT_ID); 3313 return CMD_OK; 3314 } 3315 3316 /* 3317 * Function: 3318 * _l3_cmd_egress_mpath_object_destroy 3319 * Description: 3320 * Service routine used to destroy l3 multipath egress object. 3321 * Parameters: 3322 * unit - (IN) Device number. 3323 * a - (IN) Command arguments. 3324 * Returns: 3325 * CMD_XXX 3326 */ 3327 STATIC cmd_result_t 3328 _l3_cmd_egress_mpath_object_destroy(int unit, args_t *a) 3329 { 3330 int rv; 3331 int object_id = -1; 3332 3333 if (ARG_CNT(a)) { 3334 if (!isint(ARG_CUR(a))) { 3335 cli_out("%s: Invalid object id: %s\n", ARG_CMD(a), ARG_CUR(a)); 3336 return (CMD_FAIL); 3337 } 3338 object_id = parse_integer(ARG_GET(a)); 3339 } else { 3340 cli_out("%s: Invalid arguments: %s\n", ARG_CMD(a), ARG_CUR(a)); 3341 return (CMD_FAIL); 3342 } 3343 3344 rv = bcm_l3_egress_multipath_destroy(unit, object_id); 3345 if (BCM_FAILURE(rv)) { 3346 cli_out("%s: Error deleting mpath egress object entry: %s\n", 3347 ARG_CMD(a), bcm_errmsg(rv)); 3348 return (CMD_FAIL); 3349 } 3350 return (CMD_OK); 3351 } 3352 3353 /* 3354 * Function: 3355 * _l3_cmd_egress_mpath_object_show 3356 * Description: 3357 * Service routine used to display l3 multipath egress object. 3358 * Parameters: 3359 * unit - (IN) Device number. 3360 * a - (IN) Command arguments. 3361 * Returns: 3362 * CMD_XXX 3363 */ 3364 STATIC cmd_result_t 3365 _l3_cmd_egress_mpath_object_show(int unit, args_t *a) 3366 { 3367 int rv; 3368 bcm_if_t *mpath_egr = NULL; 3369 int one_entry_only = 0; 3370 int intf_count = 0; 3371 int object_id = -1; 3372 3373 if (ARG_CNT(a)) { 3374 if (!isint(ARG_CUR(a))) { 3375 cli_out("%s: Invalid number: %s\n", ARG_CMD(a), ARG_CUR(a)); 3376 return (CMD_FAIL); 3377 } 3378 object_id = parse_integer(ARG_GET(a)); 3379 one_entry_only = 1; 3380 } 3381 3382 if (one_entry_only) { 3383 rv = bcm_l3_egress_multipath_get(unit, object_id, 0, NULL, 3384 &intf_count); 3385 mpath_egr = sal_alloc((intf_count * sizeof(int)), "ecmp group"); 3386 if (mpath_egr == NULL) { 3387 cli_out("%s: ERROR: %s\n", ARG_CMD(a), bcm_errmsg(BCM_E_MEMORY)); 3388 return (CMD_FAIL); 3389 } 3390 rv = bcm_l3_egress_multipath_get(unit, object_id, intf_count, 3391 mpath_egr, &intf_count); 3392 if (BCM_FAILURE(rv)) { 3393 sal_free(mpath_egr); 3394 cli_out("%s: Error reading egress object entry: %s\n", 3395 ARG_CMD(a), bcm_errmsg(rv)); 3396 return (CMD_FAIL); 3397 } 3398 _l3_cmd_egress_mpath_obj_print(unit, object_id, intf_count, 3399 mpath_egr, NULL); 3400 sal_free(mpath_egr); 3401 } else { 3402 rv = bcm_l3_egress_multipath_traverse(unit, 3403 _l3_cmd_egress_mpath_obj_print, 3404 NULL); 3405 } 3406 if (BCM_FAILURE(rv)) { 3407 return (CMD_FAIL); 3408 } 3409 return (CMD_OK); 3410 } 3411 3412 /* 3413 * Function: 3414 * _l3_cmd_egress_mpath_object_intf_insert 3415 * Description: 3416 * Service routine used to add an egress interface to multipath 3417 * egress object. 3418 * Parameters: 3419 * unit - (IN) Device number. 3420 * a - (IN) Command arguments. 3421 * Returns: 3422 * CMD_XXX 3423 */ 3424 STATIC cmd_result_t 3425 _l3_cmd_egress_mpath_object_intf_insert(int unit, args_t *a) 3426 { 3427 int rv; 3428 parse_table_t pt; 3429 cmd_result_t retCode; 3430 int object_id = -1; 3431 int interface = 0; 3432 3433 parse_table_init(unit, &pt); 3434 parse_table_add(&pt, "EgrId", PQ_DFL | PQ_INT, 0, (void *)&object_id, 0); 3435 parse_table_add(&pt, "INtf", PQ_DFL | PQ_INT, 0, (void *)&interface, 0); 3436 3437 if (!parseEndOk(a, &pt, &retCode)) 3438 return retCode; 3439 3440 rv = bcm_l3_egress_multipath_add(unit, object_id, interface); 3441 if (BCM_FAILURE(rv)) { 3442 cli_out("%s: Error adding interface to egress obj: %s\n", 3443 ARG_CMD(a), bcm_errmsg(rv)); 3444 return (CMD_FAIL); 3445 } 3446 return (CMD_OK); 3447 } 3448 3449 3450 /* 3451 * Function: 3452 * _l3_cmd_egress_mpath_object_intf_remove 3453 * Description: 3454 * Service routine used to remove an egress interface 3455 * from multipath egress object. 3456 * Parameters: 3457 * unit - (IN) Device number. 3458 * a - (IN) Command arguments. 3459 * Returns: 3460 * CMD_XXX 3461 */ 3462 STATIC cmd_result_t 3463 _l3_cmd_egress_mpath_object_intf_remove(int unit, args_t *a) 3464 { 3465 int rv; 3466 parse_table_t pt; 3467 cmd_result_t retCode; 3468 int object_id = -1; 3469 int interface = 0; 3470 3471 parse_table_init(unit, &pt); 3472 parse_table_add(&pt, "EgrId", PQ_DFL | PQ_INT, 0, (void *)&object_id, 0); 3473 parse_table_add(&pt, "INtf", PQ_DFL | PQ_INT, 0, (void *)&interface, 0); 3474 3475 if (!parseEndOk(a, &pt, &retCode)) 3476 return retCode; 3477 3478 rv = bcm_l3_egress_multipath_delete(unit, object_id, interface); 3479 if (BCM_FAILURE(rv)) { 3480 cli_out("%s: Error deleting interface from egress obj: %s\n", 3481 ARG_CMD(a), bcm_errmsg(rv)); 3482 return (CMD_FAIL); 3483 } 3484 return (CMD_OK); 3485 } 3486 3487 /* 3488 * Function: 3489 * _l3_cmd_egress_ecmp_object_create 3490 * Description: 3491 * Service routine used to create/update l3 ecmp egress object. 3492 * Parameters: 3493 * unit - (IN) Device number. 3494 * a - (IN) Command arguments. 3495 * Returns: 3496 * CMD_XXX 3497 */ 3498 STATIC cmd_result_t 3499 _l3_cmd_egress_ecmp_object_create(int unit, args_t *a) 3500 { 3501 int rv; 3502 parse_table_t pt; 3503 cmd_result_t retCode; 3504 bcm_if_t ecmp_egr[32]; 3505 int intf_count = 0; 3506 int object_id = -1; 3507 bcm_l3_egress_ecmp_t ecmp; 3508 3509 3510 parse_table_init(unit, &pt); 3511 parse_table_add(&pt, "EgrId", PQ_DFL | PQ_INT, 0, (void *)&object_id, 0); 3512 parse_table_add(&pt, "Size", PQ_DFL | PQ_INT, 0, (void *)&intf_count, 0); 3513 parse_table_add(&pt, "Intf0", PQ_DFL | PQ_INT, 0, (void *)&ecmp_egr[0], 0); 3514 parse_table_add(&pt, "Intf1", PQ_DFL | PQ_INT, 0, (void *)&ecmp_egr[1], 0); 3515 parse_table_add(&pt, "Intf2", PQ_DFL | PQ_INT, 0, (void *)&ecmp_egr[2], 0); 3516 parse_table_add(&pt, "Intf3", PQ_DFL | PQ_INT, 0, (void *)&ecmp_egr[3], 0); 3517 3518 if (!parseEndOk(a, &pt, &retCode)) { 3519 return retCode; 3520 } 3521 3522 bcm_l3_egress_ecmp_t_init(&ecmp); 3523 if (object_id >= 0) { 3524 ecmp.flags = (BCM_L3_WITH_ID | BCM_L3_REPLACE); 3525 ecmp.ecmp_intf = object_id; 3526 } 3527 3528 rv = bcm_l3_egress_ecmp_create(unit, &ecmp, intf_count, ecmp_egr); 3529 if (BCM_FAILURE(rv)) { 3530 cli_out("%s: Error creating ecmp egress object entry: %s\n", 3531 ARG_CMD(a), bcm_errmsg(rv)); 3532 return (CMD_FAIL); 3533 } 3534 3535 var_set_integer(ENV_EGRESS_OBJECT_ID, ecmp.ecmp_intf, TRUE, FALSE); 3536 cli_out("New ecmp egress object index: %d\n", ecmp.ecmp_intf); 3537 cli_out("Environment variable (%s) was set\n", ENV_EGRESS_OBJECT_ID); 3538 return (CMD_OK); 3539 } 3540 3541 /* 3542 * Function: 3543 * _l3_cmd_egress_ecmp_object_max_create 3544 * Description: 3545 * Service routine used to create l3 ecmp egress object 3546 * with dynamic ecmp group sizing. 3547 * Parameters: 3548 * unit - (IN) Device number. 3549 * a - (IN) Command arguments. 3550 * Returns: 3551 * CMD_XXX 3552 */ 3553 STATIC cmd_result_t 3554 _l3_cmd_egress_ecmp_object_max_create(int unit, args_t *a) 3555 { 3556 int rv; 3557 parse_table_t pt; 3558 cmd_result_t retCode; 3559 bcm_if_t ecmp_egr[32]; 3560 int max_paths = 0; 3561 int intf_count = 0; 3562 int object_id = -1; 3563 bcm_l3_egress_ecmp_t ecmp; 3564 3565 3566 parse_table_init(unit, &pt); 3567 parse_table_add(&pt, "EgrId", PQ_DFL | PQ_INT, 0, (void *)&object_id, 0); 3568 parse_table_add(&pt, "Size", PQ_DFL | PQ_INT, 0, (void *)&intf_count, 0); 3569 parse_table_add(&pt, "MaxGrpSize", PQ_DFL | PQ_INT, 0, (void *)&max_paths, 0); 3570 parse_table_add(&pt, "Intf0", PQ_DFL | PQ_INT, 0, (void *)&ecmp_egr[0], 0); 3571 parse_table_add(&pt, "Intf1", PQ_DFL | PQ_INT, 0, (void *)&ecmp_egr[1], 0); 3572 parse_table_add(&pt, "Intf2", PQ_DFL | PQ_INT, 0, (void *)&ecmp_egr[2], 0); 3573 parse_table_add(&pt, "Intf3", PQ_DFL | PQ_INT, 0, (void *)&ecmp_egr[3], 0); 3574 3575 if (!parseEndOk(a, &pt, &retCode)) { 3576 return retCode; 3577 } 3578 3579 bcm_l3_egress_ecmp_t_init(&ecmp); 3580 if (object_id >= 0) { 3581 ecmp.flags = (BCM_L3_WITH_ID | BCM_L3_REPLACE); 3582 ecmp.ecmp_intf = object_id; 3583 } 3584 3585 ecmp.max_paths = max_paths; 3586 rv = bcm_l3_egress_ecmp_create(unit, &ecmp, intf_count, ecmp_egr); 3587 if (BCM_FAILURE(rv)) { 3588 cli_out("%s: Error creating ecmp egress object entry: %s\n", 3589 ARG_CMD(a), bcm_errmsg(rv)); 3590 return (CMD_FAIL); 3591 } 3592 3593 var_set_integer(ENV_EGRESS_OBJECT_ID, ecmp.ecmp_intf, TRUE, FALSE); 3594 cli_out("New ecmp egress object index: %d\n", ecmp.ecmp_intf); 3595 cli_out("Environment variable (%s) was set\n", ENV_EGRESS_OBJECT_ID); 3596 return (CMD_OK); 3597 } 3598 3599 /* 3600 * Function: 3601 * _l3_cmd_egress_ecmp_object_lookup 3602 * Description: 3603 * Service routine used to search for matching l3 3604 * ecmp egress object. 3605 * Parameters: 3606 * unit - (IN) Device number. 3607 * a - (IN) Command arguments. 3608 * Returns: 3609 * CMD_XXX 3610 */ 3611 STATIC cmd_result_t 3612 _l3_cmd_egress_ecmp_object_lookup(int unit, args_t *a) 3613 { 3614 int rv; 3615 parse_table_t pt; 3616 cmd_result_t retCode; 3617 bcm_if_t ecmp_egr[32]; 3618 int intf_count = 0; 3619 bcm_l3_egress_ecmp_t ecmp; 3620 3621 parse_table_init(unit, &pt); 3622 parse_table_add(&pt, "Size", PQ_DFL | PQ_INT, 0, (void *)&intf_count, 0); 3623 parse_table_add(&pt, "Intf0", PQ_DFL | PQ_INT, 0, (void *)&ecmp_egr[0], 0); 3624 parse_table_add(&pt, "Intf1", PQ_DFL | PQ_INT, 0, (void *)&ecmp_egr[1], 0); 3625 parse_table_add(&pt, "Intf2", PQ_DFL | PQ_INT, 0, (void *)&ecmp_egr[2], 0); 3626 parse_table_add(&pt, "Intf3", PQ_DFL | PQ_INT, 0, (void *)&ecmp_egr[3], 0); 3627 if (!parseEndOk(a, &pt, &retCode)) { 3628 return retCode; 3629 } 3630 3631 bcm_l3_egress_ecmp_t_init(&ecmp); 3632 rv = bcm_l3_egress_ecmp_find(unit, intf_count, ecmp_egr, &ecmp); 3633 3634 if (BCM_FAILURE(rv)) { 3635 if (rv != BCM_E_NOT_FOUND) { 3636 cli_out("%s: Error finding ecmp egress object entry: %s\n", 3637 ARG_CMD(a), bcm_errmsg(rv)); 3638 return CMD_FAIL; 3639 } 3640 cli_out("%s: Couldn't find the entry\n",ARG_CMD(a)); 3641 return CMD_OK; 3642 } 3643 3644 var_set_integer(ENV_EGRESS_OBJECT_ID, ecmp.ecmp_intf, TRUE, FALSE); 3645 cli_out("Egress ecmp object interface id: %d\n", ecmp.ecmp_intf); 3646 cli_out("Environment variable (%s) was set\n", ENV_EGRESS_OBJECT_ID); 3647 return CMD_OK; 3648 } 3649 3650 /* 3651 * Function: 3652 * _l3_cmd_egress_ecmp_object_destroy 3653 * Description: 3654 * Service routine used to destroy l3 ecmp egress object. 3655 * Parameters: 3656 * unit - (IN) Device number. 3657 * a - (IN) Command arguments. 3658 * Returns: 3659 * CMD_XXX 3660 */ 3661 STATIC cmd_result_t 3662 _l3_cmd_egress_ecmp_object_destroy(int unit, args_t *a) 3663 { 3664 int rv; 3665 int object_id = -1; 3666 bcm_l3_egress_ecmp_t ecmp; 3667 3668 if (ARG_CNT(a)) { 3669 if (!isint(ARG_CUR(a))) { 3670 cli_out("%s: Invalid object id: %s\n", ARG_CMD(a), ARG_CUR(a)); 3671 return (CMD_FAIL); 3672 } 3673 object_id = parse_integer(ARG_GET(a)); 3674 } else { 3675 cli_out("%s: Invalid arguments: %s\n", ARG_CMD(a), ARG_CUR(a)); 3676 return (CMD_FAIL); 3677 } 3678 3679 bcm_l3_egress_ecmp_t_init(&ecmp); 3680 ecmp.ecmp_intf = object_id; 3681 rv = bcm_l3_egress_ecmp_destroy(unit, &ecmp); 3682 if (BCM_FAILURE(rv)) { 3683 cli_out("%s: Error deleting ecmp egress object entry: %s\n", 3684 ARG_CMD(a), bcm_errmsg(rv)); 3685 return (CMD_FAIL); 3686 } 3687 return (CMD_OK); 3688 } 3689 3690 /* 3691 * Function: 3692 * _l3_cmd_egress_ecmp_object_show 3693 * Description: 3694 * Service routine used to display l3 ecmp egress object. 3695 * Parameters: 3696 * unit - (IN) Device number. 3697 * a - (IN) Command arguments. 3698 * Returns: 3699 * CMD_XXX 3700 */ 3701 STATIC cmd_result_t 3702 _l3_cmd_egress_ecmp_object_show(int unit, args_t *a) 3703 { 3704 int rv; 3705 bcm_if_t *ecmp_egr = NULL; 3706 int one_entry_only = 0; 3707 int intf_count = 0; 3708 int object_id = -1; 3709 bcm_l3_egress_ecmp_t ecmp; 3710 3711 if (ARG_CNT(a)) { 3712 if (!isint(ARG_CUR(a))) { 3713 cli_out("%s: Invalid number: %s\n", ARG_CMD(a), ARG_CUR(a)); 3714 return (CMD_FAIL); 3715 } 3716 object_id = parse_integer(ARG_GET(a)); 3717 one_entry_only = 1; 3718 } 3719 3720 bcm_l3_egress_ecmp_t_init(&ecmp); 3721 if (one_entry_only) { 3722 ecmp.ecmp_intf = object_id; 3723 rv = bcm_l3_egress_ecmp_get(unit, &ecmp, 0, NULL, &intf_count); 3724 ecmp_egr = sal_alloc((intf_count * sizeof(int)), "ecmp group"); 3725 if (ecmp_egr == NULL) { 3726 cli_out("%s: ERROR: %s\n", ARG_CMD(a), bcm_errmsg(BCM_E_MEMORY)); 3727 return (CMD_FAIL); 3728 } 3729 rv = bcm_l3_egress_ecmp_get(unit, &ecmp, intf_count, ecmp_egr, 3730 &intf_count); 3731 if (BCM_FAILURE(rv)) { 3732 sal_free(ecmp_egr); 3733 cli_out("%s: Error reading egress object entry: %s\n", 3734 ARG_CMD(a), bcm_errmsg(rv)); 3735 return (CMD_FAIL); 3736 } 3737 _l3_cmd_egress_ecmp_obj_print(unit, &ecmp, intf_count, ecmp_egr, 3738 NULL); 3739 sal_free(ecmp_egr); 3740 } else { 3741 rv = bcm_l3_egress_ecmp_traverse(unit, _l3_cmd_egress_ecmp_obj_print, 3742 NULL); 3743 } 3744 if (BCM_FAILURE(rv)) { 3745 return (CMD_FAIL); 3746 } 3747 return (CMD_OK); 3748 } 3749 3750 /* 3751 * Function: 3752 * _l3_cmd_egress_ecmp_object_intf_insert 3753 * Description: 3754 * Service routine used to add an egress interface to ecmp 3755 * egress object. 3756 * Parameters: 3757 * unit - (IN) Device number. 3758 * a - (IN) Command arguments. 3759 * Returns: 3760 * CMD_XXX 3761 */ 3762 STATIC cmd_result_t 3763 _l3_cmd_egress_ecmp_object_intf_insert(int unit, args_t *a) 3764 { 3765 int rv; 3766 parse_table_t pt; 3767 cmd_result_t retCode; 3768 int object_id = -1; 3769 int interface = 0; 3770 bcm_l3_egress_ecmp_t ecmp; 3771 3772 parse_table_init(unit, &pt); 3773 parse_table_add(&pt, "EgrId", PQ_DFL | PQ_INT, 0, (void *)&object_id, 0); 3774 parse_table_add(&pt, "INtf", PQ_DFL | PQ_INT, 0, (void *)&interface, 0); 3775 3776 if (!parseEndOk(a, &pt, &retCode)) 3777 return retCode; 3778 3779 bcm_l3_egress_ecmp_t_init(&ecmp); 3780 ecmp.ecmp_intf = object_id; 3781 rv = bcm_l3_egress_ecmp_add(unit, &ecmp, interface); 3782 if (BCM_FAILURE(rv)) { 3783 cli_out("%s: Error adding interface to egress obj: %s\n", 3784 ARG_CMD(a), bcm_errmsg(rv)); 3785 return (CMD_FAIL); 3786 } 3787 return (CMD_OK); 3788 } 3789 3790 3791 /* 3792 * Function: 3793 * _l3_cmd_egress_ecmp_object_intf_remove 3794 * Description: 3795 * Service routine used to remove an egress interface 3796 * from ecmp egress object. 3797 * Parameters: 3798 * unit - (IN) Device number. 3799 * a - (IN) Command arguments. 3800 * Returns: 3801 * CMD_XXX 3802 */ 3803 STATIC cmd_result_t 3804 _l3_cmd_egress_ecmp_object_intf_remove(int unit, args_t *a) 3805 { 3806 int rv; 3807 parse_table_t pt; 3808 cmd_result_t retCode; 3809 int object_id = -1; 3810 int interface = 0; 3811 bcm_l3_egress_ecmp_t ecmp; 3812 3813 parse_table_init(unit, &pt); 3814 parse_table_add(&pt, "EgrId", PQ_DFL | PQ_INT, 0, (void *)&object_id, 0); 3815 parse_table_add(&pt, "INtf", PQ_DFL | PQ_INT, 0, (void *)&interface, 0); 3816 3817 if (!parseEndOk(a, &pt, &retCode)) 3818 return retCode; 3819 3820 bcm_l3_egress_ecmp_t_init(&ecmp); 3821 ecmp.ecmp_intf = object_id; 3822 rv = bcm_l3_egress_ecmp_delete(unit, &ecmp, interface); 3823 if (BCM_FAILURE(rv)) { 3824 cli_out("%s: Error deleting interface from egress obj: %s\n", 3825 ARG_CMD(a), bcm_errmsg(rv)); 3826 return (CMD_FAIL); 3827 } 3828 return (CMD_OK); 3829 } 3830 3831 /* 3832 * Function: 3833 * _l3_cmd_prefix_map_add 3834 * Description: 3835 * Service routine used to add prefix map. 3836 * Parameters: 3837 * unit - (IN) Device number. 3838 * a - (IN) Command arguments. 3839 * Returns: 3840 * CMD_XXX 3841 */ 3842 STATIC cmd_result_t 3843 _l3_cmd_prefix_map_add(int unit, args_t *a) 3844 { 3845 bcm_ip6_t ip6_addr; 3846 cmd_result_t retCode; 3847 parse_table_t pt; 3848 int rv; 3849 3850 sal_memset(&ip6_addr, 0, sizeof(bcm_ip6_t)); 3851 parse_table_init(unit, &pt); 3852 3853 parse_table_add(&pt, "IP", PQ_DFL | PQ_IP6, 0, (void *)&ip6_addr, 0); 3854 if (!parseEndOk(a, &pt, &retCode)) 3855 return retCode; 3856 3857 rv = bcm_l3_ip6_prefix_map_add(unit, ip6_addr); 3858 if (BCM_FAILURE(rv)) { 3859 cli_out("%s: Error adding ip6 prefix map: %s\n", ARG_CMD(a), 3860 bcm_errmsg(rv)); 3861 return (CMD_FAIL); 3862 } 3863 return (CMD_OK); 3864 } 3865 3866 /* 3867 * Function: 3868 * _l3_cmd_prefix_map_delete 3869 * Description: 3870 * Service routine used to delete prefix map. 3871 * Parameters: 3872 * unit - (IN) Device number. 3873 * a - (IN) Command arguments. 3874 * Returns: 3875 * CMD_XXX 3876 */ 3877 STATIC cmd_result_t 3878 _l3_cmd_prefix_map_delete(int unit, args_t *a) 3879 { 3880 bcm_ip6_t ip6_addr; 3881 cmd_result_t retCode; 3882 parse_table_t pt; 3883 int rv; 3884 3885 sal_memset(&ip6_addr, 0, sizeof(bcm_ip6_t)); 3886 parse_table_init(unit, &pt); 3887 3888 parse_table_add(&pt, "IP", PQ_DFL | PQ_IP6, 0, (void *)&ip6_addr, 0); 3889 if (!parseEndOk(a, &pt, &retCode)) 3890 return retCode; 3891 3892 rv = bcm_l3_ip6_prefix_map_delete(unit, ip6_addr); 3893 if (BCM_FAILURE(rv)) { 3894 cli_out("%s: Error adding ip6 prefix map: %s\n", 3895 ARG_CMD(a), bcm_errmsg(rv)); 3896 return (CMD_FAIL); 3897 } 3898 return (CMD_OK); 3899 } 3900 3901 /* 3902 * Function: 3903 * _l3_cmd_prefix_map_delete_all 3904 * Description: 3905 * Service routine used to flush all prefix maps. 3906 * Parameters: 3907 * unit - (IN) Device number. 3908 * a - (IN) Command arguments. 3909 * Returns: 3910 * CMD_XXX 3911 */ 3912 STATIC cmd_result_t 3913 _l3_cmd_prefix_map_delete_all(int unit, args_t *a) 3914 { 3915 int rv; 3916 3917 if ((rv = bcm_l3_ip6_prefix_map_delete_all(unit)) < 0) { 3918 cli_out("%s: Error flushing prefix map : %s\n", 3919 ARG_CMD(a), bcm_errmsg(rv)); 3920 return (CMD_FAIL); 3921 } 3922 return (CMD_OK); 3923 } 3924 3925 #define BCM_DIAG_CMD_PREFIX_MAP_SIZE (10) 3926 /* 3927 * Function: 3928 * _l3_cmd_prefix_map_show 3929 * Description: 3930 * Service routine used display prefix maps. 3931 * Parameters: 3932 * unit - (IN) Device number. 3933 * a - (IN) Command arguments. 3934 * Returns: 3935 * CMD_XXX 3936 */ 3937 STATIC cmd_result_t 3938 _l3_cmd_prefix_map_show(int unit, args_t *a) 3939 { 3940 int rv; 3941 int idx; 3942 bcm_ip6_t prefix_map[BCM_DIAG_CMD_PREFIX_MAP_SIZE]; 3943 char ip_str[IP6ADDR_STR_LEN + 3]; 3944 int intf_count = 0; 3945 3946 rv = bcm_l3_ip6_prefix_map_get(unit, BCM_DIAG_CMD_PREFIX_MAP_SIZE, 3947 prefix_map, &intf_count); 3948 if (BCM_FAILURE(rv)) { 3949 cli_out("%s: Error reading prefix map entry: %s\n", 3950 ARG_CMD(a), bcm_errmsg(rv)); 3951 return (CMD_FAIL); 3952 } 3953 3954 if (intf_count > 0) { 3955 cli_out("Entry IP6_ADDR\n"); 3956 } 3957 3958 for (idx = 0; idx < intf_count; idx++) { 3959 format_ip6addr(ip_str, prefix_map[idx]); 3960 cli_out("%-5d %s\n", idx, ip_str); 3961 } 3962 3963 return (CMD_OK); 3964 } 3965 #undef BCM_DIAG_CMD_PREFIX_MAP_SIZE 3966 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 3967 3968 /* 3969 * Function: 3970 * _l3_cmd_route_add 3971 * Description: 3972 * Service routine used to add route. 3973 * Parameters: 3974 * unit - (IN) Device number. 3975 * a - (IN) Command arguments. 3976 * v6 - (IN) IPv6 route indication. 3977 * Returns: 3978 * CMD_XXX 3979 */ 3980 STATIC cmd_result_t 3981 _l3_cmd_route_add(int unit, args_t *a, int v6) 3982 { 3983 bcm_l3_route_t route_info; 3984 cmd_result_t retCode; 3985 bcm_mac_t mac; 3986 parse_table_t pt; 3987 int rv; 3988 int interface = 0; 3989 bcm_ip_t ip_addr = 0; 3990 bcm_ip_t ip_mask = 0; 3991 int module = 0; 3992 int trunk = -1; 3993 int untag = 0; 3994 int port = 0; 3995 int hits = 0; 3996 int vlan = 0; 3997 int ipmc = 0; 3998 #if defined(BCM_XGS_SWITCH_SUPPORT) 3999 int ecmp = 0; 4000 int local_route = 0; 4001 #endif /* BCM_XGS_SWITCH_SUPPORT */ 4002 #if defined(BCM_XGS3_SWITCH_SUPPORT) 4003 int lookup_class = 0; 4004 int tunnel_opt = 0; 4005 int mpls_label = 0; 4006 int replace = 0; 4007 int rpe = 0; 4008 int pri = 0; 4009 int dst_discard = 0; 4010 int vrf = 0; 4011 int plen = 0; 4012 bcm_ip6_t ip6_addr; 4013 #endif 4014 4015 bcm_l3_route_t_init(&route_info); 4016 sal_memset(mac, 0, sizeof(bcm_mac_t)); 4017 parse_table_init(unit, &pt); 4018 4019 parse_table_add(&pt, "Mac", PQ_DFL | PQ_MAC, 0, (void *)mac, 0); 4020 parse_table_add(&pt, "Port", PQ_DFL | PQ_PORT, 0, (void *)&port, 0); 4021 parse_table_add(&pt, "INtf", PQ_DFL | PQ_INT, 0, (void *)&interface, 0); 4022 parse_table_add(&pt, "MOdule", PQ_DFL | PQ_INT, 0, (void *)&module, 0); 4023 parse_table_add(&pt, "Trunk", PQ_DFL | PQ_INT, 0, (void *)&trunk, 0); 4024 parse_table_add(&pt, "Untag", PQ_DFL | PQ_BOOL, 0, (void *)&untag, 0); 4025 parse_table_add(&pt, "Hit", PQ_DFL | PQ_BOOL, 0, (void *)&hits, 0); 4026 #if defined(BCM_XGS3_SWITCH_SUPPORT) 4027 parse_table_add(&pt, "VRF", PQ_DFL | PQ_INT, 0, (void *)&vrf, 0); 4028 parse_table_add(&pt, "DstDiscard", PQ_DFL | PQ_INT, 0, 4029 (void *)&dst_discard, 0); 4030 parse_table_add(&pt, "PRI", PQ_DFL|PQ_INT, 0, (void *)&pri, 0); 4031 parse_table_add(&pt, "RPE", PQ_DFL|PQ_BOOL, 0, (void *)&rpe, 0); 4032 parse_table_add(&pt, "Replace", PQ_DFL | PQ_BOOL, 0, (void *)&replace, 0); 4033 parse_table_add(&pt, "MplsLabel", PQ_DFL | PQ_INT, 0, 4034 (void *)&mpls_label, 0); 4035 parse_table_add(&pt, "TunnelOpt", PQ_DFL | PQ_INT, 0, 4036 (void *)&tunnel_opt, 0); 4037 parse_table_add(&pt, "LookupClass", PQ_DFL | PQ_INT, 0, (void *)&lookup_class, 0); 4038 parse_table_add(&pt, "VLAN", PQ_DFL | PQ_INT, 0, (void *)&vlan, 0); 4039 parse_table_add(&pt, "IPMC", PQ_DFL | PQ_INT, 0, (void *)&ipmc, 0); 4040 if(v6) { 4041 sal_memset(ip6_addr, 0, sizeof(bcm_ip6_t)); 4042 parse_table_add(&pt, "IP", PQ_DFL | PQ_IP6, 0, (void *)&ip6_addr, 0); 4043 parse_table_add(&pt, "MaskLen", PQ_DFL | PQ_INT, 0, (void *)&plen, 0); 4044 } else 4045 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 4046 { 4047 parse_table_add(&pt, "IP", PQ_DFL | PQ_IP, 0, (void *)&ip_addr, 0); 4048 parse_table_add(&pt, "MaSk", PQ_DFL | PQ_IP, 0, (void *)&ip_mask, 0); 4049 } 4050 4051 #if defined(BCM_XGS_SWITCH_SUPPORT) 4052 parse_table_add(&pt, "ECMP", PQ_DFL | PQ_BOOL, 0, (void *)&ecmp, 0); 4053 parse_table_add(&pt, "Local", PQ_DFL | PQ_BOOL, 0, (void *)&local_route, 0); 4054 #endif /* BCM_XGS_SWITCH_SUPPORT */ 4055 4056 if (!parseEndOk(a, &pt, &retCode)) { 4057 return retCode; 4058 } 4059 4060 #if defined(BCM_XGS3_SWITCH_SUPPORT) 4061 route_info.l3a_vrf = vrf; 4062 if (dst_discard) { 4063 route_info.l3a_flags |= BCM_L3_DST_DISCARD; 4064 } 4065 if (rpe) { 4066 route_info.l3a_flags |= BCM_L3_RPE; 4067 } 4068 if (replace) { 4069 route_info.l3a_flags |= BCM_L3_REPLACE; 4070 } 4071 if (ipmc) { 4072 route_info.l3a_flags |= BCM_L3_IPMC; 4073 BCM_MULTICAST_L3_SET(route_info.l3a_mc_group, interface); 4074 } 4075 route_info.l3a_pri = pri; 4076 4077 if (lookup_class) { 4078 route_info.l3a_lookup_class= lookup_class; 4079 } 4080 4081 if (mpls_label) { 4082 route_info.l3a_mpls_label = mpls_label; 4083 route_info.l3a_flags |= BCM_L3_ROUTE_LABEL; 4084 } else if (tunnel_opt) { 4085 route_info.l3a_tunnel_option = tunnel_opt; 4086 } 4087 if (v6) { 4088 sal_memcpy(route_info.l3a_ip6_net, ip6_addr, BCM_IP6_ADDRLEN); 4089 bcm_ip6_mask_create(route_info.l3a_ip6_mask, plen); 4090 route_info.l3a_flags |= BCM_L3_IP6; 4091 } else 4092 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 4093 { 4094 route_info.l3a_subnet = ip_addr; 4095 route_info.l3a_ip_mask = ip_mask; 4096 } 4097 4098 route_info.l3a_intf = interface; 4099 route_info.l3a_vid = vlan; 4100 sal_memcpy(route_info.l3a_nexthop_mac, mac, sizeof(bcm_mac_t)); 4101 4102 if (BCM_GPORT_IS_SET(port)) { 4103 route_info.l3a_port_tgid = port; 4104 } else { 4105 if (trunk >= 0) { 4106 route_info.l3a_flags |= BCM_L3_TGID; 4107 route_info.l3a_port_tgid = trunk; 4108 } else { 4109 route_info.l3a_port_tgid = port; 4110 } 4111 route_info.l3a_modid = module; 4112 } 4113 4114 if (untag) { 4115 route_info.l3a_flags |= BCM_L3_UNTAG; 4116 } 4117 4118 if (hits) { 4119 route_info.l3a_flags |= BCM_L3_HIT; 4120 } 4121 4122 #ifdef BCM_XGS_SWITCH_SUPPORT 4123 if (ecmp) { 4124 route_info.l3a_flags |= BCM_L3_MULTIPATH; 4125 } 4126 4127 if (local_route) { 4128 route_info.l3a_flags |= BCM_L3_DEFIP_LOCAL; 4129 } 4130 #endif 4131 rv = bcm_l3_route_add(unit, &route_info); 4132 if (BCM_FAILURE(rv)) { 4133 cli_out("%s: Error adding route table: %s\n", 4134 ARG_CMD(a), bcm_errmsg(rv)); 4135 return (CMD_FAIL); 4136 } 4137 return (CMD_OK); 4138 } 4139 4140 /* 4141 * Function: 4142 * _l3_cmd_host_add 4143 * Description: 4144 * Service routine used to add host entry. 4145 * Parameters: 4146 * unit - (IN) Device number. 4147 * a - (IN) Command arguments. 4148 * v6 - (IN) IPv6 route indication. 4149 * Returns: 4150 * CMD_XXX 4151 */ 4152 STATIC cmd_result_t 4153 _l3_cmd_host_add(int unit, args_t *a, int v6) 4154 { 4155 bcm_l3_host_t host_info; 4156 cmd_result_t retCode; 4157 bcm_mac_t mac; 4158 parse_table_t pt; 4159 int rv; 4160 int host_as_route = 0; 4161 int interface = 0; 4162 bcm_ip_t ip_addr = 0; 4163 int module = 0; 4164 int trunk = -1; 4165 int untag = 0; 4166 int port = 0; 4167 int hits = 0; 4168 int replace = 0; 4169 #ifdef BCM_XGS_SWITCH_SUPPORT 4170 int l2tocpu = 0; 4171 #endif /* BCM_XGS_SWITCH_SUPPORT */ 4172 #if defined(BCM_XGS3_SWITCH_SUPPORT) 4173 int rpe = 0; 4174 int pri = 0; 4175 int vrf = 0; 4176 int lookup_class = 0; 4177 bcm_ip6_t ip6_addr; 4178 #endif 4179 4180 bcm_l3_host_t_init(&host_info); 4181 sal_memset(mac, 0, sizeof(bcm_mac_t)); 4182 parse_table_init(unit, &pt); 4183 4184 parse_table_add(&pt, "Mac", PQ_DFL | PQ_MAC, 0, (void *)mac, 0); 4185 #if defined(BCM_XGS3_SWITCH_SUPPORT) 4186 parse_table_add(&pt, "VRF", PQ_DFL | PQ_INT, 0, (void *)&vrf, 0); 4187 parse_table_add(&pt, "PRI", PQ_DFL|PQ_INT, 0, (void *)&pri, 0); 4188 parse_table_add(&pt, "RPE", PQ_DFL|PQ_BOOL, 0, (void *)&rpe, 0); 4189 parse_table_add(&pt, "Group", PQ_DFL|PQ_INT, 0, (void *)&lookup_class, 0); 4190 if (v6) { 4191 parse_table_add(&pt, "IP", PQ_DFL | PQ_IP6, 0, (void *)&ip6_addr, 0); 4192 } else 4193 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 4194 { 4195 parse_table_add(&pt, "IP", PQ_DFL | PQ_IP, 0, (void *)&ip_addr, 0); 4196 } 4197 parse_table_add(&pt, "Replace", PQ_DFL | PQ_BOOL, 0, (void *)&replace, 0); 4198 parse_table_add(&pt, "Port", PQ_DFL | PQ_PORT, 0, (void *)&port, 0); 4199 parse_table_add(&pt, "INtf", PQ_DFL | PQ_INT, 0, (void *)&interface, 0); 4200 parse_table_add(&pt, "Hit", PQ_DFL | PQ_BOOL, 0, (void *)&hits, 0); 4201 parse_table_add(&pt, "MOdule", PQ_DFL | PQ_INT, 0, (void *)&module, 0); 4202 parse_table_add(&pt, "Trunk", PQ_DFL | PQ_INT, 0, (void *)&trunk, 0); 4203 parse_table_add(&pt, "Untag", PQ_DFL | PQ_BOOL, 0, (void *)&untag, 0); 4204 parse_table_add(&pt, "HOST_AS_ROUTE", PQ_DFL | PQ_BOOL, 0, 4205 (void *)&host_as_route, 0); 4206 #ifdef BCM_XGS_SWITCH_SUPPORT 4207 parse_table_add(&pt, "L2tocpu", PQ_DFL | PQ_BOOL, 0, (void *)&l2tocpu, 0); 4208 #endif 4209 if (!parseEndOk(a, &pt, &retCode)) 4210 return retCode; 4211 4212 #if defined(BCM_XGS3_SWITCH_SUPPORT) 4213 host_info.l3a_vrf = vrf; 4214 host_info.l3a_pri = pri; 4215 host_info.l3a_lookup_class = lookup_class; 4216 4217 if (rpe) { 4218 host_info.l3a_flags |= BCM_L3_RPE; 4219 } 4220 4221 if (v6) { 4222 sal_memcpy(host_info.l3a_ip6_addr, ip6_addr, BCM_IP6_ADDRLEN); 4223 host_info.l3a_flags |= BCM_L3_IP6; 4224 } else 4225 #endif 4226 { 4227 host_info.l3a_ip_addr = ip_addr; 4228 } 4229 4230 if (host_as_route) { 4231 host_info.l3a_flags |= BCM_L3_HOST_AS_ROUTE; 4232 } 4233 host_info.l3a_intf = interface; 4234 sal_memcpy(host_info.l3a_nexthop_mac, mac, sizeof(mac)); 4235 4236 if (BCM_GPORT_IS_SET(port)) { 4237 host_info.l3a_port_tgid = port; 4238 } else { 4239 host_info.l3a_modid = module; 4240 if (trunk >= 0) { 4241 host_info.l3a_flags |= BCM_L3_TGID; 4242 host_info.l3a_port_tgid = trunk; 4243 } else { 4244 host_info.l3a_port_tgid = port; 4245 } 4246 } 4247 4248 if (hits) { 4249 host_info.l3a_flags |= BCM_L3_HIT; 4250 } 4251 if (untag) { 4252 host_info.l3a_flags |= BCM_L3_UNTAG; 4253 } 4254 4255 if (replace) { 4256 host_info.l3a_flags |= BCM_L3_REPLACE; 4257 } 4258 4259 #ifdef BCM_XGS_SWITCH_SUPPORT 4260 if (l2tocpu) { 4261 host_info.l3a_flags |= BCM_L3_L2TOCPU; 4262 } 4263 #endif 4264 rv = bcm_l3_host_add(unit, &host_info); 4265 if (BCM_FAILURE(rv)) { 4266 cli_out("%s: Error creating entry in L3 host table: %s\n", 4267 ARG_CMD(a), bcm_errmsg(rv)); 4268 return (CMD_FAIL); 4269 } 4270 return (CMD_OK); 4271 } 4272 4273 /* Struct to track performance data of a collection of API 4274 calls (or table operations). Recommended units: micro seconds(us) */ 4275 typedef struct _l3_route_perf_data_s { 4276 int count; /* Number of times the functions is called. */ 4277 int max; /* Maximum call time. */ 4278 int min; /* Minimum call time. */ 4279 int total; /* Total duration time. */ 4280 } _l3_route_perf_data_t; 4281 4282 /* Initalizes a _l3_route_perf_data_t structure */ 4283 void 4284 _l3_route_perf_data_init(_l3_route_perf_data_t *perf) 4285 { 4286 perf->count = 0; 4287 perf->min = 0; 4288 perf->max = 0; 4289 perf->total = 0; 4290 } 4291 4292 /* Adds a time measurement to a perf_data_t instance. */ 4293 void 4294 _l3_route_perf_data_add(_l3_route_perf_data_t *perf, int duration) 4295 { 4296 if (perf->count == 0) { 4297 perf->count = 1; 4298 perf->min = duration; 4299 perf->max = duration; 4300 perf->total = duration; 4301 } else { 4302 perf->count++; 4303 if (duration > perf->max) { 4304 perf->max = duration; 4305 } 4306 if (duration < perf->min) { 4307 perf->min = duration; 4308 } 4309 perf->total += duration; 4310 } 4311 } 4312 4313 /* Dumps perf stats */ 4314 void 4315 _l3_route_perf_data_print(_l3_route_perf_data_t *perf, int route_cnt, const char *label) 4316 { 4317 if( perf->count > 0) { 4318 /*int u_avg = perf->total / perf->count;*/ 4319 uint32 temp; 4320 4321 /*cli_out("Performance Dump: %s :\n", label); 4322 cli_out(" Min: %d uSec\n", perf->min); 4323 cli_out(" Max: %d uSec\n", perf->max); 4324 cli_out(" Avg: %d uSec\n", u_avg); 4325 cli_out(" Total: %d.%3d Sec\n", (perf->total / 1000000), (perf->total%1000000/1000)); 4326 cli_out(" Count: %d\n", perf->count);*/ 4327 4328 temp = route_cnt * perf->count; 4329 if (temp > 4294) { 4330 uint32 temp2 = 0; 4331 uint32 rem = 0, divn; 4332 while ((int)temp > 0) { 4333 divn = (temp > 2147) ? 2147 : temp; 4334 divn = divn * 1000000; 4335 temp2 += (divn + rem) / perf->total; 4336 rem = (divn + rem) % perf->total; 4337 temp -= 2147; 4338 } 4339 temp = temp2; 4340 } else { 4341 temp = temp * 1000000 / perf->total; 4342 } 4343 cli_out(" %7d ", temp); 4344 } else { 4345 cli_out(" - "); 4346 } 4347 } 4348 4349 /* 4350 * Performance test to add IPv4 routes 4351 * Same as arch_ipv4_route_add_001 but also measure route update times 4352 * and runs the while test 10 times to get 10 different data points. 4353 */ 4354 int _l3_route_perf_egr_mode[SOC_MAX_NUM_DEVICES]; 4355 int _l3_route_perf_obj_id[SOC_MAX_NUM_DEVICES]; 4356 int _l3_route_perf_obj2_id[SOC_MAX_NUM_DEVICES]; 4357 int _l3_route_perf_vrf = 100; 4358 4359 4360 STATIC void 4361 _l3_route_perf_test_setup(int unit) 4362 { 4363 /* Setup */ 4364 int rv; 4365 4366 bcm_l3_intf_t l3_intf; 4367 4368 bcm_l3_egress_t egress_object; 4369 bcm_l3_egress_t egress_object2; 4370 bcm_mac_t mac; 4371 4372 /* Turn off back ground threads */ 4373 sh_process_command(unit, "l2mode"); 4374 sh_process_command(unit, "l2mode off"); 4375 sh_process_command(unit, "linkscan"); 4376 sh_process_command(unit, "linkscan off"); 4377 sh_process_command(unit, "counter"); 4378 sh_process_command(unit, "counter off"); 4379 sh_process_command(unit, "memscan"); 4380 sh_process_command(unit, "memscan off"); 4381 sh_process_command(unit, "sramscan"); 4382 sh_process_command(unit, "sramscan off"); 4383 4384 /* L3 Egress Mode */ 4385 rv = bcm_switch_control_get(unit, bcmSwitchL3EgressMode, 4386 &_l3_route_perf_egr_mode[unit]); 4387 if (BCM_FAILURE(rv)) { 4388 cli_out("Perf: Get L3 Egress Mode failed: %s\n", bcm_errmsg(rv)); 4389 return; 4390 } 4391 rv = bcm_switch_control_set(unit, bcmSwitchL3EgressMode, 1); 4392 if (BCM_FAILURE(rv)) { 4393 cli_out("Perf: Set L3 Egress Mode failed: %s\n", bcm_errmsg(rv)); 4394 return; 4395 } 4396 4397 /* L3 Interface */ 4398 bcm_l3_intf_t_init(&l3_intf); 4399 l3_intf.l3a_flags = BCM_L3_WITH_ID; 4400 l3_intf.l3a_intf_id = 1; 4401 l3_intf.l3a_mac_addr[5] = 0x1; 4402 l3_intf.l3a_vid = 1; 4403 l3_intf.l3a_vrf = _l3_route_perf_vrf; 4404 rv = bcm_l3_intf_create(unit, &l3_intf); 4405 if (BCM_FAILURE(rv)) { 4406 cli_out("Perf: Create L3 intf failed: %s\n", bcm_errmsg(rv)); 4407 return; 4408 } 4409 4410 /* L3 Egress */ 4411 bcm_l3_egress_t_init(&egress_object); 4412 sal_memset(mac, 0, sizeof(bcm_mac_t)); 4413 mac[5] = 0x1; 4414 egress_object.intf = 1; 4415 egress_object.module = 0; 4416 egress_object.port = 1; 4417 sal_memcpy(egress_object.mac_addr, mac, sizeof(mac)); 4418 4419 rv = bcm_l3_egress_create(unit, 0, &egress_object, 4420 &_l3_route_perf_obj_id[unit]); 4421 if (BCM_FAILURE(rv)) { 4422 cli_out("Perf: Error creating egress object entry: %s\n", 4423 bcm_errmsg(rv)); 4424 return ; 4425 } 4426 4427 bcm_l3_egress_t_init(&egress_object2); 4428 sal_memset(mac, 0, sizeof(bcm_mac_t)); 4429 mac[5] = 0x2; 4430 egress_object2.intf = 1; 4431 egress_object2.module = 0; 4432 egress_object2.port = 1; 4433 sal_memcpy(egress_object2.mac_addr, mac, sizeof(mac)); 4434 4435 rv = bcm_l3_egress_create(unit, 0, &egress_object2, 4436 &_l3_route_perf_obj2_id[unit]); 4437 if (BCM_FAILURE(rv)) { 4438 cli_out("Perf: Error creating egress object2 entry: %s\n", 4439 bcm_errmsg(rv)); 4440 return ; 4441 } 4442 4443 return ; 4444 } 4445 4446 STATIC void 4447 _l3_route_perf_test_clean(int unit) 4448 { 4449 int rv; 4450 bcm_l3_intf_t intf; 4451 4452 rv = bcm_l3_egress_destroy(unit, _l3_route_perf_obj2_id[unit]); 4453 if (BCM_FAILURE(rv) && rv != BCM_E_BUSY) { 4454 cli_out("Perf: Error deleting egress object2 entry: %s\n", 4455 bcm_errmsg(rv)); 4456 return ; 4457 } 4458 4459 rv = bcm_l3_egress_destroy(unit, _l3_route_perf_obj_id[unit]); 4460 if (BCM_FAILURE(rv) && rv != BCM_E_BUSY) { 4461 cli_out("Perf: Error deleting egress object entry: %s\n", 4462 bcm_errmsg(rv)); 4463 return ; 4464 } 4465 4466 bcm_l3_intf_t_init(&intf); 4467 intf.l3a_intf_id = 1; 4468 4469 if ((rv = bcm_l3_intf_delete(unit, &intf)) < 0) { 4470 cli_out("Perf: Error (%s) destroy interface (%d)\n", 4471 bcm_errmsg(rv), 1); 4472 return ; 4473 } 4474 4475 rv = bcm_switch_control_set(unit, bcmSwitchL3EgressMode, 4476 _l3_route_perf_egr_mode[unit]); 4477 if (BCM_FAILURE(rv)) { 4478 cli_out("Perf: Set L3 Egress Mode failed: %s\n", bcm_errmsg(rv)); 4479 return; 4480 } 4481 4482 /* Turn on back ground threads */ 4483 sh_process_command(unit, "l2mode on"); 4484 sh_process_command(unit, "linkscan on"); 4485 sh_process_command(unit, "counter on"); 4486 sh_process_command(unit, "memscan on"); 4487 sh_process_command(unit, "sramscan on"); 4488 4489 return ; 4490 4491 } 4492 4493 #define _L3_ROUTE_PERF_OP_ADD 1 4494 #define _L3_ROUTE_PERF_OP_UPD 2 4495 #define _L3_ROUTE_PERF_OP_GET 3 4496 #define _L3_ROUTE_PERF_OP_DEL 4 4497 4498 char *_l3_route_perf_op_str[] = { 4499 "Invalid", 4500 "Insert", 4501 "Update", 4502 "Lookup", 4503 "Delete" 4504 }; 4505 4506 STATIC int 4507 _l3_route_perf_v4_op_test(int unit, int op, int use_api, int set_idx, 4508 _l3_route_perf_data_t *route_perf, int *route_cnt, int vrf) 4509 { 4510 int rv = 0; 4511 int inx, idx; 4512 int start, end, duration = 0; 4513 bcm_l3_route_t base_route; 4514 _bcm_defip_cfg_t base_defip; 4515 4516 int (*op_func[5])(int, bcm_l3_route_t *) = { 4517 NULL, 4518 bcm_l3_route_add, 4519 bcm_l3_route_add, 4520 bcm_l3_route_get, 4521 bcm_l3_route_delete 4522 }; 4523 4524 #if defined(BCM_TOMAHAWK_SUPPORT) && defined(ALPM_ENABLE) 4525 int (*op_func_defip[5])(int, _bcm_defip_cfg_t *) = { 4526 NULL, 4527 bcm_esw_alpm_insert, 4528 bcm_esw_alpm_update, 4529 bcm_esw_alpm_lookup, 4530 bcm_esw_alpm_delete 4531 }; 4532 #endif 4533 /* 4K Entries */ 4534 uint32 ip, start_ip = 0x01010101; 4535 uint32 ip_mask = 0xffffffff; 4536 int loop = 4 * 1024; 4537 4538 /* 1K Entries */ 4539 int loop_ip = 1 * 1024; 4540 int j; 4541 uint32 prfx[4] = {22, 23, 24, 20}; 4542 uint32 mask[4] = {0xfffffc00, 0xfffffe00, 0xffffff00, 0xfffff000}; 4543 uint32 ipv4[4] = {0x02020202, 0x29020202, 0x61020202, 0x8C010101}; 4544 uint32 ipAddr; 4545 uint32 ipMask; 4546 uint32 base_ip; 4547 4548 *route_cnt = 0; 4549 4550 bcm_l3_route_t_init(&base_route); 4551 sal_memset(&base_defip, 0, sizeof(base_defip)); 4552 4553 /* Insert entry */ 4554 /*cli_out("%s 4K IPv4 routes with mask - 0x%08x\n", 4555 _l3_route_perf_op_str[op], ip_mask);*/ 4556 start = sal_time_usecs(); 4557 ip = start_ip + set_idx * loop; 4558 4559 for (inx = 0; inx < loop; inx++) { 4560 if (use_api) { 4561 base_route.l3a_vrf = vrf; 4562 base_route.l3a_subnet = ip; 4563 base_route.l3a_ip_mask = ip_mask; 4564 base_route.l3a_intf = _l3_route_perf_obj_id[unit]; 4565 if (op == _L3_ROUTE_PERF_OP_UPD) { 4566 base_route.l3a_flags = BCM_L3_REPLACE; 4567 base_route.l3a_intf = _l3_route_perf_obj2_id[unit]; 4568 } 4569 4570 rv = op_func[op](unit, &base_route); 4571 } else { 4572 #if defined(BCM_TOMAHAWK_SUPPORT) && defined(ALPM_ENABLE) 4573 sal_memset(&base_defip, 0, sizeof(base_defip)); 4574 base_defip.defip_vrf = vrf; 4575 base_defip.defip_ip_addr = ip; 4576 base_defip.defip_sub_len = bcm_ip_mask_length(ip_mask); 4577 base_defip.defip_intf = _l3_route_perf_obj_id[unit]; 4578 if (op == _L3_ROUTE_PERF_OP_UPD) { 4579 base_defip.defip_flags = BCM_L3_REPLACE; 4580 base_defip.defip_intf = _l3_route_perf_obj2_id[unit]; 4581 } 4582 4583 rv = op_func_defip[op](unit, &base_defip); 4584 #endif 4585 } 4586 if (rv < 0) { 4587 end = sal_time_usecs(); 4588 duration = end - start; 4589 /*cli_out("%s %dth route returned msg: %s\n", 4590 _l3_route_perf_op_str[op], inx, 4591 bcm_errmsg(rv));*/ 4592 goto End4; 4593 } else { 4594 *route_cnt += 1; 4595 } 4596 4597 ip++; 4598 } 4599 end = sal_time_usecs(); 4600 duration = end - start; 4601 4602 bcm_l3_route_t_init(&base_route); 4603 sal_memset(&base_defip, 0, sizeof(base_defip)); 4604 4605 for (j = 0; j < 4; j++) { 4606 /*cli_out("%s 1K IPv4 routes with mask - 0x%08x\n", 4607 _l3_route_perf_op_str[op], mask[j]);*/ 4608 start = sal_time_usecs(); 4609 for (idx = 0; idx < loop_ip; idx++) { 4610 base_ip = ((loop_ip + idx + loop_ip * set_idx) << (32 - prfx[j])); 4611 ipAddr = base_ip + ipv4[j]; 4612 ipMask = mask[j]; 4613 4614 if (use_api) { 4615 base_route.l3a_vrf = vrf; 4616 base_route.l3a_subnet = ipAddr; 4617 base_route.l3a_ip_mask = ipMask; 4618 base_route.l3a_intf = _l3_route_perf_obj_id[unit]; 4619 if (op == _L3_ROUTE_PERF_OP_UPD) { 4620 base_route.l3a_flags = BCM_L3_REPLACE; 4621 base_route.l3a_intf = _l3_route_perf_obj2_id[unit]; 4622 } 4623 4624 rv = op_func[op](unit, &base_route); 4625 } else { 4626 #if defined(BCM_TOMAHAWK_SUPPORT) && defined(ALPM_ENABLE) 4627 sal_memset(&base_defip, 0, sizeof(base_defip)); 4628 base_defip.defip_vrf = vrf; 4629 base_defip.defip_ip_addr = ipAddr; 4630 base_defip.defip_sub_len = bcm_ip_mask_length(ipMask); 4631 base_defip.defip_intf = _l3_route_perf_obj_id[unit]; 4632 if (op == _L3_ROUTE_PERF_OP_UPD) { 4633 base_defip.defip_flags = BCM_L3_REPLACE; 4634 base_defip.defip_intf = _l3_route_perf_obj2_id[unit]; 4635 } 4636 4637 rv = op_func_defip[op](unit, &base_defip); 4638 #endif 4639 } 4640 if (rv < 0) { 4641 end = sal_time_usecs(); 4642 duration += end - start; 4643 /*cli_out("%s %dth route returned msg: %s\n", 4644 _l3_route_perf_op_str[op], idx, 4645 bcm_errmsg(rv));*/ 4646 goto End4; 4647 /*return;*/ 4648 } else { 4649 *route_cnt += 1; 4650 } 4651 } 4652 end = sal_time_usecs(); 4653 duration += end - start; 4654 } 4655 4656 End4: 4657 _l3_route_perf_data_add(route_perf, duration); 4658 return rv; 4659 } 4660 4661 STATIC void 4662 _l3_route_perf_v4_test(int unit, int loops, int nsets, int use_api, 4663 int op_bitmap, int vrf, uint8 alpm_mode) 4664 { 4665 int run, i; 4666 int route_added = 0, set_size = 0, route_cnt = 0, tot_route = 0; 4667 bcm_l3_route_t base_route; 4668 _bcm_defip_cfg_t base_defip; 4669 void *pb = NULL; 4670 4671 _l3_route_perf_data_t *route_add_perf = NULL; 4672 _l3_route_perf_data_t *route_get_perf = NULL; 4673 _l3_route_perf_data_t *route_del_perf = NULL; 4674 _l3_route_perf_data_t *route_upd_perf = NULL; 4675 4676 route_add_perf = sal_alloc(sizeof(_l3_route_perf_data_t) * nsets, "add_perf"); 4677 route_get_perf = sal_alloc(sizeof(_l3_route_perf_data_t) * nsets, "get_perf"); 4678 route_del_perf = sal_alloc(sizeof(_l3_route_perf_data_t) * nsets, "del_perf"); 4679 route_upd_perf = sal_alloc(sizeof(_l3_route_perf_data_t) * nsets, "upd_perf"); 4680 4681 for (i = 0; i < nsets; i++) { 4682 _l3_route_perf_data_init(&route_add_perf[i]); 4683 _l3_route_perf_data_init(&route_get_perf[i]); 4684 _l3_route_perf_data_init(&route_del_perf[i]); 4685 _l3_route_perf_data_init(&route_upd_perf[i]); 4686 } 4687 4688 for (run = 0; run < loops; run ++) { 4689 int rv = 0; 4690 4691 route_added = 0; 4692 4693 /* Default route */ 4694 if (use_api) { 4695 bcm_l3_route_t_init(&base_route); 4696 base_route.l3a_intf = _l3_route_perf_obj_id[unit]; 4697 base_route.l3a_vrf = vrf; 4698 base_route.l3a_subnet = 0; 4699 base_route.l3a_ip_mask = 0; 4700 rv = bcm_l3_route_add(unit, &base_route); 4701 } else { 4702 sal_memset(&base_defip, 0, sizeof(base_defip)); 4703 #if defined(BCM_TOMAHAWK_SUPPORT) && defined(ALPM_ENABLE) 4704 base_defip.defip_intf = _l3_route_perf_obj_id[unit]; 4705 base_defip.defip_vrf = vrf; 4706 rv = bcm_esw_alpm_insert(unit, &base_defip); 4707 #endif 4708 } 4709 4710 if (BCM_FAILURE(rv)) { 4711 cli_out("Unable to add IPv4 default route (return %d)\n", rv); 4712 goto done; 4713 } 4714 4715 for (i = 0; i < nsets; i++) { 4716 rv = _l3_route_perf_v4_op_test(unit, _L3_ROUTE_PERF_OP_ADD, use_api, i, 4717 &route_add_perf[i], &route_cnt, vrf); 4718 route_added += route_cnt; 4719 if (BCM_FAILURE(rv)) { 4720 nsets = i + 1; 4721 if (i == 0) { 4722 set_size = route_cnt; 4723 } 4724 break; 4725 } else { 4726 set_size = route_cnt; 4727 } 4728 } 4729 4730 if (op_bitmap & (1 << (_L3_ROUTE_PERF_OP_UPD - 1))) { 4731 for (i = 0; i < nsets; i++) { 4732 rv = _l3_route_perf_v4_op_test(unit, _L3_ROUTE_PERF_OP_UPD, use_api, i, 4733 &route_upd_perf[i], &route_cnt, vrf); 4734 if (BCM_FAILURE(rv)) { 4735 break; 4736 } 4737 } 4738 } 4739 4740 if (op_bitmap & (1 << (_L3_ROUTE_PERF_OP_GET - 1))) { 4741 for (i = 0; i < nsets; i++) { 4742 rv = _l3_route_perf_v4_op_test(unit, _L3_ROUTE_PERF_OP_GET, use_api, i, 4743 &route_get_perf[i], &route_cnt, vrf); 4744 if (BCM_FAILURE(rv)) { 4745 break; 4746 } 4747 } 4748 } 4749 4750 if (op_bitmap & (1 << (_L3_ROUTE_PERF_OP_DEL - 1))) { 4751 for (i = 0; i < nsets; i++) { 4752 rv = _l3_route_perf_v4_op_test(unit, _L3_ROUTE_PERF_OP_DEL, use_api, i, 4753 &route_del_perf[i], &route_cnt, vrf); 4754 if (BCM_FAILURE(rv)) { 4755 break; 4756 } 4757 } 4758 4759 /* Cleanup */ 4760 /* Delete the default route */ 4761 if (use_api) { 4762 rv = bcm_l3_route_delete(unit, &base_route); 4763 } else { 4764 #if defined(BCM_TOMAHAWK_SUPPORT) && defined(ALPM_ENABLE) 4765 rv = bcm_esw_alpm_delete(unit, &base_defip); 4766 #endif 4767 } 4768 4769 if (BCM_FAILURE(rv)) { 4770 cli_out("Failed to delete IPv4 default route (return %d)\n", rv); 4771 goto done; 4772 } 4773 4774 /* For test purpose, flush heap memory by allocate 16MB and free, 4775 in order to trigger garbage defragmentation before next run */ 4776 pb = NULL; 4777 pb = sal_alloc(1024*1024*16, "alpm_mem_flush"); 4778 if (pb) { 4779 sal_free(pb); 4780 } 4781 } 4782 } 4783 4784 cli_out("IPv4 (%s) performance test: Added routes = %d\n", 4785 (alpm_mode == 2 ? "Combined" : (vrf < 0 ? "Global" : "Private")), 4786 route_added); 4787 cli_out(" Set RouteCnt TotRoute RPS:Add Update Lookup Delete \n"); 4788 4789 tot_route = 0; 4790 for (i = 0; i < nsets; i++) { 4791 if ((tot_route + set_size) > route_added) { 4792 route_cnt = route_added - tot_route; 4793 } else { 4794 route_cnt = set_size; 4795 } 4796 tot_route += route_cnt; 4797 4798 cli_out("%3d %7d %7d ", i, route_cnt, tot_route); 4799 4800 _l3_route_perf_data_print(&route_add_perf[i], route_cnt, ""); 4801 _l3_route_perf_data_print(&route_upd_perf[i], route_cnt, ""); 4802 _l3_route_perf_data_print(&route_get_perf[i], route_cnt, ""); 4803 _l3_route_perf_data_print(&route_del_perf[i], route_cnt, ""); 4804 cli_out("\n"); 4805 } 4806 cli_out("\n"); 4807 4808 done: 4809 sal_free(route_add_perf); 4810 sal_free(route_upd_perf); 4811 sal_free(route_get_perf); 4812 sal_free(route_del_perf); 4813 } 4814 4815 STATIC int 4816 _l3_route_perf_v6_op_test(int unit, int op, int use_api, int set_idx, 4817 _l3_route_perf_data_t *route_perf, int *route_cnt, int vrf) 4818 { 4819 int i, rv = 0; 4820 int start, end, duration = 0; 4821 bcm_l3_route_t base_route; 4822 _bcm_defip_cfg_t base_defip; 4823 4824 int (*op_func[5])(int, bcm_l3_route_t *) = { 4825 NULL, 4826 bcm_l3_route_add, 4827 bcm_l3_route_add, 4828 bcm_l3_route_get, 4829 bcm_l3_route_delete 4830 }; 4831 4832 #if defined(BCM_TOMAHAWK_SUPPORT) && defined(ALPM_ENABLE) 4833 int (*op_func_defip[5])(int, _bcm_defip_cfg_t *) = { 4834 NULL, 4835 bcm_esw_alpm_insert, 4836 bcm_esw_alpm_update, 4837 bcm_esw_alpm_lookup, 4838 bcm_esw_alpm_delete 4839 }; 4840 #endif 4841 4842 /* 1022 Entries */ 4843 int count = 1022; 4844 bcm_ip6_t v6_mask = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; 4845 bcm_ip6_t v6_ip = {0x70,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04}; 4846 int pfx_bit_loc = 32; 4847 int pfx = 0x110 + count * set_idx; 4848 4849 *route_cnt = 0; 4850 4851 bcm_l3_route_t_init(&base_route); 4852 sal_memset(&base_defip, 0, sizeof(base_defip)); 4853 4854 /* Insert entry */ 4855 increment_ip6addr(v6_ip, pfx_bit_loc/8 - 1, pfx); 4856 start = sal_time_usecs(); 4857 for (i = 0; i < count; i++) { 4858 increment_ip6addr(v6_ip, pfx_bit_loc/8 - 1, 1); 4859 4860 if (use_api) { 4861 base_route.l3a_vrf = vrf; 4862 sal_memcpy(base_route.l3a_ip6_net, v6_ip, sizeof(v6_ip)); 4863 sal_memcpy(base_route.l3a_ip6_mask, v6_mask, sizeof(v6_mask)); 4864 base_route.l3a_intf = _l3_route_perf_obj_id[unit]; 4865 if (op == _L3_ROUTE_PERF_OP_UPD) { 4866 base_route.l3a_flags = BCM_L3_REPLACE; 4867 base_route.l3a_intf = _l3_route_perf_obj2_id[unit]; 4868 } 4869 base_route.l3a_flags |= BCM_L3_IP6; 4870 4871 rv = op_func[op](unit, &base_route); 4872 } else { 4873 #if defined(BCM_TOMAHAWK_SUPPORT) && defined(ALPM_ENABLE) 4874 sal_memset(&base_defip, 0, sizeof(base_defip)); 4875 base_defip.defip_vrf = vrf; 4876 sal_memcpy(base_defip.defip_ip6_addr, v6_ip, sizeof(v6_ip)); 4877 base_defip.defip_sub_len = bcm_ip6_mask_length(v6_mask); 4878 base_defip.defip_intf = _l3_route_perf_obj_id[unit]; 4879 if (op == _L3_ROUTE_PERF_OP_UPD) { 4880 base_defip.defip_flags = BCM_L3_REPLACE; 4881 base_defip.defip_intf = _l3_route_perf_obj2_id[unit]; 4882 } 4883 base_defip.defip_flags |= BCM_L3_IP6; 4884 4885 rv = op_func_defip[op](unit, &base_defip); 4886 #endif 4887 } 4888 if (rv < 0) { 4889 end = sal_time_usecs(); 4890 duration = end - start; 4891 /*cli_out("%s %dth route returned msg: %s\n", 4892 _l3_route_perf_op_str[op], i, 4893 bcm_errmsg(rv));*/ 4894 goto End6; 4895 } else { 4896 *route_cnt += 1; 4897 } 4898 } 4899 end = sal_time_usecs(); 4900 duration = end - start; 4901 4902 End6: 4903 _l3_route_perf_data_add(route_perf, duration); 4904 return rv; 4905 } 4906 4907 STATIC void 4908 _l3_route_perf_v6_test(int unit, int loops, int nsets, int use_api, 4909 int op_bitmap, int vrf, uint8 alpm_mode) 4910 { 4911 int run, i; 4912 int route_added = 0, set_size = 0, route_cnt = 0, tot_route = 0; 4913 bcm_l3_route_t base_route; 4914 _bcm_defip_cfg_t base_defip; 4915 void *pb = NULL; 4916 4917 _l3_route_perf_data_t *route_add_perf = NULL; 4918 _l3_route_perf_data_t *route_get_perf = NULL; 4919 _l3_route_perf_data_t *route_del_perf = NULL; 4920 _l3_route_perf_data_t *route_upd_perf = NULL; 4921 4922 route_add_perf = sal_alloc(sizeof(_l3_route_perf_data_t) * nsets, "add_perf"); 4923 route_get_perf = sal_alloc(sizeof(_l3_route_perf_data_t) * nsets, "get_perf"); 4924 route_del_perf = sal_alloc(sizeof(_l3_route_perf_data_t) * nsets, "del_perf"); 4925 route_upd_perf = sal_alloc(sizeof(_l3_route_perf_data_t) * nsets, "upd_perf"); 4926 4927 for (i = 0; i < nsets; i++) { 4928 _l3_route_perf_data_init(&route_add_perf[i]); 4929 _l3_route_perf_data_init(&route_get_perf[i]); 4930 _l3_route_perf_data_init(&route_del_perf[i]); 4931 _l3_route_perf_data_init(&route_upd_perf[i]); 4932 } 4933 4934 for (run = 0; run < loops; run ++) { 4935 int rv = 0; 4936 4937 route_added = 0; 4938 4939 /* Default route */ 4940 if (use_api) { 4941 bcm_l3_route_t_init(&base_route); 4942 base_route.l3a_intf = _l3_route_perf_obj_id[unit]; 4943 base_route.l3a_vrf = vrf; 4944 base_route.l3a_flags = BCM_L3_IP6; 4945 rv = bcm_l3_route_add(unit, &base_route); 4946 } else { 4947 sal_memset(&base_defip, 0, sizeof(base_defip)); 4948 #if defined(BCM_TOMAHAWK_SUPPORT) && defined(ALPM_ENABLE) 4949 base_defip.defip_intf = _l3_route_perf_obj_id[unit]; 4950 base_defip.defip_vrf = vrf; 4951 base_defip.defip_flags = BCM_L3_IP6; 4952 rv = bcm_esw_alpm_insert(unit, &base_defip); 4953 #endif 4954 } 4955 4956 if (BCM_FAILURE(rv)) { 4957 cli_out("Unable to add IPv6 default route (return %d)\n", rv); 4958 goto done; 4959 } 4960 4961 for (i = 0; i < nsets; i++) { 4962 rv = _l3_route_perf_v6_op_test(unit, _L3_ROUTE_PERF_OP_ADD, use_api, i, 4963 &route_add_perf[i], &route_cnt, vrf); 4964 route_added += route_cnt; 4965 if (BCM_FAILURE(rv)) { 4966 nsets = i + 1; 4967 if (i == 0) { 4968 set_size = route_cnt; 4969 } 4970 break; 4971 } else { 4972 set_size = route_cnt; 4973 } 4974 } 4975 4976 if (op_bitmap & (1 << (_L3_ROUTE_PERF_OP_UPD - 1))) { 4977 for (i = 0; i < nsets; i++) { 4978 rv = _l3_route_perf_v6_op_test(unit, _L3_ROUTE_PERF_OP_UPD, use_api, i, 4979 &route_upd_perf[i], &route_cnt, vrf); 4980 if (BCM_FAILURE(rv)) { 4981 break; 4982 } 4983 } 4984 } 4985 4986 if (op_bitmap & (1 << (_L3_ROUTE_PERF_OP_GET - 1))) { 4987 for (i = 0; i < nsets; i++) { 4988 rv = _l3_route_perf_v6_op_test(unit, _L3_ROUTE_PERF_OP_GET, use_api, i, 4989 &route_get_perf[i], &route_cnt, vrf); 4990 if (BCM_FAILURE(rv)) { 4991 break; 4992 } 4993 } 4994 } 4995 4996 if (op_bitmap & (1 << (_L3_ROUTE_PERF_OP_DEL - 1))) { 4997 for (i = 0; i < nsets; i++) { 4998 rv = _l3_route_perf_v6_op_test(unit, _L3_ROUTE_PERF_OP_DEL, use_api, i, 4999 &route_del_perf[i], &route_cnt, vrf); 5000 if (BCM_FAILURE(rv)) { 5001 break; 5002 } 5003 } 5004 5005 /* Cleanup */ 5006 /* Delete the default route */ 5007 if (use_api) { 5008 rv = bcm_l3_route_delete(unit, &base_route); 5009 } else { 5010 #if defined(BCM_TOMAHAWK_SUPPORT) && defined(ALPM_ENABLE) 5011 rv = bcm_esw_alpm_delete(unit, &base_defip); 5012 #endif 5013 } 5014 5015 if (BCM_FAILURE(rv)) { 5016 cli_out("Failed to delete IPv6 default route (return %d)\n", rv); 5017 goto done; 5018 } 5019 5020 /* For test purpose, flush heap memory by allocate 16MB and free, 5021 in order to trigger garbage defragmentation before next run */ 5022 pb = NULL; 5023 pb = sal_alloc(1024*1024*16, "alpm_mem_flush"); 5024 if (pb) { 5025 sal_free(pb); 5026 } 5027 } 5028 } 5029 5030 cli_out("IPv6 (%s) performance test: Added routes = %d\n", 5031 (alpm_mode == 2 ? "Combined" : (vrf < 0 ? "Global" : "Private")), 5032 route_added); 5033 cli_out(" Set RouteCnt TotRoute RPS:Add Update Lookup Delete \n"); 5034 5035 tot_route = 0; 5036 for (i = 0; i < nsets; i++) { 5037 if ((tot_route + set_size) > route_added) { 5038 route_cnt = route_added - tot_route; 5039 } else { 5040 route_cnt = set_size; 5041 } 5042 tot_route += route_cnt; 5043 5044 cli_out("%3d %7d %7d ", i, route_cnt, tot_route); 5045 5046 _l3_route_perf_data_print(&route_add_perf[i], route_cnt, ""); 5047 _l3_route_perf_data_print(&route_upd_perf[i], route_cnt, ""); 5048 _l3_route_perf_data_print(&route_get_perf[i], route_cnt, ""); 5049 _l3_route_perf_data_print(&route_del_perf[i], route_cnt, ""); 5050 cli_out("\n"); 5051 } 5052 cli_out("\n"); 5053 5054 done: 5055 sal_free(route_add_perf); 5056 sal_free(route_upd_perf); 5057 sal_free(route_get_perf); 5058 sal_free(route_del_perf); 5059 5060 } 5061 5062 STATIC cmd_result_t 5063 _l3_cmd_route_perf_test(int unit, args_t *a) 5064 { 5065 int cons_st; 5066 int ip_type = 3; 5067 int loops = 3; 5068 int nonset, nsets = -1; 5069 int op_bitmap = 0xf; 5070 int use_api = 1; 5071 5072 cmd_result_t cmd_rv = CMD_OK; 5073 parse_table_t pt; 5074 uint8 alpm_mode = 0; 5075 5076 /* v4v6: 1 (IPv4 only), 2 (IPv6 only), 3 (IPv4 first then IPv6), 4 (IPv6 first then IPv4) 5077 OPs: bit0 (Add), bit1 (Update), bit2 (Lookup), bit3 (Delete) 5078 For capacity test: bit3 (Delete) must be disabled from OPs, e.g. 5079 l3 route test perf v4v6=3 Ops=7 5080 When not Delete, loops will be forced to 1. 5081 Global routes will be included automatically for Parallel or TCAM mixed modes. 5082 */ 5083 5084 parse_table_init(unit, &pt); 5085 parse_table_add(&pt, "v4v6", PQ_DFL | PQ_INT, (void *)3, 5086 (void *)&ip_type, 0); 5087 parse_table_add(&pt, "loops", PQ_DFL | PQ_INT, (void *)3, 5088 (void *)&loops, 0); 5089 parse_table_add(&pt, "nsets", PQ_DFL | PQ_INT, (void *)-1, 5090 (void *)&nsets, 0); 5091 parse_table_add(&pt, "UseApi", PQ_DFL | PQ_INT, (void *)1, 5092 (void *)&use_api, 0); 5093 parse_table_add(&pt, "OPs", PQ_DFL | PQ_INT, (void *)0xf, 5094 (void *)&op_bitmap, 0); 5095 5096 if (!parseEndOk(a, &pt, &cmd_rv)) { 5097 return cmd_rv; 5098 } 5099 /* OP_ADD is must */ 5100 if ((op_bitmap & (1 << (_L3_ROUTE_PERF_OP_ADD - 1))) == 0) { 5101 return CMD_USAGE; 5102 } 5103 5104 /* Force loops=1 if not OP_DEL */ 5105 if ((op_bitmap & (1 << (_L3_ROUTE_PERF_OP_DEL - 1))) == 0) { 5106 loops = 1; 5107 } 5108 5109 cons_st = bslcons_is_enabled(); 5110 if (cons_st) { 5111 bslcons_enable(0); 5112 } 5113 _l3_route_perf_test_setup(unit); 5114 bslcons_enable(cons_st); 5115 5116 #ifdef ALPM_ENABLE 5117 if (soc_feature(unit, soc_feature_alpm)) { 5118 alpm_mode = soc_property_get(unit, spn_L3_ALPM_ENABLE, 0); 5119 } 5120 #endif 5121 cli_out("Test runs: %d\n", loops); 5122 cli_out("ALPM mode: %s\n", 5123 alpm_mode == 1 ? "Parallel" : 5124 alpm_mode == 2 ? "Combined" : 5125 alpm_mode == 3 ? "ALPM/TCAM Mixed" : "Disabled"); 5126 5127 nonset = (nsets == -1); 5128 5129 if ((ip_type == 1) || (ip_type == 3)) { /* IPv4 first */ 5130 if (nonset) { 5131 nsets = 130; 5132 } 5133 /* Private VRF 100 */ 5134 _l3_route_perf_v4_test(unit, loops, nsets, use_api, op_bitmap, 5135 _l3_route_perf_vrf, alpm_mode); 5136 5137 /* Global low route test for Paralle & ALPM/TCAM mixed modes */ 5138 if ((alpm_mode == 1) || (alpm_mode == 3)) { 5139 _l3_route_perf_v4_test(unit, loops, nsets, use_api, op_bitmap, 5140 BCM_L3_VRF_GLOBAL, alpm_mode); 5141 } 5142 } 5143 5144 if (ip_type != 1) { /* IPv6 */ 5145 if (nonset) { 5146 nsets = 300; 5147 } 5148 /* Private VRF 100 */ 5149 _l3_route_perf_v6_test(unit, loops, nsets, use_api, op_bitmap, 5150 _l3_route_perf_vrf, alpm_mode); 5151 5152 /* Global low route test for Paralle & ALPM/TCAM mixed modes */ 5153 if ((alpm_mode == 1) || (alpm_mode == 3)) { 5154 _l3_route_perf_v6_test(unit, loops, nsets, use_api, op_bitmap, 5155 BCM_L3_VRF_GLOBAL, alpm_mode); 5156 } 5157 } 5158 5159 if (ip_type == 4) { /* then IPv4 */ 5160 if (nonset) { 5161 nsets = 130; 5162 } 5163 /* Private VRF 100 */ 5164 _l3_route_perf_v4_test(unit, loops, nsets, use_api, op_bitmap, 5165 _l3_route_perf_vrf, alpm_mode); 5166 5167 /* Global low route test for Paralle & ALPM/TCAM mixed modes */ 5168 if ((alpm_mode == 1) || (alpm_mode == 3)) { 5169 _l3_route_perf_v4_test(unit, loops, nsets, use_api, op_bitmap, 5170 BCM_L3_VRF_GLOBAL, alpm_mode); 5171 } 5172 } 5173 5174 cons_st = bslcons_is_enabled(); 5175 if (cons_st) { 5176 bslcons_enable(0); 5177 } 5178 _l3_route_perf_test_clean(unit); 5179 bslcons_enable(cons_st); 5180 5181 return CMD_OK; 5182 } 5183 5184 #ifdef ALPM_ENABLE 5185 /* Usage: 5186 * l3 alpm show [all] [VRF=<val>] [global-vrf=<bool>] 5187 * [Pivot=<bool>] [Bucket=<bool> [Counter=<bool] 5188 * [BucketuSage=<bool>] [InternalDebug=<bool> 5189 * l3 alpm show brief [<Bucket>=<val>] [<Index>=<val>] 5190 * - Show ALPM brief debug info 5191 */ 5192 5193 STATIC cmd_result_t 5194 _l3_cmd_alpm_debug_show(int unit, args_t *a) 5195 { 5196 int rv = CMD_OK; 5197 cmd_result_t cmd_rv; 5198 uint32 flags = 0; 5199 char *c = NULL; 5200 5201 int vrf = -1; 5202 int global_vrf = 0; 5203 int pivot = 0; 5204 int bucket = 0; 5205 int counter = 0; 5206 int bkt_usage = 0; 5207 int internal_debug = 0; 5208 int index = -1; 5209 5210 parse_table_t pt; 5211 5212 c = ARG_CUR(a); 5213 5214 if (c != NULL && sal_strcasecmp(c, "brief") == 0) { 5215 ARG_NEXT(a); 5216 5217 bucket = -1; 5218 index = -1; 5219 5220 if (ARG_CNT(a)) { 5221 parse_table_init(unit, &pt); 5222 parse_table_add(&pt, "Bucket", PQ_DFL | PQ_INT, (void *)-1, 5223 (void *)&bucket, 0); 5224 parse_table_add(&pt, "Index", PQ_DFL | PQ_INT, (void *)-1, 5225 (void *)&index, 0); 5226 if (!parseEndOk(a, &pt, &cmd_rv)) { 5227 return cmd_rv; 5228 } 5229 } 5230 5231 #if defined(BCM_TOMAHAWK_SUPPORT) 5232 if (soc_feature(unit, soc_feature_alpm2)) { 5233 rv = bcm_esw_alpm_debug_brief_show(unit, bucket, index); 5234 } else 5235 #endif 5236 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_APACHE_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 5237 if (SOC_IS_TOMAHAWKX(unit) || 5238 SOC_IS_APACHE(unit) || 5239 SOC_IS_TRIDENT3X(unit)) { 5240 rv = soc_th_alpm_debug_brief_show(unit, bucket, index); 5241 } else 5242 #endif 5243 { 5244 rv = soc_alpm_debug_brief_show(unit, bucket, index); 5245 } 5246 if (rv < 0) { 5247 return CMD_USAGE; 5248 } 5249 return CMD_OK; 5250 5251 } else if (c != NULL && sal_strcasecmp(c, "all") == 0) { 5252 ARG_NEXT(a); 5253 } else { 5254 parse_table_init(unit, &pt); 5255 parse_table_add(&pt, "VRF", PQ_DFL | PQ_INT, (void *)-1, 5256 (void *)&vrf, 0); 5257 parse_table_add(&pt, "Global-VRF", PQ_DFL | PQ_BOOL, 0, 5258 (void *)&global_vrf, 0); 5259 parse_table_add(&pt, "Pivot", PQ_DFL | PQ_BOOL, 0, 5260 (void *)&pivot, 0); 5261 parse_table_add(&pt, "Bucket", PQ_DFL | PQ_BOOL, 0, 5262 (void *)&bucket, 0); 5263 parse_table_add(&pt, "Counter", PQ_DFL | PQ_BOOL, 0, 5264 (void *)&counter, 0); 5265 parse_table_add(&pt, "BucketuSage", PQ_DFL | PQ_BOOL, 0, 5266 (void *)&bkt_usage, 0); 5267 parse_table_add(&pt, "InternalDebug", PQ_DFL | PQ_BOOL, 0, 5268 (void *)&internal_debug, 0); 5269 5270 if (!parseEndOk(a, &pt, &cmd_rv)) { 5271 return cmd_rv; 5272 } 5273 5274 if (global_vrf == TRUE) { 5275 vrf = SOC_VRF_MAX(unit) + 1; 5276 } 5277 5278 if (pivot == TRUE) { 5279 flags |= SOC_ALPM_DEBUG_SHOW_FLAG_PVT; 5280 } 5281 5282 if (bucket == TRUE) { 5283 flags |= SOC_ALPM_DEBUG_SHOW_FLAG_BKT; 5284 } 5285 5286 if (counter == TRUE) { 5287 flags |= SOC_ALPM_DEBUG_SHOW_FLAG_CNT; 5288 } 5289 5290 if (internal_debug == TRUE) { 5291 flags |= SOC_ALPM_DEBUG_SHOW_FLAG_INTDBG; 5292 } 5293 5294 if (bkt_usage == TRUE) { 5295 flags |= SOC_ALPM_DEBUG_SHOW_FLAG_BKTUSG; 5296 } 5297 } 5298 5299 if (flags == 0) { 5300 flags = SOC_ALPM_DEBUG_SHOW_FLAG_ALL; 5301 } 5302 5303 #ifdef BCM_TOMAHAWK_SUPPORT 5304 if (soc_feature(unit, soc_feature_alpm2)) { 5305 rv = bcm_esw_alpm_debug_show(unit, vrf, flags); 5306 } else if (SOC_IS_TOMAHAWKX(unit) || 5307 SOC_IS_APACHE(unit) || 5308 SOC_IS_TRIDENT3X(unit)) { 5309 rv = soc_th_alpm_debug_show(unit, vrf, flags); 5310 } else 5311 #endif 5312 { 5313 rv = soc_alpm_debug_show(unit, vrf, flags); 5314 } 5315 if (rv < 0) { 5316 return CMD_USAGE; 5317 } 5318 5319 return CMD_OK; 5320 } 5321 5322 /* Usage: 5323 * l3 alpm find [<VRF>=<val>] <IP4>=<val> <IP6>=<val> [<Length>=<val>] 5324 */ 5325 STATIC cmd_result_t 5326 _l3_cmd_alpm_find(int unit, args_t *a) 5327 { 5328 int rv = BCM_E_NONE; 5329 cmd_result_t cmd_rv = CMD_OK; 5330 bcm_ip6_t ip6addr = {0}; 5331 bcm_ip_t ip4addr = 0; 5332 int ip_len = BCM_L3_IP4_MAX_NETLEN; 5333 bcm_vrf_t vrf = 1; 5334 parse_table_t pt; 5335 int for_host = 0; 5336 int index; 5337 char ip_str[IP6ADDR_STR_LEN]; 5338 int is_ip4 = 0; 5339 int is_ip6 = 0; 5340 5341 bcm_l3_host_t host; 5342 bcm_l3_route_t route; 5343 bcm_l3_route_t input; 5344 5345 char *subcmd = NULL; 5346 5347 int arg_index_placeholder = ARG_CUR_INDEX(a); 5348 while ((subcmd = ARG_CUR(a)) != NULL) { 5349 if (parse_cmp("ip4", subcmd, '=')) { 5350 is_ip4 = 1; 5351 } 5352 5353 if (parse_cmp("ip6", subcmd, '=')) { 5354 is_ip6 = 1; 5355 } 5356 5357 ARG_NEXT(a); 5358 } 5359 5360 while (arg_index_placeholder < ARG_CUR_INDEX(a)) { 5361 ARG_PREV(a); 5362 } 5363 5364 5365 if ((is_ip4 && is_ip6) || (!is_ip4 && !is_ip6)) { 5366 return CMD_USAGE; 5367 } 5368 5369 5370 parse_table_init(unit, &pt); 5371 parse_table_add(&pt, "VRF", PQ_DFL | PQ_INT, (void *)1, 5372 (void *)&vrf, 0); 5373 parse_table_add(&pt, "IP4", PQ_DFL | PQ_IP, 0, 5374 (void *)&ip4addr, 0); 5375 parse_table_add(&pt, "IP6", PQ_DFL | PQ_IP6, 0, 5376 (void *)&ip6addr, 0); 5377 parse_table_add(&pt, "Length", PQ_DFL | PQ_INT, 5378 (void *)BCM_L3_IP4_MAX_NETLEN, 5379 (void *)&ip_len, 0); 5380 5381 if (!parseEndOk(a, &pt, &cmd_rv)) { 5382 return cmd_rv; 5383 } 5384 5385 if (is_ip4 != 0) { 5386 if (ip_len == BCM_L3_IP4_MAX_NETLEN) { 5387 for_host = 1; 5388 } 5389 } else { 5390 if (ip_len == BCM_L3_IP6_MAX_NETLEN) { 5391 for_host = 1; 5392 } 5393 } 5394 5395 bcm_l3_host_t_init(&host); 5396 bcm_l3_route_t_init(&route); 5397 bcm_l3_route_t_init(&input); 5398 if (for_host) { 5399 host.l3a_vrf = vrf; 5400 if (is_ip4 != 0) { 5401 host.l3a_ip_addr = ip4addr; 5402 format_ipaddr(ip_str, ip4addr); 5403 } else { 5404 host.l3a_flags |= BCM_L3_IP6; 5405 sal_memcpy(host.l3a_ip6_addr, ip6addr, BCM_IP6_ADDRLEN); 5406 format_ip6addr(ip_str, ip6addr); 5407 } 5408 5409 rv = bcm_l3_route_find(unit, &host, &route); 5410 } else { 5411 input.l3a_vrf = vrf; 5412 if (is_ip4 != 0) { 5413 input.l3a_subnet = ip4addr; 5414 input.l3a_ip_mask = bcm_ip_mask_create(ip_len); 5415 format_ipaddr(ip_str, ip4addr); 5416 } else { 5417 input.l3a_flags |= BCM_L3_IP6; 5418 bcm_ip6_mask_create(input.l3a_ip6_mask, ip_len); 5419 sal_memcpy(input.l3a_ip6_net, ip6addr, BCM_IP6_ADDRLEN); 5420 format_ip6addr(ip_str, ip6addr); 5421 } 5422 5423 rv = bcm_l3_subnet_route_find(unit, &input, &route); 5424 } 5425 cli_out("Matching <%d, %s/%d> ==> %s\n", vrf, ip_str, ip_len, 5426 bcm_errmsg(rv)); 5427 5428 if (rv >= 0) { 5429 if (route.l3a_flags & BCM_L3_IP6) { 5430 cli_out("%-7s %-6s %-41s %-18s %-4s %4s %5s %1s %4s %4s %s\n", "#", 5431 "VRF", "Net-addr", "Next-Hop-Mac", "INTF", "MODID", "PORT", 5432 "PRI", "CLASS", "HIT", "VLAN"); 5433 } else { 5434 cli_out("%-7s %-6s %-19s %-18s %-4s %4s %5s %1s %4s %4s %s\n", "#", 5435 "VRF", "Net-addr", "Next-Hop-Mac", "INTF", "MODID", "PORT", 5436 "PRI", "CLASS", "HIT", "VLAN"); 5437 } 5438 5439 index = route.l3a_tunnel_option; 5440 route.l3a_tunnel_option = 0; 5441 _l3_cmd_route_print(unit, index, &route, NULL); 5442 } 5443 5444 return CMD_OK; 5445 } 5446 5447 /* Process L3 ALPM Sanity Check 5448 * l3 alpm sanity [<memory>=<val>] [<index>=<val>] 5449 */ 5450 STATIC cmd_result_t 5451 _l3_cmd_alpm_sanity_check(int unit, args_t *a) 5452 { 5453 cmd_result_t cmd_rv = CMD_OK; 5454 int rv = BCM_E_NONE; 5455 static char *mem_name = NULL; 5456 int index = -1; 5457 int check_sw = 1; 5458 int copyno; 5459 parse_table_t pt; 5460 soc_mem_t mem; 5461 int def_type = 0; 5462 char *def_mem[] = {"L3_DEFIP", "L3_DEFIP_LEVEL1"}; 5463 5464 if (SOC_MEM_IS_VALID(unit, L3_DEFIP_LEVEL1m)) { 5465 def_type = 1; 5466 } 5467 5468 parse_table_init(unit, &pt); 5469 parse_table_add(&pt, "Memory", PQ_STRING|PQ_STATIC, 5470 def_mem[def_type], &mem_name, 0); 5471 parse_table_add(&pt, "Index", PQ_INT, (void *)-1, &index, 0); 5472 parse_table_add(&pt, "Sw", PQ_INT, (void *)1, &check_sw, 0); 5473 /* alpm2 OK without args */ 5474 if (!soc_feature(unit, soc_feature_alpm2) || ARG_CNT(a)) { 5475 if (!parseEndOk(a, &pt, &cmd_rv)) { 5476 return cmd_rv; 5477 } 5478 5479 if (parse_memory_name(unit, &mem, mem_name, ©no, 0) < 0) { 5480 cli_out("Parse memory name failed\n"); 5481 return CMD_USAGE; 5482 } 5483 } 5484 #if defined(BCM_TOMAHAWK_SUPPORT) 5485 if (soc_feature(unit, soc_feature_alpm2)) { 5486 rv = bcm_esw_alpm_sanity_check(unit, mem, index, check_sw); 5487 } else 5488 #endif 5489 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_APACHE_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 5490 if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_APACHE(unit) || SOC_IS_TRIDENT3X(unit)) { 5491 rv = soc_th_alpm_sanity_check(unit, mem, index, check_sw); 5492 } else 5493 #endif 5494 { 5495 rv = soc_alpm_sanity_check(unit, mem, index, check_sw); 5496 } 5497 if (BCM_FAILURE(rv)) { 5498 cli_out("%s: ALPM sanity check failed: %s\n", 5499 ARG_CMD(a), bcm_errmsg(rv)); 5500 return (CMD_FAIL); 5501 } 5502 return (CMD_OK); 5503 } 5504 5505 5506 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK_SUPPORT) 5507 char cmd_esw_alpm_usage[] = 5508 "Parameters: <init|cust1|v4|v6|pvt|bkt|fmt> <show|add>\n\t" 5509 "alpm init\n\t" 5510 "alpm hitbit <enable|disable>\n\t" 5511 "alpm trace <enable|disable|clear>\n\t" 5512 "alpm trace sanity [enable=<val>] [Start=<val>] [End=<val>]\n\t" 5513 "alpm trace wrap <enable|disable>\n\t" 5514 "alpm trace dump [Showflags=<yes|no>] [File=<filename>]\n\t" 5515 "alpm table dump [raw|chg|all|nocache] <mem> <index> <fmt> [<ent> <vrf_id>]\n\t" 5516 "\tFor Trident3, only accept L3_DEFIP_ALPM_RAW in <mem>\n\t" 5517 "\tFor Tomahawk3, other usage can be:\n\t" 5518 "\talpm table dump [nocache] <LEVEL1 mem> <index or -1(all)> <levels to print(1|2|3)> <entry 0|1>\n\t" 5519 "\t<index> is used to index <mem>\n\t" 5520 "\t<fmt> is used to parse <mem>\n\t" 5521 "\t<ent> is used to index entry in <mem>\n\t" 5522 "alpm debug info on [pvt|rte|cnt|hit|all|none]\n\t" 5523 "alpm bkt show [acb_idx]\n\t" 5524 "alpm fmt show [acb_idx]\n\t" 5525 "alpm pvtlen show [acb_idx]\n\t" 5526 "alpm stat show [acb_idx]\n\t" 5527 "alpm tcam show\n\t" 5528 "alpm config show [acb_idx]\n\t" 5529 "alpm pvt show [acb_idx] [bkt]\n"; 5530 5531 bcm_ip_t base_ipv4 = 0x1000001; 5532 bcm_ip6_t base_ipv6 = { 5533 0x2a,0x01,0x01,0x11,0xf4,0x00,0xe0,0x87, 5534 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 5535 }; 5536 5537 5538 /* Dump ALPM trace log */ 5539 STATIC int 5540 _cmd_esw_alpm_trace_dump(int u, int showflags, char *filename) 5541 { 5542 int rv = BCM_E_NONE; 5543 _alpm_log_t *p; 5544 char data[300]; 5545 #ifndef NO_FILEIO 5546 FILE *fp = NULL; 5547 #endif 5548 5549 #ifdef NO_FILEIO 5550 if (filename[0] != 0) { 5551 cli_out("File IO is not supported\n"); 5552 return BCM_E_UNAVAIL; 5553 } 5554 #endif 5555 5556 if (ALPMTR(u) == NULL) { 5557 cli_out("alpm trace not initialized yet\n"); 5558 return BCM_E_INIT; 5559 } 5560 5561 cli_out("### ALPM trace enable:%d wrap enable:%d wrap:%d count:%d " 5562 "showflags:%d file:%s ###\n", 5563 ALPMTR_TRACE_EN(u), ALPMTR_WRAP_EN(u), 5564 ALPMTR_WRAP(u), ALPMTR_CNT(u), showflags, filename); 5565 5566 #ifndef NO_FILEIO 5567 if (filename[0] != 0) { 5568 fp = sal_fopen(filename, "w"); 5569 if (fp == NULL) { 5570 rv = BCM_E_FAIL; 5571 cli_out("Open file %s failed\n", filename); 5572 goto done; 5573 } 5574 } 5575 #endif 5576 5577 if (ALPMTR_CNT(u) == 0) { 5578 goto done; 5579 } 5580 5581 #ifndef NO_FILEIO 5582 if (ALPMTR_CNT(u) > ALPM_TRACE_DUMP_SIZE && !fp) { 5583 cli_out("Too big to dump! Suggest to use: alpm trace dump file=<name>\n"); 5584 goto done; 5585 } 5586 #endif 5587 5588 p = ALPMTR_START(u); 5589 5590 do { 5591 alpm_trace_print(u, showflags, p, data); 5592 5593 #ifndef NO_FILEIO 5594 if (fp) { 5595 sal_fprintf(fp, "%s", data); 5596 } else 5597 #endif 5598 { 5599 cli_out("%s", data); 5600 } 5601 5602 p++; 5603 if (p == &ALPMTR(u)->buf[ALPM_TRACE_SIZE]) { 5604 p = ALPMTR_BUF(u); 5605 } 5606 5607 } while (p != ALPMTR_CURR(u)); 5608 5609 sal_sprintf(data, "\n### ALPM trace enable:%d wrap enable:%d wrap:%d count:%d " 5610 "showflags:%d file:%s ###\n", 5611 ALPMTR_TRACE_EN(u), ALPMTR_WRAP_EN(u), 5612 ALPMTR_WRAP(u), ALPMTR_CNT(u), showflags, filename); 5613 #ifndef NO_FILEIO 5614 if (fp) { 5615 sal_fprintf(fp, "%s", data); 5616 } else 5617 #endif 5618 { 5619 cli_out("%s", data); 5620 } 5621 5622 done: 5623 #ifndef NO_FILEIO 5624 if (fp) { 5625 sal_fclose(fp); 5626 } 5627 #endif 5628 return rv; 5629 } 5630 5631 cmd_result_t 5632 cmd_esw_alpm(int unit, args_t *a) 5633 { 5634 char *table, *subcmd_s; 5635 int subcmd = 0; 5636 int acb_bmp = 3; 5637 int flags = 0; 5638 int index = 0; 5639 int fmt = 1; 5640 int ent_idx = 0; 5641 int vrf_id = 1; 5642 int copyno; 5643 soc_mem_t mem; 5644 5645 if (!soc_feature(unit, soc_feature_alpm2)) { 5646 cli_out("Feature alpm2 is unavailable\n"); 5647 return CMD_OK; 5648 } 5649 5650 if ((table = ARG_GET(a)) == NULL) { 5651 return CMD_USAGE; 5652 } 5653 5654 if (!soc_property_get(unit, spn_L3_ALPM_ENABLE, 0)) { 5655 cli_out("ALPM is disabled!\n" ); 5656 ARG_DISCARD(a); 5657 return CMD_OK; 5658 } 5659 5660 if (sal_strcasecmp(table, "init") == 0) { 5661 bcm_esw_alpm_init(unit); 5662 return CMD_OK; 5663 } 5664 5665 if (sal_strcasecmp(table, "hitbit") == 0) { 5666 int rv; 5667 if ((subcmd_s = ARG_GET(a)) == NULL) { 5668 cli_out("Current settings:\n"); 5669 cli_out("\tInterval=%d\n", alpm_dist_hitbit_interval_get(unit)); 5670 return CMD_OK; 5671 } 5672 if (sal_strcasecmp(subcmd_s, "disable") == 0 || 5673 sal_strcasecmp(subcmd_s, "off") == 0) { 5674 if (ALPMC(unit) && !ALPM_HIT_SKIP(unit)) { 5675 rv = bcm_esw_alpm_hit_deinit(unit); 5676 ALPM_HIT_SKIP(unit) = 1; 5677 if (BCM_SUCCESS(rv)) { 5678 cli_out("ALPM hitbit disable OK!\n"); 5679 } else { 5680 cli_out("ALPM hitbit disable failed!\n"); 5681 } 5682 } 5683 } else if (sal_strcasecmp(subcmd_s, "enable") == 0 || 5684 sal_strcasecmp(subcmd_s, "on") == 0) { 5685 if (ALPMC(unit) && ALPM_HIT_SKIP(unit)) { 5686 ALPM_HIT_SKIP(unit) = 0; 5687 rv = bcm_esw_alpm_hit_init(unit); 5688 if (BCM_SUCCESS(rv)) { 5689 cli_out("ALPM hitbit enable OK!\n"); 5690 } else { 5691 cli_out("ALPM hitbit enable failed!\n"); 5692 } 5693 } 5694 } else { 5695 return CMD_USAGE; 5696 } 5697 return CMD_OK; 5698 } 5699 5700 if (sal_strcasecmp(table, "trace") == 0) { 5701 if ((subcmd_s = ARG_GET(a)) == NULL) { 5702 return CMD_USAGE; 5703 } 5704 if (sal_strcasecmp(subcmd_s, "enable") == 0) { 5705 (void)alpm_trace_set(unit, TRUE); 5706 } else if (sal_strcasecmp(subcmd_s, "disable") == 0) { 5707 (void)alpm_trace_set(unit, FALSE); 5708 } else if (sal_strcasecmp(subcmd_s, "clear") == 0) { 5709 (void)alpm_trace_clear(unit); 5710 } else if (sal_strcasecmp(subcmd_s, "sanity") == 0) { 5711 parse_table_t pt; 5712 int enable = -1, start = 0, end = -1; 5713 5714 parse_table_init(unit, &pt); 5715 /* -1 for show, 0 for disable, >0 for freq */ 5716 parse_table_add(&pt, "enable", PQ_DFL | PQ_INT, (void *)-1, 5717 (void *)&enable, 0); 5718 parse_table_add(&pt, "Start", PQ_DFL | PQ_INT, (void *)0, 5719 (void *)&start, 0); 5720 parse_table_add(&pt, "End", PQ_DFL | PQ_INT, (void *)-1, 5721 (void *)&end, 0); /* end=-1 means forever */ 5722 if (parse_arg_eq(a, &pt) < 0) { 5723 parse_arg_eq_done(&pt); 5724 return CMD_USAGE; 5725 } 5726 5727 (void)alpm_trace_sanity(unit, enable, start, end); 5728 parse_arg_eq_done(&pt); 5729 5730 } else if (sal_strcasecmp(subcmd_s, "dump") == 0) { 5731 parse_table_t pt; 5732 char *filename = NULL; 5733 5734 parse_table_init(unit, &pt); 5735 parse_table_add(&pt, "Showflags", PQ_BOOL, (void *)0, 5736 (void *)&flags, 0); 5737 parse_table_add(&pt, "File", PQ_STRING, NULL, 5738 (void *)&filename, NULL); 5739 if (parse_arg_eq(a, &pt) < 0) { 5740 parse_arg_eq_done(&pt); 5741 return CMD_USAGE; 5742 } 5743 5744 (void) _cmd_esw_alpm_trace_dump(unit, flags, filename); 5745 parse_arg_eq_done(&pt); 5746 5747 } else if (sal_strcasecmp(subcmd_s, "wrap") == 0) { 5748 if ((subcmd_s = ARG_GET(a)) == NULL) { 5749 return CMD_USAGE; 5750 } 5751 if (sal_strcasecmp(subcmd_s, "enable") == 0) { 5752 (void)alpm_trace_wrap_set(unit, TRUE); 5753 } else if (sal_strcasecmp(subcmd_s, "disable") == 0) { 5754 (void)alpm_trace_wrap_set(unit, FALSE); 5755 } else { 5756 return CMD_USAGE; 5757 } 5758 } else { 5759 return CMD_USAGE; 5760 } 5761 return CMD_OK; 5762 } 5763 5764 if (!sal_strcasecmp(table, "table")) { 5765 if ((subcmd_s = ARG_GET(a)) == NULL) { 5766 return CMD_USAGE; 5767 } 5768 if (!sal_strcasecmp(subcmd_s, "dump")) { 5769 if ((subcmd_s = ARG_GET(a)) == NULL) { 5770 return CMD_USAGE; 5771 } 5772 for (;;) { 5773 if (subcmd_s != NULL && !sal_strcasecmp(subcmd_s, "raw")) { 5774 flags |= ALPM_DUMP_TABLE_RAW; 5775 subcmd_s = ARG_GET(a); 5776 } else if (subcmd_s != NULL && !sal_strcasecmp(subcmd_s, "all")) { 5777 flags |= ALPM_DUMP_TABLE_ALL; 5778 subcmd_s = ARG_GET(a); 5779 } else if (subcmd_s != NULL && !sal_strcasecmp(subcmd_s, "chg")) { 5780 flags |= ALPM_DUMP_TABLE_CHANGED; 5781 subcmd_s = ARG_GET(a); 5782 } else if (subcmd_s != NULL && !sal_strcasecmp(subcmd_s, "nocache")) { 5783 flags |= ALPM_DUMP_TABLE_NOCACHE; 5784 subcmd_s = ARG_GET(a); 5785 } else { 5786 break; 5787 } 5788 } /* for */ 5789 5790 if (subcmd_s == NULL) { 5791 return CMD_USAGE; 5792 } 5793 5794 if (parse_memory_name(unit, &mem, subcmd_s, ©no, 0) >= 0) { 5795 if (SOC_MEM_IS_VALID(unit, L3_DEFIP_ALPM_LEVEL2m) && 5796 mem != L3_DEFIP_ALPM_LEVEL2m && 5797 mem != L3_DEFIP_ALPM_LEVEL3m && 5798 mem != L3_DEFIP_PAIR_LEVEL1m && 5799 mem != L3_DEFIP_LEVEL1m) { 5800 return CMD_USAGE; 5801 } 5802 if (SOC_MEM_IS_VALID(unit, L3_DEFIP_ALPM_RAWm) && 5803 mem != L3_DEFIP_ALPM_RAWm) { 5804 return CMD_USAGE; 5805 } 5806 5807 if (copyno == COPYNO_ALL) { 5808 copyno = SOC_MEM_BLOCK_ANY(unit, mem); 5809 } 5810 } else { 5811 return CMD_USAGE; 5812 } 5813 5814 if ((subcmd_s = ARG_GET(a)) == NULL) { 5815 return CMD_USAGE; 5816 } 5817 5818 if (mem == L3_DEFIP_LEVEL1m || mem == L3_DEFIP_PAIR_LEVEL1m) { 5819 index = parse_integer(subcmd_s); 5820 } else { 5821 index = parse_memory_index(unit, mem, subcmd_s); 5822 } 5823 5824 if ((subcmd_s = ARG_GET(a)) == NULL || !isint(subcmd_s)) { 5825 return CMD_USAGE; 5826 } 5827 fmt = parse_integer(subcmd_s); 5828 if ((subcmd_s = ARG_GET(a)) == NULL) { 5829 ent_idx = -1; /* all entries in the bank */ 5830 } else { 5831 if (!isint(subcmd_s)) { 5832 return CMD_USAGE; 5833 } 5834 ent_idx = parse_integer(subcmd_s); 5835 } 5836 if ((subcmd_s = ARG_GET(a)) == NULL) { 5837 vrf_id = 1; /* all entries in the bank */ 5838 } else { 5839 if (!isint(subcmd_s)) { 5840 return CMD_USAGE; 5841 } 5842 vrf_id = parse_integer(subcmd_s); 5843 } 5844 if (soc_feature(unit, soc_feature_alpm2)) { 5845 (void)alpm_table_dump(unit, vrf_id, mem, copyno, index, 5846 fmt, ent_idx, flags); 5847 } else { 5848 cli_out("cmd is not supported\n"); 5849 } 5850 return CMD_OK; 5851 } 5852 return CMD_USAGE; 5853 } 5854 5855 5856 if (!sal_strcasecmp(table, "debug")) { 5857 if ((subcmd_s = ARG_GET(a)) == NULL) { 5858 return CMD_USAGE; 5859 } 5860 if (!sal_strcasecmp(subcmd_s, "info")) { 5861 if ((subcmd_s = ARG_GET(a)) == NULL) { 5862 return CMD_USAGE; 5863 } 5864 if (!sal_strcasecmp(subcmd_s, "on")) { 5865 if ((subcmd_s = ARG_GET(a)) == NULL) { 5866 (void)alpm_dbg_info_bmp_show(unit); 5867 return CMD_OK; 5868 } 5869 for (;;) { 5870 if (subcmd_s != NULL && !sal_strcasecmp(subcmd_s, "pvt")) { 5871 flags |= _ALPM_DBG_INFO_PVT; 5872 subcmd_s = ARG_GET(a); 5873 } else if (subcmd_s != NULL && !sal_strcasecmp(subcmd_s, "rte")) { 5874 flags |= _ALPM_DBG_INFO_RTE; 5875 subcmd_s = ARG_GET(a); 5876 } else if (subcmd_s != NULL && !sal_strcasecmp(subcmd_s, "cnt")) { 5877 flags |= _ALPM_DBG_INFO_CNT; 5878 subcmd_s = ARG_GET(a); 5879 } else if (subcmd_s != NULL && !sal_strcasecmp(subcmd_s, "hit")) { 5880 flags |= _ALPM_DBG_INFO_HIT; 5881 subcmd_s = ARG_GET(a); 5882 } else if (subcmd_s != NULL && !sal_strcasecmp(subcmd_s, "all")) { 5883 flags |= _ALPM_DBG_INFO_ALL; 5884 subcmd_s = ARG_GET(a); 5885 } else if (subcmd_s != NULL && !sal_strcasecmp(subcmd_s, "none")) { 5886 flags = 0; 5887 subcmd_s = ARG_GET(a); 5888 } else { 5889 break; 5890 } 5891 } /* for */ 5892 5893 (void)alpm_dbg_info_bmp_set(unit, flags); 5894 return CMD_OK; 5895 } 5896 } 5897 return CMD_USAGE; 5898 } 5899 5900 if (sal_strcasecmp(table, "util") == 0) { 5901 int i; 5902 ip6_addr_t ip6; 5903 char buf[IP6ADDR_STR_LEN]; 5904 #define IP6_STR_CNT 6 5905 char *ip6_str[IP6_STR_CNT] = { 5906 "ffff::ffff:ffff:ffff:ffff:ffff:ffff", 5907 "eeee::eeee:eeee:eeee:eeee:eeee", 5908 "dddd:dddd::dddd", 5909 "cccc:cccc::", 5910 "bbbb::", 5911 "::aaaa" 5912 }; 5913 5914 for (i = 0; i < IP6_STR_CNT; i++) { 5915 if (ip6_str[i] != NULL) { 5916 parse_ip6addr(ip6_str[i], ip6); 5917 sal_memset(buf, 0, sizeof(buf)); 5918 format_ip6addr(buf, ip6); 5919 cli_out(" Original: %s\n", ip6_str[i]); 5920 cli_out("Converted: %s\n", buf); 5921 } 5922 } 5923 return CMD_OK; 5924 } 5925 5926 5927 if (sal_strcasecmp(table, "load") == 0) { 5928 if ((subcmd_s = ARG_CUR(a)) == NULL) { 5929 return CMD_USAGE; 5930 } 5931 return CMD_OK; 5932 } 5933 5934 if ((subcmd_s = ARG_GET(a)) == NULL) { 5935 return CMD_USAGE; 5936 } 5937 5938 if (sal_strcasecmp(subcmd_s, "show") == 0) { 5939 subcmd = L3_SHOW; 5940 } 5941 if (sal_strcasecmp(subcmd_s, "add") == 0) { 5942 subcmd = L3_ADD; 5943 } 5944 5945 if ((subcmd == L3_SHOW) && 5946 (sal_strcasecmp(table, "bkt") == 0 || 5947 sal_strcasecmp(table, "pvt") == 0 || 5948 sal_strcasecmp(table, "fmt") == 0 || 5949 sal_strcasecmp(table, "pvtlen") == 0 || 5950 sal_strcasecmp(table, "stat") == 0 || 5951 sal_strcasecmp(table, "config") == 0 5952 ) 5953 ) { 5954 subcmd_s = ARG_GET(a); 5955 if (subcmd_s != NULL) { 5956 acb_bmp = parse_integer(subcmd_s); 5957 } else { 5958 acb_bmp = 3; 5959 } 5960 } 5961 5962 if (sal_strcasecmp(table, "bkt") == 0) { 5963 switch (subcmd) { 5964 /* alpm bkt show */ 5965 case L3_SHOW: 5966 alpm_cb_bkt_dump(unit, acb_bmp); 5967 return CMD_OK; 5968 default: 5969 return (CMD_USAGE); 5970 } 5971 5972 return CMD_OK; 5973 } 5974 5975 if (sal_strcasecmp(table, "pvt") == 0) { 5976 int bkt = -1; 5977 switch (subcmd) { 5978 /* alpm pvt show */ 5979 case L3_SHOW: 5980 subcmd_s = ARG_GET(a); 5981 if (subcmd_s != NULL) { 5982 bkt = parse_integer(subcmd_s); 5983 } else { 5984 bkt = -1; 5985 } 5986 5987 alpm_cb_pvt_dump(unit, acb_bmp, bkt); 5988 return CMD_OK; 5989 default: 5990 return (CMD_USAGE); 5991 } 5992 5993 return CMD_OK; 5994 } 5995 5996 if (sal_strcasecmp(table, "fmt") == 0) { 5997 switch (subcmd) { 5998 /* alpm fmt show */ 5999 case L3_SHOW: 6000 alpm_cb_fmt_dump(unit, acb_bmp); 6001 return CMD_OK; 6002 default: 6003 return (CMD_USAGE); 6004 } 6005 6006 return CMD_OK; 6007 } 6008 6009 if (sal_strcasecmp(table, "pvtlen") == 0) { 6010 switch (subcmd) { 6011 /* alpm pvtlen show */ 6012 case L3_SHOW: 6013 alpm_cb_pvtlen_dump(unit, acb_bmp); 6014 return CMD_OK; 6015 default: 6016 return (CMD_USAGE); 6017 } 6018 6019 return CMD_OK; 6020 } 6021 6022 if (sal_strcasecmp(table, "stat") == 0) { 6023 switch (subcmd) { 6024 /* alpm stat show */ 6025 case L3_SHOW: 6026 alpm_cb_stat_dump(unit, acb_bmp); 6027 return CMD_OK; 6028 default: 6029 return (CMD_USAGE); 6030 } 6031 6032 return CMD_OK; 6033 } 6034 6035 if (sal_strcasecmp(table, "tcam") == 0) { 6036 switch (subcmd) { 6037 /* alpm stat show */ 6038 case L3_SHOW: 6039 bcm_esw_alpm_tcam_zone_state_dump(unit); 6040 return CMD_OK; 6041 default: 6042 return (CMD_USAGE); 6043 } 6044 6045 return CMD_OK; 6046 } 6047 6048 if (sal_strcasecmp(table, "config") == 0) { 6049 switch (subcmd) { 6050 /* alpm config show */ 6051 case L3_SHOW: 6052 alpm_cb_conf_dump(unit, acb_bmp); 6053 return CMD_OK; 6054 default: 6055 return (CMD_USAGE); 6056 } 6057 6058 return CMD_OK; 6059 } 6060 6061 6062 return CMD_USAGE; 6063 } 6064 #endif /* BCM_TRIDENT3_SUPPORT or BCM_TOMAHAWK_SUPPORT */ 6065 #endif 6066 6067 cmd_result_t 6068 if_l3(int unit, args_t *a) 6069 { 6070 char *table, *subcmd_s; 6071 int subcmd = 0; 6072 parse_table_t pt; 6073 cmd_result_t retCode; 6074 bcm_mac_t mac; 6075 int id = 0; 6076 int r, first_entry, last_entry; 6077 int num_entries = 0; 6078 int free_l3, free_defip; 6079 #if defined(BCM_XGS_SWITCH12_SUPPORT) 6080 int free_lpm_blk; 6081 #endif 6082 bcm_l3_info_t l3_hw_status; 6083 char ip_str[IP6ADDR_STR_LEN + 3]; 6084 bcm_ip_t ip_addr = 0, mask = 0; 6085 #ifdef BCM_XGS_SWITCH_SUPPORT 6086 int interface = 0, port = 0; 6087 int module = 0; 6088 bcm_vlan_t vlan = 0; 6089 bcm_ip_t gateway = 0; 6090 int sip_key = 2, hash_select = XGS_HASH_COUNT; 6091 uint8 key[SOC_MAX_MEM_WORDS * 4]; 6092 int ecmp = 0, max_ecmp = 0; 6093 #endif 6094 uint32 flags; 6095 bcm_l3_route_t route_info; 6096 bcm_l3_host_t ip_info; 6097 #if defined(BCM_XGS3_SWITCH_SUPPORT) 6098 bcm_ip6_t ip6_addr, sip6_addr; 6099 int urpf = 0, vrf = 0; 6100 int egress_flag = FALSE; 6101 #endif 6102 #if defined(BCM_FIREBOLT_SUPPORT) 6103 int i; 6104 #endif /* BCM_FIREBOLT_SUPPORT */ 6105 soc_mem_t uc_mem = L3_ENTRY_IPV4_UNICASTm; 6106 6107 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 6108 int ext_tcam_flag = 0; 6109 int defip_128_max = 0; 6110 int defip_128_free = 0; 6111 int defip_64_max = 0; 6112 int defip_64_free = 0; 6113 #endif 6114 void *user_data = NULL; 6115 6116 sal_memset(mac, 0, sizeof(bcm_mac_t)); 6117 6118 /* Check valid device to operation on ... */ 6119 if (!sh_check_attached(ARG_CMD(a), unit)) { 6120 return CMD_FAIL; 6121 } 6122 6123 if ((table = ARG_GET(a)) == NULL) { 6124 return CMD_USAGE; 6125 } 6126 6127 /* L3 init */ 6128 if (sal_strcasecmp(table, "init") == 0) { 6129 if ((r = bcm_l3_init(unit)) < 0) { 6130 cli_out("%s: error initializing: %s\n", ARG_CMD(a), bcm_errmsg(r)); 6131 } 6132 return CMD_OK; 6133 } 6134 6135 /* L3 detach */ 6136 if (sal_strcasecmp(table, "detach") == 0) { 6137 if ((r = bcm_l3_cleanup(unit)) < 0) { 6138 cli_out("%s: error detaching: %s\n", ARG_CMD(a), bcm_errmsg(r)); 6139 } 6140 return CMD_OK; 6141 } 6142 if (sal_strcasecmp(table, "defipinfo") == 0) { 6143 #if defined(BCM_KATANA_SUPPORT) 6144 if (SOC_IS_KATANAX(unit)) { 6145 bcm_l3_info_t l3_info; 6146 bcm_l3_info_t_init(&l3_info); 6147 if ((r = bcm_l3_info(unit, &l3_info)) < 0) { 6148 cli_out("%s: Error L3 info: %s\n", ARG_CMD(a), bcm_errmsg(r)); 6149 return CMD_FAIL; 6150 } 6151 _bcm_kt_l3_info_dump(unit); 6152 } 6153 #endif 6154 return CMD_OK; 6155 } 6156 6157 if ((subcmd_s = ARG_GET(a)) == NULL) { 6158 return CMD_USAGE; 6159 } 6160 #if defined(BCM_XGS3_SWITCH_SUPPORT) 6161 if ((sal_strcasecmp(table, "ecmp") == 0) && 6162 (sal_strcasecmp(subcmd_s, "egress") == 0)) { 6163 egress_flag = TRUE; 6164 if ((subcmd_s = ARG_GET(a)) == NULL) { 6165 return CMD_USAGE; 6166 } 6167 } 6168 #endif 6169 if (sal_strcasecmp(subcmd_s, "add") == 0) { 6170 subcmd = L3_ADD; 6171 } 6172 if (sal_strcasecmp(subcmd_s, "update") == 0) { 6173 subcmd = L3_UPDATE; 6174 } 6175 if (sal_strcasecmp(subcmd_s, "destroy") == 0 || 6176 sal_strcasecmp(subcmd_s, "delete") == 0) { 6177 subcmd = L3_DESTROY; 6178 } 6179 if (sal_strcasecmp(subcmd_s, "set") == 0) { 6180 subcmd = L3_SET; 6181 } 6182 if (sal_strcasecmp(subcmd_s, "clear") == 0) { 6183 subcmd = L3_CLEAR; 6184 } 6185 if (sal_strcasecmp(subcmd_s, "show") == 0) { 6186 subcmd = L3_SHOW; 6187 } 6188 if (sal_strcasecmp(subcmd_s, "age") == 0) { 6189 subcmd = L3_AGE; 6190 } 6191 #ifdef BCM_XGS_SWITCH_SUPPORT 6192 if (sal_strcasecmp(subcmd_s, "conflict") == 0) { 6193 subcmd = L3_CONFLICT; 6194 } 6195 if (sal_strcasecmp(subcmd_s, "hash") == 0) { 6196 subcmd = L3_HASH; 6197 } 6198 if (sal_strcasecmp(subcmd_s, "ip6hash") == 0) { 6199 subcmd = L3_IP6HASH; 6200 } 6201 if (sal_strcasecmp(subcmd_s, "sanity") == 0) { 6202 subcmd = L3_SANITY; 6203 } 6204 if (sal_strcasecmp(subcmd_s, "ecmp") == 0) { 6205 subcmd = L3_ECMP; 6206 } 6207 if (sal_strcasecmp(subcmd_s, "ecmphash") == 0) { 6208 subcmd = L3_ECMP_HASH; 6209 } 6210 if (sal_strcasecmp(subcmd_s, "maxadd") == 0) { 6211 subcmd = L3_MAXADD; 6212 } 6213 #endif 6214 if (sal_strcasecmp(subcmd_s, "insert") == 0) { 6215 subcmd = L3_INSERT; 6216 } 6217 if (sal_strcasecmp(subcmd_s, "remove") == 0) { 6218 subcmd = L3_REMOVE; 6219 } 6220 if (sal_strcasecmp(subcmd_s, "find") == 0) { 6221 subcmd = L3_FIND; 6222 } 6223 if (sal_strcasecmp(subcmd_s, "test") == 0) { 6224 subcmd = L3_TEST; 6225 } 6226 if (!subcmd) { 6227 return CMD_USAGE; 6228 } 6229 6230 if (sal_strcasecmp(table, "intf") == 0) { 6231 switch (subcmd) { 6232 /* l3 intf add */ 6233 case L3_ADD: 6234 return _l3_cmd_egress_intf_create(unit, a); 6235 /* l3 intf destroy */ 6236 case L3_DESTROY: 6237 return _l3_cmd_egress_intf_delete(unit, a); 6238 /* l3 intf clear */ 6239 case L3_CLEAR: 6240 return _l3_cmd_egress_intf_delete_all(unit, a); 6241 /* l3 intf show */ 6242 case L3_SHOW: 6243 return _l3_cmd_egress_intf_show(unit, a); 6244 default: 6245 return (CMD_USAGE); 6246 } 6247 } 6248 6249 if (sal_strcasecmp(table, "egress") == 0) { 6250 #if defined(BCM_XGS3_SWITCH_SUPPORT) 6251 switch (subcmd) { 6252 /* l3 egress add/update */ 6253 case L3_ADD: 6254 case L3_UPDATE: 6255 return _l3_cmd_egress_object_create(unit, a); 6256 /* l3 egress destroy */ 6257 case L3_DESTROY: 6258 return _l3_cmd_egress_object_destroy(unit, a); 6259 /* l3 egress show */ 6260 case L3_SHOW: 6261 return _l3_cmd_egress_object_show(unit, a); 6262 /* l3 egress find */ 6263 case L3_FIND: 6264 return _l3_cmd_egress_object_find(unit, a); 6265 default: 6266 return (CMD_USAGE); 6267 } 6268 /* coverity[unreachable] */ 6269 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 6270 /* coverity[unreachable] */ 6271 cli_out("Unsupported command. \n"); 6272 return (CMD_OK); 6273 } 6274 if (sal_strcasecmp(table, "prefix_map") == 0) { 6275 #if defined(BCM_XGS3_SWITCH_SUPPORT) 6276 switch (subcmd) { 6277 /* l3 prefix_map add */ 6278 case L3_ADD: 6279 return _l3_cmd_prefix_map_add(unit, a); 6280 /* l3 prefix_map delete */ 6281 case L3_DESTROY: 6282 return _l3_cmd_prefix_map_delete(unit, a); 6283 /* l3 prefix_map show */ 6284 case L3_SHOW: 6285 return _l3_cmd_prefix_map_show(unit, a); 6286 /* l3 egress clear */ 6287 case L3_CLEAR: 6288 return _l3_cmd_prefix_map_delete_all(unit, a); 6289 default: 6290 cli_out("Unsupported command. \n"); 6291 return CMD_OK; 6292 /* coverity[unreachable] */ 6293 } 6294 /** coverity[unreachable] **/ 6295 return CMD_OK; 6296 /* coverity[unreachable] */ 6297 #else 6298 /* coverity[unreachable] */ 6299 cli_out("Unsupported command. \n"); 6300 return CMD_OK; 6301 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 6302 } 6303 if (sal_strcasecmp(table, "multipath") == 0) { 6304 #if defined(BCM_XGS3_SWITCH_SUPPORT) 6305 switch (subcmd) { 6306 /* l3 multipath add */ 6307 case L3_ADD: 6308 case L3_UPDATE: 6309 return _l3_cmd_egress_mpath_object_create(unit, a); 6310 /* l3 multipath max add */ 6311 case L3_MAXADD: 6312 return _l3_cmd_egress_mpath_object_max_create(unit, a); 6313 /* l3 multipath destroy */ 6314 case L3_DESTROY: 6315 return _l3_cmd_egress_mpath_object_destroy(unit, a); 6316 /* l3 multipath show */ 6317 case L3_SHOW: 6318 return _l3_cmd_egress_mpath_object_show(unit, a); 6319 case L3_INSERT: 6320 return _l3_cmd_egress_mpath_object_intf_insert(unit, a); 6321 case L3_REMOVE: 6322 return _l3_cmd_egress_mpath_object_intf_remove(unit, a); 6323 case L3_FIND: 6324 /** coverity[unreachable] **/ 6325 return _l3_cmd_egress_mpath_object_lookup(unit, a); 6326 /** coverity[unreachable] **/ 6327 default: 6328 cli_out("Unsupported command. \n"); 6329 /** coverity[unreachable] **/ 6330 return CMD_OK; 6331 /** coverity[unreachable] **/ 6332 } 6333 /** coverity[unreachable] **/ 6334 return CMD_OK; 6335 #else 6336 /* coverity[unreachable] */ 6337 cli_out("Unsupported command. \n"); 6338 return CMD_OK; 6339 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 6340 } 6341 if (sal_strcasecmp(table, "ecmp") == 0) { 6342 #if defined(BCM_XGS3_SWITCH_SUPPORT) 6343 if (!egress_flag) { 6344 cli_out("Unsupported command. \n"); 6345 return CMD_OK; 6346 } 6347 switch (subcmd) { 6348 /* l3 ecmp add */ 6349 case L3_ADD: 6350 case L3_UPDATE: 6351 return _l3_cmd_egress_ecmp_object_create(unit, a); 6352 /* l3 ecmp max add */ 6353 case L3_MAXADD: 6354 return _l3_cmd_egress_ecmp_object_max_create(unit, a); 6355 /* l3 ecmp destroy */ 6356 case L3_DESTROY: 6357 return _l3_cmd_egress_ecmp_object_destroy(unit, a); 6358 /* l3 ecmp show */ 6359 case L3_SHOW: 6360 return _l3_cmd_egress_ecmp_object_show(unit, a); 6361 case L3_INSERT: 6362 return _l3_cmd_egress_ecmp_object_intf_insert(unit, a); 6363 case L3_REMOVE: 6364 return _l3_cmd_egress_ecmp_object_intf_remove(unit, a); 6365 case L3_FIND: 6366 /** coverity[unreachable] **/ 6367 return _l3_cmd_egress_ecmp_object_lookup(unit, a); 6368 /** coverity[unreachable] **/ 6369 default: 6370 cli_out("Unsupported command. \n"); 6371 /** coverity[unreachable] **/ 6372 return CMD_OK; 6373 /** coverity[unreachable] **/ 6374 } 6375 /** coverity[unreachable] **/ 6376 return CMD_OK; 6377 #else 6378 /* coverity[unreachable] */ 6379 cli_out("Unsupported command. \n"); 6380 return CMD_OK; 6381 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 6382 } 6383 6384 if (sal_strcasecmp(table, "l3table") == 0) { 6385 switch (subcmd) { 6386 6387 /* l3 l3table add */ 6388 case L3_ADD: 6389 return _l3_cmd_host_add(unit, a, FALSE); 6390 /* l3 l3table destroy */ 6391 case L3_DESTROY: 6392 parse_table_init(unit, &pt); 6393 #if defined(BCM_XGS3_SWITCH_SUPPORT) 6394 parse_table_add(&pt, "VRF", PQ_DFL | PQ_INT, 0, (void *)&vrf, 0); 6395 #endif 6396 parse_table_add(&pt, "IP", PQ_DFL | PQ_IP, 0, (void *)&ip_addr, 0); 6397 if (!parseEndOk(a, &pt, &retCode)) 6398 return retCode; 6399 6400 bcm_l3_host_t_init(&ip_info); 6401 #if defined(BCM_XGS3_SWITCH_SUPPORT) 6402 ip_info.l3a_vrf = vrf; 6403 #endif 6404 ip_info.l3a_ip_addr = ip_addr; 6405 6406 if ((r = bcm_l3_host_delete(unit, &ip_info)) < 0) { 6407 format_ipaddr(ip_str, ip_addr); 6408 cli_out("%s: Error destroy %s from L3 " 6409 "table: %s\n", ARG_CMD(a), ip_str, bcm_errmsg(r)); 6410 return CMD_FAIL; 6411 } 6412 break; 6413 6414 /* l3 l3table clear */ 6415 case L3_CLEAR: 6416 bcm_l3_host_delete_all(unit, NULL); 6417 break; 6418 6419 /* l3 l3table show */ 6420 case L3_SHOW: 6421 if ((r = bcm_l3_info(unit, &l3_hw_status)) < 0) { 6422 cli_out("%s: Error L3 accessing: %s\n", ARG_CMD(a), bcm_errmsg(r)); 6423 return CMD_FAIL; 6424 } 6425 free_l3 = l3_hw_status.l3info_max_host - 6426 l3_hw_status.l3info_occupied_host; 6427 last_entry = l3_hw_status.l3info_max_host; 6428 if (ARG_CNT(a)) { 6429 if (!isint(ARG_CUR(a))) { 6430 cli_out("%s: Invalid number: %s\n", ARG_CMD(a), ARG_CUR(a)); 6431 return (CMD_FAIL); 6432 } 6433 first_entry = parse_integer(ARG_GET(a)); 6434 if (first_entry > last_entry) { 6435 cli_out("%s: Error: Illegal entry number (0 to %d)\n", 6436 ARG_CMD(a), last_entry); 6437 return (CMD_FAIL); 6438 } 6439 last_entry = first_entry; 6440 } else { 6441 first_entry = 0; 6442 } 6443 6444 cli_out("Unit %d, free L3 table entries: %d\n", unit, free_l3); 6445 cli_out("Entry VRF IP address Mac Address " 6446 "INTF MOD PORT CLASS HIT H/W Index\n"); 6447 user_data = soc_cm_salloc(unit, sizeof(int), "l3host hw index"); 6448 if (NULL == user_data) { 6449 cli_out("Failed to allocate memory\n"); 6450 return CMD_FAIL; 6451 } 6452 bcm_l3_host_traverse(unit, _BCM_L3_SHOW_INDEX, first_entry, 6453 last_entry, _l3_cmd_host_print, user_data); 6454 if (user_data) { 6455 soc_cm_sfree(unit, user_data); 6456 } 6457 return CMD_OK; 6458 6459 /* l3 l3table age */ 6460 case L3_AGE: 6461 flags = BCM_L3_S_HIT; 6462 6463 bcm_l3_host_age(unit, flags, _l3_cmd_host_age_callback, NULL); 6464 return CMD_OK; 6465 6466 #ifdef BCM_XGS_SWITCH_SUPPORT 6467 case L3_HASH: 6468 6469 parse_table_init(unit, &pt); 6470 #if defined(BCM_TRX_SUPPORT) 6471 if (SOC_IS_TRX(unit)) { 6472 parse_table_add(&pt, "VRF", PQ_DFL|PQ_INT, 0, 6473 (void *)&vrf, 0); 6474 } 6475 #endif 6476 sal_memset(&ip_addr, 0, sizeof(ip_addr)); 6477 sal_memset(&gateway, 0, sizeof(gateway)); 6478 parse_table_add(&pt, "IP", PQ_DFL | PQ_IP, 0, (void *)&ip_addr, 0); 6479 parse_table_add(&pt, "SrcIP", PQ_DFL | PQ_IP, 0, 6480 (void *)&gateway, 0); 6481 parse_table_add(&pt, "VID", PQ_DFL | PQ_INT, 0, 6482 (void *)&id, 0); 6483 parse_table_add(&pt, "Hash", PQ_DFL | PQ_INT, 0, 6484 (void *)&hash_select, 0); 6485 parse_table_add(&pt, "SIPKey", PQ_DFL | PQ_INT, 0, 6486 (void *)&sip_key, 0); 6487 if (!parseEndOk(a, &pt, &retCode)) 6488 return retCode; 6489 vlan = id; 6490 6491 #ifdef BCM_ISM_SUPPORT 6492 if (soc_feature(unit, soc_feature_ism_memory)) { 6493 int b, rc, index, key_nbits, loop; 6494 l3_entry_1_entry_t l3_ipv4_uentry; 6495 l3_entry_2_entry_t l3_ipv4_mentry; 6496 soc_field_t keyflds[MAX_FIELDS], lsbfld; 6497 uint32 bucket, sizes[_SOC_ISM_MAX_BANKS]; 6498 uint8 act_zero_lsb, act_offset, zero_lsb = 0, offset = 48; 6499 uint8 banks[_SOC_ISM_MAX_BANKS], bcount, num_flds; 6500 soc_mem_t l3_entry_mem; 6501 int mcast_flag =0; 6502 void *entry; 6503 6504 if (L3X_IP_MULTICAST(ip_addr)) { 6505 mcast_flag = 1; 6506 l3_entry_mem = L3_ENTRY_2m; 6507 entry = &l3_ipv4_mentry; 6508 sal_memset(&l3_ipv4_mentry, 0, sizeof(l3_ipv4_mentry)); 6509 soc_L3_ENTRY_2m_field32_set(unit, &l3_ipv4_mentry, 6510 KEY_TYPE_0f, SOC_MEM_KEY_L3_ENTRY_2_IPV4MC_IPV4_MULTICAST); 6511 soc_L3_ENTRY_2m_field32_set(unit, &l3_ipv4_mentry, 6512 KEY_TYPE_1f, SOC_MEM_KEY_L3_ENTRY_2_IPV4MC_IPV4_MULTICAST); 6513 soc_L3_ENTRY_2m_field32_set(unit, &l3_ipv4_mentry, 6514 VALID_0f, 1); 6515 soc_L3_ENTRY_2m_field32_set(unit, &l3_ipv4_mentry, 6516 IPV4MC__GROUP_IP_ADDRf, ip_addr); 6517 soc_L3_ENTRY_2m_field32_set(unit, &l3_ipv4_mentry, 6518 IPV4MC__SOURCE_IP_ADDRf, gateway); 6519 soc_L3_ENTRY_2m_field32_set(unit, &l3_ipv4_mentry, 6520 VRF_IDf, vrf); 6521 soc_L3_ENTRY_2m_field32_set(unit, &l3_ipv4_mentry, 6522 IPV4MC__VLAN_IDf, vlan); 6523 } else { 6524 l3_entry_mem = L3_ENTRY_1m; 6525 entry = &l3_ipv4_uentry; 6526 sal_memset(&l3_ipv4_uentry, 0, sizeof(l3_ipv4_uentry)); 6527 soc_L3_ENTRY_1m_field32_set(unit, &l3_ipv4_uentry, VALIDf, 1); 6528 soc_L3_ENTRY_1m_field32_set(unit, &l3_ipv4_uentry, 6529 IP_ADDRf, ip_addr); 6530 soc_L3_ENTRY_1m_field32_set(unit, &l3_ipv4_uentry, 6531 VRF_IDf, vrf); 6532 soc_L3_ENTRY_1m_field32_set(unit, &l3_ipv4_uentry, 6533 KEY_TYPEf, SOC_MEM_KEY_L3_ENTRY_1_IPV4UC_IPV4_UNICAST); 6534 } 6535 6536 rc = soc_ism_get_banks_for_mem(unit, l3_entry_mem, banks, sizes, 6537 &bcount); 6538 if (rc || !bcount) { 6539 cli_out("Error retreiving bank info: Test aborted.\n"); 6540 return CMD_FAIL; 6541 } 6542 rc = soc_generic_get_hash_key(unit, l3_entry_mem, entry, 6543 keyflds, &lsbfld, &num_flds); 6544 if (rc) { 6545 cli_out("Error constructing key: Test aborted.\n"); 6546 return CMD_FAIL; 6547 } 6548 sal_memset(key, 0, sizeof(key)); 6549 soc_ism_gen_key_from_keyfields(unit, l3_entry_mem, 6550 entry, keyflds, key, num_flds); 6551 6552 key_nbits = soc_ism_mem_max_key_bits_get(unit, l3_entry_mem); 6553 cli_out("Hash(%s)[%d] of key 0x", 6554 (mcast_flag) ? "Ipv4MC" : "IPv4UC", hash_select); 6555 for (loop = BITS2BYTES(key_nbits); loop > 0; loop--) { 6556 cli_out("%02x", key[loop - 1]); 6557 } 6558 cli_out("\n"); 6559 for (b = 0; b < bcount; b++) { 6560 rc = soc_ism_mem_hash_config_get(unit, l3_entry_mem, &act_zero_lsb); 6561 if (rc) { 6562 cli_out("Error retreiving hash config: Test aborted.\n"); 6563 return CMD_FAIL; 6564 } 6565 rc = soc_ism_hash_offset_config_get(unit, banks[b], &act_offset); 6566 if (rc) { 6567 cli_out("Error retreiving hash offset: Test aborted.\n"); 6568 return CMD_FAIL; 6569 } 6570 switch(hash_select) { 6571 case XGS_HASH_CRC16_UPPER: 6572 offset = 48 - soc_ism_get_hash_bits(sizes[b]); 6573 break; 6574 case XGS_HASH_CRC16_LOWER: 6575 offset = 32; 6576 break; 6577 case XGS_HASH_LSB: 6578 offset = 48; zero_lsb = 1; 6579 break; 6580 case XGS_HASH_ZERO: 6581 break; 6582 case XGS_HASH_CRC32_UPPER: 6583 offset = 32 - soc_ism_get_hash_bits(sizes[b]); 6584 break; 6585 case XGS_HASH_CRC32_LOWER: 6586 offset = 0; 6587 break; 6588 case XGS_HASH_COUNT: 6589 offset = act_offset; zero_lsb = act_zero_lsb; 6590 break; 6591 default: 6592 if (hash_select > 63) { 6593 cli_out("Invalid hash offset value !!\n"); 6594 return CMD_FAIL; 6595 } 6596 offset = hash_select; if (hash_select >= 48) { zero_lsb = 1; } 6597 break; 6598 } 6599 /* get config */ 6600 if (zero_lsb != act_zero_lsb) { 6601 rc = soc_ism_mem_hash_config(unit, l3_entry_mem, zero_lsb); 6602 if (rc) { 6603 cli_out("Error setting hash config: Test aborted.\n"); 6604 return CMD_FAIL; 6605 } 6606 } 6607 if (offset != act_offset) { 6608 rc = soc_ism_hash_offset_config(unit, banks[b], offset); 6609 if (rc) { 6610 cli_out("Error setting hash offset: Test aborted.\n"); 6611 return CMD_FAIL; 6612 } 6613 } 6614 rc = soc_generic_hash(unit, l3_entry_mem, entry, 1 << banks[b], 0, 6615 &index, NULL, &bucket, NULL); 6616 if (rc) { 6617 cli_out("Error calculating hash: Test aborted.\n"); 6618 return CMD_FAIL; 6619 } 6620 cli_out("\tBank[%d] num: %d, bucket: %d, index: %d\n", b, 6621 banks[b], bucket, index); 6622 /* restore config */ 6623 if (zero_lsb != act_zero_lsb) { 6624 rc = soc_ism_mem_hash_config(unit, l3_entry_mem, act_zero_lsb); 6625 if (rc) { 6626 cli_out("Error setting hash config: Test aborted.\n"); 6627 return CMD_FAIL; 6628 } 6629 } 6630 if (offset != act_offset) { 6631 rc = soc_ism_hash_offset_config(unit, banks[b], act_offset); 6632 if (rc) { 6633 cli_out("Error setting hash offset: Test aborted.\n"); 6634 return CMD_FAIL; 6635 } 6636 } 6637 } 6638 return CMD_OK; 6639 } 6640 #endif /* BCM_ISM_SUPPORT */ 6641 6642 #ifdef BCM_TRX_SUPPORT 6643 if (SOC_MEM_FIELD_VALID(unit, L3_ENTRY_ONLYm, KEY_TYPEf)) { 6644 6645 int mcast_flag = 0; 6646 int hash_bucket; 6647 int key_nbits; 6648 l3_entry_ipv4_multicast_entry_t l3x_ip4_mentry; 6649 l3_entry_ipv4_unicast_entry_t l3x_ip4_uentry; 6650 soc_field_t key_type_field; 6651 int key_type_value; 6652 6653 if (hash_select == FB_HASH_COUNT) { 6654 /* Get the hash selection from hardware */ 6655 uint32 regval; 6656 int rv; 6657 if ((rv = READ_HASH_CONTROLr(unit, ®val)) < 0) { 6658 cli_out("%s: ERROR: %s\n", ARG_CMD(a), soc_errmsg(rv)); 6659 return CMD_FAIL; 6660 } 6661 hash_select = soc_reg_field_get(unit, HASH_CONTROLr, regval, 6662 L3_HASH_SELECTf); 6663 } 6664 6665 if (L3X_IP_MULTICAST(ip_addr)) { 6666 /* Given IP address is multicast IP address */ 6667 mcast_flag = 1; 6668 key_type_field = (SOC_MEM_FIELD_VALID(unit, 6669 L3_ENTRY_IPV4_MULTICASTm, KEY_TYPEf))? 6670 KEY_TYPEf : KEY_TYPE_0f; 6671 #if defined(BCM_TRIDENT2_SUPPORT) 6672 if (SOC_IS_TRIDENT2X(unit)) { 6673 key_type_value = TD2_L3_HASH_KEY_TYPE_V4MC; 6674 } else 6675 #endif /* BCM_TRIDENT2_SUPPORT */ 6676 { 6677 key_type_value = TR_L3_HASH_KEY_TYPE_V4MC; 6678 } 6679 6680 sal_memset(&l3x_ip4_mentry, 0, 6681 sizeof(l3_entry_ipv4_multicast_entry_t)); 6682 6683 6684 soc_mem_field32_set(unit, L3_ENTRY_IPV4_MULTICASTm, 6685 (uint32 *) &l3x_ip4_mentry, 6686 key_type_field, key_type_value); 6687 6688 soc_mem_field32_set(unit, L3_ENTRY_IPV4_MULTICASTm, 6689 (uint32 *) &l3x_ip4_mentry, 6690 GROUP_IP_ADDRf, ip_addr); 6691 6692 soc_mem_field32_set(unit, L3_ENTRY_IPV4_MULTICASTm, 6693 (uint32 *) &l3x_ip4_mentry, 6694 SOURCE_IP_ADDRf, gateway); 6695 6696 soc_mem_field32_set(unit, L3_ENTRY_IPV4_MULTICASTm, 6697 (uint32 *) &l3x_ip4_mentry, VLAN_IDf, 6698 vlan); 6699 6700 /* prevent the case once VRF_ID field is not existed */ 6701 if (soc_mem_field_valid(unit, L3_ENTRY_IPV4_MULTICASTm, VRF_IDf)) { 6702 soc_mem_field32_set(unit, L3_ENTRY_IPV4_MULTICASTm, 6703 (uint32 *) &l3x_ip4_mentry, 6704 VRF_IDf, vrf); 6705 } 6706 /* coverity[overrun-buffer-val : FALSE] */ 6707 key_nbits = soc_fb_l3x_base_entry_to_key(unit, 6708 (uint32 *) &l3x_ip4_mentry, key); 6709 } else { 6710 /* Given IP address is Unicast IP address */ 6711 #if defined(BCM_TRIDENT2_SUPPORT) 6712 if (SOC_IS_TRIDENT2X(unit)) { 6713 key_type_value = TD2_L3_HASH_KEY_TYPE_V4UC; 6714 } else 6715 #endif /* BCM_TRIDENT2_SUPPORT */ 6716 { 6717 key_type_value = TR_L3_HASH_KEY_TYPE_V4UC; 6718 } 6719 sal_memset(&l3x_ip4_uentry, 0, 6720 sizeof(l3_entry_ipv4_unicast_entry_t)); 6721 6722 soc_mem_field32_set(unit, L3_ENTRY_IPV4_UNICASTm, 6723 (uint32 *) &l3x_ip4_mentry, KEY_TYPEf, 6724 key_type_value); 6725 6726 soc_mem_field32_set(unit, L3_ENTRY_IPV4_UNICASTm, 6727 (uint32 *) &l3x_ip4_uentry, 6728 IP_ADDRf, ip_addr); 6729 6730 /* prevent the case once VRF_ID field is not existed */ 6731 if (soc_mem_field_valid(unit, L3_ENTRY_IPV4_UNICASTm, VRF_IDf)) { 6732 soc_mem_field32_set(unit, L3_ENTRY_IPV4_UNICASTm, 6733 (uint32 *) &l3x_ip4_uentry, 6734 VRF_IDf, vrf); 6735 } 6736 /* coverity[overrun-buffer-val : FALSE] */ 6737 key_nbits = soc_fb_l3x_base_entry_to_key(unit, 6738 (uint32 *) &l3x_ip4_uentry, 6739 key); 6740 } 6741 6742 hash_bucket = soc_fb_l3_hash(unit, hash_select, key_nbits, key); 6743 6744 if (mcast_flag) { 6745 cli_out("Hash(IPMC)[%d] of key " 6746 "0x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x " 6747 "is bucket 0x%03x (%d)\n", hash_select, 6748 key[9], key[8], key[7], key[6], key[5], 6749 key[4], key[3], key[2], key[1], key[0], 6750 hash_bucket, hash_bucket); 6751 } else { 6752 cli_out("Hash(UC)[%d] of key " 6753 "0x%02x%02x%02x%02x " 6754 "is bucket 0x%03x (%d)\n", hash_select, 6755 key[3], key[2], key[1], key[0], 6756 hash_bucket, hash_bucket); 6757 } 6758 break; 6759 } 6760 #endif /* end of BCM_TRX_SUPPORT*/ 6761 #ifdef BCM_FIREBOLT_SUPPORT 6762 if (SOC_IS_FBX(unit)) { 6763 6764 int mcast_flag = 0; 6765 int hash_bucket; 6766 int key_nbits; 6767 l3_entry_ipv4_multicast_entry_t l3x_ip4_mentry; 6768 l3_entry_ipv4_unicast_entry_t l3x_ip4_uentry; 6769 6770 if (hash_select == FB_HASH_COUNT) { 6771 /* Get the hash selection from hardware */ 6772 uint32 regval; 6773 int rv; 6774 if ((rv = READ_HASH_CONTROLr(unit, ®val)) < 0) { 6775 cli_out("%s: ERROR: %s\n", ARG_CMD(a), soc_errmsg(rv)); 6776 return CMD_FAIL; 6777 } 6778 hash_select = soc_reg_field_get(unit, HASH_CONTROLr, regval, 6779 L3_HASH_SELECTf); 6780 } 6781 6782 if (L3X_IP_MULTICAST(ip_addr)) { 6783 /* Given IP address is multicast IP address */ 6784 mcast_flag = 1; 6785 sal_memset(&l3x_ip4_mentry, 0, 6786 sizeof(l3_entry_ipv4_multicast_entry_t)); 6787 6788 soc_mem_field32_set(unit, L3_ENTRY_IPV4_MULTICASTm, 6789 (uint32 *) &l3x_ip4_mentry, IPMCf, 1); 6790 6791 soc_mem_field32_set(unit, L3_ENTRY_IPV4_MULTICASTm, 6792 (uint32 *) &l3x_ip4_mentry, 6793 GROUP_IP_ADDRf, ip_addr); 6794 6795 soc_mem_field32_set(unit, L3_ENTRY_IPV4_MULTICASTm, 6796 (uint32 *) &l3x_ip4_mentry, 6797 SOURCE_IP_ADDRf, gateway); 6798 6799 soc_mem_field32_set(unit, L3_ENTRY_IPV4_MULTICASTm, 6800 (uint32 *) &l3x_ip4_mentry, VLAN_IDf, 6801 vlan); 6802 /* coverity[overrun-buffer-val : FALSE] */ 6803 key_nbits = soc_fb_l3x_base_entry_to_key(unit, 6804 (uint32 *) &l3x_ip4_mentry, key); 6805 } else { 6806 /* Given IP address is Unicast IP address */ 6807 sal_memset(&l3x_ip4_uentry, 0, 6808 sizeof(l3_entry_ipv4_unicast_entry_t)); 6809 6810 #ifdef BCM_TRIDENT3_SUPPORT 6811 if (SOC_IS_TRIDENT3X(unit)) { 6812 uc_mem = L3_ENTRY_SINGLEm; 6813 } 6814 #endif 6815 if (L3X_IP_MULTICAST(ip_addr)) { 6816 soc_mem_field32_set(unit, uc_mem, 6817 (uint32 *) &l3x_ip4_uentry, IPMCf, 1); 6818 } 6819 6820 soc_mem_field32_set(unit, uc_mem, 6821 (uint32 *) &l3x_ip4_uentry, 6822 IP_ADDRf, ip_addr); 6823 /* coverity[overrun-buffer-val : FALSE] */ 6824 key_nbits = soc_fb_l3x_base_entry_to_key(unit, 6825 (uint32 *) &l3x_ip4_uentry, 6826 key); 6827 } 6828 6829 hash_bucket = soc_fb_l3_hash(unit, hash_select, key_nbits, key); 6830 6831 if (mcast_flag) { 6832 cli_out("Hash(IPMC)[%d] of key " 6833 "0x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x " 6834 "is bucket 0x%03x (%d)\n", hash_select, 6835 key[9], key[8], key[7], key[6], key[5], 6836 key[4], key[3], key[2], key[1], key[0], 6837 hash_bucket, hash_bucket); 6838 } else { 6839 cli_out("Hash(UC)[%d] of key " 6840 "0x%02x%02x%02x%02x " 6841 "is bucket 0x%03x (%d)\n", hash_select, 6842 key[3], key[2], key[1], key[0], 6843 hash_bucket, hash_bucket); 6844 } 6845 } 6846 #endif /* end of BCM_FIREBOLT_SUPPORT */ 6847 break; 6848 6849 /* l3 l3table ip6hash */ 6850 case L3_IP6HASH: 6851 if (!SOC_IS_FBX(unit)) { 6852 cli_out("Command valid only for FB and ER switches\n"); 6853 return CMD_FAIL; 6854 } 6855 #ifdef BCM_XGS3_SWITCH_SUPPORT 6856 parse_table_init(unit, &pt); 6857 #if defined(BCM_TRX_SUPPORT) 6858 if (SOC_IS_TRX(unit)) { 6859 parse_table_add(&pt, "VRF", PQ_DFL|PQ_INT, 0, 6860 (void *)&vrf, 0); 6861 } 6862 #endif 6863 sal_memset(&ip6_addr, 0, sizeof(ip6_addr)); 6864 sal_memset(&sip6_addr, 0, sizeof(sip6_addr)); 6865 parse_table_add(&pt, "IP", PQ_DFL | PQ_IP6, 0, 6866 (void *)&ip6_addr, 0); 6867 parse_table_add(&pt, "SrcIP", PQ_DFL | PQ_IP6, 0, 6868 (void *)&sip6_addr, 0); 6869 parse_table_add(&pt, "VID", PQ_DFL | PQ_INT, 0, 6870 (void *)&id, 0); 6871 parse_table_add(&pt, "Hash", PQ_DFL | PQ_INT, 0, 6872 (void *)&hash_select, 0); 6873 parse_table_add(&pt, "SIPKey", PQ_DFL | PQ_INT, 0, 6874 (void *)&sip_key, 0); 6875 if (!parseEndOk(a, &pt, &retCode)) { 6876 return retCode; 6877 } 6878 vlan = id; 6879 6880 #ifdef BCM_ISM_SUPPORT 6881 if (soc_feature(unit, soc_feature_ism_memory)) { 6882 int b, rc, index, loop, key_nbits; 6883 l3_entry_2_entry_t l3_ipv6_uentry; 6884 l3_entry_4_entry_t l3_ipv6_mentry; 6885 soc_field_t keyflds[MAX_FIELDS], lsbfld; 6886 uint32 bucket, sizes[_SOC_ISM_MAX_BANKS]; 6887 uint8 act_zero_lsb, act_offset, zero_lsb = 0, offset = 48; 6888 uint8 banks[_SOC_ISM_MAX_BANKS], bcount, num_flds; 6889 soc_mem_t l3_entry_mem; 6890 int mcast_flag = 0; 6891 void *entry; 6892 6893 if (BCM_IP6_MULTICAST(ip6_addr)) { 6894 soc_field_t typef[] = {KEY_TYPE_0f, KEY_TYPE_1f, 6895 KEY_TYPE_2f, KEY_TYPE_3f}; 6896 mcast_flag = 1; 6897 l3_entry_mem = L3_ENTRY_4m; 6898 entry = &l3_ipv6_mentry; 6899 sal_memset(&l3_ipv6_mentry, 0, sizeof(l3_ipv6_mentry)); 6900 soc_L3_ENTRY_4m_field32_set(unit, &l3_ipv6_mentry, 6901 VALID_0f, 1); 6902 soc_mem_ip6_addr_set(unit, L3_ENTRY_4m, &l3_ipv6_mentry, 6903 IPV6MC__GROUP_IP_ADDR_LWR_96f, ip6_addr, 6904 SOC_MEM_IP6_LOWER_96BIT); 6905 soc_mem_ip6_addr_set(unit, L3_ENTRY_4m, &l3_ipv6_mentry, 6906 IPV6MC__GROUP_IP_ADDR_UPR_24f, ip6_addr, 6907 SOC_MEM_IP6_BITS_119_96); 6908 soc_mem_ip6_addr_set(unit, L3_ENTRY_4m, &l3_ipv6_mentry, 6909 IPV6MC__SOURCE_IP_ADDR_LWR_64f, sip6_addr, 6910 SOC_MEM_IP6_LOWER_ONLY); 6911 soc_mem_ip6_addr_set(unit, L3_ENTRY_4m, &l3_ipv6_mentry, 6912 IPV6MC__SOURCE_IP_ADDR_UPR_64f, sip6_addr, 6913 SOC_MEM_IP6_UPPER_ONLY); 6914 soc_L3_ENTRY_4m_field32_set(unit, &l3_ipv6_mentry, 6915 IPV6MC__VRF_IDf, vrf); 6916 soc_L3_ENTRY_4m_field32_set(unit, &l3_ipv6_mentry, 6917 IPV6MC__VLAN_IDf, id); 6918 for (i = 0; i < 4; i++) { 6919 soc_L3_ENTRY_4m_field32_set(unit, &l3_ipv6_mentry, 6920 typef[i], 6921 SOC_MEM_KEY_L3_ENTRY_4_IPV6MC_IPV6_MULTICAST); 6922 } 6923 } else { 6924 l3_entry_mem = L3_ENTRY_2m; 6925 entry = &l3_ipv6_uentry; 6926 sal_memset(&l3_ipv6_uentry, 0, sizeof(l3_ipv6_uentry)); 6927 soc_L3_ENTRY_2m_field32_set(unit, &l3_ipv6_uentry, 6928 VALID_0f, 1); 6929 soc_mem_ip6_addr_set(unit, L3_ENTRY_2m, &l3_ipv6_uentry, 6930 IPV6UC__IP_ADDR_LWR_64f, ip6_addr, 6931 SOC_MEM_IP6_LOWER_ONLY); 6932 soc_mem_ip6_addr_set(unit, L3_ENTRY_2m, &l3_ipv6_uentry, 6933 IPV6UC__IP_ADDR_UPR_64f, ip6_addr, 6934 SOC_MEM_IP6_UPPER_ONLY); 6935 soc_L3_ENTRY_2m_field32_set(unit, &l3_ipv6_uentry, 6936 VRF_IDf, vrf); 6937 soc_L3_ENTRY_2m_field32_set(unit, &l3_ipv6_uentry, 6938 KEY_TYPE_0f, 6939 SOC_MEM_KEY_L3_ENTRY_2_IPV6UC_IPV6_UNICAST); 6940 soc_L3_ENTRY_2m_field32_set(unit, &l3_ipv6_uentry, 6941 KEY_TYPE_1f, 6942 SOC_MEM_KEY_L3_ENTRY_2_IPV6UC_IPV6_UNICAST); 6943 } 6944 6945 rc = soc_ism_get_banks_for_mem(unit, l3_entry_mem, banks, sizes, 6946 &bcount); 6947 if (rc || !bcount) { 6948 cli_out("Error retreiving bank info: Test aborted.\n"); 6949 return CMD_FAIL; 6950 } 6951 rc = soc_generic_get_hash_key(unit, l3_entry_mem, entry, 6952 keyflds, &lsbfld, &num_flds); 6953 if (rc) { 6954 cli_out("Error constructing key: Test aborted.\n"); 6955 return CMD_FAIL; 6956 } 6957 sal_memset(key, 0, sizeof(key)); 6958 soc_ism_gen_key_from_keyfields(unit, l3_entry_mem, 6959 entry, keyflds, key, num_flds); 6960 6961 key_nbits = soc_ism_mem_max_key_bits_get(unit, l3_entry_mem); 6962 cli_out("Hash(%s)[%d] of key 0x", 6963 (mcast_flag) ? "Ipv6MC" : "IPv6UC", hash_select); 6964 for (loop = BITS2BYTES(key_nbits); loop > 0; loop--) { 6965 cli_out("%02x", key[loop - 1]); 6966 } 6967 cli_out("\n"); 6968 for (b = 0; b < bcount; b++) { 6969 rc = soc_ism_mem_hash_config_get(unit, l3_entry_mem, &act_zero_lsb); 6970 if (rc) { 6971 cli_out("Error retreiving hash config: Test aborted.\n"); 6972 return CMD_FAIL; 6973 } 6974 rc = soc_ism_hash_offset_config_get(unit, banks[b], &act_offset); 6975 if (rc) { 6976 cli_out("Error retreiving hash offset: Test aborted.\n"); 6977 return CMD_FAIL; 6978 } 6979 switch(hash_select) { 6980 case XGS_HASH_CRC16_UPPER: 6981 offset = 48 - soc_ism_get_hash_bits(sizes[b]); 6982 break; 6983 case XGS_HASH_CRC16_LOWER: 6984 offset = 32; 6985 break; 6986 case XGS_HASH_LSB: 6987 offset = 48; zero_lsb = 1; 6988 break; 6989 case XGS_HASH_ZERO: 6990 break; 6991 case XGS_HASH_CRC32_UPPER: 6992 offset = 32 - soc_ism_get_hash_bits(sizes[b]); 6993 break; 6994 case XGS_HASH_CRC32_LOWER: 6995 offset = 0; 6996 break; 6997 case XGS_HASH_COUNT: 6998 offset = act_offset; zero_lsb = act_zero_lsb; 6999 break; 7000 default: 7001 if (hash_select > 63) { 7002 cli_out("Invalid hash offset value !!\n"); 7003 return CMD_FAIL; 7004 } 7005 offset = hash_select; if (hash_select >= 48) { zero_lsb = 1; } 7006 break; 7007 } 7008 /* get config */ 7009 if (zero_lsb != act_zero_lsb) { 7010 rc = soc_ism_mem_hash_config(unit, l3_entry_mem, zero_lsb); 7011 if (rc) { 7012 cli_out("Error setting hash config: Test aborted.\n"); 7013 return CMD_FAIL; 7014 } 7015 } 7016 if (offset != act_offset) { 7017 rc = soc_ism_hash_offset_config(unit, banks[b], offset); 7018 if (rc) { 7019 cli_out("Error setting hash offset: Test aborted.\n"); 7020 return CMD_FAIL; 7021 } 7022 } 7023 rc = soc_generic_hash(unit, l3_entry_mem, entry, 1 << banks[b], 0, 7024 &index, NULL, &bucket, NULL); 7025 if (rc) { 7026 cli_out("Error calculating hash: Test aborted.\n"); 7027 return CMD_FAIL; 7028 } 7029 cli_out("\tBank[%d] num: %d, bucket: %d, index: %d\n", b, 7030 banks[b], bucket, index); 7031 /* restore config */ 7032 if (zero_lsb != act_zero_lsb) { 7033 rc = soc_ism_mem_hash_config(unit, l3_entry_mem, act_zero_lsb); 7034 if (rc) { 7035 cli_out("Error setting hash config: Test aborted.\n"); 7036 return CMD_FAIL; 7037 } 7038 } 7039 if (offset != act_offset) { 7040 rc = soc_ism_hash_offset_config(unit, banks[b], act_offset); 7041 if (rc) { 7042 cli_out("Error setting hash offset: Test aborted.\n"); 7043 return CMD_FAIL; 7044 } 7045 } 7046 } 7047 return CMD_OK; 7048 } 7049 #endif /* BCM_ISM_SUPPORT */ 7050 7051 if (hash_select == FB_HASH_COUNT) { 7052 /* Get the hash selection from hardware */ 7053 uint32 regval; 7054 int rv; 7055 7056 if ((rv = READ_HASH_CONTROLr(unit, ®val)) < 0) { 7057 cli_out("%s: ERROR: %s\n", ARG_CMD(a), soc_errmsg(rv)); 7058 return CMD_FAIL; 7059 } 7060 hash_select = soc_reg_field_get(unit, HASH_CONTROLr, regval, 7061 L3_HASH_SELECTf); 7062 } 7063 #endif 7064 #ifdef BCM_TRX_SUPPORT 7065 if (SOC_MEM_FIELD_VALID(unit, L3_ENTRY_ONLYm, KEY_TYPEf)) { 7066 int key_nbits; 7067 int hash_bucket = 0; 7068 int mcast_flag =0; 7069 int loop; 7070 l3_entry_ipv6_unicast_entry_t l3x_ip6_uentry; 7071 l3_entry_ipv6_multicast_entry_t l3x_ip6_mentry; 7072 soc_field_t vrf_field, vlan_field; 7073 int key_type_value; 7074 7075 if (BCM_IP6_MULTICAST(ip6_addr)) { 7076 soc_field_t typef[] = {KEY_TYPE_0f, KEY_TYPE_1f, 7077 KEY_TYPE_2f, KEY_TYPE_3f}; 7078 mcast_flag = 1; 7079 7080 #if defined(BCM_TRIDENT2_SUPPORT) 7081 if (SOC_IS_TRIDENT2X(unit)) { 7082 key_type_value = TD2_L3_HASH_KEY_TYPE_V6MC; 7083 } else 7084 #endif /* BCM_TRIDENT2_SUPPORT */ 7085 { 7086 key_type_value = TR_L3_HASH_KEY_TYPE_V6MC; 7087 } 7088 sal_memset(&l3x_ip6_mentry, 0, 7089 sizeof(l3_entry_ipv6_multicast_entry_t)); 7090 7091 soc_mem_ip6_addr_set(unit, L3_ENTRY_IPV6_MULTICASTm, 7092 &l3x_ip6_mentry, 7093 GROUP_IP_ADDR_LWR_64f, 7094 (uint8*) &ip6_addr, 7095 SOC_MEM_IP6_LOWER_ONLY); 7096 7097 ip6_addr[0] = 0x0; 7098 soc_mem_ip6_addr_set(unit, L3_ENTRY_IPV6_MULTICASTm, 7099 &l3x_ip6_mentry, GROUP_IP_ADDR_UPR_56f, 7100 (uint8*) &ip6_addr, 7101 SOC_MEM_IP6_UPPER_ONLY); 7102 7103 soc_mem_ip6_addr_set(unit, L3_ENTRY_IPV6_MULTICASTm, 7104 &l3x_ip6_mentry, SOURCE_IP_ADDR_LWR_64f, 7105 (uint8*) &sip6_addr, 7106 SOC_MEM_IP6_LOWER_ONLY); 7107 7108 soc_mem_ip6_addr_set(unit, L3_ENTRY_IPV6_MULTICASTm, 7109 &l3x_ip6_mentry, SOURCE_IP_ADDR_UPR_64f, 7110 (uint8*) &sip6_addr, 7111 SOC_MEM_IP6_UPPER_ONLY); 7112 7113 vlan_field = (SOC_MEM_FIELD_VALID(unit, 7114 L3_ENTRY_IPV6_MULTICASTm, VLAN_IDf))? \ 7115 VLAN_IDf: VLAN_ID_0f; 7116 7117 soc_L3_ENTRY_IPV6_MULTICASTm_field32_set(unit, 7118 &l3x_ip6_mentry, vlan_field, vlan); 7119 7120 vrf_field = (SOC_MEM_FIELD_VALID(unit, 7121 L3_ENTRY_IPV6_MULTICASTm, VRF_IDf))? \ 7122 VRF_IDf: VRF_ID_0f; 7123 7124 /* prevent the case once VRF_ID field is not existed */ 7125 if (soc_mem_field_valid(unit, 7126 L3_ENTRY_IPV6_MULTICASTm, vrf_field)) { 7127 soc_L3_ENTRY_IPV6_MULTICASTm_field32_set(unit, 7128 &l3x_ip6_mentry, vrf_field, vrf); 7129 } 7130 7131 for (i=0; i < 4; i++) { 7132 soc_L3_ENTRY_IPV6_MULTICASTm_field32_set 7133 (unit, &l3x_ip6_mentry, typef[i], 7134 key_type_value); 7135 } 7136 /* coverity[overrun-buffer-val : FALSE] */ 7137 key_nbits = soc_fb_l3x_base_entry_to_key(unit, 7138 (uint32 *) &l3x_ip6_mentry, key); 7139 } else { 7140 #if defined(BCM_TRIDENT2_SUPPORT) 7141 if (SOC_IS_TRIDENT2X(unit)) { 7142 key_type_value = TD2_L3_HASH_KEY_TYPE_V6UC; 7143 } else 7144 #endif /* BCM_TRIDENT2_SUPPORT */ 7145 { 7146 key_type_value = TR_L3_HASH_KEY_TYPE_V6UC; 7147 } 7148 sal_memset(&l3x_ip6_uentry, 0, 7149 sizeof(l3_entry_ipv6_unicast_entry_t)); 7150 7151 soc_mem_ip6_addr_set(unit, L3_ENTRY_IPV6_UNICASTm, 7152 &l3x_ip6_uentry, IP_ADDR_LWR_64f, 7153 ip6_addr, SOC_MEM_IP6_LOWER_ONLY); 7154 7155 soc_mem_ip6_addr_set(unit, L3_ENTRY_IPV6_UNICASTm, 7156 &l3x_ip6_uentry, IP_ADDR_UPR_64f, 7157 ip6_addr, SOC_MEM_IP6_UPPER_ONLY); 7158 7159 soc_L3_ENTRY_IPV6_UNICASTm_field32_set 7160 (unit, &l3x_ip6_uentry, KEY_TYPE_1f, key_type_value); 7161 7162 soc_L3_ENTRY_IPV6_UNICASTm_field32_set 7163 (unit, &l3x_ip6_uentry, KEY_TYPE_0f, key_type_value); 7164 7165 vrf_field = (SOC_MEM_FIELD_VALID(unit, 7166 L3_ENTRY_IPV6_UNICASTm, VRF_IDf))? \ 7167 VRF_IDf: VRF_ID_0f; 7168 7169 /* prevent the case once VRF_ID field is not existed */ 7170 if (soc_mem_field_valid(unit, 7171 L3_ENTRY_IPV6_UNICASTm, vrf_field)) { 7172 soc_L3_ENTRY_IPV6_UNICASTm_field32_set(unit, 7173 &l3x_ip6_mentry, vrf_field, vrf); 7174 } 7175 /* coverity[overrun-buffer-val : FALSE] */ 7176 key_nbits = soc_fb_l3x_base_entry_to_key(unit, 7177 (uint32 *) &l3x_ip6_uentry, key); 7178 } 7179 hash_bucket = soc_fb_l3_hash(unit, hash_select, key_nbits, key); 7180 if (mcast_flag) { 7181 cli_out("Hash(IPMC)[%d] of key 0x",hash_select); 7182 for (loop = BITS2BYTES(key_nbits); loop > 0; loop--) { 7183 cli_out("%02x", key[loop - 1]); 7184 } 7185 cli_out(" "); 7186 cli_out("is bucket 0x%3x (%d)\n", hash_bucket, 7187 hash_bucket); 7188 } else { 7189 cli_out("Hash(UC)[%d] of key 0x",hash_select); 7190 for (loop = BITS2BYTES(key_nbits); loop > 0; loop--) { 7191 cli_out("%02x", key[loop - 1]); 7192 } 7193 cli_out(" "); 7194 cli_out("is bucket 0x%3x (%d)\n", hash_bucket, 7195 hash_bucket); 7196 } 7197 break; 7198 } 7199 #endif /* BCM_TRX_SUPPORT */ 7200 #ifdef BCM_FIREBOLT_SUPPORT 7201 if (SOC_IS_FBX(unit)) { 7202 int key_nbits; 7203 int hash_bucket = 0; 7204 int mcast_flag =0; 7205 int loop; 7206 l3_entry_ipv6_unicast_entry_t l3x_ip6_uentry; 7207 l3_entry_ipv6_multicast_entry_t l3x_ip6_mentry; 7208 7209 if (BCM_IP6_MULTICAST(ip6_addr)) { 7210 soc_field_t v6f[] = {V6_0f, V6_1f, V6_2f, V6_3f}; 7211 soc_field_t mcf[] = {IPMC_0f, IPMC_1f, IPMC_2f, IPMC_3f}; 7212 soc_field_t vidf[] = {VLAN_ID_0f, VLAN_ID_1f, VLAN_ID_2f, 7213 VLAN_ID_3f}; 7214 mcast_flag = 1; 7215 7216 sal_memset(&l3x_ip6_mentry, 0, 7217 sizeof(l3_entry_ipv6_multicast_entry_t)); 7218 7219 soc_mem_ip6_addr_set(unit, L3_ENTRY_IPV6_MULTICASTm, 7220 &l3x_ip6_mentry, 7221 GROUP_IP_ADDR_LWR_64f, 7222 (uint8*) &ip6_addr, 7223 SOC_MEM_IP6_LOWER_ONLY); 7224 7225 ip6_addr[0] = 0x0; 7226 soc_mem_ip6_addr_set(unit, L3_ENTRY_IPV6_MULTICASTm, 7227 &l3x_ip6_mentry, GROUP_IP_ADDR_UPR_56f, 7228 (uint8*) &ip6_addr, 7229 SOC_MEM_IP6_UPPER_ONLY); 7230 7231 soc_mem_ip6_addr_set(unit, L3_ENTRY_IPV6_MULTICASTm, 7232 &l3x_ip6_mentry, SOURCE_IP_ADDR_LWR_64f, 7233 (uint8*) &sip6_addr, 7234 SOC_MEM_IP6_LOWER_ONLY); 7235 7236 soc_mem_ip6_addr_set(unit, L3_ENTRY_IPV6_MULTICASTm, 7237 &l3x_ip6_mentry, SOURCE_IP_ADDR_UPR_64f, 7238 (uint8*) &sip6_addr, 7239 SOC_MEM_IP6_UPPER_ONLY); 7240 7241 for (i=0; i < 4; i++) { 7242 soc_L3_ENTRY_IPV6_MULTICASTm_field32_set(unit, 7243 &l3x_ip6_mentry, v6f[i], 1); 7244 soc_L3_ENTRY_IPV6_MULTICASTm_field32_set(unit, 7245 &l3x_ip6_mentry, mcf[i], 1); 7246 soc_L3_ENTRY_IPV6_MULTICASTm_field32_set(unit, 7247 &l3x_ip6_mentry, vidf[i], vlan); 7248 } 7249 /* coverity[overrun-buffer-val : FALSE] */ 7250 key_nbits = soc_fb_l3x_base_entry_to_key(unit, 7251 (uint32 *) &l3x_ip6_mentry, key); 7252 } else { 7253 sal_memset(&l3x_ip6_uentry, 0, 7254 sizeof(l3_entry_ipv6_unicast_entry_t)); 7255 7256 soc_mem_ip6_addr_set(unit, L3_ENTRY_IPV6_UNICASTm, 7257 &l3x_ip6_uentry, IP_ADDR_LWR_64f, 7258 ip6_addr, SOC_MEM_IP6_LOWER_ONLY); 7259 7260 soc_mem_ip6_addr_set(unit, L3_ENTRY_IPV6_UNICASTm, 7261 &l3x_ip6_uentry, IP_ADDR_UPR_64f, 7262 ip6_addr, SOC_MEM_IP6_UPPER_ONLY); 7263 7264 soc_L3_ENTRY_IPV6_UNICASTm_field32_set(unit, 7265 &l3x_ip6_uentry, 7266 V6_1f, 1); 7267 7268 soc_L3_ENTRY_IPV6_UNICASTm_field32_set(unit, 7269 &l3x_ip6_uentry, 7270 V6_0f, 1); 7271 /* coverity[overrun-buffer-val : FALSE] */ 7272 key_nbits = soc_fb_l3x_base_entry_to_key(unit, 7273 (uint32 *) &l3x_ip6_uentry, key); 7274 } 7275 hash_bucket = soc_fb_l3_hash(unit, hash_select, 7276 key_nbits, key); 7277 if (mcast_flag) { 7278 cli_out("Hash(IPMC)[%d] of key 0x",hash_select); 7279 for (loop = BITS2BYTES(key_nbits); loop > 0; loop--) { 7280 cli_out("%02x", key[loop - 1]); 7281 } 7282 cli_out(" "); 7283 cli_out("is bucket 0x%3x (%d)\n", hash_bucket, 7284 hash_bucket); 7285 } else { 7286 cli_out("Hash(UC)[%d] of key 0x",hash_select); 7287 for (loop = BITS2BYTES(key_nbits); loop > 0; loop--) { 7288 cli_out("%02x", key[loop - 1]); 7289 } 7290 cli_out(" "); 7291 cli_out("is bucket 0x%3x (%d)\n", hash_bucket, 7292 hash_bucket); 7293 } 7294 } 7295 #endif /* BCM_FIREBOLT_SUPPORT */ 7296 break; 7297 7298 /* l3 l3table sanity */ 7299 case L3_SANITY: 7300 cli_out("Command only valid for XGS2 switches\n"); 7301 return CMD_FAIL; 7302 case L3_CONFLICT: 7303 return _l3_cmd_l3_conflict_show(unit, a); 7304 #endif /* BCM_XGS_SWITCH_SUPPORT*/ 7305 default: 7306 return CMD_USAGE; 7307 break; 7308 } 7309 7310 return CMD_OK; 7311 } 7312 7313 if (sal_strcasecmp(table, "defip") == 0) { 7314 switch (subcmd) { 7315 /* l3 defip add */ 7316 case L3_ADD: 7317 return _l3_cmd_route_add(unit, a, FALSE); 7318 /* l3 defip destroy */ 7319 case L3_DESTROY: 7320 parse_table_init(unit, &pt); 7321 #if defined(BCM_XGS3_SWITCH_SUPPORT) 7322 parse_table_add(&pt, "VRF", PQ_DFL | PQ_INT, 0, (void *)&vrf, 0); 7323 #endif 7324 parse_table_add(&pt, "IP", PQ_DFL | PQ_IP, 0, (void *)&ip_addr, 0); 7325 parse_table_add(&pt, "MaSk", PQ_DFL | PQ_IP, 0, (void *)&mask, 0); 7326 #ifdef BCM_XGS_SWITCH_SUPPORT 7327 parse_table_add(&pt, "ECMP", PQ_DFL | PQ_BOOL, 0, (void *)&ecmp, 0); 7328 parse_table_add(&pt, "Mac", PQ_DFL | PQ_MAC, 0, (void *)mac, 0); 7329 parse_table_add(&pt, "Gateway", PQ_DFL | PQ_IP, 0, (void *)&gateway, 0); 7330 parse_table_add(&pt, "Port", PQ_DFL | PQ_PORT, 0, (void *)&port, 0); 7331 parse_table_add(&pt, "MOdule", PQ_DFL | PQ_INT, 0, (void*)&module, 0); 7332 parse_table_add(&pt, "INtf", PQ_DFL | PQ_INT, 0, (void *)&interface, 0); 7333 parse_table_add(&pt, "VLAN", PQ_DFL | PQ_INT, 0, (void *)&id, 0); 7334 #endif 7335 if (!parseEndOk(a, &pt, &retCode)) { 7336 return retCode; 7337 } 7338 7339 bcm_l3_route_t_init(&route_info); 7340 7341 #if defined(BCM_XGS3_SWITCH_SUPPORT) 7342 route_info.l3a_vrf = vrf; 7343 #endif 7344 route_info.l3a_subnet = ip_addr; 7345 route_info.l3a_ip_mask = mask; 7346 route_info.l3a_vid = id; 7347 if (((mask & 0x80000000) == 0) && ip_addr != 0) { 7348 cli_out("%s: Invalid mask\n", ARG_CMD(a)); 7349 return CMD_FAIL; 7350 } 7351 #ifdef BCM_XGS_SWITCH_SUPPORT 7352 7353 if (ecmp) { 7354 route_info.l3a_flags |= BCM_L3_MULTIPATH; 7355 sal_memcpy(route_info.l3a_nexthop_mac, mac, sizeof(mac)); 7356 route_info.l3a_nexthop_ip = gateway; 7357 route_info.l3a_intf = interface; 7358 route_info.l3a_modid = module; 7359 route_info.l3a_port_tgid = port; 7360 } 7361 #endif 7362 7363 if ((r = bcm_l3_route_delete(unit, &route_info)) < 0) { 7364 format_ipaddr(ip_str, ip_addr); 7365 cli_out("%s: Error deleting %d.%d.%d.%d from DEF IP " 7366 "table: %s\n", ARG_CMD(a), 7367 (route_info.l3a_subnet >> 24) & 0xff, 7368 (route_info.l3a_subnet >> 16) & 0xff, 7369 (route_info.l3a_subnet >> 8) & 0xff, 7370 route_info.l3a_subnet & 0xff, 7371 bcm_errmsg(r)); 7372 return CMD_FAIL; 7373 } 7374 break; 7375 7376 /* l3 defip clear */ 7377 case L3_CLEAR: 7378 bcm_l3_route_delete_all(unit, NULL); 7379 break; 7380 7381 /* l3 defip age */ 7382 case L3_AGE: 7383 bcm_l3_route_age(unit, 0, _l3_cmd_route_age_callback, NULL); 7384 return CMD_OK; 7385 7386 /* l3 defip show */ 7387 case L3_SHOW: 7388 if ((r = bcm_l3_info(unit, &l3_hw_status)) < 0) { 7389 cli_out("%s: Error L3 accessing: %s\n", 7390 ARG_CMD(a), bcm_errmsg(r)); 7391 return CMD_FAIL; 7392 } 7393 free_defip = l3_hw_status.l3info_max_route - 7394 l3_hw_status.l3info_occupied_route; 7395 #if defined(BCM_XGS_SWITCH12_SUPPORT) 7396 free_lpm_blk = l3_hw_status.l3info_max_lpm_block - 7397 l3_hw_status.l3info_used_lpm_block; 7398 #endif 7399 last_entry = l3_hw_status.l3info_max_route; 7400 num_entries = last_entry; 7401 7402 if (ARG_CNT(a)) { 7403 if (!isint(ARG_CUR(a))) { 7404 cli_out("%s: Invalid entry number: %s\n", ARG_CMD(a), 7405 ARG_CUR(a)); 7406 return (CMD_FAIL); 7407 } 7408 first_entry = parse_integer(ARG_GET(a)); 7409 if (first_entry > last_entry) { 7410 cli_out("%s: Error: Illegal entry number (0 to %d)\n", 7411 ARG_CMD(a), last_entry); 7412 return (CMD_FAIL); 7413 } 7414 if (ARG_CNT(a)) { 7415 int tmp_last_entry = 0; 7416 if (!isint(ARG_CUR(a))) { 7417 cli_out("%s: Invalid count: %s\n", ARG_CMD(a), 7418 ARG_CUR(a)); 7419 return (CMD_FAIL); 7420 } 7421 tmp_last_entry = 7422 parse_integer(ARG_GET(a)) + first_entry - 1; 7423 if ((tmp_last_entry > last_entry) || 7424 (tmp_last_entry < first_entry)) { 7425 cli_out("%s: Error: Illegal entry count (1 to %d)\n", 7426 ARG_CMD(a), last_entry - first_entry + 1); 7427 return (CMD_FAIL); 7428 } 7429 last_entry = tmp_last_entry; 7430 } else { 7431 last_entry = first_entry; 7432 } 7433 } else { 7434 first_entry = 0; 7435 } 7436 7437 cli_out("Unit %d, Total Number of DEFIP entries: %d\n", 7438 unit, num_entries); 7439 cli_out("# VRF Net addr Next Hop Mac " 7440 " INTF MODID PORT PRIO CLASS HIT VLAN\n"); 7441 bcm_l3_route_traverse(unit, 0, first_entry, last_entry, 7442 _l3_cmd_route_print, NULL); 7443 return CMD_OK; 7444 7445 #ifdef BCM_XGS_SWITCH_SUPPORT 7446 /* l3 defip ecmp <MAX>=<val> */ 7447 case L3_ECMP: 7448 parse_table_init(unit, &pt); 7449 parse_table_add(&pt, "MAX", PQ_DFL | PQ_INT, 0, (void *)&max_ecmp, 0); 7450 if (!parseEndOk(a, &pt, &retCode)) { 7451 return retCode; 7452 } 7453 7454 bcm_l3_route_max_ecmp_set(unit, max_ecmp); 7455 break; 7456 7457 /* l3 defip ecmphash */ 7458 case L3_ECMP_HASH: 7459 return _l3_cmd_defip_ecmp_hash(unit, a); 7460 #endif /* BCM_XGS_SWITCH_SUPPORT */ 7461 #ifdef FB_LPM_DEBUG 7462 /* l3 defip state check */ 7463 case L3_SANITY: 7464 if (soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) { 7465 if ((r = lpm128_state_verify(unit)) < 0) { 7466 return (CMD_FAIL); 7467 } 7468 cli_out("Successful: Unit %d, Checking lpm states passed!\n", 7469 unit); 7470 } else { 7471 cli_out("Error: Command only valid for LPM scaling mode\n"); 7472 } 7473 break; 7474 #endif /* FB_LPM_DEBUG */ 7475 default: 7476 return CMD_USAGE; 7477 break; 7478 } 7479 7480 return CMD_OK; 7481 } 7482 7483 #if defined(BCM_XGS3_SWITCH_SUPPORT) 7484 7485 #ifdef ALPM_ENABLE 7486 if (sal_strcasecmp(table, "alpm") == 0) { 7487 if (SOC_IS_TD2_TT2(unit) && 7488 soc_feature(unit, soc_feature_alpm) && 7489 soc_property_get(unit, spn_L3_ALPM_ENABLE, 0)) { 7490 switch (subcmd) { 7491 case L3_SHOW: 7492 return _l3_cmd_alpm_debug_show(unit, a); 7493 case L3_FIND: 7494 return _l3_cmd_alpm_find(unit, a); 7495 case L3_SANITY: 7496 return _l3_cmd_alpm_sanity_check(unit, a); 7497 default: 7498 return CMD_USAGE; 7499 } 7500 return CMD_OK; 7501 7502 } else { 7503 cli_out("ALPM is unsupported or disabled!\n" ); 7504 ARG_DISCARD(a); 7505 return CMD_OK; 7506 } 7507 } 7508 #endif 7509 7510 if (sal_strcasecmp(table, "ip6host") == 0) { 7511 switch (subcmd) { 7512 /* l3 ip6host add */ 7513 case L3_ADD: 7514 return _l3_cmd_host_add(unit, a, TRUE); 7515 /* l3 ip6host delete */ 7516 case L3_DESTROY: 7517 parse_table_init(unit, &pt); 7518 parse_table_add(&pt, "VRF", PQ_DFL | PQ_INT, 0, (void *)&vrf, 0); 7519 parse_table_add(&pt, "IP", PQ_DFL | PQ_IP6, 0, (void *)&ip6_addr, 0); 7520 if (!parseEndOk(a, &pt, &retCode)) { 7521 return retCode; 7522 } 7523 7524 sal_memcpy(ip_info.l3a_ip6_addr, ip6_addr, BCM_IP6_ADDRLEN); 7525 ip_info.l3a_vrf = vrf; 7526 ip_info.l3a_flags = BCM_L3_IP6; 7527 if ((r = bcm_l3_host_delete(unit, &ip_info)) < 0) { 7528 cli_out("%s: Error deleting from L3 table %s\n", 7529 ARG_CMD(a), bcm_errmsg(r)); 7530 return CMD_FAIL; 7531 } 7532 break; 7533 7534 /* l3 ip6host clear */ 7535 case L3_CLEAR: 7536 ip_info.l3a_flags = BCM_L3_IP6; 7537 bcm_l3_host_delete_all(unit, &ip_info); 7538 break; 7539 7540 /* l3 ip6host age */ 7541 case L3_AGE: 7542 bcm_l3_host_age(unit, BCM_L3_HIT | BCM_L3_IP6, 7543 _l3_cmd_host_age_callback, NULL); 7544 return CMD_OK; 7545 7546 /* l3 ip6host show */ 7547 case L3_SHOW: 7548 if ((r = bcm_l3_info(unit, &l3_hw_status)) < 0) { 7549 cli_out("%s: Error L3 accessing: %s\n", ARG_CMD(a), bcm_errmsg(r)); 7550 return CMD_FAIL; 7551 } 7552 free_l3 = (l3_hw_status.l3info_max_host - 7553 l3_hw_status.l3info_occupied_host) / 2; 7554 last_entry = l3_hw_status.l3info_max_host / 2; 7555 if (ARG_CNT(a)) { 7556 if (!isint(ARG_CUR(a))) { 7557 cli_out("%s: Invalid number: %s\n", ARG_CMD(a), ARG_CUR(a)); 7558 return (CMD_FAIL); 7559 } 7560 first_entry = parse_integer(ARG_GET(a)); 7561 if (first_entry > last_entry) { 7562 cli_out("%s: Error: Illegal entry number (0 to %d)\n", 7563 ARG_CMD(a), last_entry); 7564 return (CMD_FAIL); 7565 } 7566 last_entry = first_entry; 7567 } else { 7568 first_entry = 0; 7569 } 7570 7571 cli_out("Unit %d, free IPv6 table entries: %d\n", unit, free_l3); 7572 cli_out("Entry VRF IP address " 7573 " Mac Address INTF MOD PORT CLASS HIT" 7574 " H/W Index\n"); 7575 user_data = soc_cm_salloc(unit, sizeof(int), "l3host hw index"); 7576 if (NULL == user_data) { 7577 cli_out("Failed to allocate memory\n"); 7578 return CMD_FAIL; 7579 } 7580 bcm_l3_host_traverse(unit, BCM_L3_IP6 | _BCM_L3_SHOW_INDEX, 7581 first_entry, last_entry, 7582 _l3_cmd_host_print, user_data); 7583 cli_out("\n"); 7584 if (user_data) { 7585 soc_cm_sfree(unit, user_data); 7586 } 7587 return CMD_OK; 7588 default: 7589 return CMD_USAGE; 7590 break; 7591 } 7592 return CMD_OK; 7593 } 7594 7595 if (sal_strcasecmp(table, "ip6route") == 0) { 7596 bcm_ip6_t ip6_mask; 7597 int masklen = -1; 7598 int mask_len_max = 7599 soc_feature(unit, soc_feature_lpm_prefix_length_max_128) ? 128 : 64; 7600 7601 switch (subcmd) { 7602 /* l3 ip6route add */ 7603 case L3_ADD: 7604 return _l3_cmd_route_add(unit, a, TRUE); 7605 7606 /* l3 ip6route delete */ 7607 case L3_DESTROY: 7608 parse_table_init(unit, &pt); 7609 parse_table_add(&pt, "VRF", PQ_DFL | PQ_INT, 0, (void *)&vrf, 0); 7610 parse_table_add(&pt, "IP", PQ_DFL | PQ_IP6, 0, (void *)&ip6_addr, 0); 7611 parse_table_add(&pt, "MaskLen", PQ_DFL | PQ_INT, 0, 7612 (void *)&masklen, 0); 7613 parse_table_add(&pt, "ECMP", PQ_DFL | PQ_BOOL, 0, (void *)&ecmp, 0); 7614 parse_table_add(&pt, "Mac", PQ_DFL | PQ_MAC, 0, (void *)mac, 0); 7615 parse_table_add(&pt, "Port", PQ_DFL | PQ_PORT, 0, (void *)&port, 0); 7616 parse_table_add(&pt, "MOdule", PQ_DFL | PQ_INT, 0, (void*)&module, 0); 7617 parse_table_add(&pt, "INtf", PQ_DFL | PQ_INT, 0, (void *)&interface, 0); 7618 if (!parseEndOk(a, &pt, &retCode)) { 7619 return retCode; 7620 } 7621 7622 if ((masklen < 0) || (masklen > mask_len_max)) { 7623 cli_out("%s: Invalid prefix length.\n", ARG_CMD(a)); 7624 return CMD_FAIL; 7625 } 7626 bcm_l3_route_t_init(&route_info); 7627 7628 route_info.l3a_vrf = vrf; 7629 sal_memcpy(route_info.l3a_ip6_net, ip6_addr, BCM_IP6_ADDRLEN); 7630 bcm_ip6_mask_create(ip6_mask, masklen); 7631 sal_memcpy(route_info.l3a_ip6_mask, ip6_mask, BCM_IP6_ADDRLEN); 7632 sal_memcpy(route_info.l3a_nexthop_mac, mac, sizeof(mac)); 7633 route_info.l3a_flags = BCM_L3_IP6; 7634 if (ecmp) { 7635 route_info.l3a_flags |= BCM_L3_MULTIPATH; 7636 sal_memcpy(route_info.l3a_nexthop_mac, mac, sizeof(mac)); 7637 route_info.l3a_intf = interface; 7638 route_info.l3a_modid = module; 7639 route_info.l3a_port_tgid = port; 7640 } 7641 7642 if ((r = bcm_l3_route_delete(unit, &route_info)) < 0) { 7643 format_ip6addr(ip_str, ip6_addr); 7644 cli_out("ERROR %s: delete %s/%d from DEF IP " 7645 "table: %s\n", ARG_CMD(a), ip_str, masklen, bcm_errmsg(r)); 7646 return CMD_FAIL; 7647 } 7648 break; 7649 7650 /* l3 ip6route clear */ 7651 case L3_CLEAR: 7652 route_info.l3a_flags = BCM_L3_IP6; 7653 bcm_l3_route_delete_all(unit, &route_info); 7654 break; 7655 7656 /* l3 defip age */ 7657 case L3_AGE: 7658 bcm_l3_route_age(unit, BCM_L3_IP6, _l3_cmd_route_age_callback, NULL); 7659 break; 7660 7661 /* l3 ip6route show */ 7662 case L3_SHOW: 7663 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 7664 #ifdef BCM_TRX_SUPPORT 7665 ext_tcam_flag = EXT_TCAM_IS_L3_ENABLED(unit); 7666 #endif 7667 if ((SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT2X(unit) || SOC_IS_TRIUMPH3(unit)) && 7668 soc_feature(unit, soc_feature_l3_shared_defip_table) && 7669 !(soc_property_get(unit, spn_L3_ALPM_ENABLE, 0) && 7670 soc_feature(unit, soc_feature_alpm)) && 7671 !ext_tcam_flag) { 7672 if ((r = bcm_switch_object_count_get(unit, 7673 bcmSwitchObjectL3RouteV6Routes64bMax, 7674 &defip_64_max)) < 0) { 7675 cli_out("%s: Error getting max number of 64bv6: %s\n", 7676 ARG_CMD(a), bcm_errmsg(r)); 7677 return CMD_FAIL; 7678 } 7679 if ((r = bcm_switch_object_count_get(unit, 7680 bcmSwitchObjectL3RouteV6Routes128bMax, 7681 &defip_128_max)) < 0) { 7682 cli_out("%s: Error getting max number of 128bv6: %s\n", 7683 ARG_CMD(a), bcm_errmsg(r)); 7684 return CMD_FAIL; 7685 } 7686 num_entries = defip_64_max + defip_128_max; 7687 last_entry = num_entries - 1 ; 7688 if ((r = bcm_switch_object_count_get(unit, 7689 bcmSwitchObjectL3RouteV6Routes64bFree, 7690 &defip_64_free)) < 0) { 7691 cli_out("%s: Error getting free number of 64bv6: %s\n", 7692 ARG_CMD(a), bcm_errmsg(r)); 7693 return CMD_FAIL; 7694 } 7695 if ((r = bcm_switch_object_count_get(unit, 7696 bcmSwitchObjectL3RouteV6Routes128bFree, 7697 &defip_128_free)) < 0) { 7698 cli_out("%s: Error getting free number of 128bv6: %s\n", 7699 ARG_CMD(a), bcm_errmsg(r)); 7700 return CMD_FAIL; 7701 } 7702 free_defip = defip_64_free + defip_128_free; 7703 } else 7704 #endif 7705 { 7706 if ((r = bcm_l3_info(unit, &l3_hw_status)) < 0) { 7707 cli_out("%s: Error L3 accessing: %s\n", ARG_CMD(a), bcm_errmsg(r)); 7708 return CMD_FAIL; 7709 } 7710 if (soc_feature(unit, soc_feature_urpf)) { 7711 if ((r = bcm_switch_control_get(unit, 7712 bcmSwitchL3UrpfRouteEnable, &urpf)) < 0) { 7713 cli_out("%s: Error L3 accessing: %s\n", ARG_CMD(a), bcm_errmsg(r)); 7714 return CMD_FAIL; 7715 } 7716 } 7717 free_defip = (l3_hw_status.l3info_max_route - 7718 l3_hw_status.l3info_occupied_route) / 2; 7719 last_entry = l3_hw_status.l3info_max_route / 2; 7720 num_entries = last_entry; 7721 if (urpf) { 7722 free_defip = (l3_hw_status.l3info_max_route - 7723 (l3_hw_status.l3info_occupied_route * 2)) / 4; 7724 last_entry = last_entry / 2; 7725 num_entries = last_entry + 1; 7726 } 7727 7728 } 7729 if (ARG_CNT(a)) { 7730 if (!isint(ARG_CUR(a))) { 7731 cli_out("%s: Invalid number: %s\n", ARG_CMD(a), ARG_CUR(a)); 7732 return (CMD_FAIL); 7733 } 7734 first_entry = parse_integer(ARG_GET(a)); 7735 if (first_entry > last_entry) { 7736 cli_out("%s: Error: Illegal entry number (0 to %d)\n", 7737 ARG_CMD(a), last_entry); 7738 return (CMD_FAIL); 7739 } 7740 if (ARG_CNT(a)) { 7741 int tmp_last_entry = 0; 7742 if (!isint(ARG_CUR(a))) { 7743 cli_out("%s: Invalid count: %s\n", ARG_CMD(a), ARG_CUR(a)); 7744 return (CMD_FAIL); 7745 } 7746 tmp_last_entry = parse_integer(ARG_GET(a)) + first_entry - 1; 7747 if ((tmp_last_entry > last_entry) || 7748 (tmp_last_entry < first_entry)) { 7749 cli_out("%s: Error: Illegal entry count (1 to %d)\n", 7750 ARG_CMD(a), last_entry - first_entry + 1); 7751 return (CMD_FAIL); 7752 } 7753 last_entry = tmp_last_entry; 7754 } else { 7755 last_entry = first_entry; 7756 } 7757 } else { 7758 first_entry = 0; 7759 } 7760 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 7761 if ((SOC_IS_TRIDENT2X(unit) || SOC_IS_TRIUMPH3(unit)) && 7762 soc_feature(unit, soc_feature_l3_shared_defip_table) && 7763 !(soc_property_get(unit, spn_L3_ALPM_ENABLE, 0) && 7764 soc_feature(unit, soc_feature_alpm))) { 7765 cli_out("Unit %d, Total Number of IPv6 entries: %d " 7766 "(IPv6/64 %d, IPv6/128 %d)\n", unit, num_entries, 7767 defip_64_max, defip_128_max); 7768 } else 7769 #endif 7770 cli_out("Unit %d, Total Number of IPv6 entries: %d\n", 7771 unit, num_entries); 7772 bcm_l3_route_max_ecmp_get(unit, &max_ecmp); 7773 if (max_ecmp) { 7774 cli_out("Max number of ECMP paths %d\n", max_ecmp); 7775 } 7776 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 7777 if ((SOC_IS_TRIDENT2X(unit) || SOC_IS_TRIUMPH3(unit)) && 7778 soc_feature(unit, soc_feature_l3_shared_defip_table) && 7779 !(soc_property_get(unit, spn_L3_ALPM_ENABLE, 0) && 7780 soc_feature(unit, soc_feature_alpm))) { 7781 cli_out("Free IPv6 entries available: %d " 7782 "(IPv6/64 %d, IPv6/128 %d)\n", free_defip, 7783 defip_64_free, defip_128_free); 7784 } else 7785 #endif 7786 cli_out("Free IPv6 entries available: %d\n", free_defip); 7787 7788 cli_out("# VRF Net addr " 7789 " Next Hop Mac " 7790 " INTF MODID PORT PRIO CLASS HIT VLAN\n"); 7791 bcm_l3_route_traverse(unit, BCM_L3_IP6, first_entry, last_entry, 7792 _l3_cmd_route_print, NULL); 7793 return CMD_OK; 7794 7795 default: 7796 return CMD_USAGE; 7797 break; 7798 } 7799 return CMD_OK; 7800 } 7801 7802 if (sal_strcasecmp(table, "tunnel_init") == 0) { 7803 switch (subcmd) { 7804 7805 /* l3 tunnel_init set */ 7806 case L3_SET: 7807 return _l3_cmd_tunnel_init_add(unit, a); 7808 /* l3 tunnel_init show */ 7809 case L3_SHOW: 7810 return _l3_cmd_tunnel_init_show(unit, a); 7811 /* l3 tunnel_init clear */ 7812 case L3_CLEAR: 7813 return _l3_cmd_tunnel_init_clear(unit, a); 7814 default: 7815 return CMD_USAGE; 7816 break; 7817 } 7818 return CMD_OK; 7819 } 7820 7821 if (sal_strcasecmp(table, "tunnel_term") == 0) { 7822 switch (subcmd) { 7823 /* l3 tunnel_term add */ 7824 case L3_ADD: 7825 return _l3_cmd_tunnel_term_add(unit, a); 7826 /* l3 tunnel_term delete */ 7827 case L3_DESTROY: 7828 return _l3_cmd_tunnel_term_delete(unit, a); 7829 /* l3 tunnel_term show */ 7830 case L3_SHOW: 7831 return _l3_cmd_tunnel_term_get(unit, a); 7832 default: 7833 return CMD_USAGE; 7834 break; 7835 } 7836 return CMD_OK; 7837 } 7838 7839 if (sal_strcasecmp(table, "dscp_map_port") == 0) { 7840 switch (subcmd) { 7841 /* l3 dscp_map_port show */ 7842 case L3_SHOW: 7843 return _l3_cmd_dscp_map_port_show(unit, a); 7844 /* l3 dscp_map_port set */ 7845 case L3_ADD: 7846 case L3_SET: 7847 return _l3_cmd_dscp_map_port_set(unit, a); 7848 default: 7849 return (CMD_USAGE); 7850 } 7851 return CMD_OK; 7852 } 7853 if (sal_strcasecmp(table, "dscp_map") == 0) { 7854 switch (subcmd) { 7855 /* l3 dscp_map add */ 7856 case L3_ADD: 7857 return _l3_cmd_dscp_map_add(unit, a); 7858 /* l3 dscp_map destroy */ 7859 case L3_DESTROY: 7860 return _l3_cmd_dscp_map_delete(unit, a); 7861 7862 /* l3 dscp_map show */ 7863 case L3_SHOW: 7864 return _l3_cmd_dscp_map_show(unit, a); 7865 /* l3 dscp_map set */ 7866 case L3_SET: 7867 return _l3_cmd_dscp_map_set(unit, a); 7868 7869 default: 7870 return CMD_USAGE; 7871 } 7872 return CMD_OK; 7873 } 7874 if (soc_feature(unit, soc_feature_nat)) { 7875 if (sal_strcasecmp(table, "nat_ingress") == 0) { 7876 switch (subcmd) { 7877 /* l3 nat_ingress show */ 7878 case L3_SHOW: 7879 return _l3_cmd_nat_ingress_show(unit, a); 7880 default: 7881 return CMD_USAGE; 7882 } 7883 return CMD_OK; 7884 } 7885 if (sal_strcasecmp(table, "nat_egress") == 0) { 7886 switch (subcmd) { 7887 /* l3 nat_egress show */ 7888 case L3_SHOW: 7889 return _l3_cmd_nat_egress_show(unit, a); 7890 case L3_ADD: 7891 return _l3_cmd_nat_egress_add(unit, a); 7892 default: 7893 return CMD_USAGE; 7894 } 7895 return CMD_OK; 7896 } 7897 } 7898 7899 if (sal_strcasecmp(table, "route") == 0) { 7900 char *subcmd2; 7901 switch (subcmd) { 7902 /* l3 route test */ 7903 case L3_TEST: 7904 subcmd2 = ARG_GET(a); 7905 if ((subcmd2 != NULL) && sal_strcasecmp(subcmd2, "perf") == 0) { 7906 return _l3_cmd_route_perf_test(unit, a); 7907 } else { 7908 return CMD_USAGE; 7909 } 7910 default: 7911 return CMD_USAGE; 7912 } 7913 return CMD_OK; 7914 } 7915 7916 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 7917 7918 return CMD_USAGE; 7919 } 7920 #endif /* INCLUDE_L3 */