visibility.c (17153B)
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 #include <shared/bsl.h> 8 #include <soc/defs.h> 9 10 #ifdef BCM_INSTRUMENTATION_SUPPORT 11 12 #include <bcm/pkt.h> 13 #include <bcm/trunk.h> 14 #include <bcm/stg.h> 15 16 #include <appl/diag/system.h> 17 #include <appl/diag/visibility.h> 18 19 /* hex dump without offset header 20 * blocks of 8 bytes, 16 bytes per line 21 * 22 * 0000000000000000 0000000000000000 23 */ 24 static void hexdump_8x2(uint8 *raw_data, int len) 25 { 26 int ri; 27 uint8 data[8] = {0}; 28 29 for (ri = 0; ri + 16 <= len; ) { 30 sal_memcpy(&data, &raw_data[ri], 8); 31 cli_out("%02x%02x%02x%02x%02x%02x%02x%02x ", 32 data[0], data[1], data[2], data[3], 33 data[4], data[5], data[6], data[7]); 34 ri += 8; 35 sal_memcpy(&data, &raw_data[ri], 8); 36 cli_out("%02x%02x%02x%02x%02x%02x%02x%02x\n", 37 data[0], data[1], data[2], data[3], 38 data[4], data[5], data[6], data[7]); 39 ri += 8; 40 } 41 } 42 43 /* hex dump with 2 bytes offset header 44 * blocks of 4 bytes, 32 bytes per line 45 * 46 * 0000 00000000 11222222 33333333 44444444 55555555 66666666 77777777 47 */ 48 static void hexdump_offset_4x8(uint8 *raw_data, int len) 49 { 50 int ri; 51 52 for (ri = 0; ri < len; ri++) { 53 if (!(ri & 0x1f)) { 54 cli_out("\n%04x ", ri); 55 } 56 cli_out("%s%s%02x", 57 (!(ri & 0x03)) ? " " : "", 58 (!(ri & 0x0f)) ? " " : "", 59 raw_data[ri]); 60 } 61 cli_out("\n"); 62 } 63 64 typedef struct { 65 bcm_switch_pkt_trace_resolution_t resolution; 66 char *name; 67 } abs_resolution_t; 68 69 static void abs_resolution_print(int unit, bcm_switch_pkt_trace_resolution_t resolution) 70 { 71 abs_resolution_t abs_resolution_table[] = { 72 { bcmSwitchPktTraceResolutionUnkown, "UnknownPkt" }, 73 { bcmSwitchPktTraceResolutionControlPkt, "ControlPkt" }, 74 { bcmSwitchPktTraceResolutionOamPkt, "OamPkt" }, 75 { bcmSwitchPktTraceResolutionBfdPkt, "BfdPkt" }, 76 { bcmSwitchPktTraceResolutionBpduPkt, "BpduPkt" }, 77 { bcmSwitchPktTraceResolution1588Pkt, "1588Pkt" }, 78 { bcmSwitchPktTraceResolutionKnownL2UcPkt, "KnownL2UcPkt" }, 79 { bcmSwitchPktTraceResolutionUnknownL2UcPkt, "UnknownL2UcPkt" }, 80 { bcmSwitchPktTraceResolutionKnownL2McPkt, "KnownL2McPkt" }, 81 { bcmSwitchPktTraceResolutionUnknownL2McPkt, "UnknownL2McPkt" }, 82 { bcmSwitchPktTraceResolutionL2BcPkt, "L2BcPkt" }, 83 { bcmSwitchPktTraceResolutionKnownL3UcPkt, "KnownL3UcPkt" }, 84 { bcmSwitchPktTraceResolutionUnknownL3UcPkt, "UnknownL3UcPkt" }, 85 { bcmSwitchPktTraceResolutionKnownIpmcPkt, "KnownIpmcPkt" }, 86 { bcmSwitchPktTraceResolutionUnknownIpmcPkt, "UnknownIpmcPkt" }, 87 { bcmSwitchPktTraceResolutionKnownMplsL2Pkt, "KnownMplsL2Pkt" }, 88 { bcmSwitchPktTraceResolutionUnknownMplsPkt, "UnknownMplsPkt" }, 89 { bcmSwitchPktTraceResolutionKnownMplsL3Pkt, "KnownMplsL3Pkt" }, 90 { bcmSwitchPktTraceResolutionKnownMplsPkt, "KnownMplsPkt" }, 91 { bcmSwitchPktTraceResolutionKnownMimPkt, "KnownMimPkt" }, 92 { bcmSwitchPktTraceResolutionUnknownMimPkt, "UnknownMimPkt" }, 93 { bcmSwitchPktTraceResolutionKnownTrillPkt, "KnownTrillPkt" }, 94 { bcmSwitchPktTraceResolutionUnknownTrillPkt, "UnknownTrillPkt" }, 95 { bcmSwitchPktTraceResolutionKnownNivPkt, "KnownNivPkt" }, 96 { bcmSwitchPktTraceResolutionUnknownNivPkt, "UnknownNivPkt" }, 97 { bcmSwitchPktTraceResolutionKnownL2GrePkt, "KnownL2GrePkt" }, 98 { bcmSwitchPktTraceResolutionKnownVxlanPkt, "KnownVxlanPkt" }, 99 { bcmSwitchPktTraceResolutionKnownFCOEPkt, "KnownFCOEPkt" }, 100 { bcmSwitchPktTraceResolutionUnknownFCOEPkt, "UnknownFCOEPkt" }, 101 { 0, NULL } 102 }; 103 104 abs_resolution_t *artp = &(abs_resolution_table[0]); 105 cli_out("Packet Resolution Result:\n"); 106 while (1) { 107 if (! artp->name) { 108 break; 109 } 110 111 if (resolution == artp->resolution) { 112 cli_out(" %s\n", artp->name); 113 } 114 artp++; 115 } 116 } 117 118 typedef struct { 119 bcm_switch_pkt_trace_drop_reason_t bit; 120 char *name; 121 } abs_drop_reasons_t; 122 123 static void abs_drop_reasons_print(int unit, bcm_switch_pkt_trace_drop_reason_t *dr) 124 { 125 uint32 i = 0; 126 abs_drop_reasons_t abs_drop_reasons_table[] = { 127 { bcmSwitchPktTraceNoDrop, 128 "NoDrop" }, 129 { bcmSwitchPktTraceDropReasonInternal, 130 "Internal" }, 131 {bcmSwitchPktTraceDropReasonMplsLabelLookupMiss, 132 "MplsLabelLookupMiss"}, 133 {bcmSwitchPktTraceDropReasonMplsInvalidAction, 134 "MplsInvalidAction"}, 135 {bcmSwitchPktTraceDropReasonMplsInvalidPayload, 136 "MplsInvalidPayload"}, 137 {bcmSwitchPktTraceDropReasonMplsTtlCheckFail, 138 "MplsTtlCheckFail"}, 139 {bcmSwitchPktTraceDropReasonMplsInvalidControlWord, 140 "MplsInvalidControlWord"}, 141 {bcmSwitchPktTraceDropReasonL2greSipLookupMiss, 142 "L2greSipLookupMiss"}, 143 {bcmSwitchPktTraceDropReasonL2greVpnLookupMiss, 144 "L2greVpnLookupMiss"}, 145 {bcmSwitchPktTraceDropReasonL2greTunnelError, 146 "L2greTunnelError"}, 147 {bcmSwitchPktTraceDropReasonVxlanSipLookupMiss, 148 "VxlanSipLookupMiss"}, 149 {bcmSwitchPktTraceDropReasonVxlanVnidLookupMiss, 150 "VxlanVnidLookupMiss"}, 151 {bcmSwitchPktTraceDropReasonVxlanTunnelError, 152 "VxlanTunnelError"}, 153 {bcmSwitchPktTraceDropReasonVlanNotValid, 154 "VlanNotValid"}, 155 {bcmSwitchPktTraceDropReasonIngressPortNotInVlanMember, 156 "IngressPortNotInVlanMember"}, 157 {bcmSwitchPktTraceDropReasonTpidMismatch, 158 "TpidMismatch"}, 159 {bcmSwitchPktTraceDropReasonIpv4ProtocolError, 160 "Ipv4ProtocolError"}, 161 {bcmSwitchPktTraceDropReasonHigigLoopback, 162 "HigigLoopback"}, 163 {bcmSwitchPktTraceDropReasonHigigMirrorOnly, 164 "HigigMirrorOnly"}, 165 {bcmSwitchPktTraceDropReasonHigigUnknownHeader, 166 "HigigUnknownHeader"}, 167 {bcmSwitchPktTraceDropReasonHigigUnknownOpcode, 168 "HigigUnknownOpcode"}, 169 {bcmSwitchPktTraceDropReasonLagFailLoopback, 170 "LagFailLoopback"}, 171 {bcmSwitchPktTraceDropReasonL2SrcEqualL2Dst, 172 "L2SrcEqualL2Dst"}, 173 {bcmSwitchPktTraceDropReasonIpv6ProtocolError, 174 "Ipv6ProtocolError"}, 175 {bcmSwitchPktTraceDropReasonNivVntagPresent, 176 "NivVntagPresent"}, 177 {bcmSwitchPktTraceDropReasonNivVntagNotPresent, 178 "NivVntagNotPresent"}, 179 {bcmSwitchPktTraceDropReasonNivVntagFormat, 180 "NivVntagFormat"}, 181 {bcmSwitchPktTraceDropReasonTrillErrorFrame, 182 "TrillErrorFrame"}, 183 {bcmSwitchPktTraceDropReasonBpdu, 184 "Bpdu"}, 185 {bcmSwitchPktTraceDropReasonBadUdpChecksum, 186 "BadUdpChecksum"}, 187 {bcmSwitchPktTraceDropReasonTunnlDecapEcnError, 188 "TunnlDecapEcnError"}, 189 {bcmSwitchPktTraceDropReasonIpv4HeaderError, 190 "Ipv4HeaderError"}, 191 {bcmSwitchPktTraceDropReasonIpv6HeaderError, 192 "Ipv6HeaderError"}, 193 {bcmSwitchPktTraceDropReasonParityError, 194 "ParityError"}, 195 {bcmSwitchPktTraceDropReasonRpfCheckFail, 196 "RpfCheckFail"}, 197 {bcmSwitchPktTraceDropReasonStageLookup, 198 "StageLookup"}, 199 {bcmSwitchPktTraceDropReasonStageIngress, 200 "StageIngress"}, 201 {bcmSwitchPktTraceDropReasonTunnelObjectValidationFail, 202 "TunnelObjectValidationFail"}, 203 {bcmSwitchPktTraceDropReasonTunnelShimHeaderError, 204 "TunnelShimHeaderError"}, 205 {bcmSwitchPktTraceDropReasonTunnelTTLError, 206 "TunnelTTLError"}, 207 {bcmSwitchPktTraceDropReasonTunnelInterfaceCheckFail, 208 "TunnelInterfaceCheckFail"}, 209 {bcmSwitchPktTraceDropReasonTunnelError, 210 "TunnelError"}, 211 {bcmSwitchPktTraceDropReasonTunnelAdapt1LookupMiss, 212 "TunnelAdapt1LookupMiss"}, 213 {bcmSwitchPktTraceDropReasonTunnelAdapt2LookupMiss, 214 "TunnelAdapt2LookupMiss"}, 215 {bcmSwitchPktTraceDropReasonTunnelAdapt3LookupMiss, 216 "TunnelAdapt3LookupMiss"}, 217 {bcmSwitchPktTraceDropReasonTunnelAdapt4LookupMiss, 218 "TunnelAdapt4LookupMiss"}, 219 {bcmSwitchPktTraceDropReasonCount, 220 NULL } 221 222 }; 223 abs_drop_reasons_t *adrtp = &(abs_drop_reasons_table[0]); 224 225 cli_out("Drop Reasons:\n"); 226 while (1) { 227 if (!adrtp->name) { 228 break; 229 } 230 i = (adrtp->bit / BYTES2BITS(sizeof(uint32))); 231 if (dr[i] & (1 << (adrtp->bit - (32 * i)))) { 232 cli_out(" %s\n", adrtp->name); 233 } 234 adrtp++; 235 } 236 } 237 238 typedef struct { 239 bcm_switch_pkt_trace_lookup_t bit; 240 char *name; 241 } abs_lookup_results_t; 242 243 static void abs_lookup_results_print(int unit, bcm_switch_pkt_trace_lookup_result_t *lr) 244 { 245 abs_lookup_results_t abs_lookup_results_table[] = { 246 { bcmSwitchPktTraceLookupFirstVlanTranslationHit, 247 "FirstVlanTranslationHit" }, 248 { bcmSwitchPktTraceLookupSecondVlanTranslationHit, 249 "SecondVlanTranslationHit" }, 250 { bcmSwitchPktTraceLookupForwardingVlanValid, 251 "ForwardingVlanValid" }, 252 { bcmSwitchPktTraceLookupL2SrcHit, 253 "L2SrcHit" }, 254 { bcmSwitchPktTraceLookupL2SrcStatic, 255 "L2SrcStatic" }, 256 { bcmSwitchPktTraceLookupL2DstHit, 257 "L2DstHit" }, 258 { bcmSwitchPktTraceLookupL2CacheHit, 259 "L2CacheHit" }, 260 { bcmSwitchPktTraceLookupL3SrcHostHit, 261 "L3SrcHostHit" }, 262 { bcmSwitchPktTraceLookupL3DestHostHit, 263 "L3DestHostHit" }, 264 { bcmSwitchPktTraceLookupL3DestRouteHit, 265 "L3DestRouteHit" }, 266 { bcmSwitchPktTraceLookupL2SrcMiss, 267 "L2SrcMiss" }, 268 { bcmSwitchPktTraceLookupDosAttack, 269 "DosAttack" }, 270 { bcmSwitchPktTraceLookupIpTunnelHit, 271 "IpTunnelHit" }, 272 { bcmSwitchPktTraceLookupMplsLabel1Hit, 273 "MplsLabel1Hit" }, 274 { bcmSwitchPktTraceLookupMplsLabel2Hit, 275 "MplsLabel2Hit" }, 276 { bcmSwitchPktTraceLookupMplsTerminated, 277 "MplsTerminated" }, 278 { bcmSwitchPktTraceLookupMystationHit, 279 "MystationHit" }, 280 { bcmSwitchPktTraceLookupInvalid, 281 NULL } 282 }; 283 abs_lookup_results_t *alrtp = &(abs_lookup_results_table[0]); 284 285 cli_out("Lookup Status Results:\n"); 286 while (1) { 287 if (! alrtp->name) { 288 break; 289 } 290 291 if (lr->pkt_trace_status_bitmap[0] & (1 << alrtp->bit )) { 292 cli_out(" %s\n", alrtp->name); 293 } 294 alrtp++; 295 } 296 } 297 298 299 static void gport_print(bcm_port_t gp) 300 { 301 if (BCM_GPORT_IS_SET(gp)) { 302 if (BCM_GPORT_IS_LOCAL(gp)) 303 cli_out("local(%d)\n", BCM_GPORT_LOCAL_GET(gp)); 304 else if (BCM_GPORT_IS_MODPORT(gp)) 305 cli_out("modport(%d, %d)\n", 306 BCM_GPORT_MODPORT_MODID_GET(gp), 307 BCM_GPORT_MODPORT_PORT_GET(gp)); 308 else if (BCM_GPORT_IS_TRUNK(gp)) 309 cli_out("trunk(%d)\n", BCM_GPORT_TRUNK_GET(gp)); 310 else if (BCM_GPORT_IS_BLACK_HOLE(gp)) 311 cli_out("blackhole\n"); 312 else if (BCM_GPORT_IS_LOCAL_CPU(gp)) 313 cli_out("cpu\n"); 314 } else if (gp == BCM_GPORT_INVALID) { 315 cli_out("Invalid GPORT\n"); 316 } else { 317 cli_out("%d\n", gp); 318 } 319 } 320 321 static void fp_trunk_print(int unit, bcm_trunk_t tid) 322 { 323 int rv; 324 int i; 325 bcm_trunk_info_t tinfo; 326 bcm_trunk_member_t member_array[BCM_TRUNK_MAX_PORTCNT]; 327 int member_count; 328 329 rv = bcm_trunk_get(unit, 330 tid, 331 &tinfo, 332 BCM_TRUNK_MAX_PORTCNT, 333 member_array, 334 &member_count); 335 336 if (BCM_FAILURE(rv)) { 337 cli_out("bcm_trunk_get(unit=%d,tid=%d): rv=%d, %s\n", 338 unit, 339 tid, 340 rv, 341 bcm_errmsg(rv)); 342 return; 343 } 344 cli_out(" Trunk id: %d\n", tid); 345 cli_out(" Rtag: %d\n", tinfo.psc); 346 cli_out(" Members: %d ports\n", member_count); 347 for (i = 0; i < member_count; i++) { 348 cli_out(" "); gport_print(member_array[i].gport); 349 } 350 } 351 352 static void abs_hashing_info_print(int unit, bcm_switch_pkt_trace_hashing_info_t *hi) 353 { 354 /* Hashing resolution? */ 355 if (hi->flags == 0) { 356 return; 357 } 358 if (hi->flags & BCM_SWITCH_PKT_TRACE_ECMP_1) { 359 cli_out("Hash resolution: ECMP1 (MULTIPATH)\n"); 360 cli_out(" ecmp_1_group %d\n", hi->ecmp_1_group); 361 cli_out(" > l3 multipath show %d\n", hi->ecmp_1_group); 362 363 cli_out("Egress multipath interface:\n"); 364 cli_out(" ecmp_1_egress %d\n", hi->ecmp_1_egress); 365 cli_out(" > l3 egress show %d\n", hi->ecmp_1_egress); 366 } 367 if (hi->flags & BCM_SWITCH_PKT_TRACE_ECMP_2) { 368 cli_out("Hash resolution: ECMP2 (MULTIPATH)\n"); 369 cli_out(" ecmp_2_group %d\n", hi->ecmp_2_group); 370 cli_out(" > l3 multipath show %d\n", hi->ecmp_2_group); 371 cli_out(" ecmp2_egress %d\n", hi->ecmp_2_egress); 372 } 373 if (hi->flags & BCM_SWITCH_PKT_TRACE_TRUNK) { 374 cli_out("Hash resolution: Trunk\n"); 375 fp_trunk_print(unit, hi->trunk); 376 cli_out(" Trunk egress member: "); gport_print(hi->trunk_member); 377 } 378 if (hi->flags & BCM_SWITCH_PKT_TRACE_FABRIC_TRUNK) { 379 cli_out("Hash resolution: Fabric trunk\n"); 380 cli_out(" Fabric trunk: "); gport_print(hi->fabric_trunk); 381 cli_out(" Fabric trunk egress member: "); gport_print(hi->fabric_trunk_member); 382 } 383 } 384 385 static void abs_fwd_dst_info_print(int unit, bcm_switch_pkt_trace_fwd_dst_info_t *fd) 386 { 387 /* Forward destination information*/ 388 if (fd->flags == 0) { 389 return; 390 } 391 if (fd->flags & BCM_SWITCH_PKT_TRACE_FWD_DST_DGPP) { 392 cli_out(" Destination port %x\n", fd->port); 393 } 394 if (fd->flags & BCM_SWITCH_PKT_TRACE_FWD_DST_DVP) { 395 cli_out(" DVP %x\n", fd->dvp); 396 } 397 if (fd->flags & BCM_SWITCH_PKT_TRACE_FWD_DST_DVP) { 398 cli_out(" DVP %d\n", fd->dvp); 399 } 400 if (fd->flags & BCM_SWITCH_PKT_TRACE_FWD_DST_VLAN) { 401 cli_out(" Forwarding VlAN %d\n", fd->fwd_vlan); 402 } 403 if (fd->flags & BCM_SWITCH_PKT_TRACE_FWD_DST_L2MC) { 404 cli_out(" l2 multicast group %d\n", fd->mc_group); 405 } 406 if (fd->flags & BCM_SWITCH_PKT_TRACE_FWD_DST_IPMC) { 407 cli_out(" l3 multicast group %d\n", fd->mc_group); 408 } 409 if (fd->flags & BCM_SWITCH_PKT_TRACE_FWD_DST_NH) { 410 cli_out(" > l3 egress show %d\n", fd->egress_intf); 411 } 412 } 413 414 static void abs_stp_state_print(int unit, bcm_stg_stp_t stp_state) 415 { 416 char *stp_state_names[] = { 417 /* In Tomahawk, there is no learning */ 418 "Disable", "Block", "Listen", "Forward", "Forward" 419 }; 420 421 cli_out("Source port STP state: "); 422 if (stp_state > BCM_STG_STP_FORWARD) { 423 cli_out(" Invalid STP state\n"); 424 } else { 425 cli_out(" %s\n", stp_state_names[stp_state]); 426 } 427 } 428 429 void appl_pkt_trace_info_print(int unit, bcm_switch_pkt_trace_info_t *pkt_trace_info) 430 { 431 abs_lookup_results_print(unit, &pkt_trace_info->pkt_trace_lookup_status); 432 abs_resolution_print(unit, pkt_trace_info->pkt_trace_resolution); 433 abs_stp_state_print(unit, pkt_trace_info->pkt_trace_stp_state); 434 abs_hashing_info_print(unit, &pkt_trace_info->pkt_trace_hash_info); 435 abs_fwd_dst_info_print(unit, &pkt_trace_info->pkt_trace_fwd_dst_info); 436 abs_drop_reasons_print(unit, pkt_trace_info->pkt_trace_drop_reason); 437 } 438 439 440 int appl_visibility_trace(int unit, int vis_options, int vis_sport, bcm_pkt_t *pkt_info) 441 { 442 int rv; 443 uint16 i = 0; 444 uint16 print_raw_data = 0; 445 bcm_switch_pkt_trace_info_t pkt_trace_info; 446 447 rv = bcm_switch_pkt_trace_info_get(unit, 448 vis_options, 449 vis_sport, 450 pkt_info->pkt_data->len, 451 pkt_info->pkt_data->data, 452 &pkt_trace_info); 453 cli_out("\n=====PACKET TRACE source_port=%s, %s\n", 454 BCM_PORT_NAME(unit, vis_sport), 455 bcm_errmsg(rv)); 456 if (rv == BCM_E_NONE) { 457 cli_out("\n=====RAW PACKET"); 458 hexdump_offset_4x8(pkt_info->pkt_data->data, 459 pkt_info->pkt_data->len); 460 cli_out("\n=====RESULTS\n"); 461 cli_out("Ingress pipeline = %d\n", 462 pkt_trace_info.dest_pipe_num); 463 appl_pkt_trace_info_print(unit, &pkt_trace_info); 464 465 for (i = 0; i < BCM_SWITCH_PKT_TRACE_RAW_DATA_MAX; i++) { 466 if (pkt_trace_info.raw_data[i]) { 467 print_raw_data = 1; 468 break; 469 } 470 } 471 if (print_raw_data) { 472 cli_out("\n=====RAW DATA\n"); 473 hexdump_8x2(pkt_trace_info.raw_data, 474 sizeof(pkt_trace_info.raw_data)); 475 } 476 } 477 478 return rv; 479 } 480 #endif /* BCM_INSTRUMENTATION_SUPPORT */