mirror.c (32362B)
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 * Mirror CLI commands 8 */ 9 10 #include <appl/diag/system.h> 11 #include <appl/diag/parse.h> 12 #include <appl/diag/dport.h> 13 #include <shared/bsl.h> 14 #include <bcm/error.h> 15 #include <bcm/mirror.h> 16 #include <bcm/stack.h> 17 #include <bcm/debug.h> 18 #include <bcm_int/control.h> 19 #include <bcm_int/esw/mirror.h> 20 21 #ifdef BCM_TRIUMPH2_SUPPORT 22 #include <bcm_int/esw/triumph2.h> 23 #ifdef BCM_TRIDENT_SUPPORT 24 #include <bcm_int/esw/trident.h> 25 #endif 26 #ifdef BCM_TRIUMPH3_SUPPORT 27 #include <bcm_int/esw/triumph3.h> 28 #endif 29 #ifdef BCM_TRIUMPH_SUPPORT 30 #include <bcm_int/esw/triumph.h> 31 #endif 32 #ifdef BCM_MPLS_SUPPORT 33 #include <bcm_int/esw/mpls.h> 34 #endif 35 #endif 36 37 38 static int 39 show_mirror_destination_cb(int unit, bcm_mirror_destination_t * mirror_dest, 40 void *user_data) 41 { 42 int *count = (int *) user_data; 43 44 (*count)++; 45 cli_out("Mirror Dest %2d: ", *count); 46 cli_out("Mirror ID: %2d; ", BCM_GPORT_MIRROR_GET(mirror_dest->mirror_dest_id)); 47 if (mirror_dest->flags & BCM_MIRROR_DEST_TUNNEL_L2) { 48 cli_out("%s ", "L2 Tunnel to"); 49 } 50 if (mirror_dest->flags & BCM_MIRROR_DEST_TUNNEL_IP_GRE) { 51 cli_out("IPv%d GRE Tunnel\n", mirror_dest->version); 52 53 if (4 == mirror_dest->version) { 54 char buffer[SAL_IPADDR_STR_LEN]; 55 56 format_ipaddr(buffer, mirror_dest->src_addr); 57 cli_out("\tSrc IP=%s\n", buffer); 58 format_ipaddr(buffer, mirror_dest->dst_addr); 59 cli_out("\tDst IP=%s\n", buffer); 60 } else if (6 == mirror_dest->version) { 61 char buffer[IP6ADDR_STR_LEN]; 62 63 format_ip6addr(buffer, mirror_dest->src6_addr); 64 cli_out("\tSrc IP=%s\n", buffer); 65 format_ip6addr(buffer, mirror_dest->dst6_addr); 66 cli_out("\tDst IP=%s\n", buffer); 67 cli_out("\tFlow Label=0x%04x\n", mirror_dest->flow_label); 68 } 69 cli_out("\tsrc_mac=%02x:%02x:%02x:%02x:%02x:%02x\n", 70 mirror_dest->src_mac[0], mirror_dest->src_mac[1], 71 mirror_dest->src_mac[2], mirror_dest->src_mac[3], 72 mirror_dest->src_mac[4], mirror_dest->src_mac[5]); 73 cli_out("\tdst_mac=%02x:%02x:%02x:%02x:%02x:%02x\n", mirror_dest->dst_mac[0], 74 mirror_dest->dst_mac[1], mirror_dest->dst_mac[2], 75 mirror_dest->dst_mac[3], mirror_dest->dst_mac[4], 76 mirror_dest->dst_mac[5]); 77 78 cli_out("\tvlan_id=0x%04x\n", mirror_dest->vlan_id); 79 cli_out("\ttpid=0x%04x\n", mirror_dest->tpid); 80 cli_out("\tttl=%d\n", mirror_dest->ttl); 81 cli_out("\ttos=%d\n", mirror_dest->tos); 82 cli_out("\tmirrored to "); 83 } 84 if (mirror_dest->flags & BCM_MIRROR_DEST_PAYLOAD_UNTAGGED) { 85 cli_out("%s ", "Payload Untagged"); 86 } 87 if (mirror_dest->flags & BCM_MIRROR_DEST_TUNNEL_TRILL) { 88 cli_out("%s ", "Trill Tunnel to"); 89 } 90 if (mirror_dest->flags & BCM_MIRROR_DEST_TUNNEL_NIV) { 91 cli_out("%s ", "NIV Tunnel to"); 92 } 93 if (mirror_dest->flags & BCM_MIRROR_DEST_TUNNEL_ETAG) { 94 cli_out("%s ", "ETAG Tunnel to"); 95 } 96 97 if (BCM_GPORT_IS_LOCAL(mirror_dest->gport)) { 98 cli_out("local port %s", 99 BCM_PORT_NAME(unit, BCM_GPORT_LOCAL_GET(mirror_dest->gport))); 100 } else if (BCM_GPORT_IS_MODPORT(mirror_dest->gport)) { 101 bcm_port_t local_port; 102 103 if (bcm_port_local_get(unit, mirror_dest->gport, &local_port) != BCM_E_NONE) { 104 cli_out("modport %d/%d", BCM_GPORT_MODPORT_MODID_GET(mirror_dest->gport), 105 BCM_GPORT_MODPORT_PORT_GET(mirror_dest->gport)); 106 } else { 107 cli_out("local port %s", BCM_PORT_NAME(unit, local_port)); 108 } 109 } else if (BCM_GPORT_IS_TRUNK(mirror_dest->gport)) { 110 cli_out("trunk group %d", BCM_GPORT_TRUNK_GET(mirror_dest->gport)); 111 } else { 112 cli_out("GPORT 0x%08X", mirror_dest->gport); 113 } 114 cli_out("\n"); 115 return BCM_E_NONE; 116 } 117 118 cmd_result_t 119 _if_esw_mirror_dest(int unit, args_t *a) 120 { 121 parse_table_t pt; 122 cmd_result_t retCode; 123 bcm_gport_t mirror_dest_id = 0; 124 bcm_port_t src_port = 0, dest_port = 0; 125 bcm_ip_t src_ip = 0, dest_ip = 0; 126 bcm_ip6_t src_ip6,dest_ip6; 127 uint32 flow_lable; 128 uint32 mirror_port_flags = 0; 129 bcm_mac_t src_mac, dest_mac; 130 bcm_vlan_t vid = BCM_VLAN_INVALID; 131 uint16 tpid; 132 int vlan_id = -1, tag_id = -1; 133 int ttl = 0,tos = 0, version = 0; 134 int rv, mode = 0, tunnel = 0, strip_vlan = 0; 135 bcm_mirror_destination_t mirror_dest; 136 char *cmd = NULL; 137 char *modeList[] = {"OFF", "Ingress", "Egress", "EgressTrue", "IngressEgress", NULL}; 138 char *tunnelList[] = {"OFF","L2", "GRE", NULL}; 139 140 if ((cmd = ARG_GET(a)) == NULL) { 141 return CMD_USAGE; 142 } 143 if (0 == sal_strcasecmp("show", cmd)) { 144 int md_count = 0; 145 146 rv = bcm_mirror_destination_traverse(unit, show_mirror_destination_cb, 147 &md_count); 148 if (BCM_FAILURE(rv)) { 149 cli_out("%s bcm_mirror_destination_traverse() failed %s\n", 150 ARG_CMD(a), bcm_errmsg(rv)); 151 return CMD_FAIL; 152 } 153 if (md_count == 0) { 154 cli_out("No mirror destinations currently defined\n"); 155 } 156 return CMD_OK; 157 } 158 159 sal_memset(src_ip6, 0, sizeof(bcm_ip6_t)); 160 sal_memset(dest_ip6, 0, sizeof(bcm_ip6_t)); 161 sal_memset(src_mac, 0, sizeof(bcm_mac_t)); 162 sal_memset(dest_mac, 0, sizeof(bcm_mac_t)); 163 164 parse_table_init(unit, &pt); 165 166 parse_table_add(&pt, "Id", PQ_DFL | PQ_INT,0, &mirror_dest_id, NULL); 167 parse_table_add(&pt, "Mode", PQ_DFL | PQ_MULTI,(void *)(0), &mode, modeList); 168 parse_table_add(&pt, "Tunnel", PQ_DFL | PQ_MULTI,(void *)(0), &tunnel, tunnelList); 169 parse_table_add(&pt, "SrcPort", PQ_DFL | PQ_PORT, 0, &src_port, NULL); 170 parse_table_add(&pt, "DestPort", PQ_DFL | PQ_PORT, 0, &dest_port, NULL); 171 parse_table_add(&pt, "SrcIP", PQ_DFL | PQ_IP, 0, (void *)&src_ip, NULL); 172 parse_table_add(&pt, "DestIP", PQ_DFL | PQ_IP, 0, (void *)&dest_ip, NULL); 173 parse_table_add(&pt, "SrcIP6", PQ_DFL | PQ_IP6, 0, (void *)&src_ip6, NULL); 174 parse_table_add(&pt, "DestIP6", PQ_DFL | PQ_IP6, 0, (void *)&dest_ip6, NULL); 175 parse_table_add(&pt, "SrcMAC", PQ_DFL|PQ_MAC, 0, (void *)src_mac, NULL); 176 parse_table_add(&pt, "DestMAC", PQ_DFL|PQ_MAC, 0, (void *)dest_mac, NULL); 177 parse_table_add(&pt, "VLAN", PQ_DFL|PQ_INT, 0, (void *)&vlan_id, NULL); 178 parse_table_add(&pt, "tpid", PQ_DFL|PQ_INT, 0, (void *)&tag_id, NULL); 179 parse_table_add(&pt, "Version", PQ_DFL|PQ_INT, 0, (void*)&version, NULL); 180 parse_table_add(&pt, "TTL", PQ_DFL|PQ_INT, 0, (void*)&ttl, NULL); 181 parse_table_add(&pt, "TOS", PQ_DFL|PQ_INT, 0, (void*)&tos, NULL); 182 parse_table_add(&pt, "FlowLable", PQ_DFL|PQ_INT, 0, (void*)&flow_lable, NULL); 183 parse_table_add(&pt, "NoVLAN", PQ_DFL|PQ_BOOL, 0, (void*)&strip_vlan, NULL); 184 185 if (!parseEndOk( a, &pt, &retCode)) { 186 return retCode; 187 } 188 189 vid = (bcm_vlan_t) (vlan_id & 0xffff); 190 tpid = (uint16) (tag_id & 0xffff); 191 bcm_mirror_destination_t_init(&mirror_dest); 192 193 switch (mode) { 194 case 1: 195 mirror_port_flags |= BCM_MIRROR_PORT_INGRESS; 196 break; 197 case 2: 198 mirror_port_flags |= BCM_MIRROR_PORT_EGRESS; 199 break; 200 case 3: 201 mirror_port_flags |= BCM_MIRROR_PORT_EGRESS_TRUE; 202 break; 203 case 4: 204 mirror_port_flags |= 205 (BCM_MIRROR_PORT_INGRESS | BCM_MIRROR_PORT_EGRESS); 206 break; 207 default: 208 break; 209 } 210 211 switch (tunnel) { 212 case 1: 213 mirror_dest.flags |= BCM_MIRROR_DEST_TUNNEL_L2; 214 sal_memcpy(mirror_dest.src_mac, src_mac, sizeof(src_mac)); 215 sal_memcpy(mirror_dest.dst_mac, dest_mac, sizeof(dest_mac)); 216 mirror_dest.vlan_id = vid; 217 mirror_dest.tpid = tpid; 218 break; 219 case 2: 220 mirror_dest.flags |= BCM_MIRROR_DEST_TUNNEL_IP_GRE; 221 sal_memcpy(mirror_dest.src_mac, src_mac, sizeof(src_mac)); 222 sal_memcpy(mirror_dest.dst_mac, dest_mac, sizeof(dest_mac)); 223 mirror_dest.vlan_id = vid; 224 mirror_dest.tpid = tpid; 225 mirror_dest.src_addr = src_ip; 226 mirror_dest.dst_addr = dest_ip; 227 mirror_dest.ttl = ttl; 228 mirror_dest.tos = tos; 229 mirror_dest.flow_label = flow_lable; 230 mirror_dest.version = version; 231 sal_memcpy(mirror_dest.src6_addr, src_ip6, sizeof(src_ip6)); 232 sal_memcpy(mirror_dest.dst6_addr, dest_ip6, sizeof(dest_ip6)); 233 break; 234 default: 235 break; 236 } 237 238 if (strip_vlan) { 239 mirror_dest.flags |= BCM_MIRROR_DEST_PAYLOAD_UNTAGGED; 240 } 241 242 if (!BCM_GPORT_IS_SET(dest_port)) { 243 rv = bcm_port_gport_get(unit, dest_port, &dest_port); 244 if (BCM_FAILURE(rv)) { 245 cli_out("Illegal port [%d]\n", dest_port); 246 return CMD_FAIL; 247 } 248 } 249 250 /* Dest port can be trunk, api handles this with no flags */ 251 mirror_dest.gport = dest_port; 252 253 if (mirror_dest_id != 0) { 254 mirror_dest.flags |= BCM_MIRROR_DEST_WITH_ID; 255 mirror_dest.mirror_dest_id = mirror_dest_id; 256 } 257 258 if (0 == sal_strcasecmp("create", cmd)) { 259 rv = bcm_mirror_destination_create(unit, &mirror_dest); 260 if (BCM_FAILURE(rv)) { 261 cli_out("%s bcm_mirror_destination_create() failed %s\n", 262 ARG_CMD(a), bcm_errmsg(rv)); 263 return CMD_FAIL; 264 } 265 cli_out(" Mirror Id = 0x%x\n", mirror_dest.mirror_dest_id); 266 return CMD_OK; 267 } else if (0 == sal_strcasecmp("add", cmd)) { 268 rv = bcm_mirror_port_dest_add(unit, src_port, 269 mirror_port_flags, mirror_dest_id); 270 if (BCM_FAILURE(rv)) { 271 cli_out("%s bcm_mirror_port_dest_add() failed %s\n", 272 ARG_CMD(a), bcm_errmsg(rv)); 273 return CMD_FAIL; 274 } 275 return CMD_OK; 276 } else if (0 == sal_strcasecmp("destroy", cmd)) { 277 if (0 == mirror_dest_id) { 278 cli_out("%s mirror destination id is missing\n", ARG_CMD(a)); 279 return CMD_FAIL; 280 } 281 rv = bcm_mirror_destination_destroy(unit, mirror_dest_id); 282 if (BCM_FAILURE(rv)) { 283 cli_out("%s bcm_mirror_destination_destroy failed() %s\n", 284 ARG_CMD(a), bcm_errmsg(rv)); 285 return CMD_FAIL; 286 } 287 return CMD_OK; 288 } else if (0 == sal_strcasecmp("delete", cmd)) { 289 rv = bcm_mirror_port_dest_delete(unit, src_port, 290 mirror_port_flags, mirror_dest_id); 291 if (BCM_FAILURE(rv)) { 292 cli_out("%s bcm_mirror_port_dest_delete failed %s\n", 293 ARG_CMD(a), bcm_errmsg(rv)); 294 return CMD_FAIL; 295 } 296 return CMD_OK; 297 } 298 299 return CMD_USAGE; 300 } 301 302 static void _dmirror_show(int unit, int port, int dstmod, int dstport, uint32 flags); 303 static int 304 _mirror_show(int unit) 305 { 306 const uint32 flags[3] = { BCM_MIRROR_PORT_INGRESS, BCM_MIRROR_PORT_EGRESS, 307 BCM_MIRROR_PORT_EGRESS_TRUE }; 308 bcm_gport_t mirror_dest[BCM_MIRROR_MTP_COUNT]; 309 bcm_port_config_t pcfg; 310 int count = 0; 311 int fc; 312 int mirror_dest_count; 313 int port, dport; 314 int rv; 315 #if defined(INCLUDE_L3) && defined(BCM_TRIUMPH2_SUPPORT) 316 bcm_gport_t gport = 0; 317 int vp = 0; 318 int first = TRUE; 319 #endif 320 321 if (bcm_port_config_get(unit, &pcfg) != BCM_E_NONE) { 322 cli_out("Error: bcm ports not initialized\n"); 323 return CMD_FAIL; 324 } 325 326 /* coverity[overrun-local] */ 327 DPORT_BCM_PBMP_ITER(unit, pcfg.all, dport, port) { 328 for (fc = 0; fc < sizeof(flags) / sizeof(uint32); fc++) { 329 if(flags[fc] == BCM_MIRROR_PORT_EGRESS_TRUE) { 330 if(!soc_feature(unit, soc_feature_egr_mirror_true)) 331 continue; 332 } 333 rv = 334 bcm_mirror_port_dest_get(unit, 335 port, 336 flags[fc], 337 BCM_MIRROR_MTP_COUNT, mirror_dest, 338 &mirror_dest_count); 339 if (rv < 0) { 340 cli_out("bcm_mirror_port_dest_get() FAILED: %s\n", bcm_errmsg(rv)); 341 return CMD_FAIL; 342 } 343 if (mirror_dest_count != 0) { 344 int i; 345 346 for (i = 0; i < mirror_dest_count; i++) { 347 bcm_mirror_destination_t mirror_dest_desc; 348 349 bcm_mirror_destination_t_init(&mirror_dest_desc); 350 mirror_dest_desc.flags = flags[fc]; 351 rv = 352 bcm_mirror_destination_get(unit, mirror_dest[i], 353 &mirror_dest_desc); 354 if (rv < 0) { 355 cli_out("bcm_mirror_destination_get() FAILED: %s\n", 356 bcm_errmsg(rv)); 357 return CMD_FAIL; 358 } 359 _dmirror_show(unit, port, 0, mirror_dest_desc.gport, flags[fc]); 360 } 361 count += mirror_dest_count; 362 } 363 } 364 } 365 366 #if defined(INCLUDE_L3) && defined(BCM_TRIUMPH2_SUPPORT) 367 if (SOC_MEM_IS_VALID(unit,SOURCE_VPm)) { 368 for (vp = soc_mem_index_min(unit, SOURCE_VPm); 369 vp <= soc_mem_index_max(unit, SOURCE_VPm); 370 vp++) { 371 gport = 0; 372 BCM_GPORT_VP_GROUP_SET(gport, vp); 373 374 for (fc = 0; fc < sizeof(flags) / sizeof(uint32); fc++) { 375 if(flags[fc] == BCM_MIRROR_PORT_EGRESS_TRUE) { 376 if(!soc_feature(unit, soc_feature_egr_mirror_true)) 377 continue; 378 } 379 rv = 380 bcm_mirror_port_dest_get(unit, 381 gport, 382 flags[fc], 383 BCM_MIRROR_MTP_COUNT, mirror_dest, 384 &mirror_dest_count); 385 if (BCM_E_INTERNAL == rv) { 386 continue; 387 } else if (rv < 0) { 388 cli_out("bcm_mirror_port_dest_get() FAILED: %s\n", bcm_errmsg(rv)); 389 return CMD_FAIL; 390 } 391 392 if (first) { 393 cli_out("-----------------------------------------\n"); 394 first = FALSE; 395 } 396 397 if (mirror_dest_count != 0) { 398 int i; 399 400 for (i = 0; i < mirror_dest_count; i++) { 401 bcm_mirror_destination_t mirror_dest_desc; 402 403 bcm_mirror_destination_t_init(&mirror_dest_desc); 404 mirror_dest_desc.flags = flags[fc]; 405 rv = 406 bcm_mirror_destination_get(unit, mirror_dest[i], 407 &mirror_dest_desc); 408 if (rv < 0) { 409 cli_out("bcm_mirror_destination_get() FAILED: %s\n", 410 bcm_errmsg(rv)); 411 return CMD_FAIL; 412 } 413 _dmirror_show(unit, gport, 0, mirror_dest_desc.gport, flags[fc]); 414 } 415 count += mirror_dest_count; 416 } 417 } 418 } 419 } 420 #endif 421 if (count == 0) { 422 cli_out("No mirror ports configured\n"); 423 } 424 return CMD_OK; 425 } 426 427 cmd_result_t 428 if_esw_mirror(int unit, args_t *a) 429 { 430 int rv; 431 soc_port_t port, dport; 432 char pfmt[SOC_PBMP_FMT_LEN]; 433 char bmstr[FORMAT_PBMP_MAX]; 434 char *modeList[] = {"Off", "L2", "L3", NULL}; 435 int argMode = -1, argPort = -1; 436 bcm_pbmp_t argIngBmp, argEgrBmp; 437 bcm_port_config_t pcfg; 438 parse_table_t pt; 439 cmd_result_t retCode; 440 char *subcmd = NULL; 441 442 BCM_PBMP_CLEAR(argIngBmp); 443 BCM_PBMP_CLEAR(argEgrBmp); 444 445 if (!sh_check_attached(ARG_CMD(a), unit)) { 446 return CMD_FAIL; 447 } 448 449 if ((subcmd = ARG_GET(a)) != NULL) { 450 if (parse_cmp("DEST", subcmd, '\0')) { 451 return _if_esw_mirror_dest(unit, a); 452 } else if ((ARG_CNT(a) == 0) && parse_cmp("SHow", subcmd, '\0')) { 453 /* coverity[stack_use_overflow : FALSE] */ 454 return _mirror_show(unit); 455 } 456 /* no sub command going down, all arguments are treated as mirror parameter 457 decrement processed parameter count by 1 to check it properly */ 458 ARG_PREV(a); 459 } 460 461 if (bcm_port_config_get(unit, &pcfg) != BCM_E_NONE) { 462 cli_out("%s: Error: bcm ports not initialized\n", ARG_CMD(a)); 463 return CMD_FAIL; 464 } 465 466 if (!SOC_IS_XGS12_FABRIC(unit) ) { 467 rv = bcm_mirror_to_get(unit, &argPort); 468 if (rv < 0) { 469 cli_out("%s: bcm_mirror_to_get() failed: %s\n", ARG_CMD(a), 470 bcm_errmsg(rv)); 471 return CMD_FAIL; 472 } 473 474 rv = bcm_mirror_mode_get(unit, &argMode); 475 if (rv < 0) { 476 cli_out("%s: bcm_mirror_mode_get() failed: %s\n", ARG_CMD(a), 477 bcm_errmsg(rv)); 478 return CMD_FAIL; 479 } 480 481 BCM_PBMP_CLEAR(argIngBmp); 482 BCM_PBMP_CLEAR(argEgrBmp); 483 484 /* coverity[overrun-local] */ 485 DPORT_BCM_PBMP_ITER(unit, pcfg.all, dport, port) { 486 int enable; 487 488 rv = bcm_mirror_ingress_get(unit, port, &enable); 489 /* coverity[overrun-local] */ 490 if (rv < 0 && !IS_CPU_PORT(unit, port)) { 491 cli_out("%s: bcm_mirror_ingress_get() failed: %s\n", ARG_CMD(a), 492 bcm_errmsg(rv)); 493 return CMD_FAIL; 494 } 495 496 if (enable) { 497 /* coverity[overrun-local] */ 498 BCM_PBMP_PORT_ADD(argIngBmp, port); 499 } 500 501 rv = bcm_mirror_egress_get(unit, port, &enable); 502 if (rv < 0 && !IS_CPU_PORT(unit, port)) { 503 cli_out("%s: bcm_mirror_egress_get() failed: %s\n", ARG_CMD(a), 504 bcm_errmsg(rv)); 505 return CMD_FAIL; 506 } 507 508 if (enable) { 509 /* coverity[overrun-local] */ 510 BCM_PBMP_PORT_ADD(argEgrBmp, port); 511 } 512 } 513 514 parse_table_init(unit, &pt); 515 parse_table_add(&pt, "Mode", PQ_DFL|PQ_MULTI, 516 (void *)(0), &argMode, modeList); 517 parse_table_add(&pt, "Port", PQ_DFL|PQ_PORT|PQ_BCM, 518 (void *)(0), &argPort, NULL); 519 parse_table_add(&pt, "IngressBitMap", PQ_DFL|PQ_PBMP|PQ_BCM, 520 (void *)(0), &argIngBmp, NULL); 521 parse_table_add(&pt, "EgressBitMap", PQ_DFL|PQ_PBMP|PQ_BCM, 522 (void *)(0), &argEgrBmp, NULL); 523 if (!parseEndOk( a, &pt, &retCode)) { 524 return retCode; 525 } 526 527 rv = bcm_mirror_to_set(unit, argPort); 528 if (rv < 0) { 529 cli_out("%s: bcm_mirror_to_set() failed: %s\n", ARG_CMD(a), 530 bcm_errmsg(rv)); 531 return CMD_FAIL; 532 } 533 534 switch (argMode) { 535 case 0: 536 rv = bcm_mirror_mode_set(unit, BCM_MIRROR_DISABLE); 537 break; 538 case 1: 539 rv = bcm_mirror_mode_set(unit, BCM_MIRROR_L2); 540 break; 541 case 2: 542 rv = bcm_mirror_mode_set(unit, BCM_MIRROR_L2_L3); 543 break; 544 } 545 546 if (rv < 0) { 547 cli_out("%s: bcm_mirror_mode_set() failed: %s\n", ARG_CMD(a), 548 bcm_errmsg(rv)); 549 return CMD_FAIL; 550 } 551 552 if (argMode == 0) { /* skip ingress/egress for disable case */ 553 return CMD_OK; 554 } 555 556 /* coverity[overrun-local] */ 557 DPORT_BCM_PBMP_ITER(unit, pcfg.all, dport, port) { 558 rv = bcm_mirror_ingress_set(unit, port, 559 BCM_PBMP_MEMBER(argIngBmp, port) ? 1 : 0); 560 if (rv < 0 && !BCM_PBMP_MEMBER(pcfg.cpu, port)) { 561 cli_out("%s: bcm_mirror_ingress_set() failed: %s\n", ARG_CMD(a), 562 bcm_errmsg(rv)); 563 return CMD_FAIL; 564 } 565 rv = bcm_mirror_egress_set(unit, port, 566 BCM_PBMP_MEMBER(argEgrBmp, port) ? 1 : 0); 567 if (rv < 0 && !BCM_PBMP_MEMBER(pcfg.cpu, port)) { 568 cli_out("%s: bcm_mirror_egress_set failed: %s\n", ARG_CMD(a), 569 bcm_errmsg(rv)); 570 return CMD_FAIL; 571 } 572 } 573 574 return CMD_OK; 575 } else { 576 /* Hercules chip */ 577 578 if (ARG_CNT(a) == 0) { 579 /* Dump mirroring bitmaps */ 580 cli_out("Mirroring configuration:\n"); 581 /* coverity[overrun-local] */ 582 DPORT_BCM_PBMP_ITER(unit, pcfg.port, dport, port) { 583 if ( (rv = bcm_mirror_to_pbmp_get(unit, 584 port, &argIngBmp)) < 0){ 585 cli_out("%s: ERROR: %s\n", ARG_CMD(a), bcm_errmsg(rv)); 586 return CMD_FAIL; 587 } 588 format_bcm_pbmp(unit, bmstr, sizeof(bmstr), argIngBmp); 589 cli_out("\t%s\tmirror bitmap %s, %s\n", 590 BCM_PORT_NAME(unit, port), 591 SOC_PBMP_FMT(argIngBmp, pfmt), 592 bmstr); 593 } 594 } else { 595 parse_table_init(unit, &pt); 596 parse_table_add(&pt, "Port", PQ_DFL|PQ_PORT|PQ_BCM, 597 (void *)( 0), &argPort, NULL); 598 parse_table_add(&pt, "BitMap", PQ_DFL|PQ_PBMP|PQ_BCM, 599 (void *)(0), &argIngBmp, NULL); 600 if (!parseEndOk( a, &pt, &retCode)) { 601 return retCode; 602 } 603 604 if ( (rv = bcm_mirror_to_pbmp_set(unit, argPort, argIngBmp)) < 0) { 605 cli_out("%s: ERROR: %s\n", ARG_CMD(a), bcm_errmsg(rv)); 606 return CMD_FAIL; 607 } 608 } 609 } 610 611 return CMD_OK; 612 } 613 614 static void 615 _dmirror_show(int unit, int port, int dstmod, int dstport, uint32 flags) 616 { 617 int rv, show_dest; 618 bcm_port_t local_port; 619 bcm_gport_t gport; 620 char *mstr; 621 char *vptype = ""; 622 uint16 tpid, vlan; 623 int vp = 0; 624 625 show_dest = 1; 626 if (flags & BCM_MIRROR_PORT_INGRESS) { 627 if (flags & (BCM_MIRROR_PORT_EGRESS|BCM_MIRROR_PORT_EGRESS_TRUE)) { 628 mstr = "Mirror all"; 629 } else { 630 mstr = "Mirror ingress"; 631 } 632 } else if (flags & BCM_MIRROR_PORT_EGRESS) { 633 mstr = "Mirror egress"; 634 } else if (flags & BCM_MIRROR_PORT_EGRESS_TRUE) { 635 mstr = "Mirror egress true"; 636 } else if (flags & BCM_MIRROR_PORT_ENABLE) { 637 mstr = "Mirror"; 638 } else { 639 mstr = "-"; 640 show_dest = 0; 641 } 642 643 if (BCM_GPORT_IS_SET(port)) { 644 #if defined(BCM_TRIUMPH2_SUPPORT) && defined(INCLUDE_L3) 645 bcm_module_t mod_out; 646 bcm_trunk_t trunk_id; 647 int id; 648 bcm_vlan_port_t vlan_vp; 649 650 vp = BCM_GPORT_VP_GROUP_GET(port); 651 652 BCM_GPORT_VLAN_PORT_ID_SET(port, vp); 653 bcm_vlan_port_t_init(&vlan_vp); 654 vlan_vp.vlan_port_id = port; 655 rv = bcm_vlan_port_find(unit, &vlan_vp); 656 if (BCM_E_NONE == rv) { 657 (void)_bcm_esw_gport_resolve(unit, vlan_vp.port, &mod_out, 658 &port, &trunk_id, &id); 659 vptype = "Vlan"; 660 } 661 #ifdef BCM_TRIDENT_SUPPORT 662 if (rv != BCM_E_NONE) { 663 bcm_niv_port_t niv_port; 664 665 BCM_GPORT_NIV_PORT_ID_SET(port, vp); 666 bcm_niv_port_t_init(&niv_port); 667 niv_port.niv_port_id = port; 668 rv = bcm_niv_port_get(unit, &niv_port); 669 if (BCM_E_NONE == rv) { 670 (void)_bcm_esw_gport_resolve(unit, niv_port.port, &mod_out, 671 &port, &trunk_id, &id); 672 vptype = "Niv"; 673 } 674 } 675 #endif /* BCM_TRIDENT_SUPPORT */ 676 #ifdef BCM_TRIUMPH3_SUPPORT 677 if (rv != BCM_E_NONE) { 678 bcm_extender_port_t extender_port; 679 680 BCM_GPORT_EXTENDER_PORT_ID_SET(port, vp); 681 bcm_extender_port_t_init(&extender_port); 682 extender_port.extender_port_id = port; 683 rv = bcm_extender_port_get(unit, &extender_port); 684 if (BCM_E_NONE == rv) { 685 (void)_bcm_esw_gport_resolve(unit, extender_port.port, &mod_out, 686 &port, &trunk_id, &id); 687 vptype = "Extender"; 688 } 689 } 690 #endif /* BCM_TRIUMPH3_SUPPORT */ 691 #ifdef BCM_MPLS_SUPPORT 692 if (rv != BCM_E_NONE) { 693 bcm_mpls_port_t mpls_port; 694 int vpn0; 695 696 BCM_GPORT_MPLS_PORT_ID_SET(port, vp); 697 bcm_mpls_port_t_init(&mpls_port); 698 mpls_port.mpls_port_id = port; 699 _BCM_MPLS_VPN_SET(vpn0,_BCM_MPLS_VPN_TYPE_VPWS,0); 700 rv = bcm_mpls_port_get(unit, vpn0, &mpls_port); 701 if (BCM_E_NONE == rv) { 702 (void)_bcm_esw_gport_resolve(unit, mpls_port.port, &mod_out, 703 &port, &trunk_id, &id); 704 vptype = "Mpls"; 705 } 706 } 707 #endif /* BCM_MPLS_SUPPORT */ 708 #endif 709 cli_out("%s vp%d(%4s): %s", vptype, vp, BCM_PORT_NAME(unit, port), mstr); 710 } else { 711 cli_out("%4s: %s", BCM_PORT_NAME(unit, port), mstr); 712 } 713 714 if (show_dest) { 715 if (BCM_GPORT_IS_MODPORT(dstport)) { 716 gport = dstport; 717 dstmod = BCM_GPORT_MODPORT_MODID_GET(gport); 718 dstport = BCM_GPORT_MODPORT_PORT_GET(gport); 719 } else { 720 BCM_GPORT_MODPORT_SET(gport, dstmod, dstport); 721 } 722 if (bcm_port_local_get(unit, gport, &local_port) != BCM_E_NONE) { 723 local_port = -1; 724 } 725 if (BCM_GPORT_IS_TRUNK(dstport)) { 726 cli_out(" to trunk group %d", BCM_GPORT_TRUNK_GET(dstport)); 727 } else if (flags & BCM_MIRROR_PORT_DEST_TRUNK) { 728 cli_out(" to trunk group %d", dstport); 729 } else if (local_port >= 0) { 730 cli_out(" to local port %s", BCM_PORT_NAME(unit, local_port)); 731 } else { 732 cli_out(" to module %d, port %d", dstmod, dstport); 733 } 734 if (local_port >= 0) { 735 rv = bcm_mirror_vlan_get(unit, local_port, &tpid, &vlan); 736 if (rv == BCM_E_NONE && vlan > 0) { 737 cli_out(" (TPID=0x%04X(%d), VLAN=0x%04X(%d))", tpid, tpid, vlan, vlan); 738 } 739 } 740 } 741 cli_out("\n"); 742 } 743 744 char if_dmirror_usage[] = 745 "Parameters: <ports> [Mode=<Off|On|Ingress|Egress|All>]\n" 746 "\t[DestPort=<port>] [DestModule=<modid>] [DestTrunk=<tgid>]\n" 747 "\t[MirrorTagProtocolID=<tpid>] [MirrorVlanID=<vid>\n" 748 "\tDestTrunk overrides DestModule/DestPort.\n" 749 "\tTPID and VLAN are set only if DestPort is a local port.\n"; 750 751 cmd_result_t 752 if_dmirror(int unit, args_t *a) 753 { 754 int rv; 755 int port, dport, dstmod, dstport; 756 int mymodid; 757 uint32 flags; 758 parse_table_t pt; 759 cmd_result_t retCode; 760 bcm_pbmp_t pbm, tmp_pbm; 761 bcm_port_config_t pcfg; 762 char *mstr; 763 int argDestPort = -1, argDestMod = -1, argDestTrunk = -1; 764 int argMode = -1, argTpid = -1, argVlan = -1; 765 766 char *modeList[] = {"OFF", "ON", "Ingress", "Egress", "All", NULL}; 767 768 if (!sh_check_attached(ARG_CMD(a), unit)) { 769 return CMD_FAIL; 770 } 771 772 if (SOC_IS_XGS12_FABRIC(unit) ) { 773 cli_out("%s: command not supported for switch fabric chips\n", ARG_CMD(a)); 774 return CMD_FAIL; 775 } 776 777 if (bcm_port_config_get(unit, &pcfg) != BCM_E_NONE) { 778 cli_out("%s: Error: bcm ports not initialized\n", ARG_CMD(a)); 779 return CMD_FAIL; 780 } 781 782 rv = bcm_stk_my_modid_get(unit, &mymodid); 783 if (rv < 0) { 784 cli_out("%s: bcm_stk_my_modid_get: %s\n", ARG_CMD(a), 785 bcm_errmsg(rv)); 786 return CMD_FAIL; 787 } 788 789 if ((mstr = ARG_GET(a)) == NULL) { 790 return CMD_USAGE; 791 } 792 793 if ((ARG_CNT(a) == 0) && parse_cmp("SHow", mstr, '\0')) { 794 int count = 0; 795 796 /* coverity[overrun-local] */ 797 DPORT_BCM_PBMP_ITER(unit, pcfg.all, dport, port) { 798 rv = bcm_mirror_port_get(unit, port, &dstmod, &dstport, &flags); 799 if (rv < 0) { 800 cli_out("%s: bcm_mirror_port_get: %s\n", ARG_CMD(a), bcm_errmsg(rv)); 801 return CMD_FAIL; 802 } 803 if (flags != 0) { 804 count++; 805 _dmirror_show(unit, port, dstmod, dstport, flags); 806 } 807 } 808 if (count == 0) { 809 cli_out("%s: No mirror ports configured\n", ARG_CMD(a)); 810 } 811 return CMD_OK; 812 } 813 if (parse_bcm_pbmp(unit, mstr, &pbm) < 0) { 814 cli_out("%s: Error: unrecognized port bitmap: %s\n", 815 ARG_CMD(a), mstr); 816 return CMD_FAIL; 817 } 818 819 if (soc_feature(unit, soc_feature_cpuport_mirror)) { 820 BCM_PBMP_AND(pbm, pcfg.all); 821 } else { 822 BCM_PBMP_AND(pbm, pcfg.port); 823 } 824 825 if (BCM_PBMP_IS_NULL(pbm)) { 826 cli_out("%s: Error: unsupported port bitmap: %s\n", 827 ARG_CMD(a), mstr); 828 return CMD_FAIL; 829 } 830 831 if (ARG_CNT(a) == 0) { 832 /* Show FE ports separately (for Tucana) */ 833 tmp_pbm = pbm; 834 BCM_PBMP_AND(tmp_pbm, pcfg.fe); 835 /* coverity[overrun-local] */ 836 DPORT_BCM_PBMP_ITER(unit, tmp_pbm, dport, port) { 837 rv = bcm_mirror_port_get(unit, port, &dstmod, &dstport, &flags); 838 if (rv < 0) { 839 cli_out("%s: bcm_mirror_port_get: %s\n", ARG_CMD(a), 840 bcm_errmsg(rv)); 841 return CMD_FAIL; 842 } 843 _dmirror_show(unit, port, dstmod, dstport, flags); 844 } 845 /* Show non-FE ports */ 846 tmp_pbm = pbm; 847 BCM_PBMP_REMOVE(tmp_pbm, pcfg.fe); 848 DPORT_BCM_PBMP_ITER(unit, tmp_pbm, dport, port) { 849 rv = bcm_mirror_port_get(unit, port, &dstmod, &dstport, &flags); 850 if (rv < 0) { 851 cli_out("%s: bcm_mirror_port_get: %s\n", ARG_CMD(a), 852 bcm_errmsg(rv)); 853 return CMD_FAIL; 854 } 855 _dmirror_show(unit, port, dstmod, dstport, flags); 856 } 857 return CMD_OK; 858 } 859 860 parse_table_init(unit, &pt); 861 parse_table_add(&pt, "DestPort", PQ_DFL|PQ_PORT, 862 (void *)(0), &argDestPort, NULL); 863 parse_table_add(&pt, "DestModule", PQ_DFL|PQ_INT, 864 (void *)(0), &argDestMod, NULL); 865 parse_table_add(&pt, "DestTrunk", PQ_DFL|PQ_INT, 866 (void *)(0), &argDestTrunk, NULL); 867 parse_table_add(&pt, "MirrorTagProtocolID", PQ_DFL|PQ_INT, 868 (void *)(0), &argTpid, NULL); 869 parse_table_add(&pt, "MirrorVlanID", PQ_DFL|PQ_INT, 870 (void *)(0), &argVlan, NULL); 871 parse_table_add(&pt, "Mode", PQ_DFL|PQ_MULTI, 872 (void *)(0), &argMode, modeList); 873 if (!parseEndOk( a, &pt, &retCode)) { 874 return retCode; 875 } 876 877 flags = 0; 878 879 if (argMode < 0) { 880 cli_out("%s: must specify a mode\n", ARG_CMD(a)); 881 return CMD_USAGE; 882 } 883 884 if ((argMode > 0) && (argDestPort < 0) && (argDestTrunk < 0)) { 885 cli_out("%s: missing DestPort or DestTrunk\n", ARG_CMD(a)); 886 return CMD_USAGE; 887 } 888 if ((argDestPort >= 0) && (argDestTrunk >= 0)) { 889 cli_out("%s: cannot specify both DestPort and DestTrunk\n", ARG_CMD(a)); 890 return CMD_USAGE; 891 } 892 893 if (argDestTrunk < 0) { 894 dstport = argDestPort; 895 } else { 896 dstport = argDestTrunk; 897 flags |= BCM_MIRROR_PORT_DEST_TRUNK; 898 } 899 900 switch (argMode) { 901 case 1: 902 flags |= BCM_MIRROR_PORT_ENABLE; 903 break; 904 case 2: 905 flags |= BCM_MIRROR_PORT_INGRESS; 906 break; 907 case 3: 908 flags |= BCM_MIRROR_PORT_EGRESS; 909 break; 910 case 4: 911 flags |= (BCM_MIRROR_PORT_INGRESS | BCM_MIRROR_PORT_EGRESS); 912 break; 913 default: 914 break; 915 } 916 917 DPORT_BCM_PBMP_ITER(unit, pbm, dport, port) { 918 rv = bcm_mirror_port_set(unit, port, argDestMod, dstport, flags); 919 920 if (rv < 0) { 921 cli_out("%s: bcm_mirror_port_set: %s\n", ARG_CMD(a), 922 bcm_errmsg(rv)); 923 return CMD_FAIL; 924 } 925 926 if (argDestMod < 0 || argDestMod == mymodid) { 927 if (argTpid >= 0 && argVlan >= 0 && argDestTrunk < 0) { 928 rv = bcm_mirror_vlan_set(unit, dstport, argTpid, argVlan); 929 930 if (rv < 0) { 931 cli_out("%s: bcm_mirror_vlan_set failed: %s\n", ARG_CMD(a), 932 bcm_errmsg(rv)); 933 return CMD_FAIL; 934 } 935 } 936 } 937 } 938 939 return CMD_OK; 940 }