instrumentation.c (36621B)
1 /* 2 * 3 * 4 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 5 * 6 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 7 * 8 * File: instrumentation.c 9 * Purpose: Tomahawk3 Instrumentation code 10 */ 11 #if defined(BCM_TOMAHAWK3_SUPPORT) 12 #include <soc/drv.h> 13 14 #if defined(BCM_INSTRUMENTATION_SUPPORT) 15 #include <soc/mem.h> 16 #include <soc/format.h> 17 #include <soc/tomahawk3.h> 18 #include <bcm/switch.h> 19 #include <bcm_int/esw/instrumentation.h> 20 #include <bcm_int/esw_dispatch.h> 21 #include <bcm_int/esw/port.h> 22 #include <bcm_int/esw/firebolt.h> 23 #include <bcm_int/esw/stg.h> 24 #include <shared/bitop.h> 25 26 #define TH3_PTR_RESULTS_IADAPT_MAX_INDEX 1 27 #define TH3_PTR_RESULTS_IPARS_MAX_INDEX 1 28 #define TH3_PTR_RESULTS_IFWD_MAX_INDEX 4 29 #define TH3_PTR_RESULTS_ISW_MAX_INDEX 7 30 31 #define TH3_IP_STAGE_PER_ENTRY_SIZE 8 32 33 #define TH3_IADAPT_RAW_DATA_BYTES \ 34 (TH3_PTR_RESULTS_IADAPT_MAX_INDEX * TH3_IP_STAGE_PER_ENTRY_SIZE) 35 #define TH3_IPARS_RAW_DATA_BYTES \ 36 (TH3_PTR_RESULTS_IPARS_MAX_INDEX * TH3_IP_STAGE_PER_ENTRY_SIZE) 37 #define TH3_IFWD_RAW_DATA_BYTES \ 38 (TH3_PTR_RESULTS_IFWD_MAX_INDEX * TH3_IP_STAGE_PER_ENTRY_SIZE) 39 #define TH3_ISW_RAW_DATA_BYTES \ 40 (TH3_PTR_RESULTS_ISW_MAX_INDEX * TH3_IP_STAGE_PER_ENTRY_SIZE) 41 42 #define TH3_IPARS_RAW_DATA_OFFSET 0 43 #define TH3_IADAPT_RAW_DATA_OFFSET \ 44 (TH3_IPARS_RAW_DATA_OFFSET + TH3_IPARS_RAW_DATA_BYTES) 45 #define TH3_IFWD_RAW_DATA_OFFSET \ 46 (TH3_IADAPT_RAW_DATA_OFFSET + TH3_IADAPT_RAW_DATA_BYTES) 47 #define TH3_ISW_RAW_DATA_OFFSET \ 48 (TH3_IFWD_RAW_DATA_OFFSET + TH3_IFWD_RAW_DATA_BYTES) 49 50 /* 51 * Function: 52 * _bcm_th3_pkt_trace_hw_reset 53 * 54 * Purpose: 55 * clean PTR_RESULTS_BUFFER_IADAPT/IPARS/IFWD/ISW memories 56 * call this function before sending a visibilty packet 57 * 58 * Parameters: 59 * unit - (IN) Device Number 60 * pipe - (IN) Ingress Pipeline Number 61 * 62 * Returns: 63 * BCM_E_XXX 64 * 65 * Notes: 66 * If 'pipe' parameter is -1, memories for all pipes will 67 * get reset else memory for only that pipe gets reset 68 */ 69 int _bcm_th3_pkt_trace_hw_reset(int unit, int pipe) 70 { 71 int rv = BCM_E_NONE; 72 uint32 active_pipes_bmap = 0x0; 73 soc_mem_t mem; 74 75 if (-1 == pipe) { 76 SOC_IF_ERROR_RETURN( 77 soc_mem_clear(unit, PTR_RESULTS_BUFFER_IPARSm, MEM_BLOCK_ALL, 0)); 78 SOC_IF_ERROR_RETURN( 79 soc_mem_clear(unit, PTR_RESULTS_BUFFER_IADAPTm, MEM_BLOCK_ALL, 0)); 80 SOC_IF_ERROR_RETURN( 81 soc_mem_clear(unit, PTR_RESULTS_BUFFER_IFWDm, MEM_BLOCK_ALL, 0)); 82 SOC_IF_ERROR_RETURN( 83 soc_mem_clear(unit, PTR_RESULTS_BUFFER_ISWm, MEM_BLOCK_ALL, 0)); 84 85 } else if ((pipe > -1) && (pipe < SOC_MAX_NUM_PIPES)) { 86 87 /* Get pipe bitmap for active pipes in the system */ 88 soc_tomahawk3_pipe_map_get(unit, &active_pipes_bmap); 89 90 /* Check if the given pipe is active on the device */ 91 if (active_pipes_bmap & (1 << pipe)) { 92 mem = SOC_MEM_UNIQUE_ACC(unit, PTR_RESULTS_BUFFER_IPARSm)[pipe]; 93 SOC_IF_ERROR_RETURN(soc_mem_clear(unit, mem, MEM_BLOCK_ALL, 0)); 94 95 mem = SOC_MEM_UNIQUE_ACC(unit, PTR_RESULTS_BUFFER_IADAPTm)[pipe]; 96 SOC_IF_ERROR_RETURN(soc_mem_clear(unit, mem, MEM_BLOCK_ALL, 0)); 97 98 mem = SOC_MEM_UNIQUE_ACC(unit, PTR_RESULTS_BUFFER_IFWDm)[pipe]; 99 SOC_IF_ERROR_RETURN(soc_mem_clear(unit, mem, MEM_BLOCK_ALL, 0)); 100 101 mem = SOC_MEM_UNIQUE_ACC(unit, PTR_RESULTS_BUFFER_ISWm)[pipe]; 102 SOC_IF_ERROR_RETURN(soc_mem_clear(unit, mem, MEM_BLOCK_ALL, 0)); 103 } else { 104 /* If the given pipe is not active then return error */ 105 rv = BCM_E_PARAM; 106 } 107 } else { 108 rv = BCM_E_PARAM; 109 } 110 111 return rv; 112 } 113 114 /* 115 * Function: 116 * _bcm_th3_pkt_trace_drop_reason_decode 117 * 118 * Purpose: 119 * decode the raw drop reason bits into Application 120 * understandable format 121 * 122 * Parameters: 123 * unit - (IN) Device Number 124 * pkt_trace_info - (IN/OUT) User given packet trace structure. 125 * 126 * Returns: 127 * BCM_E_XXX 128 * 129 * Notes: 130 * Parameter 'pkt_trace_info' will be used as input to this function 131 * for member 'raw_data' and will be used as an output with respect 132 * to member 'pkt_trace_drop_reason' 133 */ 134 static 135 int _bcm_th3_pkt_trace_drop_reason_decode(int unit, 136 bcm_switch_pkt_trace_info_t *pkt_trace_info) 137 { 138 int fld_idx; 139 int bit_set_cnt = 0; 140 uint32 pre_coun_v = 0; 141 uint32 pkt_dp_v[2] = {0}; 142 uint32 disc_dp_v = 0; 143 uint32 rsel_dp_v = 0; 144 uint32 tl_dp_v = 0; 145 uint32 vlan_dp_v = 0; 146 uint32 pre_dp_v = 0; 147 uint32 *isw_raw_data = 148 (uint32 *)(pkt_trace_info->raw_data + TH3_ISW_RAW_DATA_OFFSET); 149 static const soc_field_t dp_flds[] = { 150 RIPD4f, 151 RIPHE4f, 152 RIPD6f, 153 RIPHE6f, 154 BLOCK_MASK_DROPf, 155 MTU_CHECK_FAILf, 156 PARITYDf, 157 PDISCf, 158 RDROPf, 159 RIMDRf, 160 RPORTDf, 161 RTUNEf 162 }; 163 164 typedef struct { 165 soc_field_t field; 166 uint8 idx_fmt_map; 167 uint8 reason; 168 } drop_reason_map_t; 169 170 /* Drop reasons TH3 cares to provide to Applications */ 171 const drop_reason_map_t drop_reason_map[] = { 172 { INVALID_VLANf, 0 /* VLAN_DROP_VECTORfmt */, 173 (uint8)bcmSwitchPktTraceDropReasonVlanNotValid }, 174 { ENIFILTERf, 0 /* VLAN_DROP_VECTORfmt */, 175 (uint8)bcmSwitchPktTraceDropReasonIngressPortNotInVlanMember}, 176 { INVALID_TPIDf, 0 /* VLAN_DROP_VECTORfmt */, 177 (uint8)bcmSwitchPktTraceDropReasonTpidMismatch }, 178 { IFP_DROPf, 1 /* RSEL_DROP_VECTORfmt */, 179 (uint8)bcmSwitchPktTraceDropReasonStageIngress }, 180 { TUNNEL_ERRORf, 1 /* RSEL_DROP_VECTORfmt */, 181 (uint8)bcmSwitchPktTraceDropReasonTunnelError }, 182 { BPDUf, 2 /* PKT_PROC_DROP_VECTORfmt */, 183 (uint8)bcmSwitchPktTraceDropReasonBpdu }, 184 { TUNNEL_DECAP_ECNf, 2 /* PKT_PROC_DROP_VECTORfmt */, 185 (uint8)bcmSwitchPktTraceDropReasonTunnlDecapEcnError }, 186 { VFPf, 2 /* PKT_PROC_DROP_VECTORfmt */, 187 (uint8)bcmSwitchPktTraceDropReasonStageLookup }, 188 { CMLf, 2 /* PKT_PROC_DROP_VECTORfmt */, 189 (uint8)bcmSwitchPktTraceDropReasonUnknownSrcMac }, 190 { L2DST_DISCARDf, 2 /* PKT_PROC_DROP_VECTORfmt */, 191 (uint8)bcmSwitchPktTraceDropReasonL2DstDiscard }, 192 { L2SRC_DISCARDf, 2 /* PKT_PROC_DROP_VECTORfmt */, 193 (uint8)bcmSwitchPktTraceDropReasonL2SrcDiscard }, 194 { L2SRC_STATIC_MOVEf, 2 /* PKT_PROC_DROP_VECTORfmt */, 195 (uint8)bcmSwitchPktTraceDropReasonL2SrcStaticMove }, 196 { L3DST_DISCARDf, 2 /* PKT_PROC_DROP_VECTORfmt */, 197 (uint8)bcmSwitchPktTraceDropReasonL3DstDiscard }, 198 { MACSA0f, 2 /* PKT_PROC_DROP_VECTORfmt */, 199 (uint8)bcmSwitchPktTraceDropReasonSrcMacZero }, 200 { MULTICAST_INDEX_ERRORf, 2 /* PKT_PROC_DROP_VECTORfmt */, 201 (uint8)bcmSwitchPktTraceDropReasonMcastIndexError }, 202 { MY_STATIONf, 2 /* PKT_PROC_DROP_VECTORfmt */, 203 (uint8)bcmSwitchPktTraceDropReasonMyStation }, 204 { PFMf, 2 /* PKT_PROC_DROP_VECTORfmt */, 205 (uint8)bcmSwitchPktTraceDropReasonMcastLookupMiss }, 206 { PROTCOL_PKTf, 2 /* PKT_PROC_DROP_VECTORfmt */, 207 (uint8)bcmSwitchPktTraceDropReasonProtocolPkt }, 208 { SRC_ROUTEf, 2 /* PKT_PROC_DROP_VECTORfmt */, 209 (uint8)bcmSwitchPktTraceDropReasonSrcRoute }, 210 { TAG_UNTAG_DISCARDf, 2 /* PKT_PROC_DROP_VECTORfmt */, 211 (uint8)bcmSwitchPktTraceDropReasonPortTagPresentError }, 212 { TIME_SYNC_PKTf, 2 /* PKT_PROC_DROP_VECTORfmt */, 213 (uint8)bcmSwitchPktTraceDropReasonTimeSyncPkt }, 214 { VLAN_CC_OR_PBTf, 2 /* PKT_PROC_DROP_VECTORfmt */, 215 (uint8)bcmSwitchPktTraceDropReasonL2DstMissOrPbt }, 216 { MPLS_LABEL_MISSf, 3 /* TUNNEL_PROC_DROP_VECTORfmt */, 217 (uint8)bcmSwitchPktTraceDropReasonMplsLabelLookupMiss }, 218 { MPLS_INVALID_ACTIONf, 3 /* TUNNEL_PROC_DROP_VECTORfmt */, 219 (uint8)bcmSwitchPktTraceDropReasonMplsInvalidAction }, 220 { MPLS_INVALID_PAYLOADf, 3 /* TUNNEL_PROC_DROP_VECTORfmt */, 221 (uint8)bcmSwitchPktTraceDropReasonMplsInvalidPayload }, 222 { MPLS_INVALID_CWf, 3 /* TUNNEL_PROC_DROP_VECTORfmt */, 223 (uint8)bcmSwitchPktTraceDropReasonMplsInvalidControlWord }, 224 { MPLS_TTL_CHECK_FAILf, 3 /* TUNNEL_PROC_DROP_VECTORfmt */, 225 (uint8)bcmSwitchPktTraceDropReasonMplsTtlCheckFail }, 226 { MPLS_GAL_LABELf, 3 /* TUNNEL_PROC_DROP_VECTORfmt */, 227 (uint8)bcmSwitchPktTraceDropReasonMplsGalLabel }, 228 { CONTROL_FRAMEf, 4 /* DISCARD_PROC_DROP_VECTORfmt */, 229 (uint8)bcmSwitchPktTraceDropReasonControlFrame }, 230 { IPV4_PROTOCOL_ERRORf, 4 /* DISCARD_PROC_DROP_VECTORfmt */, 231 (uint8)bcmSwitchPktTraceDropReasonIpv4ProtocolError }, 232 { IPV6_PROTOCOL_ERRORf, 4 /* DISCARD_PROC_DROP_VECTORfmt */, 233 (uint8)bcmSwitchPktTraceDropReasonIpv6ProtocolError }, 234 { LAG_FAIL_LOOPBACKf, 4 /* DISCARD_PROC_DROP_VECTORfmt */, 235 (uint8)bcmSwitchPktTraceDropReasonLagFailLoopback }, 236 { MACSA_EQUALS_DAf, 4 /* DISCARD_PROC_DROP_VECTORfmt */, 237 (uint8)bcmSwitchPktTraceDropReasonL2SrcEqualL2Dst }, 238 { RIPHE4f, 5 /* PRE_COUNTER_UPDATE_VECTORfmt */, 239 (uint8)bcmSwitchPktTraceDropReasonIpv4HeaderError }, 240 { RIPHE6f, 5 /* PRE_COUNTER_UPDATE_VECTORfmt */, 241 (uint8)bcmSwitchPktTraceDropReasonIpv6HeaderError }, 242 { RDROPf, 5 /* PRE_COUNTER_UPDATE_VECTORfmt */, 243 (uint8)bcmSwitchPktTraceDropReasonPortBitmapZero }, 244 { RPORTDf, 5 /* PRE_COUNTER_UPDATE_VECTORfmt */, 245 (uint8)bcmSwitchPktTraceDropReasonStpNotForwarding }, 246 { PARITYDf, 5 /* PRE_COUNTER_UPDATE_VECTORfmt */, 247 (uint8)bcmSwitchPktTraceDropReasonParityError } 248 }; 249 250 typedef struct { 251 soc_format_t fmt; 252 void * fmt_entry; 253 } format_map_t; 254 255 format_map_t fmt_map[] = { 256 { VLAN_DROP_VECTORfmt, NULL }, 257 { RSEL_DROP_VECTORfmt, NULL }, 258 { PKT_PROC_DROP_VECTORfmt, NULL }, 259 { TUNNEL_PROC_DROP_VECTORfmt, NULL }, 260 { DISCARD_PROC_DROP_VECTORfmt, NULL }, 261 { PRE_COUNTER_UPDATE_VECTORfmt, NULL } 262 }; 263 264 fmt_map[0].fmt_entry = (void *)&vlan_dp_v; 265 fmt_map[1].fmt_entry = (void *)&rsel_dp_v; 266 fmt_map[2].fmt_entry = (void *)&pkt_dp_v; 267 fmt_map[3].fmt_entry = (void *)&tl_dp_v; 268 fmt_map[4].fmt_entry = (void *)&disc_dp_v; 269 fmt_map[5].fmt_entry = (void *)&pre_dp_v; 270 271 /* Extract the PKT_PROC_DROP_VECTOR from the ISW.DW5 raw data */ 272 soc_format_field_get(unit, 273 INGRESS_COUNTER_UPDATE_VECTORfmt, 274 isw_raw_data + 10, 275 PKT_PROC_DROP_VECTORf, 276 pkt_dp_v); 277 278 /* Extract the DISCARD_PROC_DROP_VECTOR from PKT_PROC_DROP_VECTOR 279 * field and then clear the DISCARD_PROC_DROP_VECTOR from the pkt_dp_v 280 */ 281 disc_dp_v = soc_format_field32_get(unit, PKT_PROC_DROP_VECTORfmt, 282 pkt_dp_v, DISCARD_PROC_DROP_VECTORf); 283 soc_format_field32_set(unit, PKT_PROC_DROP_VECTORfmt, 284 pkt_dp_v, DISCARD_PROC_DROP_VECTORf, 0x0); 285 286 /* Extract the RSEL_DROP_VECTOR from PKT_PROC_DROP_VECTOR 287 * field and then clear the RSEL_DROP_VECTOR from the pkt_dp_v 288 */ 289 rsel_dp_v = soc_format_field32_get(unit, PKT_PROC_DROP_VECTORfmt, 290 pkt_dp_v, RSEL_DROP_VECTORf); 291 soc_format_field32_set(unit, PKT_PROC_DROP_VECTORfmt, 292 pkt_dp_v, RSEL_DROP_VECTORf, 0x0); 293 294 /* Extract the TUNNEL_PROC_DROP_VECTOR from PKT_PROC_DROP_VECTOR 295 * field and then clear the TUNNEL_PROC_DROP_VECTOR from the pkt_dp_v 296 */ 297 tl_dp_v = soc_format_field32_get(unit, PKT_PROC_DROP_VECTORfmt, 298 pkt_dp_v, TUNNEL_PROC_DROP_VECTORf); 299 soc_format_field32_set(unit, PKT_PROC_DROP_VECTORfmt, 300 pkt_dp_v, TUNNEL_PROC_DROP_VECTORf, 0x0); 301 302 /* Extract the VLAN_DROP_VECTOR from PKT_PROC_DROP_VECTOR 303 * field and then clear the VLAN_DROP_VECTOR from the pkt_dp_v 304 */ 305 vlan_dp_v = soc_format_field32_get(unit, PKT_PROC_DROP_VECTORfmt, 306 pkt_dp_v, VLAN_DROP_VECTORf); 307 soc_format_field32_set(unit, PKT_PROC_DROP_VECTORfmt, 308 pkt_dp_v, VLAN_DROP_VECTORf, 0x0); 309 310 /* Extract the PRE_COUNTER_UPDATE_VECTORf from ISW Stage buffer */ 311 pre_coun_v = soc_format_field32_get(unit, 312 INSTR_BUFFER_ISW_DW6fmt, 313 isw_raw_data + 12, 314 PRE_COUNTER_UPDATE_VECTORf); 315 316 /* Extract required drop vector from pre counter vector 317 * RIPD4, RIPHE4, RIPD6, RIPHE6, BLOCK_MASK_DROP, 318 * MTU_CHECK_FAIL, PARITYD, PDISC, RDROP, RIMDR, RPORTD, RTUNE 319 */ 320 for (fld_idx=0 ; fld_idx < COUNTOF(dp_flds) ; fld_idx++) { 321 if(soc_format_field32_get(unit, 322 PRE_COUNTER_UPDATE_VECTORfmt, &pre_coun_v, dp_flds[fld_idx])) { 323 soc_format_field32_set(unit, 324 PRE_COUNTER_UPDATE_VECTORfmt, &pre_dp_v, dp_flds[fld_idx], 0x1); 325 } 326 } 327 328 /* Clear the drop reason bitmap begin-with */ 329 sal_memset(pkt_trace_info->pkt_trace_drop_reason, 330 0, sizeof(pkt_trace_info->pkt_trace_drop_reason)); 331 332 /* Capture the necessary drop reasons and clear the corresponding bit 333 * in the source bitmap to indicate that the drop reason has been processed 334 */ 335 for (fld_idx=0 ; fld_idx < COUNTOF(drop_reason_map) ; fld_idx++) { 336 if (soc_format_field32_get(unit, 337 fmt_map[drop_reason_map[fld_idx].idx_fmt_map].fmt, 338 fmt_map[drop_reason_map[fld_idx].idx_fmt_map].fmt_entry, 339 drop_reason_map[fld_idx].field)) 340 { 341 SHR_BITSET(pkt_trace_info->pkt_trace_drop_reason, 342 drop_reason_map[fld_idx].reason); 343 soc_format_field32_set(unit, 344 fmt_map[drop_reason_map[fld_idx].idx_fmt_map].fmt, 345 fmt_map[drop_reason_map[fld_idx].idx_fmt_map].fmt_entry, 346 drop_reason_map[fld_idx].field, 347 0x0); 348 } 349 } 350 351 /* If there are more drop reasons which are not yet captured/decoded 352 * individually then mark the Internal drop reason too in the bitmap. 353 */ 354 if (tl_dp_v || disc_dp_v || vlan_dp_v || 355 pre_dp_v || pkt_dp_v[0] || pkt_dp_v[1] || rsel_dp_v) { 356 SHR_BITSET(pkt_trace_info->pkt_trace_drop_reason, 357 bcmSwitchPktTraceDropReasonInternal); 358 } 359 360 /* See if the drop reason bitmap has any drop bit set */ 361 SHR_BITCOUNT_RANGE(pkt_trace_info->pkt_trace_drop_reason, 362 bit_set_cnt, 0, bcmSwitchPktTraceDropReasonCount); 363 364 /* If no error or drop bit is set then mark the bit for No Drop */ 365 if (0 == bit_set_cnt) { 366 SHR_BITSET( 367 pkt_trace_info->pkt_trace_drop_reason, bcmSwitchPktTraceNoDrop); 368 } 369 370 return BCM_E_NONE; 371 } 372 373 /* 374 * Function: 375 * _bcm_th3_pkt_trace_raw_data_decode 376 * 377 * Purpose: 378 * decode the raw data from PTR_RESULTS_BUFFER_IADAPT/IFWD/ISW memories 379 * The memories are not read instead the data is interpreted from the 380 * 'raw_data' buffer which already has been filled-in with the entries 381 * from the above mentioned memories. 382 * 383 * Parameters: 384 * unit - (IN) Device Number 385 * pkt_trace_info - (IN/OUT) User given packet trace structure. 386 * 387 * Returns: 388 * BCM_E_XXX 389 * 390 * Notes: 391 * Parameter 'pkt_trace_info' will be used as input to this function 392 * for member 'raw_data' and will be used as an output with respect 393 * to other members. 394 */ 395 static 396 int _bcm_th3_pkt_trace_raw_data_decode(int unit, 397 bcm_switch_pkt_trace_info_t *pkt_trace_info) 398 { 399 int rv = BCM_E_NONE; 400 401 /* pkt lookup and resolution vars*/ 402 int l2x_index = -1; 403 uint32 lookup_status; 404 uint32 ing_stp_state; 405 l2x_entry_t l2x_entry; 406 407 /* Trunk/LAG related vars */ 408 int tgid; 409 uint32 lag_hash_val; 410 uint32 trunk_group_size; 411 uint32 trunk_member_index; 412 _bcm_gport_dest_t dest; 413 fast_trunk_size_entry_t trunk_size_entry; 414 415 #ifdef INCLUDE_L3 416 /* ECMP hashing information vars */ 417 int ecmp_id; 418 uint32 ecmp_ptr; 419 uint32 ecmp_index; 420 ecmp_entry_t ecmp_entry; 421 ecmp_count_entry_t ecmpc_entry; 422 uint32 ecmp_offset; 423 uint32 ecmp_rsl_done1; 424 uint32 ecmp_rsl_done2; 425 #endif 426 427 /* get hold of the respective pipeline stage data */ 428 uint32 *offset_isw_data; 429 uint32 *iadapt_raw_data = 430 (uint32 *)(pkt_trace_info->raw_data + TH3_IADAPT_RAW_DATA_OFFSET); 431 uint32 *ifwd_raw_data = 432 (uint32 *)(pkt_trace_info->raw_data + TH3_IFWD_RAW_DATA_OFFSET); 433 uint32 *isw_raw_data = 434 (uint32 *)(pkt_trace_info->raw_data + TH3_ISW_RAW_DATA_OFFSET); 435 436 /* retrieve lookup status */ 437 lookup_status = 438 soc_format_field32_get( 439 unit, INSTR_BUFFER_IFWD_DW3fmt, ifwd_raw_data + 6, LOOKUP_STATUSf); 440 441 /* fill ingress stp enum*/ 442 ing_stp_state = 443 soc_format_field32_get(unit, 444 IFP_LOOKUP_STATUS_VECTORfmt, &lookup_status, INGRESS_STG_STATEf); 445 BCM_IF_ERROR_RETURN(_bcm_stg_pvp_translate( 446 unit, ing_stp_state, (int *)&(pkt_trace_info->pkt_trace_stp_state))); 447 448 /* fill in the lookup status bit vector */ 449 if (soc_format_field32_get( 450 unit, IFP_LOOKUP_STATUS_VECTORfmt, &lookup_status, VALID_VLAN_IDf)) { 451 SHR_BITSET(pkt_trace_info->pkt_trace_lookup_status. 452 pkt_trace_status_bitmap, bcmSwitchPktTraceLookupForwardingVlanValid); 453 } 454 455 if (soc_format_field32_get( 456 unit, INSTR_BUFFER_IFWD_DW0fmt, ifwd_raw_data, L2LU_SRC_HITf)) { 457 SHR_BITSET(pkt_trace_info->pkt_trace_lookup_status. 458 pkt_trace_status_bitmap, bcmSwitchPktTraceLookupL2SrcHit); 459 460 /* Extract the index into L2X table for later use */ 461 l2x_index = soc_format_field32_get( 462 unit, INSTR_BUFFER_IFWD_DW0fmt, ifwd_raw_data, L2LU_SRC_INDEXf); 463 } 464 465 if (-1 != l2x_index) { 466 soc_mem_lock(unit, L2Xm); 467 rv = soc_mem_read(unit, L2Xm, MEM_BLOCK_ANY, l2x_index, &l2x_entry); 468 soc_mem_unlock(unit, L2Xm); 469 470 SOC_IF_ERROR_RETURN(rv); 471 472 if(soc_L2Xm_field32_get(unit, &l2x_entry, BASE_VALIDf)) { 473 if(soc_L2Xm_field32_get(unit, &l2x_entry, STATIC_BITf)) { 474 SHR_BITSET(pkt_trace_info-> 475 pkt_trace_lookup_status.pkt_trace_status_bitmap, 476 bcmSwitchPktTraceLookupL2SrcStatic); 477 } 478 } else { 479 return BCM_E_NOT_FOUND; 480 } 481 } 482 483 if (soc_format_field32_get( 484 unit, INSTR_BUFFER_IFWD_DW0fmt, ifwd_raw_data, L2LU_DST_HITf)) { 485 SHR_BITSET(pkt_trace_info->pkt_trace_lookup_status. 486 pkt_trace_status_bitmap, bcmSwitchPktTraceLookupL2DstHit); 487 } 488 489 /* bcmSwitchPktTraceLookupL2CacheHit: Not available in TH3 */ 490 491 if (soc_format_field32_get(unit, 492 INSTR_BUFFER_IFWD_DW1fmt, ifwd_raw_data + 2, L3_ENTRY_SRC_HITf)) { 493 SHR_BITSET(pkt_trace_info->pkt_trace_lookup_status. 494 pkt_trace_status_bitmap, bcmSwitchPktTraceLookupL3SrcHostHit); 495 } 496 497 if (soc_format_field32_get(unit, 498 INSTR_BUFFER_IFWD_DW1fmt, ifwd_raw_data + 2, L3_ENTRY_DST_HITf)) { 499 SHR_BITSET(pkt_trace_info->pkt_trace_lookup_status. 500 pkt_trace_status_bitmap, bcmSwitchPktTraceLookupL3DestHostHit); 501 } 502 503 if (soc_format_field32_get( 504 unit, INSTR_BUFFER_IFWD_DW2fmt, ifwd_raw_data + 4, LPM_HITf)) { 505 SHR_BITSET(pkt_trace_info->pkt_trace_lookup_status. 506 pkt_trace_status_bitmap, bcmSwitchPktTraceLookupL3DestRouteHit); 507 } 508 509 /* bcmSwitchPktTraceLookupL2SrcMiss: Not available in TH3 */ 510 511 if (soc_format_field32_get( 512 unit, IFP_LOOKUP_STATUS_VECTORfmt, &lookup_status, DOS_ATTACKf)) { 513 SHR_BITSET(pkt_trace_info->pkt_trace_lookup_status. 514 pkt_trace_status_bitmap, bcmSwitchPktTraceLookupDosAttack); 515 } 516 517 if (soc_format_field32_get( 518 unit, IFP_LOOKUP_STATUS_VECTORfmt, &lookup_status, L3_TUNNEL_HITf)) { 519 SHR_BITSET(pkt_trace_info->pkt_trace_lookup_status. 520 pkt_trace_status_bitmap, bcmSwitchPktTraceLookupIpTunnelHit); 521 } 522 523 if (soc_format_field32_get(unit, IFP_LOOKUP_STATUS_VECTORfmt, 524 &lookup_status, MPLS_ENTRY_TABLE_LOOKUP_0_HITf)) { 525 SHR_BITSET(pkt_trace_info->pkt_trace_lookup_status. 526 pkt_trace_status_bitmap, bcmSwitchPktTraceLookupMplsLabel1Hit); 527 } 528 529 if (soc_format_field32_get(unit, IFP_LOOKUP_STATUS_VECTORfmt, 530 &lookup_status, MPLS_ENTRY_TABLE_LOOKUP_1_HITf)) { 531 SHR_BITSET(pkt_trace_info->pkt_trace_lookup_status. 532 pkt_trace_status_bitmap, bcmSwitchPktTraceLookupMplsLabel2Hit); 533 } 534 535 if (soc_format_field32_get(unit, 536 IFP_LOOKUP_STATUS_VECTORfmt, &lookup_status, MPLS_BOS_TERMINATEDf)) { 537 SHR_BITSET(pkt_trace_info->pkt_trace_lookup_status. 538 pkt_trace_status_bitmap, bcmSwitchPktTraceLookupMplsTerminated); 539 } 540 541 if (soc_format_field32_get( 542 unit, INSTR_BUFFER_IADAPT_DW0fmt, iadapt_raw_data, MY_STATION_HITf)) { 543 SHR_BITSET(pkt_trace_info->pkt_trace_lookup_status. 544 pkt_trace_status_bitmap, bcmSwitchPktTraceLookupMystationHit); 545 } 546 547 /* fill packet resolution vector */ 548 pkt_trace_info->pkt_trace_resolution = 549 soc_format_field32_get(unit, INSTR_BUFFER_ISW_DW0fmt, 550 isw_raw_data, PKT_RESOLUTION_VECTORf); 551 552 #ifdef INCLUDE_L3 553 /* Retrieve the ECMP member resolution details */ 554 offset_isw_data = isw_raw_data + 2; 555 ecmp_rsl_done1 = soc_format_field32_get(unit, 556 INSTR_BUFFER_ISW_DW1fmt, offset_isw_data, ECMP_RESOLUTION_DONE1f); 557 ecmp_rsl_done2 = soc_format_field32_get(unit, 558 INSTR_BUFFER_ISW_DW1fmt, offset_isw_data, ECMP_RESOLUTION_DONE2f); 559 if (ecmp_rsl_done1) { 560 ecmp_id = soc_format_field32_get(unit, 561 INSTR_BUFFER_ISW_DW1fmt, offset_isw_data, ECMP_GROUP1f); 562 563 SOC_IF_ERROR_RETURN 564 (READ_L3_ECMP_COUNTm(unit, MEM_BLOCK_ANY, ecmp_id, &ecmpc_entry)); 565 566 ecmp_ptr = 567 soc_L3_ECMP_COUNTm_field32_get(unit, &ecmpc_entry, BASE_PTRf); 568 569 ecmp_offset = soc_format_field32_get(unit, 570 INSTR_BUFFER_ISW_DW1fmt, offset_isw_data, ECMP_OFFSET1f); 571 572 ecmp_index = (ecmp_ptr + ecmp_offset) & 573 (soc_mem_index_count(unit, L3_ECMPm) - 1); 574 575 SOC_IF_ERROR_RETURN 576 (READ_L3_ECMPm(unit, MEM_BLOCK_ANY, ecmp_index, &ecmp_entry)); 577 pkt_trace_info->pkt_trace_hash_info.ecmp_1_group = ecmp_id; 578 pkt_trace_info->pkt_trace_hash_info.ecmp_1_group += 579 BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit); 580 581 pkt_trace_info->pkt_trace_hash_info.ecmp_1_egress = 582 soc_L3_ECMPm_field32_get(unit, &ecmp_entry, NEXT_HOP_INDEXf); 583 pkt_trace_info->pkt_trace_hash_info.ecmp_1_egress += 584 ecmp_rsl_done2 ? 585 BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit) : BCM_XGS3_EGRESS_IDX_MIN(unit); 586 587 pkt_trace_info->pkt_trace_hash_info.flags +=BCM_SWITCH_PKT_TRACE_ECMP_1; 588 } 589 590 if (ecmp_rsl_done2) { 591 ecmp_id = soc_format_field32_get(unit, 592 INSTR_BUFFER_ISW_DW1fmt, offset_isw_data, ECMP_GROUP2f); 593 594 SOC_IF_ERROR_RETURN 595 (READ_L3_ECMP_COUNTm(unit, MEM_BLOCK_ANY, ecmp_id, &ecmpc_entry)); 596 597 ecmp_ptr = 598 soc_L3_ECMP_COUNTm_field32_get(unit, &ecmpc_entry, BASE_PTRf); 599 600 offset_isw_data = isw_raw_data + 4; 601 ecmp_offset = soc_format_field32_get(unit, 602 INSTR_BUFFER_ISW_DW2fmt, offset_isw_data, ECMP_OFFSET2f); 603 604 ecmp_index = (ecmp_ptr + ecmp_offset) & 605 (soc_mem_index_count(unit, L3_ECMPm) - 1); 606 607 SOC_IF_ERROR_RETURN 608 (READ_L3_ECMPm(unit, MEM_BLOCK_ANY, ecmp_index, &ecmp_entry)); 609 610 pkt_trace_info->pkt_trace_hash_info.ecmp_2_group = ecmp_id; 611 pkt_trace_info->pkt_trace_hash_info.ecmp_2_group += 612 BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit); 613 614 pkt_trace_info->pkt_trace_hash_info.ecmp_2_egress = 615 soc_L3_ECMPm_field32_get(unit, &ecmp_entry, NEXT_HOP_INDEXf); 616 pkt_trace_info->pkt_trace_hash_info.ecmp_2_egress += 617 BCM_XGS3_EGRESS_IDX_MIN(unit); 618 pkt_trace_info->pkt_trace_hash_info.flags +=BCM_SWITCH_PKT_TRACE_ECMP_2; 619 } 620 #endif 621 622 /* Decode LAG related fields */ 623 offset_isw_data = isw_raw_data + 4; 624 if (soc_format_field32_get(unit, 625 INSTR_BUFFER_ISW_DW2fmt, offset_isw_data, LAG_RESOLUTION_DONEf)) { 626 627 /* Get the LAG ID */ 628 tgid = soc_format_field32_get( 629 unit, INSTR_BUFFER_ISW_DW2fmt, offset_isw_data, LAG_IDf); 630 631 /* Get the number of Trunk members */ 632 BCM_IF_ERROR_RETURN( 633 READ_FAST_TRUNK_SIZEm(unit, MEM_BLOCK_ANY, tgid, &trunk_size_entry)); 634 trunk_group_size = 635 soc_FAST_TRUNK_SIZEm_field32_get(unit, &trunk_size_entry, TG_SIZEf); 636 637 /* Extract the member determination hash */ 638 lag_hash_val = soc_format_field32_get(unit, 639 INSTR_BUFFER_ISW_DW2fmt, offset_isw_data, HASH_VALUE_LAGf); 640 641 /* Derive the Trunk member from Hash and Trunk group size */ 642 trunk_member_index = (lag_hash_val % (trunk_group_size + 1)) & 0x3F; 643 644 /* Determine the Port number from the Trunk member index */ 645 if (trunk_member_index < 32) { 646 fast_trunk_ports_1_entry_t trunk_entry; 647 static const soc_field_t _th3_fast_port_fld[32] = { 648 TRUNK_MEMBER_0f, TRUNK_MEMBER_1f, TRUNK_MEMBER_2f, 649 TRUNK_MEMBER_3f, TRUNK_MEMBER_4f, TRUNK_MEMBER_5f, 650 TRUNK_MEMBER_6f, TRUNK_MEMBER_7f, TRUNK_MEMBER_8f, 651 TRUNK_MEMBER_9f, TRUNK_MEMBER_10f, TRUNK_MEMBER_11f, 652 TRUNK_MEMBER_12f, TRUNK_MEMBER_13f, TRUNK_MEMBER_14f, 653 TRUNK_MEMBER_15f, TRUNK_MEMBER_16f, TRUNK_MEMBER_17f, 654 TRUNK_MEMBER_18f, TRUNK_MEMBER_19f, TRUNK_MEMBER_20f, 655 TRUNK_MEMBER_21f, TRUNK_MEMBER_22f, TRUNK_MEMBER_23f, 656 TRUNK_MEMBER_24f, TRUNK_MEMBER_25f, TRUNK_MEMBER_26f, 657 TRUNK_MEMBER_27f, TRUNK_MEMBER_28f, TRUNK_MEMBER_29f, 658 TRUNK_MEMBER_30f, TRUNK_MEMBER_31f 659 }; 660 BCM_IF_ERROR_RETURN( 661 READ_FAST_TRUNK_PORTS_1m(unit, MEM_BLOCK_ANY, tgid, &trunk_entry)); 662 dest.port = soc_FAST_TRUNK_PORTS_1m_field32_get( 663 unit, &trunk_entry, _th3_fast_port_fld[trunk_member_index]); 664 } else { 665 fast_trunk_ports_2_entry_t trunk_entry; 666 static const soc_field_t _th3_fast_port_fld[32] = { 667 TRUNK_MEMBER_32f, TRUNK_MEMBER_33f, TRUNK_MEMBER_34f, 668 TRUNK_MEMBER_35f, TRUNK_MEMBER_36f, TRUNK_MEMBER_37f, 669 TRUNK_MEMBER_38f, TRUNK_MEMBER_39f, TRUNK_MEMBER_40f, 670 TRUNK_MEMBER_41f, TRUNK_MEMBER_42f, TRUNK_MEMBER_43f, 671 TRUNK_MEMBER_44f, TRUNK_MEMBER_45f, TRUNK_MEMBER_46f, 672 TRUNK_MEMBER_47f, TRUNK_MEMBER_48f, TRUNK_MEMBER_49f, 673 TRUNK_MEMBER_50f, TRUNK_MEMBER_51f, TRUNK_MEMBER_52f, 674 TRUNK_MEMBER_53f, TRUNK_MEMBER_54f, TRUNK_MEMBER_55f, 675 TRUNK_MEMBER_56f, TRUNK_MEMBER_57f, TRUNK_MEMBER_58f, 676 TRUNK_MEMBER_59f, TRUNK_MEMBER_60f, TRUNK_MEMBER_61f, 677 TRUNK_MEMBER_62f, TRUNK_MEMBER_63f 678 }; 679 BCM_IF_ERROR_RETURN( 680 READ_FAST_TRUNK_PORTS_2m(unit, MEM_BLOCK_ANY, tgid, &trunk_entry)); 681 dest.port = soc_FAST_TRUNK_PORTS_2m_field32_get( 682 unit, &trunk_entry, _th3_fast_port_fld[trunk_member_index-32]); 683 } 684 685 /* Create a MODPORT GPORT from the local port numberii and save it */ 686 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &(dest.modid))); 687 dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 688 BCM_IF_ERROR_RETURN( 689 _bcm_esw_gport_construct(unit, 690 &dest, &(pkt_trace_info->pkt_trace_hash_info.trunk_member))); 691 692 /* Save the other Trunk information */ 693 pkt_trace_info->pkt_trace_hash_info.trunk = tgid; 694 pkt_trace_info->pkt_trace_hash_info.flags += BCM_SWITCH_PKT_TRACE_TRUNK; 695 696 } /* end lag resolution */ 697 698 /* Decode the drop reason raw bits */ 699 BCM_IF_ERROR_RETURN( 700 _bcm_th3_pkt_trace_drop_reason_decode(unit, pkt_trace_info)); 701 return BCM_E_NONE; 702 } 703 704 /* 705 * Function: 706 * __bcm_th3_pkt_trace_hw_buffer_read 707 * 708 * Purpose: 709 * Read the raw data from PTR_RESULTS_BUFFER_IADAPT/IFWD/ISW memories. 710 * Store the read data in its raw format into the given buffer. Also 711 * store the number of bytes written to the buffer if 'bytes_read' 712 * parameter is provided byt the caller. 713 * 714 * Parameters: 715 * unit - (IN) Device Number 716 * pipe - (IN) Ingress pipeline number 717 * buffer - (OUT) buffer where the captured data would be dumped. 718 * bytes_read - (OUT) Stores the number of bytes written to the buffer 719 * 720 * Returns: 721 * BCM_E_XXX 722 * 723 * Notes: 724 * Assumption is that all parameters are valid. 725 * Hence no addtional checks performed on them here. 726 */ 727 static int __bcm_th3_pkt_trace_hw_buffer_read( 728 int unit, int pipe, uint8 *buffer, uint32 *bytes_read) 729 { 730 731 uint8 mem_idx; 732 uint8 entry_idx; 733 uint32 byte_cnt; 734 soc_mem_t mem; 735 736 const struct ptr_results_mem_info_s { 737 soc_mem_t mem; /* Buffer Memory */ 738 uint8 max_idx; /* Max number of entries */ 739 } mem_info_arr[] = { 740 { PTR_RESULTS_BUFFER_IPARSm, TH3_PTR_RESULTS_IPARS_MAX_INDEX }, 741 { PTR_RESULTS_BUFFER_IADAPTm, TH3_PTR_RESULTS_IADAPT_MAX_INDEX }, 742 { PTR_RESULTS_BUFFER_IFWDm, TH3_PTR_RESULTS_IFWD_MAX_INDEX }, 743 { PTR_RESULTS_BUFFER_ISWm, TH3_PTR_RESULTS_ISW_MAX_INDEX } 744 }; 745 746 /* Initialize the bytes read count to 0 at first */ 747 if (NULL != bytes_read) { 748 *bytes_read = 0; 749 } 750 751 /* Loop through all the entries of all the Ing. Pipe Stage Buffers */ 752 for (mem_idx=0, byte_cnt=0 ; mem_idx < COUNTOF(mem_info_arr) ; mem_idx++) 753 { 754 /* Retrieve the pipe specific memory instance */ 755 if (NULL == SOC_MEM_UNIQUE_ACC(unit, mem_info_arr[mem_idx].mem)) { 756 return BCM_E_INTERNAL; 757 } 758 mem = SOC_MEM_UNIQUE_ACC(unit, mem_info_arr[mem_idx].mem)[pipe]; 759 if (mem == INVALIDm) { 760 return BCM_E_INTERNAL; 761 } 762 763 /* Read the entry from HW tables entry by entry */ 764 for (entry_idx = 0 ; 765 entry_idx < mem_info_arr[mem_idx].max_idx ; entry_idx++) { 766 SOC_IF_ERROR_RETURN( 767 soc_mem_read(unit, mem, MEM_BLOCK_ANY, 768 entry_idx, buffer + byte_cnt)); 769 770 /* Adjust byte count with the number of bytes already read */ 771 byte_cnt += TH3_IP_STAGE_PER_ENTRY_SIZE; 772 } 773 } 774 775 /* Populate the length of the data stored to the buffer */ 776 if (NULL != bytes_read) { 777 *bytes_read = byte_cnt; 778 } 779 780 return BCM_E_NONE; 781 } 782 783 /* 784 * Function: 785 * _bcm_th3_pkt_trace_info_retrieve_data 786 * 787 * Purpose: 788 * Read the data from PTR_RESULTS_BUFFER_IPARS/IADAPT/IFWD/ISW memories 789 * for the given pipe instance. Store the data in its raw format into the 790 * 'raw_data' buffer in given data structure. Further it calls the decode 791 * function to decode some of the raw data. 792 * 793 * If pipe parameter is passed as '-1' then all pipe instances for 794 * PTR_RESULTS_BUFFER_XXX memories would be polled for. The first 795 * available valid captured data would be given back to the user. 796 * 797 * Parameters: 798 * unit - (IN) Device Number 799 * pipe - (IN) Ingress pipeline number 800 * pkt_trace_info - (OUT) User given packet trace structure. 801 * 802 * Returns: 803 * BCM_E_XXX 804 * 805 * Notes: 806 * 'pipe' parameter shoule be either -1 or range between 0 to 7 (inclusive). 807 */ 808 int _bcm_th3_pkt_trace_info_retrieve_data(int unit, int pipe, 809 bcm_switch_pkt_trace_info_t *pkt_trace_info) 810 { 811 int pipe_idx; 812 int min_pipe = pipe; 813 int max_pipe = pipe; 814 uint32 byte_cnt = 0; 815 uint32 byte_idx = 0; 816 uint32 active_pipes_bmap = 0x0; 817 818 /* Check for input parameters validity */ 819 if ((NULL == pkt_trace_info) || (pipe < -1) || (pipe >= SOC_MAX_NUM_PIPES)) { 820 return BCM_E_PARAM; 821 } 822 823 /* Get pipe bitmap for the active pipes */ 824 soc_tomahawk3_pipe_map_get(unit, &active_pipes_bmap); 825 826 /* If pipe is passed in as -1 then poll for data from all pipes */ 827 if (-1 == pipe) { 828 min_pipe = 0; 829 max_pipe = SOC_MAX_NUM_PIPES - 1; 830 } else if (!(active_pipes_bmap & (1 << pipe))) { 831 /* If a pipe is a valid number but it is inactive then return error */ 832 return BCM_E_PARAM; 833 } 834 835 /* Run the loop for the number of pipes */ 836 for (pipe_idx = min_pipe ; pipe_idx <= max_pipe ; pipe_idx++) { 837 838 /* If the pipe is inactive, skip it */ 839 if (!(active_pipes_bmap & (1 << pipe_idx))) { 840 continue; 841 } 842 843 /* Call routine to read the HW PktTrace capture memories for the pipe */ 844 BCM_IF_ERROR_RETURN( 845 __bcm_th3_pkt_trace_hw_buffer_read( 846 unit, pipe_idx, pkt_trace_info->raw_data, &byte_cnt)); 847 848 /* See if we got valid data */ 849 for (byte_idx = 0 ; byte_idx < byte_cnt ; byte_idx += sizeof(uint32) ) { 850 /* No need to worry about dword boundary as is is dword-aligned */ 851 if (*((uint32 *)(pkt_trace_info->raw_data + byte_idx))) { 852 break; 853 } 854 } 855 856 /* If there is valid data then break out the loop to interpret it */ 857 if (byte_idx < byte_cnt) { 858 break; 859 } 860 } 861 862 /* If no valid data found then mark so */ 863 if (pipe_idx > max_pipe) { 864 return BCM_E_BUSY; 865 } 866 867 /* Populate the lenght of the data stored to the buffer */ 868 pkt_trace_info->raw_data_length = byte_cnt; 869 870 /* Store the pipe information on which the pkt trace has been captured */ 871 pkt_trace_info->dest_pipe_num = pipe_idx; 872 873 /* Decode the raw data */ 874 BCM_IF_ERROR_RETURN( 875 _bcm_th3_pkt_trace_raw_data_decode(unit, pkt_trace_info)); 876 877 return BCM_E_NONE; 878 } 879 880 #endif /* BCM_INSTRUMENTATION_SUPPORT */ 881 #endif /* BCM_TOMAHAWK3_SUPPORT */