switch.c (50586B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * File: switch.c 8 * Purpose: 9 */ 10 #if defined(BCM_TOMAHAWK3_SUPPORT) 11 #include <soc/debug.h> 12 #include <soc/drv.h> 13 #include <soc/mem.h> 14 #include <bcm/switch.h> 15 #include <bcm/error.h> 16 #include <bcm_int/esw/switch.h> 17 #include <bcm_int/esw/port.h> 18 #include <bcm_int/esw/flex_ctr.h> 19 #if defined(BCM_INSTRUMENTATION_SUPPORT) 20 #include <bcm_int/esw/instrumentation.h> 21 #endif 22 #if defined(INCLUDE_L3) 23 #include <bcm/l3.h> 24 #include <bcm_int/esw/firebolt.h> 25 #include <bcm_int/tomahawk3_dispatch.h> 26 #endif /* INCLUDE_L3 */ 27 28 #define AGM_LOCK(unit) soc_mem_lock(unit, AGM_MONITOR_TABLEm) 29 #define AGM_UNLOCK(unit) soc_mem_unlock(unit, AGM_MONITOR_TABLEm) 30 31 /* Helper routines for argument translation */ 32 static int 33 _th3_bool_invert(int unit, int arg, int set) 34 { 35 /* Same for both set/get */ 36 return !arg; 37 } 38 39 bcm_switch_binding_t tomahawk3_bindings[] = 40 { 41 { bcmSwitchUnknownVlanToCpu, 0, 42 CPU_CONTROL_0r, UVLAN_TOCPUf, 43 NULL, 0 }, 44 { bcmSwitchArpReplyToCpu, 0, 45 PROTOCOL_PKT_CONTROLr, ARP_REPLY_TO_CPUf, 46 NULL, 0 }, 47 { bcmSwitchArpReplyDrop, 0, 48 PROTOCOL_PKT_CONTROLr, ARP_REPLY_DROPf, 49 NULL, 0 }, 50 { bcmSwitchArpRequestToCpu, 0, 51 PROTOCOL_PKT_CONTROLr, ARP_REQUEST_TO_CPUf, 52 NULL, 0 }, 53 { bcmSwitchArpRequestDrop, 0, 54 PROTOCOL_PKT_CONTROLr, ARP_REQUEST_DROPf, 55 NULL, 0 }, 56 { bcmSwitchNdPktToCpu, 0, 57 PROTOCOL_PKT_CONTROLr, ND_PKT_TO_CPUf, 58 NULL, 0 }, 59 { bcmSwitchNdPktDrop, 0, 60 PROTOCOL_PKT_CONTROLr, ND_PKT_DROPf, 61 NULL, 0 }, 62 { bcmSwitchDhcpPktToCpu, 0, 63 PROTOCOL_PKT_CONTROLr, DHCP_PKT_TO_CPUf, 64 NULL, 0 }, 65 { bcmSwitchDhcpPktDrop, 0, 66 PROTOCOL_PKT_CONTROLr, DHCP_PKT_DROPf, 67 NULL, 0 }, 68 { bcmSwitchL2StaticMoveToCpu, 0, 69 CPU_CONTROL_1r, STATICMOVE_TOCPUf, 70 NULL, 0 }, 71 { bcmSwitchL2NonStaticMoveToCpu, 0, 72 CPU_CONTROL_1r, NONSTATICMOVE_TOCPUf, 73 NULL, 0 }, 74 { bcmSwitchSharedVlanEnable, 0, 75 ING_CONFIG_64r, SVL_ENABLEf, 76 NULL, 0}, 77 { bcmSwitchSharedVlanMismatchToCpu, 0, 78 CPU_CONTROL_0r, PVLAN_VID_MISMATCH_TOCPUf , 79 NULL, 0}, 80 { bcmSwitchSharedVlanL2McastEnable, 0, 81 ING_CONFIG_64r, LOOKUP_L2MC_WITH_FID_IDf, 82 NULL, 0}, 83 { bcmSwitchBpduInvalidVlanDrop, 0, 84 EGR_CONFIG_1r, BPDU_INVALID_VLAN_DROPf, 85 NULL, soc_feature_igmp_mld_support }, 86 { bcmSwitchMirrorInvalidVlanDrop, 0, 87 EGR_CONFIG_1r, MIRROR_INVALID_VLAN_DROPf, 88 NULL, soc_feature_igmp_mld_support }, 89 { bcmSwitchMcastFloodBlocking, 0, 90 IGMP_MLD_PKT_CONTROLr, PFM_RULE_APPLYf, 91 NULL, soc_feature_igmp_mld_support }, 92 { bcmSwitchMldUcastEnable, 0, 93 ING_CONFIG_64r, MLD_PKTS_UNICAST_IGNOREf, 94 _th3_bool_invert, soc_feature_igmp_mld_support }, 95 { bcmSwitchMldDirectAttachedOnly, 0, 96 ING_CONFIG_64r, MLD_CHECKS_ENABLEf, 97 NULL, soc_feature_igmp_mld_support }, 98 { bcmSwitchIgmpReservedMcastEnable, 0, 99 ING_CONFIG_64r, IPV4_RESERVED_MC_ADDR_IGMP_ENABLEf, 100 NULL, soc_feature_igmp_mld_support }, 101 { bcmSwitchMldReservedMcastEnable, 0, 102 ING_CONFIG_64r, IPV6_RESERVED_MC_ADDR_MLD_ENABLEf, 103 NULL, soc_feature_igmp_mld_support }, 104 { bcmSwitchIgmpUcastEnable, 0, 105 ING_CONFIG_64r, IGMP_PKTS_UNICAST_IGNOREf, 106 _th3_bool_invert, soc_feature_igmp_mld_support }, 107 { bcmSwitchPortEgressBlockL2, 0, 108 ING_CONFIG_64r, APPLY_EGR_MASK_ON_L2f, 109 NULL, 0}, 110 { bcmSwitchIp4McastL2DestCheck, 0, 111 ING_CONFIG_64r, IPV4_MC_MACDA_CHECK_ENABLEf, 112 NULL, 0}, 113 { bcmSwitchIp6McastL2DestCheck, 0, 114 ING_CONFIG_64r, IPV6_MC_MACDA_CHECK_ENABLEf, 115 NULL, 0}, 116 { bcmSwitchUnknownIpmcAsMcast, 0, 117 ING_MISC_CONFIG2r, IPMC_MISS_AS_L2MCf, 118 NULL, 0 }, 119 { bcmSwitchIpmcSameVlanL3Route, 0, 120 EGR_CONFIG_1r, IPMC_ROUTE_SAME_VLANf, 121 NULL, 0}, 122 { bcmSwitchHashUseFlowSelMplsEcmp, 0, 123 RTAG7_HASH_SELr, USE_FLOW_SEL_MPLS_ECMPf, 124 NULL, 0}, 125 { bcmSwitchHashMPLSUseLabelStack, 0, 126 RTAG7_HASH_CONTROL_2r, USE_MPLS_STACK_FOR_HASHINGf, 127 NULL, 0}, 128 { bcmSwitchMplsPortIndependentLowerRange1, 0, 129 GLOBAL_MPLS_RANGE_1_LOWERr, LABELf, 130 NULL, 0}, 131 { bcmSwitchMplsPortIndependentUpperRange1, 0, 132 GLOBAL_MPLS_RANGE_1_UPPERr, LABELf, 133 NULL, 0}, 134 { bcmSwitchMplsPortIndependentLowerRange2, 0, 135 GLOBAL_MPLS_RANGE_2_LOWERr, LABELf, 136 NULL, 0}, 137 { bcmSwitchMplsPortIndependentUpperRange2, 0, 138 GLOBAL_MPLS_RANGE_2_UPPERr, LABELf, 139 NULL, 0}, 140 { bcmSwitchEcmpMacroFlowHashEnable, 0, 141 RTAG7_HASH_SELr, USE_FLOW_SEL_ECMPf, 142 NULL, 0}, 143 { bcmSwitchDosAttackV4FirstFrag, 0, 144 DOS_CONTROLr, IPV4_FIRST_FRAG_CHECK_ENABLEf, 145 NULL, 0 }, 146 { bcmSwitchDosAttackSipEqualDip, 0, 147 DOS_CONTROLr, DROP_IF_SIP_EQUALS_DIPf, 148 NULL, 0 }, 149 { bcmSwitchDosAttackMACSAEqualMACDA, 0, 150 DOS_CONTROLr, MACSA_EQUALS_MACDA_DROPf, 151 NULL, soc_feature_enhanced_dos_ctrl }, 152 { bcmSwitchDosAttackFlagZeroSeqZero, 0, 153 DOS_CONTROLr, TCP_FLAGS_CTRL0_SEQ0_ENABLEf, 154 NULL, 0 }, 155 { bcmSwitchDosAttackSynFrag, 0, 156 DOS_CONTROLr, TCP_FLAGS_SYN_FRAG_ENABLEf, 157 NULL, 0}, 158 { bcmSwitchDosAttackIcmpFragments, 0, 159 DOS_CONTROL_2r, ICMP_FRAG_PKTS_ENABLEf, 160 NULL, soc_feature_enhanced_dos_ctrl }, 161 { bcmSwitchDosAttackIcmpV4, 0, 162 DOS_CONTROL_2r, ICMP_V4_PING_SIZE_ENABLEf, 163 NULL, 0 }, 164 { bcmSwitchDosAttackIcmpV6, 0, 165 DOS_CONTROL_2r, ICMP_V6_PING_SIZE_ENABLEf, 166 NULL, 0 }, 167 { bcmSwitchDosAttackTcpOffset, 0, 168 DOS_CONTROL_2r, TCP_HDR_OFFSET_EQ1_ENABLEf, 169 NULL, soc_feature_enhanced_dos_ctrl }, 170 { bcmSwitchDosAttackUdpPortsEqual, 0, 171 DOS_CONTROL_2r, UDP_SPORT_EQ_DPORT_ENABLEf, 172 NULL, soc_feature_enhanced_dos_ctrl }, 173 { bcmSwitchDosAttackTcpPortsEqual, 0, 174 DOS_CONTROL_2r, TCP_SPORT_EQ_DPORT_ENABLEf, 175 NULL, soc_feature_enhanced_dos_ctrl }, 176 { bcmSwitchDosAttackTcpFlagsSF, 0, 177 DOS_CONTROL_2r, TCP_FLAGS_SYN_FIN_ENABLEf, 178 NULL, soc_feature_enhanced_dos_ctrl }, 179 { bcmSwitchDosAttackTcpFlagsFUP, 0, 180 DOS_CONTROL_2r, TCP_FLAGS_FIN_URG_PSH_SEQ0_ENABLEf, 181 NULL, soc_feature_enhanced_dos_ctrl }, 182 { bcmSwitchDosAttackTcpHdrPartial, 0, 183 DOS_CONTROL_2r, TCP_HDR_PARTIAL_ENABLEf, 184 NULL, soc_feature_enhanced_dos_ctrl }, 185 { bcmSwitchDosAttackV6MinFragEnable, 0, 186 DOS_CONTROL_2r, IPV6_MIN_FRAG_SIZE_ENABLEf, 187 NULL, soc_feature_enhanced_dos_ctrl }, 188 { bcmSwitchDosAttackIcmpPktOversize, 0, 189 DOS_CONTROL_3r, BIG_ICMP_PKT_SIZEf, 190 NULL, 0 }, 191 { bcmSwitchDosAttackIcmpV6PingSize, 0, 192 DOS_CONTROL_3r, BIG_ICMPV6_PKT_SIZEf, 193 NULL, soc_feature_big_icmpv6_ping_check }, 194 { bcmSwitchDosAttackMinTcpHdrSize, 0, 195 DOS_CONTROL_3r, MIN_TCPHDR_SIZEf, 196 NULL, 0 }, 197 { bcmSwitchDosAttackToCpu, 0, 198 CPU_CONTROL_0r, DOSATTACK_TOCPUf, 199 NULL, 0 }, 200 { bcmSwitchTunnelIp4IdShared, 0, 201 EGR_TUNNEL_ID_MASKr, SHARED_FRAG_ID_ENABLEf, 202 NULL, 0}, 203 { bcmSwitchPortEgressBlockL3, 0, 204 ING_CONFIG_64r, APPLY_EGR_MASK_ON_L3f, 205 NULL, 0}, 206 { bcmSwitchParityErrorToCpu, 0, 207 CPU_CONTROL_0r, PARITY_ERR_TOCPUf, 208 NULL, soc_feature_parity_err_tocpu }, 209 { bcmSwitchSourceMacZeroDrop, 0, 210 CPU_CONTROL_0r, MACSA_ALL_ZERO_DROPf, 211 NULL, 0}, 212 { bcmSwitchMplsSequenceErrToCpu, 0, 213 ING_MISC_CONFIGr, MPLS_SEQ_NUM_FAIL_TOCPUf, 214 NULL, 0}, 215 { bcmSwitchMplsLabelMissToCpu, 0, 216 CPU_CONTROL_Mr, MPLS_LABEL_MISSf, 217 NULL, 0}, 218 { bcmSwitchMplsTtlErrToCpu, 0, 219 CPU_CONTROL_Mr, MPLS_TTL_CHECK_FAILf, 220 NULL, 0}, 221 { bcmSwitchMplsInvalidL3PayloadToCpu, 0, 222 CPU_CONTROL_Mr, MPLS_INVALID_PAYLOADf, 223 NULL, 0}, 224 { bcmSwitchMplsInvalidActionToCpu, 0, 225 CPU_CONTROL_Mr, MPLS_INVALID_ACTIONf, 226 NULL, 0}, 227 { bcmSwitchMplsPortIndependentLowerRange1, 0, 228 GLOBAL_MPLS_RANGE_1_LOWERr, LABELf, 229 NULL, 0}, 230 { bcmSwitchMplsPortIndependentUpperRange1, 0, 231 GLOBAL_MPLS_RANGE_1_UPPERr, LABELf, 232 NULL, 0}, 233 { bcmSwitchMplsPortIndependentLowerRange2, 0, 234 GLOBAL_MPLS_RANGE_2_LOWERr, LABELf, 235 NULL, 0}, 236 { bcmSwitchMplsPortIndependentUpperRange2, 0, 237 GLOBAL_MPLS_RANGE_2_UPPERr, LABELf, 238 NULL, 0}, 239 { bcmSwitchMplsPWControlWordToCpu, 0, 240 ING_MISC_CONFIGr, PWACH_TOCPUf, 241 NULL, soc_feature_mpls}, 242 { bcmSwitchCpuToCpuEnable, 0, 243 ING_MISC_CONFIGr, DO_NOT_COPY_FROM_CPU_TO_CPUf, 244 _th3_bool_invert, 0 }, 245 { bcmSwitchIpmcTtl1ToCpu, 0, 246 CPU_CONTROL_1r, IPMC_TTL1_ERR_TOCPUf, 247 NULL, 0 }, 248 { bcmSwitchL3UcastTtl1ToCpu, 0, 249 CPU_CONTROL_1r, L3UC_TTL1_ERR_TOCPUf, 250 NULL, 0 }, 251 { bcmSwitchDhcpLearn, 0, 252 ING_MISC_CONFIG2r, DO_NOT_LEARN_DHCPf, 253 NULL, 0 }, 254 { bcmSwitchTunnelUnknownIpmcDrop, 0, 255 ING_MISC_CONFIG2r, UNKNOWN_TUNNEL_IPMC_DROPf, 256 NULL, 0 }, 257 { bcmSwitchMcastUnknownErrToCpu, 0, 258 CPU_CONTROL_1r, MC_INDEX_ERROR_TOCPUf, 259 NULL,0}, 260 { bcmSwitchDosAttackV6MinFragSize, 0, 261 IPV6_MIN_FRAG_SIZEr, PKT_LENGTHf, 262 NULL, soc_feature_enhanced_dos_ctrl }, 263 { bcmSwitchEgressBlockUcast, 0, 264 ING_MISC_CONFIGr, APPLY_EGR_MASK_ON_UC_ONLYf, 265 NULL, soc_feature_egress_blk_ucast_override }, 266 { bcmSwitchHgHdrMcastFloodOverride, 0, 267 EGR_CONFIG_1r, FORCE_STATIC_MH_PFMf, 268 NULL, soc_feature_static_pfm }, 269 { bcmSwitchShaperAdjust, 0, 270 EGR_SHAPING_CONTROLr, PACKET_IFG_BYTESf, 271 NULL, soc_feature_meter_adjust }, 272 { bcmSwitchUnknownMcastToCpu, 0, 273 CPU_CONTROL_1r, UMC_TOCPUf, 274 NULL, 0 }, 275 { bcmSwitchUnknownUcastToCpu, 0, 276 CPU_CONTROL_1r, UUCAST_TOCPUf, 277 NULL, 0 }, 278 { bcmSwitchL3HeaderErrToCpu, 0, 279 CPU_CONTROL_1r, V4L3ERR_TOCPUf, 280 NULL, 0 }, 281 { bcmSwitchUnknownL3DestToCpu, 0, 282 CPU_CONTROL_1r, V4L3DSTMISS_TOCPUf, 283 NULL, 0 }, 284 { bcmSwitchIpmcPortMissToCpu, 0, 285 CPU_CONTROL_1r, IPMCPORTMISS_TOCPUf, 286 NULL, 0 }, 287 { bcmSwitchIpmcErrorToCpu, 0, 288 CPU_CONTROL_1r, IPMCERR_TOCPUf, 289 NULL, 0 }, 290 { bcmSwitchV6L3ErrToCpu, 0, 291 CPU_CONTROL_1r, V6L3ERR_TOCPUf, 292 NULL, 0 }, 293 { bcmSwitchV6L3DstMissToCpu, 0, 294 CPU_CONTROL_1r, V6L3DSTMISS_TOCPUf, 295 NULL, 0 }, 296 { bcmSwitchV4L3ErrToCpu, 0, 297 CPU_CONTROL_1r, V4L3ERR_TOCPUf, 298 NULL, 0 }, 299 { bcmSwitchV4L3DstMissToCpu, 0, 300 CPU_CONTROL_1r, V4L3DSTMISS_TOCPUf, 301 NULL, 0 }, 302 { bcmSwitchTunnelErrToCpu, 0, 303 CPU_CONTROL_1r, TUNNEL_ERR_TOCPUf, 304 NULL, 0 }, 305 { bcmSwitchMartianAddrToCpu, 0, 306 CPU_CONTROL_1r, MARTIAN_ADDR_TOCPUf, 307 NULL, 0 }, 308 { bcmSwitchL3UcTtlErrToCpu, 0, 309 CPU_CONTROL_1r, L3UC_TTL_ERR_TOCPUf, 310 NULL, 0 }, 311 { bcmSwitchL3SlowpathToCpu, 0, 312 CPU_CONTROL_1r, L3_SLOWPATH_TOCPUf, 313 NULL, 0 }, 314 { bcmSwitchIpmcTtlErrToCpu, 0, 315 CPU_CONTROL_1r, IPMC_TTL_ERR_TOCPUf, 316 NULL, 0 }, 317 { bcmSwitchSampleIngressRandomSeed, 0, 318 SFLOW_ING_RAND_SEEDr, SEEDf, 319 NULL, 0 }, 320 { bcmSwitchSampleEgressRandomSeed, 0, 321 SFLOW_EGR_RAND_SEEDr, SEEDf, 322 NULL, 0 }, 323 { bcmSwitchNonIpL3ErrToCpu, 0, 324 CPU_CONTROL_1r, NIP_L3ERR_TOCPUf, 325 NULL, soc_feature_nip_l3_err_tocpu }, 326 { bcmSwitchSourceRouteToCpu, 0, 327 CPU_CONTROL_1r, SRCROUTE_TOCPUf, 328 NULL, 0 }, 329 { bcmSwitchL3MtuFailToCpu, 0, 330 CPU_CONTROL_1r, L3_MTU_FAIL_TOCPUf, 331 NULL, soc_feature_l3mtu_fail_tocpu }, 332 { bcmSwitchV6L3LocalLinkDrop,0, 333 ING_MISC_CONFIG2r, IPV6_SIP_LINK_LOCAL_DROPf, 334 NULL, 0}, 335 { bcmSwitchMplsGalAlertLabelToCpu, 0, 336 CPU_CONTROL_Mr, MPLS_GAL_EXPOSED_TO_CPUf, 337 NULL, 0}, 338 { bcmSwitchMplsRalAlertLabelToCpu, 0, 339 CPU_CONTROL_Mr, MPLS_RAL_EXPOSED_TO_CPUf, 340 NULL, 0}, 341 { bcmSwitchMplsIllegalReservedLabelToCpu, 0, 342 CPU_CONTROL_Mr, MPLS_ILLEGAL_RSVD_LABEL_TO_CPUf, 343 NULL, 0}, 344 { bcmSwitchMplsUnknownAchTypeToCpu, 0, 345 CPU_CONTROL_Mr, MPLS_UNKNOWN_ACH_TYPE_TO_CPUf, 346 NULL, 0}, 347 { bcmSwitchMplsUnknownAchVersionToCpu, 0, 348 CPU_CONTROL_Mr, MPLS_UNKNOWN_ACH_VERSION_TOCPUf, 349 NULL, 0}, 350 { bcmSwitchTimesyncUnknownVersionToCpu, 0, 351 CPU_CONTROL_Mr, UNKNOWN_1588_VERSION_TO_CPUf, 352 NULL, 0}, 353 { bcmSwitchTimesyncIngressVersion, 0, 354 ING_1588_PARSING_CONTROLr, VERSION_CONTROLf, 355 NULL, 0}, 356 { bcmSwitchTimesyncEgressVersion, 0, 357 EGR_1588_PARSING_CONTROLr, VERSION_CONTROLf, 358 NULL, 0}, 359 { bcmSwitchL2GreTunnelMissToCpu, 0, 360 CPU_CONTROL_Mr, L2GRE_SIP_LOOKUP_FAIL_COPY_TOCPUf, 361 NULL, 0}, 362 { bcmSwitchVxlanTunnelMissToCpu, 0, 363 CPU_CONTROL_Mr, VXLAN_SIP_LOOKUP_FAIL_COPY_TOCPUf, 364 NULL, 0}, 365 { bcmSwitchHashL2GreKeyMask0, 0, 366 RTAG7_HASH_CONTROL_L2GRE_MASK_Ar, L2GRE_TUNNEL_GRE_KEY_MASK_Af, 367 NULL, soc_feature_l2gre}, 368 { bcmSwitchHashL2GreKeyMask1, 0, 369 RTAG7_HASH_CONTROL_L2GRE_MASK_Br, L2GRE_TUNNEL_GRE_KEY_MASK_Bf, 370 NULL, soc_feature_l2gre}, 371 { bcmSwitchHashSctpL4Port, 0, 372 ING_SCTP_CONTROLr, PARSE_SCTPf, 373 NULL, 0}, 374 { bcmSwitchHashUseL2GreTunnelGreKey0, 0, 375 RTAG7_HASH_CONTROL_2r, L2GRE_TUNNEL_USE_GRE_KEY_Af, 376 NULL, soc_feature_l2gre}, 377 { bcmSwitchHashUseL2GreTunnelGreKey1, 0, 378 RTAG7_HASH_CONTROL_2r, L2GRE_TUNNEL_USE_GRE_KEY_Bf, 379 NULL, soc_feature_l2gre}, 380 { bcmSwitchHashField0Ip6FlowLabel,0, 381 RTAG7_HASH_CONTROL_2r, ENABLE_FLOW_LABEL_IPV6_Af, 382 NULL, 0}, 383 { bcmSwitchHashField1Ip6FlowLabel,0, 384 RTAG7_HASH_CONTROL_2r, ENABLE_FLOW_LABEL_IPV6_Bf, 385 NULL, 0}, 386 { bcmSwitchMacroFlowHashUseMSB, 0, 387 RTAG7_HASH_CONTROL_2r, MACRO_FLOW_HASH_BYTE_SELf, 388 NULL, 0}, 389 { bcmSwitchHashField0OverlayCntagRpidEnable, 0, 390 RTAG7_HASH_CONTROL_2r, ENABLE_BIN_12_OVERLAY_Af, 391 NULL, 0}, 392 { bcmSwitchHashField1OverlayCntagRpidEnable, 0, 393 RTAG7_HASH_CONTROL_2r, ENABLE_BIN_12_OVERLAY_Bf, 394 NULL, 0}, 395 { bcmSwitchHashMPLSUseLabelStack, 0, 396 RTAG7_HASH_CONTROL_2r, USE_MPLS_STACK_FOR_HASHINGf, 397 NULL, 0}, 398 { bcmSwitchHashMPLSExcludeReservedLabel, 0, 399 RTAG7_HASH_CONTROL_2r, EXCLUDE_ALL_RESERVED_LABELS_FROM_MPLS_HASHf, 400 NULL, 0}, 401 { bcmSwitchHashUseFlowSelTrunkUc , 0, 402 RTAG7_HASH_SELr, USE_FLOW_SEL_TRUNK_UCf, 403 NULL, 0}, 404 { bcmSwitchHashUseFlowSelEcmp, 0, 405 RTAG7_HASH_SELr, USE_FLOW_SEL_ECMPf, 406 NULL, 0}, 407 { bcmSwitchV6L3SrcDstLocalLinkDropCancel, 0, 408 ING_MISC_CONFIG2r, IPV6_SIP_AND_DIP_LINK_LOCAL_DO_NOT_DROPf, 409 NULL, 0}, 410 { bcmSwitchHashUseFlowSelTrunkNonUnicast, 0, 411 RTAG7_HASH_SELr, USE_FLOW_SEL_TRUNK_NONUCf, 412 NULL, 0}, 413 { bcmSwitchHashUseFlowSelEntropy, 0, 414 RTAG7_HASH_SELr, USE_FLOW_SEL_ENTROPY_LABELf, 415 NULL, 0}, 416 { bcmSwitchFieldMultipathHashSeed, 0, 417 FP_ECMP_HASH_CONTROLr, ECMP_HASH_SALTf, 418 NULL, 0}, 419 { bcmSwitchRateLimitLinear, 0, 420 MMU_MTRO_CONFIGr, ITU_MODE_SELf, 421 _th3_bool_invert, 0} 422 }; 423 424 425 int 426 _bcm_th3_switch_control_port_binding_set(int unit, 427 bcm_port_t port, 428 bcm_switch_control_t type, 429 int arg, int *found) 430 { 431 uint64 oval64, val64; 432 int i; 433 bcm_switch_binding_t *b; 434 uint32 max; 435 int fval, fwidth, prt, idx; 436 437 *found = 0; 438 /* 439 * Tomahawk3_bindings can only handle switch type that requires 440 * configuration in one field within one/multiple register. If the switch 441 * type need to configure multiple fields, it need to be processed with 442 * switch case method: 443 */ 444 switch (type) { 445 case bcmSwitchDosAttackIcmp: 446 if (arg >= 0) { 447 SOC_IF_ERROR_RETURN( 448 soc_reg_get(unit, DOS_CONTROL_2r, port, 0, &val64)); 449 oval64 = val64; 450 soc_reg64_field32_set(unit, 451 DOS_CONTROL_2r, &val64, ICMP_V4_PING_SIZE_ENABLEf, !!arg); 452 soc_reg64_field32_set(unit, 453 DOS_CONTROL_2r, &val64, ICMP_V6_PING_SIZE_ENABLEf, !!arg); 454 if (COMPILER_64_NE(val64, oval64)) { 455 SOC_IF_ERROR_RETURN( 456 soc_reg_set(unit, DOS_CONTROL_2r, port, 0, val64)); 457 } 458 *found = 1; 459 return BCM_E_NONE; 460 } else { 461 return BCM_E_PARAM; 462 } 463 464 case bcmSwitchMeterAdjust: 465 if (soc_feature(unit, soc_feature_meter_adjust)) { 466 if (arg < 0) { 467 return BCM_E_PARAM; 468 } 469 470 /* EGR_COUNTER_CONTROLr */ 471 SOC_IF_ERROR_RETURN( 472 soc_reg_get(unit, EGR_COUNTER_CONTROLr, port, 0, &val64)); 473 oval64 = val64; 474 fwidth = soc_reg_field_length( 475 unit, EGR_COUNTER_CONTROLr, PACKET_IFG_BYTESf); 476 max = (fwidth < 32) ? ((1 << fwidth)) - 1 : -1; 477 soc_reg64_field32_set(unit, EGR_COUNTER_CONTROLr, &val64, 478 PACKET_IFG_BYTESf, ((uint32)arg > max) ? max : (uint32)arg); 479 if (COMPILER_64_NE(val64, oval64)) { 480 SOC_IF_ERROR_RETURN( 481 soc_reg_set(unit, EGR_COUNTER_CONTROLr, port, 0, val64)); 482 } 483 484 /* EGR_SHAPING_CONTROLr */ 485 SOC_IF_ERROR_RETURN( 486 soc_reg_get(unit, EGR_SHAPING_CONTROLr, port, 0, &val64)); 487 oval64 = val64; 488 fwidth = soc_reg_field_length( 489 unit, EGR_SHAPING_CONTROLr, PACKET_IFG_BYTESf); 490 max = (fwidth < 32) ? ((1 << fwidth)) - 1 : -1; 491 soc_reg64_field32_set(unit, EGR_SHAPING_CONTROLr, &val64, 492 PACKET_IFG_BYTESf, ((uint32)arg > max) ? max : (uint32)arg); 493 if (COMPILER_64_NE(val64, oval64)) { 494 SOC_IF_ERROR_RETURN( 495 soc_reg_set(unit, EGR_SHAPING_CONTROLr, port, 0, val64)); 496 } 497 498 /* IFP_METER_CONTROLr */ 499 SOC_IF_ERROR_RETURN( 500 soc_reg_get(unit, IFP_METER_CONTROLr, port, 0, &val64)); 501 oval64 = val64; 502 fwidth = soc_reg_field_length( 503 unit, IFP_METER_CONTROLr, PACKET_IFG_BYTESf); 504 max = (fwidth < 32) ? ((1 << fwidth)) - 1 : -1; 505 soc_reg64_field32_set(unit, IFP_METER_CONTROLr, &val64, 506 PACKET_IFG_BYTESf, ((uint32)arg > max) ? max : (uint32)arg); 507 if (COMPILER_64_NE(val64, oval64)) { 508 SOC_IF_ERROR_RETURN( 509 soc_reg_set(unit, IFP_METER_CONTROLr, port, 0, val64)); 510 } 511 *found = 1; 512 } 513 return BCM_E_NONE; 514 515 case bcmSwitchRemoteLearnTrust: 516 arg = _th3_bool_invert(unit, arg, 1); 517 if (arg < 0) { 518 return BCM_E_PARAM; 519 } 520 521 /* ING_CONFIG_64r */ 522 SOC_IF_ERROR_RETURN( 523 soc_reg_get(unit, ING_CONFIG_64r, port, 0, &val64)); 524 oval64 = val64; 525 soc_reg64_field32_set( 526 unit, ING_CONFIG_64r, &val64, IGNORE_HG_HDR_DONOT_LEARNf, arg); 527 if (COMPILER_64_NE(val64, oval64)) { 528 SOC_IF_ERROR_RETURN( 529 soc_reg_set(unit, ING_CONFIG_64r, port, 0, val64)); 530 } 531 532 /* EGR_CONFIG_1r */ 533 SOC_IF_ERROR_RETURN( 534 soc_reg_get(unit, EGR_CONFIG_1r, port, 0, &val64)); 535 oval64 = val64; 536 soc_reg64_field32_set( 537 unit, EGR_CONFIG_1r, &val64, IGNORE_HG_HDR_DONOT_LEARNf, arg); 538 if (COMPILER_64_NE(val64, oval64)) { 539 SOC_IF_ERROR_RETURN( 540 soc_reg_set(unit, EGR_CONFIG_1r, port, 0, val64)); 541 } 542 *found = 1; 543 return BCM_E_NONE; 544 545 default: 546 break; 547 } 548 549 for (i = 0; i < COUNTOF(tomahawk3_bindings); i++) { 550 b = &tomahawk3_bindings[i]; 551 if (b->type == type) { 552 /* We don't check the b->chip since the table is specific for TH3 */ 553 if (b->feature && !soc_feature(unit, b->feature)) { 554 continue; 555 } 556 if (!SOC_REG_FIELD_VALID(unit, b->reg, b->field)) { 557 continue; 558 } 559 if (b->xlate_arg) { 560 if ((fval = (b->xlate_arg)(unit, arg, 1)) < 0) { 561 return fval; 562 } 563 } else { 564 fval = arg; 565 } 566 /* Negative values should be treated as errors */ 567 if (fval < 0) { 568 return BCM_E_PARAM; 569 } 570 if ((b->reg == PROTOCOL_PKT_CONTROLr) || 571 (b->reg == IGMP_MLD_PKT_CONTROLr)) { 572 int index; 573 574 BCM_IF_ERROR_RETURN 575 (_bcm_esw_port_tab_get(unit, port, 576 PROTOCOL_PKT_INDEXf, &index)); 577 prt = port; 578 idx = index; 579 } else { 580 prt = port; 581 idx = 0; 582 } 583 584 fwidth = soc_reg_field_length(unit, b->reg, b->field); 585 if (fwidth < 32) { 586 max = (1 << fwidth) - 1; 587 } else { 588 max = -1; 589 } 590 SOC_IF_ERROR_RETURN(soc_reg_get(unit, b->reg, prt, idx, &val64)); 591 oval64 = val64; 592 soc_reg64_field32_set(unit, b->reg, &val64, b->field, 593 ((uint32)fval > max) ? max : (uint32)fval); 594 if (COMPILER_64_NE(val64, oval64)) { 595 SOC_IF_ERROR_RETURN(soc_reg_set(unit, b->reg, prt, idx, val64)); 596 } 597 598 *found = 1; 599 break; 600 } 601 } 602 return BCM_E_NONE; 603 } 604 605 606 int 607 _bcm_th3_switch_control_port_binding_get(int unit, 608 bcm_port_t port, 609 bcm_switch_control_t type, 610 int *arg, int *found) 611 { 612 uint64 val64; 613 int i; 614 bcm_switch_binding_t *b; 615 int prt, idx; 616 617 *found = 0; 618 619 /* 620 * Tomahawk3_bindings can only handle switch type that requires 621 * configuration in one field within one/multiple register. If the switch 622 * type need to configure multiple fields, it need to be processed with 623 * switch case method: 624 */ 625 switch (type) { 626 case bcmSwitchDosAttackIcmp: 627 SOC_IF_ERROR_RETURN( 628 soc_reg_get(unit, DOS_CONTROL_2r, port, 0, &val64)); 629 *arg = soc_reg64_field32_get( 630 unit, DOS_CONTROL_2r, val64, ICMP_V4_PING_SIZE_ENABLEf); 631 *found = 1; 632 return BCM_E_NONE; 633 634 case bcmSwitchMeterAdjust: 635 if (soc_feature(unit, soc_feature_meter_adjust)) { 636 SOC_IF_ERROR_RETURN( 637 soc_reg_get(unit, EGR_COUNTER_CONTROLr, port, 0, &val64)); 638 *arg = soc_reg64_field32_get( 639 unit, EGR_COUNTER_CONTROLr, val64, PACKET_IFG_BYTESf); 640 *found = 1; 641 } 642 return BCM_E_NONE; 643 644 case bcmSwitchRemoteLearnTrust: 645 SOC_IF_ERROR_RETURN( 646 soc_reg_get(unit, ING_CONFIG_64r, port, 0, &val64)); 647 *arg = soc_reg64_field32_get( 648 unit, ING_CONFIG_64r, val64, IGNORE_HG_HDR_DONOT_LEARNf); 649 *arg = _th3_bool_invert(unit, *arg, 0); 650 *found = 1; 651 return BCM_E_NONE; 652 653 default: 654 break; 655 } 656 657 for (i = 0; i < COUNTOF(tomahawk3_bindings); i++) { 658 b = &tomahawk3_bindings[i]; 659 if (b->type == type) { 660 if (b->feature && !soc_feature(unit, b->feature)) { 661 continue; 662 } 663 664 if (!SOC_REG_FIELD_VALID(unit, b->reg, b->field)) { 665 continue; 666 } 667 if ((b->reg == PROTOCOL_PKT_CONTROLr) || 668 (b->reg == IGMP_MLD_PKT_CONTROLr)) { 669 int index; 670 671 BCM_IF_ERROR_RETURN 672 (_bcm_esw_port_tab_get(unit, port, 673 PROTOCOL_PKT_INDEXf, &index)); 674 prt = port; 675 idx = index; 676 } else { 677 prt = port; 678 idx = 0; 679 } 680 SOC_IF_ERROR_RETURN(soc_reg_get(unit, b->reg, prt, idx, &val64)); 681 *arg = soc_reg64_field32_get(unit, b->reg, val64, b->field); 682 683 if (b->xlate_arg) { 684 *arg = (b->xlate_arg)(unit, *arg, 0); 685 } 686 *found = 1; 687 break; 688 } 689 } 690 return BCM_E_NONE; 691 } 692 693 /* 694 * Function: 695 * bcm_tomahawk3_switch_pkt_trace_info_clear 696 * 697 * Purpose: 698 * This API is used to clear the existing SDK states for the visibility 699 * capture on the given port. It also clears the HW capture buffers for 700 * the pipe on which the given port resides. 701 * If the port parameter is passed in as -1 then SDK will reset the SW 702 * and HW capture states respective to all the pipes. 703 * 704 * Parameters: 705 * unit - (IN) Unit number. 706 * port - (IN) Logical port number 707 * 708 * Returns: 709 * BCM_E_xxx 710 * 711 * Notes: 712 */ 713 int bcm_tomahawk3_switch_pkt_trace_info_clear(int unit, bcm_port_t port) 714 { 715 int rv = BCM_E_UNAVAIL; 716 #ifdef BCM_INSTRUMENTATION_SUPPORT 717 int pipe = -1; 718 719 /* Extract the pipe information from the given valid port */ 720 if (-1 != port) { 721 if (!SOC_PORT_VALID(unit, port) || 722 SOC_FAILURE(soc_port_pipe_get(unit, port, &pipe))) { 723 return BCM_E_PORT; 724 } 725 } 726 727 /* There are no SW states so just reset the HW states */ 728 rv = _bcm_th3_pkt_trace_hw_reset(unit, pipe); 729 #endif 730 return rv; 731 } 732 733 #if defined(INCLUDE_L3) 734 /* 735 * Function: 736 * bcmi_th3_switch_agm_l3_ecmp_get_entries_per_period 737 * 738 * Purpose: 739 * This helper function determines the number of counter entries needed 740 * or already allocated for an ECMP group. For ECMP groups which are 741 * configured with dynamic mode RESILIENT HASH, dynamic size of the grp 742 * is the number of counters. For all other ECMP groups it is the number 743 * of actual members in the group. 744 * 745 * Parameters: 746 * unit - (IN) Unit number. 747 * agm_id - (IN) AGM identifier 748 * ecmp_id - (IN) ECMP Group identifier 749 * num_entries - (OUT) Number of entries to be returned to caller 750 * 751 * Returns: 752 * BCM_E_xxx 753 * 754 * Notes: 755 * This helper routine does not take any locks. It is assumed the caller 756 * would lock approriate resources before calling it. 757 */ 758 static int 759 bcmi_th3_switch_agm_l3_ecmp_get_entries_per_period(int unit, 760 bcm_switch_agm_id_t agm_id, bcm_if_t ecmp_id, uint32 *num_entries) { 761 762 int rv = BCM_E_NONE; 763 int mbr_cnt; 764 agm_monitor_t agm_mnt; 765 bcm_l3_egress_ecmp_t ecmp_info; 766 767 if (!num_entries) { 768 return BCM_E_PARAM; 769 } 770 771 BCM_IF_ERROR_RETURN(_bcm_th_switch_agm_info(unit, agm_id, &agm_mnt)); 772 *num_entries = agm_mnt.attr.num_members; 773 bcm_l3_egress_ecmp_t_init(&ecmp_info); 774 775 ecmp_info.ecmp_intf = ecmp_id; 776 rv = bcm_esw_l3_ecmp_get(unit, &ecmp_info, 0, NULL, &mbr_cnt); 777 if (BCM_SUCCESS(rv)) { 778 if (BCM_L3_ECMP_DYNAMIC_MODE_RESILIENT == ecmp_info.dynamic_mode) { 779 if (ecmp_info.dynamic_size > *num_entries) { 780 *num_entries = ecmp_info.dynamic_size; 781 } 782 } 783 } else { 784 LOG_ERROR(BSL_LS_BCM_SWITCH, (BSL_META_U(unit, 785 "L3 ECMP ID %d info get failed (%d)\n"), ecmp_id, rv)); 786 } 787 return rv; 788 } 789 790 /* 791 * Function: 792 * bcm_th3_switch_agm_l3_ecmp_stat_destroy 793 * 794 * Purpose: 795 * This function detaches and de-allocates the flex stat counter 796 * associated with the AGM with the given AGM ID. Once flex stat APIs 797 * successfully complete the counter ID in the AGM is reset to 0. 798 * 799 * Parameters: 800 * unit - (IN) Unit number. 801 * agm_id - (IN) AGM identifier 802 * 803 * Returns: 804 * BCM_E_xxx 805 * 806 * Notes: 807 * This function takes AGM_LOCK, so the caller does not need to lock 808 */ 809 int bcm_th3_switch_agm_l3_ecmp_stat_destroy(int unit, 810 bcm_switch_agm_id_t agm_id) { 811 812 int rv = BCM_E_NONE; 813 agm_monitor_t agm_mnt; 814 815 AGM_LOCK(unit); 816 rv = _bcm_th_switch_agm_info(unit, agm_id, &agm_mnt); 817 818 if (BCM_SUCCESS(rv)) { 819 /* Detach the flex stat counter */ 820 rv = bcm_th_agm_stat_detach(unit, agm_mnt.attr.agm_id, 821 agm_mnt.agm_pool_id, (uint32)agm_mnt.counter_id); 822 823 if (BCM_SUCCESS(rv)) { 824 /* Destroy flex counter */ 825 rv = bcm_th_agm_stat_id_clear(unit, agm_mnt.counter_id); 826 827 if (BCM_SUCCESS(rv)) { 828 /* Update software bookkeeping information */ 829 _bcm_th_switch_agm_update_counter_id(unit, agm_id, 0); 830 } else { 831 LOG_ERROR(BSL_LS_BCM_SWITCH, (BSL_META_U(unit, 832 "AGM %d destroy counter id failed, rv = %d.\n"), agm_id, rv)); 833 } 834 } else { 835 LOG_ERROR(BSL_LS_BCM_SWITCH, (BSL_META_U(unit, 836 "AGM %d detach failed, rv = %d.\n"), agm_id, rv)); 837 } 838 } 839 AGM_UNLOCK(unit); 840 return rv; 841 } 842 843 /* 844 * Function: 845 * bcm_th3_switch_agm_l3_ecmp_stat_create 846 * 847 * Purpose: 848 * This function allocates and attaches a flex stat counter associated 849 * with an AGM with the given ID for given ECMP group ID. The number of 850 * counter indexes to be allocated is determined based on the ECMP group 851 * type. If the ECMP group was created with dynamic mode RESILIENT, the 852 * number of counter entries would be (dynamic_size * agm_periods), else 853 * it would be (ecmp_grp_member_count * agm_periods). Once flex stat APIs 854 * successfully complete, the counter ID in the AGM is set to Flex stat 855 * given counter ID. 856 * 857 * Parameters: 858 * unit - (IN) Unit number. 859 * agm_id - (IN) AGM identifier 860 * l3_ecmp_id - (IN) ECMP group identifier 861 * 862 * Returns: 863 * BCM_E_xxx 864 * 865 * Notes: 866 * This function takes AGM_LOCK, so the caller does not need to lock 867 */ 868 int bcm_th3_switch_agm_l3_ecmp_stat_create(int unit, 869 bcm_switch_agm_id_t agm_id, bcm_if_t l3_ecmp_id) { 870 871 int rv = BCM_E_NONE; 872 uint32 counter_id = 0; 873 uint32 stat_cnt_per_period = 0; 874 agm_monitor_t agm_mnt; 875 876 AGM_LOCK(unit); 877 rv = _bcm_th_switch_agm_info(unit, agm_id, &agm_mnt); 878 879 if (BCM_SUCCESS(rv)) { 880 /* Get number of counter entries to be created for one AGM period */ 881 rv = bcmi_th3_switch_agm_l3_ecmp_get_entries_per_period( 882 unit, agm_id, l3_ecmp_id, &stat_cnt_per_period); 883 884 if (BCM_SUCCESS(rv)) { 885 /* Allocate a flex stat counter ID */ 886 rv = bcm_th_agm_stat_id_get(unit, 887 agm_id, 888 agm_mnt.agm_pool_id, 889 stat_cnt_per_period*(agm_mnt.attr.period_num + 1), 890 &counter_id); 891 892 if (BCM_SUCCESS(rv)) { 893 LOG_VERBOSE(BSL_LS_BCM_SWITCH, 894 (BSL_META_U(unit, "Allocated counter id %d for AGM %d.\n"), 895 counter_id, agm_id)); 896 897 /* Attach the counter */ 898 rv = bcm_th_agm_stat_attach( 899 unit, agm_id, agm_mnt.agm_pool_id, counter_id); 900 if (BCM_FAILURE(rv)) { 901 AGM_UNLOCK(unit); 902 return rv; 903 } 904 905 if (BCM_SUCCESS(rv)) { 906 LOG_VERBOSE(BSL_LS_BCM_SWITCH, 907 (BSL_META_U(unit, "Attached counter id %d to AGM %d\n"), 908 counter_id, agm_id)); 909 910 /* Update software bookkeeping information */ 911 _bcm_th_switch_agm_update_counter_id( 912 unit, agm_id, counter_id); 913 } else { 914 LOG_ERROR(BSL_LS_BCM_SWITCH, (BSL_META_U(unit, 915 "Attach failed of counter %d for AGM %d failed\n"), 916 counter_id, agm_id)); 917 bcm_th_agm_stat_id_clear(unit, counter_id); 918 } 919 } else { 920 LOG_ERROR(BSL_LS_BCM_SWITCH, (BSL_META_U(unit, 921 "Allocation of counter with count %d for AGM %d failed\n"), 922 stat_cnt_per_period*(agm_mnt.attr.period_num + 1), agm_id)); 923 } 924 } 925 } 926 927 AGM_UNLOCK(unit); 928 return rv; 929 } 930 #endif /* INCLUDE_L3 */ 931 932 /* 933 * Function: 934 * _bcmi_th3_agm_stat_retrieve 935 * 936 * Purpose: 937 * This helper function retrieves the packet stat count and byte stat count 938 * for the given flex stat counter index. At first pkt count is retrieved. 939 * Only if it is non zero byte count is retrieved else byte count is 940 * assumed to be zero. 941 * 942 * Parameters: 943 * unit - (IN) Unit number. 944 * agm_id - (IN) AGM identifier 945 * ctr_idx - (IN) Flex stat counter index 946 * ctr_val - (OUT) counter value to be sent back to caller 947 * 948 * Returns: 949 * BCM_E_xxx 950 * 951 * Notes: 952 * This helper routine does not take any locks. It is assumed the caller 953 * would lock approriate resources before calling it. 954 */ 955 static int 956 _bcmi_th3_agm_stat_retrieve(int unit, 957 bcm_switch_agm_id_t agm_id, 958 uint32 ctr_idx, 959 bcm_stat_value_t *ctr_val) { 960 961 int rv = BCM_E_NONE; 962 uint32 num_table; 963 bcm_stat_flex_table_info_t tbl_info; 964 965 if (!ctr_val) { 966 return BCM_E_PARAM; 967 } 968 969 /* Initialize to 0 */ 970 sal_memset(ctr_val, 0, sizeof(bcm_stat_value_t)); 971 972 BCM_IF_ERROR_RETURN( 973 bcm_th_agm_stat_get_table_info(unit, agm_id, &num_table, &tbl_info)); 974 if (bcmStatFlexDirectionIngress != tbl_info.direction) { 975 return BCM_E_NONE; 976 } 977 978 /* Get Pkt count */ 979 rv = _bcm_esw_stat_counter_get(unit, TRUE, 980 tbl_info.index, tbl_info.table, 0, 981 0 /* packet flag*/, ctr_idx, ctr_val); 982 983 if (BCM_FAILURE(rv)) { 984 sal_memset(ctr_val, 0, sizeof(bcm_stat_value_t)); 985 LOG_ERROR(BSL_LS_BCM_SWITCH, (BSL_META_U(unit, 986 "AGM %d collected pkt counter %d failed, rv = %d.\n"), 987 agm_id, ctr_idx, rv)); 988 } else if (!COMPILER_64_IS_ZERO(ctr_val->packets64)) { 989 990 /* Get byte count */ 991 rv = _bcm_esw_stat_counter_get(unit, TRUE, 992 tbl_info.index, tbl_info.table, 0, 993 1 /* byte flag */, ctr_idx, ctr_val); 994 995 if (BCM_FAILURE(rv)) { 996 sal_memset(ctr_val, 0, sizeof(bcm_stat_value_t)); 997 LOG_ERROR(BSL_LS_BCM_SWITCH, (BSL_META_U(unit, 998 "AGM %d collected byte counter %d failed, rv = %d.\n"), 999 agm_id, ctr_idx, rv)); 1000 } 1001 } 1002 1003 return rv; 1004 } 1005 1006 /* 1007 * Function: 1008 * _bcmi_th3_switch_agm_trunk_stat_get 1009 * 1010 * Purpose: 1011 * This internal function gets the AGM stats for Trunk. 1012 * 1013 * Parameters: 1014 * unit - (IN) Unit number. 1015 * agm_mnt - (IN) AGM monitor 1016 * member_arr - (IN) array to hold Trunk member gport IDs 1017 * nstat - (IN) size of the stat array passed in 1018 * stat_arr - (OUT) retrieved flex stat values 1019 * 1020 * Returns: 1021 * BCM_E_xxx 1022 * 1023 * Notes: 1024 * This function does not check validity of given parameters, as it is 1025 * meant to be called after doing such validations. Hence it also does 1026 * not takes appr. locks, Caller need to take locks before calling it 1027 */ 1028 static int 1029 _bcmi_th3_switch_agm_trunk_stat_get(int unit, 1030 agm_monitor_t *agm_mnt, 1031 void *member_arr, 1032 int nstat, 1033 bcm_switch_agm_stat_t *stat_arr) { 1034 int i; 1035 int mbr_cnt; 1036 bcm_trunk_member_t *mbr_arr = (bcm_trunk_member_t *)member_arr; 1037 bcm_trunk_info_t tinfo; 1038 bcm_stat_value_t ctr_val; 1039 1040 LOG_VERBOSE(BSL_LS_BCM_SWITCH, ( 1041 BSL_META_U(unit, "AGM %d(Trunk) stat get: mbr cnt %d, period %d.\n"), 1042 agm_mnt->attr.agm_id, agm_mnt->attr.num_members, 1043 (nstat / agm_mnt->attr.num_members) + 1)); 1044 1045 1046 BCM_IF_ERROR_RETURN( 1047 bcm_esw_trunk_get(unit, (bcm_trunk_t)agm_mnt->group_id, 1048 &tinfo, agm_mnt->attr.num_members, mbr_arr, &mbr_cnt)); 1049 1050 if (0 == mbr_cnt) { 1051 return BCM_E_FAIL; 1052 } 1053 1054 /* Fill in the nstat array with available data */ 1055 for (i = 0; i < nstat ; i++) { 1056 stat_arr[i].period = i / agm_mnt->attr.num_members; 1057 stat_arr[i].intf_id = BCM_IF_INVALID; 1058 stat_arr[i].gport_id = mbr_arr[i % mbr_cnt].gport; 1059 1060 BCM_IF_ERROR_RETURN( 1061 _bcmi_th3_agm_stat_retrieve(unit, agm_mnt->attr.agm_id, i, &ctr_val)); 1062 1063 stat_arr[i].packets = ctr_val.packets64; 1064 stat_arr[i].bytes = ctr_val.bytes; 1065 } 1066 1067 return BCM_E_NONE; 1068 } 1069 1070 #if defined(INCLUDE_L3) 1071 /* 1072 * Function: 1073 * _bcmi_th3_switch_agm_l3_ecmp_stat_get 1074 * 1075 * Purpose: 1076 * This internal function gets the AGM stats for ECMP group. 1077 * 1078 * Parameters: 1079 * unit - (IN) Unit number. 1080 * agm_mnt - (IN) AGM monitor 1081 * member_arr - (IN) array to hold ECMP Egr obj intf IDs 1082 * nstat - (IN) size of the stat array passed in 1083 * stat_arr - (OUT) retrieved flex stat values 1084 * 1085 * Returns: 1086 * BCM_E_xxx 1087 * 1088 * Notes: 1089 * This function does not check validity of given parameters, as it is 1090 * meant to be called after doing such validations. Hence it also does 1091 * not takes appr. locks, Caller need to take locks before calling it 1092 */ 1093 static int 1094 _bcmi_th3_switch_agm_l3_ecmp_stat_get(int unit, 1095 agm_monitor_t *agm_mnt, 1096 void *member_arr, 1097 int nstat, 1098 bcm_switch_agm_stat_t *stat_arr) { 1099 1100 int i, j; 1101 int stat_arr_idx; 1102 int num_periods = 0; 1103 int mbr, mbr_cnt = 0; 1104 int nhop_to_intf_offset = 0; 1105 uint32 nhop_idx; 1106 uint32 counter_idx; 1107 uint32 ecmp_base_ptr = 0; 1108 uint32 entries_per_period = agm_mnt->attr.num_members; 1109 bcm_if_t egr_obj_intf; 1110 bcm_if_t *mbr_arr = (bcm_if_t *)member_arr; 1111 bcm_if_t ecmp_intf = (bcm_if_t)agm_mnt->group_id; 1112 soc_mem_t ecmp_mem = INVALIDm; 1113 ecmp_entry_t ecmp_entry; 1114 bcm_stat_value_t counter_val; 1115 ecmp_count_entry_t ecmp_grp_entry; 1116 bcm_l3_egress_ecmp_t ecmp_info; 1117 1118 1119 /* Calculate number of periods based on given nstat parameter */ 1120 num_periods = 1121 (nstat + agm_mnt->attr.num_members - 1) / agm_mnt->attr.num_members; 1122 1123 LOG_VERBOSE(BSL_LS_BCM_SWITCH, (BSL_META_U(unit, 1124 "AGM %d(ECMP) stat get: group member count %d, period %d.\n"), 1125 agm_mnt->attr.agm_id, agm_mnt->attr.num_members, num_periods)); 1126 1127 /* Retrieve and validate the members of the ECMP group */ 1128 bcm_l3_egress_ecmp_t_init(&ecmp_info); 1129 ecmp_info.ecmp_intf = ecmp_intf; 1130 BCM_IF_ERROR_RETURN( 1131 bcm_esw_l3_egress_ecmp_get(unit, &ecmp_info, 0, NULL, &mbr_cnt)); 1132 BCM_IF_ERROR_RETURN(bcm_esw_l3_egress_multipath_get( 1133 unit, ecmp_intf, agm_mnt->attr.num_members, mbr_arr, &mbr_cnt)); 1134 if (0 == mbr_cnt) { 1135 return BCM_E_FAIL; 1136 } 1137 1138 /* For RH ECMPs find out the base address for L3_ECMP memory and offset 1139 * which will be used to covert nhop to corresponding egr obj interface ID. 1140 * Also adjust the counter entries per AGM period values based on dyn size. 1141 */ 1142 if (BCM_L3_ECMP_DYNAMIC_MODE_RESILIENT == ecmp_info.dynamic_mode) { 1143 if (ecmp_info.dynamic_size > agm_mnt->attr.num_members) { 1144 entries_per_period = ecmp_info.dynamic_size; 1145 } 1146 1147 if (bcmSwitchAgmTypeL3EcmpOverlay == agm_mnt->attr.agm_type) { 1148 ecmp_mem = ECMP_GROUP_HIERARCHICALm; 1149 nhop_to_intf_offset = BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit); 1150 } else { 1151 ecmp_mem = L3_ECMP_COUNTm; 1152 nhop_to_intf_offset = BCM_XGS3_EGRESS_IDX_MIN(unit); 1153 } 1154 SOC_IF_ERROR_RETURN(soc_mem_read(unit, ecmp_mem, 1155 MEM_BLOCK_ANY, ecmp_intf - BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit), 1156 &ecmp_grp_entry)); 1157 ecmp_base_ptr = 1158 soc_mem_field32_get(unit, ecmp_mem, &ecmp_grp_entry, BASE_PTRf); 1159 } 1160 1161 /* Initialize the stat arr with known rese values */ 1162 for (i = 0; i < nstat ; i++) { 1163 stat_arr[i].period = i / agm_mnt->attr.num_members; 1164 COMPILER_64_ZERO(stat_arr[i].packets); 1165 COMPILER_64_ZERO(stat_arr[i].bytes); 1166 stat_arr[i].gport_id = BCM_GPORT_INVALID; 1167 stat_arr[i].intf_id = mbr_arr[i % mbr_cnt]; 1168 } 1169 1170 for (i = 0; i < num_periods; i++) { 1171 for (j = 0; j < entries_per_period; j++) { 1172 counter_idx = (i * entries_per_period) + j; 1173 1174 /* Retrieve the stat counts */ 1175 BCM_IF_ERROR_RETURN( 1176 _bcmi_th3_agm_stat_retrieve(unit, 1177 agm_mnt->attr.agm_id, counter_idx, &counter_val)); 1178 1179 /* If there are no packets on this counter then skip to next ctr */ 1180 if (COMPILER_64_IS_ZERO(counter_val.packets64)) { 1181 continue; 1182 } 1183 1184 /* Calculate the index into arr where the stats are to be updated */ 1185 if (BCM_L3_ECMP_DYNAMIC_MODE_RESILIENT == ecmp_info.dynamic_mode) { 1186 1187 /* For RH ECMPs, index into stat arr is derived indirectly. 1188 * First next hop index is retrieved from L3 ECMP memory which 1189 * is then used to deduce the egr object interface ID. This egr 1190 * intf is further searched into the member array. The offset of 1191 * member array where the intf is found is used directly to 1192 * derive the index into USer given stat array. 1193 */ 1194 SOC_IF_ERROR_RETURN(READ_L3_ECMPm( 1195 unit, MEM_BLOCK_ANY, j + ecmp_base_ptr, &ecmp_entry)); 1196 1197 nhop_idx = 1198 soc_L3_ECMPm_field32_get( 1199 unit, &ecmp_entry, NEXT_HOP_INDEXf); 1200 1201 egr_obj_intf = nhop_to_intf_offset + (bcm_if_t)nhop_idx; 1202 1203 for (mbr=0 ; mbr<mbr_cnt ; mbr++) { 1204 if (mbr_arr[mbr] == egr_obj_intf) { 1205 stat_arr_idx = mbr + (i * agm_mnt->attr.num_members); 1206 break; 1207 } 1208 } 1209 1210 if (mbr >= mbr_cnt) { 1211 LOG_ERROR(BSL_LS_BCM_SWITCH, (BSL_META_U(unit, 1212 "AGM %d ECMP egr obj %d not found.\n"), 1213 agm_mnt->attr.agm_id, egr_obj_intf)); 1214 return BCM_E_FAIL; 1215 } 1216 } else { 1217 /* For non RH ECMPs, derive the index into stat arr directly */ 1218 stat_arr_idx = (i * agm_mnt->attr.num_members) + j; 1219 } 1220 1221 /* Update the stat arr if the index is within the max arr size */ 1222 if (stat_arr_idx < nstat) { 1223 COMPILER_64_ADD_64( stat_arr[stat_arr_idx].packets, 1224 counter_val.packets64 ); 1225 COMPILER_64_ADD_64( stat_arr[stat_arr_idx].bytes, 1226 counter_val.bytes ); 1227 } else { 1228 /* If the calculated index is out of range then assert, however 1229 * for last AGM period there could be possibility that User did 1230 * not provide enough space to accomodate data for all members, 1231 * hence in this case only assert if calculated index is out of 1232 * range provided if the given array was of sufficient size. 1233 */ 1234 if (i != (num_periods-1)) { 1235 assert(stat_arr_idx < nstat); 1236 } else if (stat_arr_idx >= ((i+1)*agm_mnt->attr.num_members)) { 1237 assert(stat_arr_idx < ((i+1)*agm_mnt->attr.num_members)); 1238 } 1239 } 1240 } 1241 } 1242 1243 return BCM_E_NONE; 1244 } 1245 #endif /* INCLUDE_L3 */ 1246 1247 /* 1248 * Function: 1249 * bcm_th3_switch_agm_stat_get 1250 * 1251 * Purpose: 1252 * This function initializes the given stat array with reset values. It 1253 * allocates an array to hold ECMP or Trunk member information based on 1254 * the AGM type. Then it calls appr. function based on AGM type to 1255 * retrieve the flex stats. 1256 * 1257 * Parameters: 1258 * unit - (IN) Unit number. 1259 * agm_id - (IN) AGM identifier 1260 * nstat - (IN) size of the stat array passed in 1261 * stat_arr - (OUT) retrieved flex stat values 1262 * 1263 * Returns: 1264 * BCM_E_xxx 1265 * 1266 * Notes: 1267 * This function checks validity of all the given parameters, as it is 1268 * meant to be called from API dispatch layer. It also takes appr. locks 1269 * so caller need not take locks. 1270 */ 1271 int bcm_th3_switch_agm_stat_get(int unit, 1272 bcm_switch_agm_id_t agm_id, 1273 int nstat, 1274 bcm_switch_agm_stat_t *stat_arr) { 1275 1276 int elm_size = 0; 1277 int rv = BCM_E_UNAVAIL; 1278 void *mbr_arr = NULL; 1279 agm_monitor_t agm_mnt; 1280 int (*func_p)(int, agm_monitor_t *, void *, int, bcm_switch_agm_stat_t *); 1281 1282 /* Validate parameters */ 1283 if (!SOC_UNIT_VALID(unit)) { 1284 return BCM_E_UNIT; 1285 } 1286 if (NULL == stat_arr || nstat <= 0) { 1287 return BCM_E_PARAM; 1288 } 1289 BCM_IF_ERROR_RETURN(bcm_th_switch_agm_id_validate(unit, agm_id)); 1290 1291 func_p = NULL; 1292 AGM_LOCK(unit); 1293 1294 /* Get hold of AGM monitor info */ 1295 rv = _bcm_th_switch_agm_info(unit, agm_id, &agm_mnt); 1296 1297 if (BCM_SUCCESS(rv)) { 1298 /* Validate the nstat supported by the AGM. If the user has 1299 * provided larger than needed buffer, return BCM_E_PARAM 1300 */ 1301 if (nstat > ((agm_mnt.attr.period_num+1) * agm_mnt.attr.num_members)) { 1302 AGM_UNLOCK(unit); 1303 return BCM_E_PARAM; 1304 } 1305 1306 if ((bcmSwitchAgmTypeL3Ecmp == agm_mnt.attr.agm_type) || 1307 (bcmSwitchAgmTypeL3EcmpOverlay == agm_mnt.attr.agm_type)) { 1308 #if defined(INCLUDE_L3) 1309 if (soc_feature(unit, soc_feature_l3)) { 1310 elm_size = sizeof(bcm_if_t); 1311 func_p = _bcmi_th3_switch_agm_l3_ecmp_stat_get; 1312 } else 1313 #endif 1314 { 1315 AGM_UNLOCK(unit); 1316 return BCM_E_UNAVAIL; 1317 } 1318 } else if (bcmSwitchAgmTypeTrunk == agm_mnt.attr.agm_type) { 1319 elm_size = sizeof(bcm_trunk_member_t); 1320 func_p = _bcmi_th3_switch_agm_trunk_stat_get; 1321 } else { 1322 AGM_UNLOCK(unit); 1323 return BCM_E_UNAVAIL; 1324 } 1325 1326 /* Allocate member array */ 1327 mbr_arr = sal_alloc(elm_size * agm_mnt.attr.num_members, "mbr_arr"); 1328 if (mbr_arr) { 1329 /* Call AGM type specific function to get the stats */ 1330 rv = func_p(unit, &agm_mnt, mbr_arr, nstat, stat_arr); 1331 1332 /* Free the member array */ 1333 sal_free(mbr_arr); 1334 } else { 1335 rv = BCM_E_MEMORY; 1336 } 1337 } 1338 1339 AGM_UNLOCK(unit); 1340 return rv; 1341 } 1342 1343 /* 1344 * Function: 1345 * bcm_th3_switch_agm_stat_clear 1346 * 1347 * Purpose: 1348 * This function calls appr. flex stat APIs to clear the counter value for 1349 * counter associated with the given AGM ID. 1350 * 1351 * Parameters: 1352 * unit - (IN) Unit number. 1353 * agm_id - (IN) AGM identifier 1354 * 1355 * Returns: 1356 * BCM_E_xxx 1357 * 1358 * Notes: 1359 * This function checks validity of all the given parameters, as it is 1360 * meant to be called from API dispatch layer. It also takes appr. locks 1361 * so caller need not take locks. 1362 */ 1363 int bcm_th3_switch_agm_stat_clear(int unit, 1364 bcm_switch_agm_id_t agm_id) { 1365 1366 int i, j; 1367 int num_periods; 1368 int rv = BCM_E_NONE; 1369 uint32 num_table; 1370 uint32 entries_per_period; 1371 agm_monitor_t agm_mnt; 1372 bcm_stat_value_t counter_val; 1373 bcm_stat_flex_table_info_t tbl_info; 1374 1375 /* Validate parameters */ 1376 if (!SOC_UNIT_VALID(unit)) { 1377 return BCM_E_UNIT; 1378 } 1379 1380 BCM_IF_ERROR_RETURN(bcm_th_switch_agm_id_validate(unit, agm_id)); 1381 1382 AGM_LOCK(unit); 1383 rv = bcm_th_agm_stat_get_table_info(unit, agm_id, &num_table, &tbl_info); 1384 if (BCM_FAILURE(rv) || bcmStatFlexDirectionIngress != tbl_info.direction) { 1385 goto _exit_stat_cl; 1386 } 1387 1388 rv = _bcm_th_switch_agm_info(unit, agm_id, &agm_mnt); 1389 if (BCM_FAILURE(rv)) { 1390 goto _exit_stat_cl; 1391 } 1392 1393 num_periods = agm_mnt.attr.period_num + 1; 1394 entries_per_period = agm_mnt.attr.num_members; 1395 1396 if ((bcmSwitchAgmTypeL3Ecmp == agm_mnt.attr.agm_type) || 1397 (bcmSwitchAgmTypeL3EcmpOverlay == agm_mnt.attr.agm_type)) { 1398 #if defined(INCLUDE_L3) 1399 if (soc_feature(unit, soc_feature_l3)) { 1400 rv = bcmi_th3_switch_agm_l3_ecmp_get_entries_per_period(unit, 1401 agm_id, (bcm_if_t)agm_mnt.group_id, &entries_per_period); 1402 } else 1403 #endif 1404 { 1405 rv = BCM_E_UNAVAIL; 1406 } 1407 if (BCM_FAILURE(rv)) { 1408 goto _exit_stat_cl; 1409 } 1410 } 1411 1412 sal_memset(&counter_val, 0, sizeof(bcm_stat_value_t)); 1413 1414 for (i = 0; i < num_periods; i++) { 1415 for (j = 0; j < entries_per_period; j++) { 1416 1417 /* Clear packet and byte count, both at once */ 1418 rv = _bcm_esw_stat_counter_set( 1419 unit, tbl_info.index, tbl_info.table, 1420 0, -1, ((i * entries_per_period) + j), &counter_val); 1421 if (BCM_FAILURE(rv)) { 1422 LOG_ERROR(BSL_LS_BCM_SWITCH, (BSL_META_U(unit, 1423 "AGM %d clear packet/byte counter %d failed, rv = %d.\n"), 1424 agm_id, ((i * entries_per_period) + j), rv)); 1425 goto _exit_stat_cl; 1426 } 1427 } 1428 } 1429 1430 _exit_stat_cl: 1431 AGM_UNLOCK(unit); 1432 return rv; 1433 } 1434 #endif /* BCM_TOMAHAWK3_SUPPORT */