ipfix.c (124228B)
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: ipfix.c 8 * Purpose: IPFIX API 9 */ 10 11 #include <shared/bsl.h> 12 13 #include <soc/drv.h> 14 #include <soc/scache.h> 15 #include <soc/profile_mem.h> 16 #include <bcm/error.h> 17 #include <bcm/ipfix.h> 18 #include <bcm/mirror.h> 19 #include <bcm_int/common/multicast.h> 20 #include <bcm_int/esw/xgs3.h> 21 #include <bcm_int/esw/port.h> 22 #include <bcm_int/esw/virtual.h> 23 #include <bcm_int/esw/multicast.h> 24 #include <bcm_int/esw/ipfix.h> 25 #include <bcm_int/esw/mirror.h> 26 27 #ifdef BCM_CMICM_SUPPORT 28 #include <soc/cmicm.h> 29 #endif 30 31 #ifdef BCM_WARM_BOOT_SUPPORT 32 #include <bcm/module.h> 33 #include <bcm_int/esw/switch.h> 34 #endif 35 36 #ifdef BCM_IPFIX_SUPPORT 37 static _bcm_ipfix_ctrl_t *_bcm_ipfix_ctrl[BCM_MAX_NUM_UNITS]; 38 39 #ifdef BCM_TRIUMPH_SUPPORT 40 static const _bcm_ipfix_id_def_t _ipfix_tr_id_def = { 41 { ING_IPFIX_PORT_CONFIGr, EGR_IPFIX_PORT_CONFIGr }, 42 { ING_IPFIX_PROFILEm, EGR_IPFIX_PROFILEm }, 43 { ING_IPFIX_EXPORT_FIFOm, EGR_IPFIX_EXPORT_FIFOm }, 44 { IPFIX_AGE_CONTROLr, EGR_IPFIX_AGE_CONTROLr }, 45 { ING_IPFIX_MIRROR_CONTROL_64r, EGR_IPFIX_MIRROR_CONTROL_64r }, 46 { MTP_INDEX0f, MTP_INDEX1f, MTP_INDEX2f, MTP_INDEX3f }, 47 }; 48 49 /* Mapping between profile and field in bcm_ipfix_config_t */ 50 static const _bcm_ipfix_profile_def_t _ipfix_tr_profile_def[] = { 51 { 52 _BCM_IPFIX_PROFILE_TYPE_MEM, 53 IP_DSCP_PROFILEf, 54 { /* stage */ 55 { /* ingress */ 56 _BCM_IPFIX_PROFILE_ID_ING_DSCP_XLATE_TABLE, 57 { ING_IPFIX_DSCP_XLATE_TABLEm, INVALIDm }, 58 { sizeof(ing_ipfix_dscp_xlate_table_entry_t) / sizeof(uint32), 59 0 }, 60 }, 61 { /* egress */ 62 _BCM_IPFIX_PROFILE_ID_EGR_DSCP_XLATE_TABLE, 63 { EGR_IPFIX_DSCP_XLATE_TABLEm, INVALIDm }, 64 { sizeof(egr_ipfix_dscp_xlate_table_entry_t) / sizeof(uint32), 65 0 }, 66 }, 67 }, 68 }, 69 { 70 _BCM_IPFIX_PROFILE_TYPE_MEM, 71 IP_IPV4_MASK_PROFILEf, 72 { /* stage */ 73 { /* ingress */ 74 _BCM_IPFIX_PROFILE_ID_ING_IPV4_MASK_SET_A, 75 { ING_IPFIX_IPV4_MASK_SET_Am, ING_IPFIX_IPV4_MASK_SET_Bm }, 76 { sizeof(ing_ipfix_ipv4_mask_set_a_entry_t) / sizeof(uint32), 77 sizeof(ing_ipfix_ipv4_mask_set_b_entry_t) / sizeof(uint32) }, 78 }, 79 { /* egress */ 80 _BCM_IPFIX_PROFILE_ID_EGR_IPV4_MASK_SET_A, 81 { EGR_IPFIX_IPV4_MASK_SET_Am, INVALIDm }, 82 { sizeof(egr_ipfix_ipv4_mask_set_a_entry_t) / sizeof(uint32), 83 0 }, 84 }, 85 }, 86 }, 87 { 88 _BCM_IPFIX_PROFILE_TYPE_MEM, 89 IP_IPV6_MASK_PROFILEf, 90 { /* stage */ 91 { /* ingress */ 92 _BCM_IPFIX_PROFILE_ID_ING_IPV6_MASK_SET_A, 93 { ING_IPFIX_IPV6_MASK_SET_Am, ING_IPFIX_IPV6_MASK_SET_Bm }, 94 { sizeof(ing_ipfix_ipv6_mask_set_a_entry_t) / sizeof(uint32), 95 sizeof(ing_ipfix_ipv6_mask_set_b_entry_t) / sizeof(uint32) }, 96 }, 97 { /* egress */ 98 _BCM_IPFIX_PROFILE_ID_EGR_IPV6_MASK_SET_A, 99 { EGR_IPFIX_IPV6_MASK_SET_Am, INVALIDm }, 100 { sizeof(egr_ipfix_ipv6_mask_set_a_entry_t) / sizeof(uint32), 101 0 }, 102 }, 103 }, 104 }, 105 { 106 _BCM_IPFIX_PROFILE_TYPE_REG, 107 PORT_LIMIT_PROFILEf, 108 { /* stage */ 109 { /* ingress */ 110 _BCM_IPFIX_PROFILE_ID_ING_PORT_RECORD_LIMIT_SET, 111 { ING_IPFIX_PORT_RECORD_LIMIT_SETr, INVALIDr }, 112 { 0, 0 }, 113 }, 114 { /* egress */ 115 _BCM_IPFIX_PROFILE_ID_EGR_PORT_RECORD_LIMIT_SET, 116 { EGR_IPFIX_PORT_RECORD_LIMIT_SETr, INVALIDr }, 117 { 0, 0 }, 118 }, 119 }, 120 }, 121 { 122 _BCM_IPFIX_PROFILE_TYPE_REG, 123 MIN_LIVE_TIME_PROFILEf, 124 { /* stage */ 125 { /* ingress */ 126 _BCM_IPFIX_PROFILE_ID_ING_MINIMUM_LIVE_TIME_SET, 127 { ING_IPFIX_MINIMUM_LIVE_TIME_SETr, INVALIDr }, 128 { 0, 0 }, 129 }, 130 { /* egress */ 131 _BCM_IPFIX_PROFILE_ID_EGR_MINIMUM_LIVE_TIME_SET, 132 { EGR_IPFIX_MINIMUM_LIVE_TIME_SETr, INVALIDr }, 133 { 0, 0 }, 134 }, 135 }, 136 }, 137 #ifdef BCM_TRIUMPH2_SUPPORT 138 { 139 _BCM_IPFIX_PROFILE_TYPE_REG, 140 MAX_LIVE_TIME_PROFILEf, 141 { /* stage */ 142 { /* ingress */ 143 _BCM_IPFIX_PROFILE_ID_ING_MAXIMUM_LIVE_TIME_SET, 144 { ING_IPFIX_MAXIMUM_LIVE_TIME_SETr, INVALIDr }, 145 { 0, 0 }, 146 }, 147 { /* egress */ 148 _BCM_IPFIX_PROFILE_ID_EGR_MAXIMUM_LIVE_TIME_SET, 149 { EGR_IPFIX_MAXIMUM_LIVE_TIME_SETr, INVALIDr }, 150 { 0, 0 }, 151 }, 152 }, 153 }, 154 #endif /* BCM_TRIUMPH2_SUPPORT */ 155 { 156 _BCM_IPFIX_PROFILE_TYPE_REG, 157 MAX_IDLE_AGE_PROFILEf, 158 { /* stage */ 159 { /* ingress */ 160 _BCM_IPFIX_PROFILE_ID_ING_MAXIMUM_IDLE_AGE_SET, 161 { ING_IPFIX_MAXIMUM_IDLE_AGE_SETr, INVALIDr }, 162 { 0, 0 }, 163 }, 164 { /* egress */ 165 _BCM_IPFIX_PROFILE_ID_EGR_MAXIMUM_IDLE_AGE_SET, 166 { EGR_IPFIX_MAXIMUM_IDLE_AGE_SETr, INVALIDr }, 167 { 0, 0 }, 168 }, 169 }, 170 }, 171 { 172 _BCM_IPFIX_PROFILE_TYPE_REG, 173 SAMPLING_LIMIT_PROFILEf, 174 { /* stage */ 175 { /* ingress */ 176 _BCM_IPFIX_PROFILE_ID_ING_SAMPLING_LIMIT_SET, 177 { ING_IPFIX_SAMPLING_LIMIT_SETr, INVALIDr }, 178 { 0, 0 }, 179 }, 180 { /* egress */ 181 _BCM_IPFIX_PROFILE_ID_EGR_SAMPLING_LIMIT_SET, 182 { EGR_IPFIX_SAMPLING_LIMIT_SETr, INVALIDr }, 183 { 0, 0 }, 184 }, 185 }, 186 }, 187 { 188 _BCM_IPFIX_PROFILE_TYPE_NONE, /* end of table mark */ 189 }, 190 }; 191 192 /* 193 * Mapping between bcm_ipfix_config_t.flags bit mask and field 194 * of ING_IPFIX_PORT_CONFIG (or EGR_IPFIX_PORT_CONFIG) 195 */ 196 static const _bcm_ipfix_flags_def_t _ipfix_tr_port_config_flags_def[] = { 197 { BCM_IPFIX_CONFIG_TCP_END_DETECT, TCP_END_DETECT_ENABLEf }, 198 { BCM_IPFIX_CONFIG_KEY_SRC_IP, IP_SIP_ENABLEf }, 199 { BCM_IPFIX_CONFIG_KEY_DST_IP, IP_DIP_ENABLEf }, 200 { BCM_IPFIX_CONFIG_KEY_IP_PROT, IP_PROTOCOL_ENABLEf }, 201 { BCM_IPFIX_CONFIG_KEY_IP_DSCP, IP_DSCP_ENABLEf }, 202 { BCM_IPFIX_CONFIG_KEY_IP_ECN, IP_ECN_ENABLEf }, 203 { BCM_IPFIX_CONFIG_KEY_L4_SRC_PORT, IP_TCP_SRC_PORT_ENABLEf }, 204 { BCM_IPFIX_CONFIG_KEY_L4_DST_PORT, IP_TCP_DEST_PORT_ENABLEf }, 205 { BCM_IPFIX_CONFIG_KEY_IP6_FLOW, IP_IPV6_LABEL_ENABLEf }, 206 { BCM_IPFIX_CONFIG_KEY_ICMP_TYPE, IP_ICMP_TYPE_ENABLEf }, 207 { BCM_IPFIX_CONFIG_KEY_ICMP_CODE, IP_ICMP_CODE_ENABLEf }, 208 { BCM_IPFIX_CONFIG_KEY_MACDA, L2_MAC_DA_ENABLEf }, 209 { BCM_IPFIX_CONFIG_KEY_MACSA, L2_MAC_SA_ENABLEf }, 210 { BCM_IPFIX_CONFIG_KEY_VLAN_ID, L2_VLAN_ID_ENABLEf }, 211 { BCM_IPFIX_CONFIG_KEY_VLAN_PRI, L2_VLAN_PRI_ENABLEf }, 212 { BCM_IPFIX_CONFIG_KEY_ETHER_TYPE, L2_ETH_TYPE_ENABLEf }, 213 { BCM_IPFIX_CONFIG_KEY_VLAN_TAGGED, L2_TAGGED_ENABLEf }, 214 { 0 }, 215 }; 216 #endif /* BCM_TRIUMPH_SUPPORT */ 217 218 #ifdef BCM_WARM_BOOT_SUPPORT 219 220 #define BCM_WB_VERSION_1_0 SOC_SCACHE_VERSION(1,0) 221 #define BCM_WB_DEFAULT_VERSION BCM_WB_VERSION_1_0 222 223 /* 224 * Function: 225 * _bcm_ipfix_reinit 226 * Description: 227 * Recovers ipfix rate config data info. 228 * Parameters: 229 * unit - (IN) BCM unit number 230 * Notes: 231 * None. 232 */ 233 STATIC int 234 _bcm_ipfix_reinit(int unit) 235 { 236 _bcm_ipfix_ctrl_t *ipfix_ctrl = _bcm_ipfix_ctrl[unit]; 237 soc_scache_handle_t scache_handle; 238 uint8 *ipfix_scache = NULL; 239 int size; 240 int rv = BCM_E_NONE; 241 int arry_size; 242 243 sal_memset(&scache_handle , 0, sizeof(soc_scache_handle_t)); 244 size = soc_mem_index_count(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm); 245 arry_size = _SHR_BITDCLSIZE(size); 246 247 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_IPFIX, 0); 248 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0, &ipfix_scache, 249 BCM_WB_DEFAULT_VERSION, NULL); 250 if (BCM_E_NOT_FOUND == rv) { 251 ipfix_scache = NULL; 252 } else if (BCM_FAILURE(rv)) { 253 return rv; 254 } else { 255 sal_memcpy(&ipfix_ctrl->rate_used_count, ipfix_scache, 256 sizeof(ipfix_ctrl->rate_used_count)); 257 ipfix_scache += sizeof(ipfix_ctrl->rate_used_count); 258 /* 259 * Copy rate_id pbmp value from scache to ipfix control structure. 260 */ 261 sal_memcpy(ipfix_ctrl->rate_used_bmp, ipfix_ctrl, arry_size); 262 } 263 264 return rv; 265 } 266 #endif 267 268 STATIC int 269 _bcm_ipfix_gport_resolve(int unit, 270 bcm_gport_t gport, 271 bcm_port_t *local_port) 272 { 273 bcm_module_t modid; 274 bcm_port_t port; 275 bcm_trunk_t tgid; 276 int id; 277 278 if (BCM_GPORT_IS_SET(gport)) { 279 BCM_IF_ERROR_RETURN 280 (_bcm_esw_gport_resolve(unit, gport, &modid, &port, &tgid, &id)); 281 if (id != -1 || tgid != -1) { 282 return BCM_E_PARAM; 283 } 284 *local_port = port; 285 } else { 286 if (!SOC_PORT_VALID(unit, gport)) { 287 return BCM_E_PORT; 288 } 289 *local_port = gport; 290 } 291 292 return BCM_E_NONE; 293 } 294 295 STATIC int 296 _bcm_ipfix_init(int unit, 297 const _bcm_ipfix_profile_def_t *profile_def, 298 const _bcm_ipfix_id_def_t *id_def) 299 { 300 _bcm_ipfix_ctrl_t *ipfix_ctrl = _bcm_ipfix_ctrl[unit]; 301 const _bcm_ipfix_profile_def_t *def; 302 void *profile; 303 soc_reg_t reg; 304 int stage, ids[2], entry_words[2]; 305 uint32 rval; 306 int size; 307 #ifdef BCM_WARM_BOOT_SUPPORT 308 soc_scache_handle_t scache_handle; 309 uint32 ipfix_scache_size; 310 uint32 flow_rate_tbl_size; 311 uint8 *ipfix_scache = NULL; 312 int rv = BCM_E_NONE; 313 #endif /* !BCM_WARM_BOOT_SUPPORT */ 314 315 if (ipfix_ctrl == NULL) { 316 ipfix_ctrl = sal_alloc(sizeof(_bcm_ipfix_ctrl_t), "IPFIX Control Data"); 317 if (ipfix_ctrl == NULL) { 318 return BCM_E_MEMORY; 319 } 320 sal_memset(ipfix_ctrl, 0, sizeof(_bcm_ipfix_ctrl_t)); 321 322 if (soc_feature(unit, soc_feature_ipfix_rate)) { 323 size = soc_mem_index_count(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm); 324 ipfix_ctrl->rate_used_bmp = 325 sal_alloc(SHR_BITALLOCSIZE(size), "IPFIX Rate Used BMP"); 326 if (ipfix_ctrl->rate_used_bmp == NULL) { 327 sal_free(ipfix_ctrl); 328 return BCM_E_MEMORY; 329 } 330 sal_memset(ipfix_ctrl->rate_used_bmp, 0, SHR_BITALLOCSIZE(size)); 331 SHR_BITSET(ipfix_ctrl->rate_used_bmp, 0); /* index 0 is reserved */ 332 } 333 334 _bcm_ipfix_ctrl[unit] = ipfix_ctrl; 335 336 for (def = profile_def; def->type != _BCM_IPFIX_PROFILE_TYPE_NONE; 337 def++) { 338 for (stage = 0; stage < 2; stage++) { 339 if (!soc_mem_field_valid(unit, id_def->profile[stage], 340 def->index_field)) { 341 continue; 342 } 343 profile = &ipfix_ctrl->profiles[def->stage[stage].profile_id]; 344 if (def->type == _BCM_IPFIX_PROFILE_TYPE_REG) { 345 soc_profile_reg_t_init(profile); 346 } else if (def->type == _BCM_IPFIX_PROFILE_TYPE_MEM) { 347 soc_profile_mem_t_init(profile); 348 } 349 } 350 } 351 352 ipfix_ctrl->pid = SAL_THREAD_ERROR; 353 #ifdef BCM_TRIUMPH3_SUPPORT 354 if (SOC_IS_TRIUMPH3(unit)) { 355 ipfix_ctrl->dma_chan[0] = SOC_MEM_FIFO_DMA_CHANNEL_2; 356 } else 357 #endif /* BCM_TRIUMPH3_SUPPORT */ 358 { 359 ipfix_ctrl->dma_chan[0] = SOC_MEM_FIFO_DMA_CHANNEL_0; 360 } 361 ipfix_ctrl->dma_chan[1] = SOC_MEM_FIFO_DMA_CHANNEL_3; 362 363 #ifdef BCM_WARM_BOOT_SUPPORT 364 if (soc_feature(unit, soc_feature_ipfix_rate)) { 365 /* 366 * Get the number of flow rate meter entries supported in the 367 * ING_IPFIX_FLOW_RATE_METER_TABLEm table. 368 */ 369 flow_rate_tbl_size = 370 soc_mem_index_count(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm); 371 ipfix_scache_size = SHR_BITALLOCSIZE(flow_rate_tbl_size) + 372 sizeof(ipfix_ctrl->rate_used_count); 373 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_IPFIX, 0); 374 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, 375 (0 == SOC_WARM_BOOT(unit)), 376 ipfix_scache_size, 377 &ipfix_scache, 378 BCM_WB_DEFAULT_VERSION, NULL); 379 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 380 _bcm_esw_ipfix_deinit(unit); 381 return rv; 382 } 383 sal_memset(&ipfix_scache, 0, sizeof(ipfix_scache_size)); 384 } 385 #endif /* !BCM_WARM_BOOT_SUPPORT */ 386 } 387 388 for (def = profile_def; def->type != _BCM_IPFIX_PROFILE_TYPE_NONE; def++) { 389 for (stage = 0; stage < 2; stage++) { 390 if (!soc_mem_field_valid(unit, id_def->profile[stage], 391 def->index_field)) { 392 continue; 393 } 394 profile = &ipfix_ctrl->profiles[def->stage[stage].profile_id]; 395 ids[0] = def->stage[stage].reg_mem_id[0]; 396 ids[1] = def->stage[stage].reg_mem_id[1]; 397 if (def->type == _BCM_IPFIX_PROFILE_TYPE_REG) { 398 BCM_IF_ERROR_RETURN(soc_profile_reg_create(unit, ids, 1, 399 profile)); 400 } else if (def->type == _BCM_IPFIX_PROFILE_TYPE_MEM) { 401 entry_words[0] = def->stage[stage].entry_words[0]; 402 entry_words[1] = def->stage[stage].entry_words[1]; 403 BCM_IF_ERROR_RETURN 404 (soc_profile_mem_create(unit, ids, entry_words, 405 ids[1] != INVALIDm ? 2 : 1, 406 profile)); 407 } 408 } 409 } 410 411 for (stage = 0; stage < 2; stage++) { 412 reg = id_def->age_control[stage]; 413 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 414 soc_reg_field_set(unit, reg, &rval, AGE_ENABLEf, 1); 415 if (SAL_BOOT_QUICKTURN) { 416 if (soc_reg_field_valid(unit, reg, CLK_GRANf)) { 417 soc_reg_field_set(unit, reg, &rval, CLK_GRANf, 0); 418 } 419 } 420 BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 421 } 422 423 #ifdef BCM_TRIUMPH3_SUPPORT 424 if (SOC_IS_TRIUMPH3(unit)) { 425 BCM_IF_ERROR_RETURN(READ_AUX_ARB_CONTROL_2r(unit, &rval)); 426 soc_reg_field_set(unit, AUX_ARB_CONTROL_2r, &rval, 427 IPFIX_REFRESH_ENABLEf, 1); 428 if (SAL_BOOT_QUICKTURN) { 429 soc_reg_field_set(unit, AUX_ARB_CONTROL_2r, 430 &rval, IPFIX_CLK_GRANf, 0); 431 } 432 BCM_IF_ERROR_RETURN(WRITE_AUX_ARB_CONTROL_2r(unit, rval)); 433 } 434 #endif 435 436 #if defined(BCM_WARM_BOOT_SUPPORT) && defined(BCM_IPFIX_SUPPORT) 437 if (SOC_WARM_BOOT(unit)) { 438 /* 439 * Reload IPFIX module data. 440 */ 441 BCM_IF_ERROR_RETURN(_bcm_ipfix_reinit(unit)); 442 } 443 #endif /* !BCM_WARM_BOOT_SUPPORT */ 444 return BCM_E_NONE; 445 } 446 447 STATIC int 448 _bcm_ipfix_profile_del(int unit, 449 const _bcm_ipfix_profile_def_t *profile_def, 450 const _bcm_ipfix_id_def_t *id_def, 451 bcm_ipfix_stage_t stage, 452 bcm_port_t port, 453 int count) 454 { 455 _bcm_ipfix_ctrl_t *ipfix_ctrl; 456 const _bcm_ipfix_profile_def_t *def; 457 void *profile; 458 union { 459 ing_ipfix_profile_entry_t ing_ipfix_profile; 460 egr_ipfix_profile_entry_t egr_ipfix_profile; 461 } profile_entry; 462 soc_mem_t profile_mem; 463 uint32 index; 464 int rv; 465 466 ipfix_ctrl = _bcm_ipfix_ctrl[unit]; 467 profile_mem = id_def->profile[stage]; 468 469 BCM_IF_ERROR_RETURN(soc_mem_read(unit, profile_mem, MEM_BLOCK_ANY, 470 port, &profile_entry)); 471 rv = BCM_E_NONE; 472 for (def = profile_def; count && def->type != _BCM_IPFIX_PROFILE_TYPE_NONE; 473 count--, def++) { 474 if (!soc_mem_field_valid(unit, profile_mem, def->index_field)) { 475 continue; 476 } 477 profile = &ipfix_ctrl->profiles[def->stage[stage].profile_id]; 478 index = soc_mem_field32_get(unit, profile_mem, &profile_entry, 479 def->index_field); 480 if (def->type == _BCM_IPFIX_PROFILE_TYPE_REG) { 481 rv |= soc_profile_reg_delete(unit, profile, index); 482 } else if (def->type == _BCM_IPFIX_PROFILE_TYPE_MEM) { 483 if (def->stage[stage].reg_mem_id[0] == 484 ING_IPFIX_DSCP_XLATE_TABLEm || 485 def->stage[stage].reg_mem_id[0] == 486 EGR_IPFIX_DSCP_XLATE_TABLEm) { 487 index *= 64; 488 } 489 rv |= soc_profile_mem_delete(unit, profile, index); 490 } 491 } 492 493 return rv; 494 } 495 496 /* 497 * Function: 498 * _bcm_ipfix_rate_id_check 499 * Description: 500 * To check the status of the specified rate_id 501 * Parameters: 502 * unit device number 503 * rate_id rate identifier 504 * Return: 505 * BCM_E_UNAVAIL ipfix feature is not supported for this device 506 * BCM_E_INIT ipfix component is not initialized on this device 507 * BCM_E_BADID specified rate_id is not in valid range 508 * BCM_E_NOT_FOUND spefified rate_id is in valid range but not in used 509 * BCM_E_NONE specified rate_id is in used 510 */ 511 STATIC int 512 _bcm_ipfix_rate_id_check(int unit, 513 bcm_ipfix_rate_id_t rate_id) 514 { 515 if (!soc_feature(unit, soc_feature_ipfix_rate)) { 516 return BCM_E_UNAVAIL; 517 } 518 519 if (_bcm_ipfix_ctrl[unit] == NULL) { 520 return BCM_E_INIT; 521 } 522 523 /* rate_id 0 is reserved by hardware to indicate disabling rate metering */ 524 if (rate_id < 1 || rate_id >= 525 soc_mem_index_count(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm)) { 526 return BCM_E_BADID; 527 } 528 529 if (!SHR_BITGET(_bcm_ipfix_ctrl[unit]->rate_used_bmp, rate_id)) { 530 return BCM_E_NOT_FOUND; 531 } 532 533 return BCM_E_NONE; 534 } 535 536 /* 537 * Function: 538 * _bcm_ipfix_rate_get 539 * Description: 540 * To check the status of the specified rate_id 541 * Parameters: 542 * unit device number 543 * rate_id rate identifier 544 * rate_info pointer to rate info structure 545 * Return: 546 * BCM_E_XXX 547 * Note: 548 * Caller needs to make sure all arguments are valid for this internal 549 * function. 550 */ 551 STATIC int 552 _bcm_ipfix_rate_get(int unit, 553 bcm_ipfix_rate_id_t rate_id, 554 bcm_ipfix_rate_t *rate_info) 555 { 556 ing_ipfix_flow_rate_meter_table_entry_t entry; 557 uint32 cng; 558 559 BCM_IF_ERROR_RETURN(soc_mem_read(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, 560 MEM_BLOCK_ANY, rate_id, &entry)); 561 562 sal_memset(rate_info, 0, sizeof(*rate_info)); 563 rate_info->rate_id = rate_id; 564 rate_info->flags |= BCM_IPFIX_RATE_VIOLATION_WITH_ID; 565 /* the token size for BUCKETCOUNT is 1/128 of a flow */ 566 rate_info->count = 567 soc_mem_field32_get(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry, 568 BUCKETCOUNTf) >> 7; 569 rate_info->limit = 570 soc_mem_field32_get(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry, 571 BUCKETSIZEf); 572 rate_info->rate = 573 soc_mem_field32_get(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry, 574 REFRESHCOUNTf); 575 if (soc_mem_field32_get(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry, 576 DROPf)) { 577 rate_info->flags |= BCM_IPFIX_RATE_VIOLATION_DROP; 578 } 579 if (soc_mem_field32_get(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry, 580 COPY_TO_CPUf)) { 581 rate_info->flags |= BCM_IPFIX_RATE_VIOLATION_COPY_TO_CPU; 582 } 583 if (soc_mem_field32_get(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry, 584 CHANGE_DSCPf)) { 585 rate_info->flags |= BCM_IPFIX_RATE_VIOLATION_DSCP_SET; 586 rate_info->dscp = 587 soc_mem_field32_get(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry, 588 NEW_DSCPf); 589 } 590 if (soc_mem_field32_get(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry, 591 CHANGE_CNGf)) { 592 rate_info->flags |= BCM_IPFIX_RATE_VIOLATION_COLOR_SET; 593 cng = soc_mem_field32_get(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, 594 &entry, NEW_CNGf); 595 rate_info->color = _BCM_COLOR_DECODING(unit, cng); 596 } 597 if (soc_mem_field32_get(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry, 598 CHANGE_PKT_PRIf)) { 599 rate_info->flags |= BCM_IPFIX_RATE_VIOLATION_PKT_PRI_SET; 600 rate_info->pkt_pri = 601 soc_mem_field32_get(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry, 602 NEW_PRIf); 603 } 604 if (soc_mem_field32_get(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry, 605 CHANGE_INT_PRIf)) { 606 rate_info->flags |= BCM_IPFIX_RATE_VIOLATION_INT_PRI_SET; 607 rate_info->int_pri = 608 soc_mem_field32_get(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry, 609 NEW_INT_PRIf); 610 } 611 612 return BCM_E_NONE; 613 } 614 #endif /* BCM_IPFIX_SUPPORT */ 615 616 /* 617 * Function: 618 * bcm_esw_ipfix_register 619 * Description: 620 * To register the callback function for flow info export 621 * Parameters: 622 * unit device number 623 * callback user callback function 624 * userdata user data used as argument during callback 625 * Return: 626 * BCM_E_NONE 627 * BCM_E_PARAM 628 * BCM_E_RESOURCE 629 * BCM_E_UNAVAIL 630 */ 631 int 632 bcm_esw_ipfix_register(int unit, 633 bcm_ipfix_callback_t callback, 634 void *userdata) 635 { 636 #ifdef BCM_IPFIX_SUPPORT 637 _bcm_ipfix_ctrl_t *ipfix_ctrl; 638 const _bcm_ipfix_profile_def_t *profile_def = NULL; 639 const _bcm_ipfix_id_def_t *id_def = NULL; 640 _bcm_ipfix_callback_entry_t *entry; 641 int free_index, i; 642 643 if (!soc_feature(unit, soc_feature_ipfix)) { 644 return BCM_E_UNAVAIL; 645 } 646 647 #ifdef BCM_TRIUMPH_SUPPORT 648 if (SOC_IS_TR_VL(unit)) { 649 profile_def = _ipfix_tr_profile_def; 650 id_def = &_ipfix_tr_id_def; 651 } 652 #endif /* BCM_TRIUMPH_SUPPORT */ 653 if (profile_def == NULL || id_def == NULL) { 654 return BCM_E_INTERNAL; 655 } 656 657 if (_bcm_ipfix_ctrl[unit] == NULL) { 658 BCM_IF_ERROR_RETURN(_bcm_ipfix_init(unit, profile_def, id_def)); 659 } 660 ipfix_ctrl = _bcm_ipfix_ctrl[unit]; 661 662 if (callback == NULL) { 663 return BCM_E_PARAM; 664 } 665 666 free_index = -1; 667 for (i = 0; i < _BCM_IPFIX_CB_MAX; i++) { 668 entry = &ipfix_ctrl->callback_entry[i]; 669 if (entry->state == _BCM_IPFIX_CALLBACK_STATE_INVALID || 670 (ipfix_ctrl->pid == SAL_THREAD_ERROR && 671 entry->state == _BCM_IPFIX_CALLBACK_STATE_UNREGISTERED)) { 672 if (free_index < 0) { 673 free_index = i; 674 } 675 } else if (entry->state == _BCM_IPFIX_CALLBACK_STATE_ACTIVE || 676 entry->state == _BCM_IPFIX_CALLBACK_STATE_REGISTERED) { 677 if (entry->callback == callback && entry->userdata == userdata) { 678 return BCM_E_NONE; 679 } 680 } 681 } 682 683 if (free_index < 0) { 684 return BCM_E_RESOURCE; 685 } 686 687 entry = &ipfix_ctrl->callback_entry[free_index]; 688 entry->callback = callback; 689 entry->userdata = userdata; 690 entry->state = _BCM_IPFIX_CALLBACK_STATE_REGISTERED; 691 692 return BCM_E_NONE; 693 #else /* BCM_IPFIX_SUPPORT */ 694 return BCM_E_UNAVAIL; 695 #endif /* BCM_IPFIX_SUPPORT */ 696 } 697 698 /* 699 * Function: 700 * bcm_esw_ipfix_unregister 701 * Description: 702 * To unregister the callback function for flow info export 703 * Parameters: 704 * unit device number 705 * callback user callback function 706 * userdata user data used as argument during callback 707 * Return: 708 * BCM_E_NONE 709 * BCM_E_NOT_FOUND 710 * BCM_E_UNAVAIL 711 * BCM_E_INIT 712 */ 713 int 714 bcm_esw_ipfix_unregister(int unit, 715 bcm_ipfix_callback_t callback, 716 void *userdata) 717 { 718 #ifdef BCM_IPFIX_SUPPORT 719 _bcm_ipfix_ctrl_t *ipfix_ctrl; 720 _bcm_ipfix_callback_entry_t *entry; 721 int i; 722 723 if (!soc_feature(unit, soc_feature_ipfix)) { 724 return BCM_E_UNAVAIL; 725 } 726 727 if (_bcm_ipfix_ctrl[unit] == NULL) { 728 return BCM_E_INIT; 729 } 730 ipfix_ctrl = _bcm_ipfix_ctrl[unit]; 731 732 for (i = 0; i < _BCM_IPFIX_CB_MAX; i++) { 733 entry = &ipfix_ctrl->callback_entry[i]; 734 735 if (ipfix_ctrl->pid == SAL_THREAD_ERROR || 736 entry->state == _BCM_IPFIX_CALLBACK_STATE_ACTIVE) { 737 if (entry->callback == callback && entry->userdata == userdata) { 738 entry->state = _BCM_IPFIX_CALLBACK_STATE_UNREGISTERED; 739 return BCM_E_NONE; 740 } 741 } 742 } 743 744 return BCM_E_NOT_FOUND; 745 #else /* BCM_IPFIX_SUPPORT */ 746 return BCM_E_UNAVAIL; 747 #endif /* BCM_IPFIX_SUPPORT */ 748 } 749 750 /* 751 * Function: 752 * bcm_esw_ipfix_config_set 753 * Description: 754 * To set per port IPFIX configuration 755 * Parameters: 756 * unit device number 757 * stage BCM_IPFIX_STAGE_INGRESS or BCM_IPFIX_STAGE_EGRESS 758 * port port number 759 * config pointer to ipfix configuration 760 * Return: 761 * BCM_E_NONE 762 * BCM_E_PARAM 763 * BCM_E_RESOURCE 764 * BCM_E_UNAVAIL 765 * BCM_E_PORT 766 */ 767 int 768 bcm_esw_ipfix_config_set(int unit, 769 bcm_ipfix_stage_t stage, 770 bcm_port_t port, 771 bcm_ipfix_config_t *config) 772 { 773 #ifdef BCM_IPFIX_SUPPORT 774 _bcm_ipfix_ctrl_t *ipfix_ctrl; 775 const _bcm_ipfix_profile_def_t *profile_def = NULL, *def; 776 const _bcm_ipfix_id_def_t *id_def = NULL; 777 const _bcm_ipfix_flags_def_t *flags_def = NULL; 778 void *profile; 779 union { 780 ing_ipfix_profile_entry_t ing_ipfix_profile; 781 egr_ipfix_profile_entry_t egr_ipfix_profile; 782 } profile_entry; 783 union { 784 ing_ipfix_ipv4_mask_set_a_entry_t ing_ipfix_ipv4_mask_set_a; 785 ing_ipfix_ipv4_mask_set_b_entry_t ing_ipfix_ipv4_mask_set_b; 786 ing_ipfix_ipv6_mask_set_a_entry_t ing_ipfix_ipv6_mask_set_a; 787 ing_ipfix_ipv6_mask_set_b_entry_t ing_ipfix_ipv6_mask_set_b; 788 egr_ipfix_ipv4_mask_set_a_entry_t egr_ipfix_ipv4_mask_set_a; 789 egr_ipfix_ipv6_mask_set_a_entry_t egr_ipfix_ipv6_mask_set_a; 790 ing_ipfix_dscp_xlate_table_entry_t ing_ipfix_dscp_xlate_table[64]; 791 egr_ipfix_dscp_xlate_table_entry_t egr_ipfix_dscp_xlate_table[64]; 792 uint32 w[1]; 793 } entry0, entry1; 794 void *entries[2]; 795 uint64 rval64, *rval64s[2]; 796 soc_reg_t reg; 797 soc_mem_t mems[2], profile_mem; 798 uint32 rval, fval, index, flags; 799 int rv, count, size, i; 800 801 if (!soc_feature(unit, soc_feature_ipfix)) { 802 return BCM_E_UNAVAIL; 803 } 804 805 #ifdef BCM_TRIUMPH_SUPPORT 806 if (SOC_IS_TR_VL(unit)) { 807 profile_def = _ipfix_tr_profile_def; 808 id_def = &_ipfix_tr_id_def; 809 flags_def = _ipfix_tr_port_config_flags_def; 810 } 811 #endif /* BCM_TRIUMPH_SUPPORT */ 812 if (profile_def == NULL || id_def == NULL || flags_def == NULL) { 813 return BCM_E_INTERNAL; 814 } 815 816 if (_bcm_ipfix_ctrl[unit] == NULL) { 817 BCM_IF_ERROR_RETURN(_bcm_ipfix_init(unit, profile_def, id_def)); 818 } 819 ipfix_ctrl = _bcm_ipfix_ctrl[unit]; 820 821 if (stage != BCM_IPFIX_STAGE_INGRESS && stage != BCM_IPFIX_STAGE_EGRESS) { 822 return BCM_E_PARAM; 823 } 824 825 BCM_IF_ERROR_RETURN(_bcm_ipfix_gport_resolve(unit, port, &port)); 826 827 if (config == NULL) { 828 return BCM_E_PARAM; 829 } 830 831 profile_mem = id_def->profile[stage]; 832 833 reg = id_def->port_config[stage]; 834 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, &rval)); 835 836 /* Remove all previously programmed profile for the port */ 837 if (soc_reg_field_get(unit, reg, rval, IPFIX_ENABLEf)) { 838 soc_reg_field_set(unit, reg, &rval, IPFIX_ENABLEf, 0); 839 BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, rval)); 840 841 BCM_IF_ERROR_RETURN(_bcm_ipfix_profile_del(unit, profile_def, id_def, 842 stage, port, -1)); 843 } 844 845 /* Profile */ 846 sal_memset(&profile_entry, 0, sizeof(profile_entry)); 847 for (count = 0, def = profile_def; 848 def->type != _BCM_IPFIX_PROFILE_TYPE_NONE; count++, def++) { 849 if (!soc_mem_field_valid(unit, profile_mem, def->index_field)) { 850 continue; 851 } 852 profile = &ipfix_ctrl->profiles[def->stage[stage].profile_id]; 853 rv = BCM_E_NONE; 854 if (def->type == _BCM_IPFIX_PROFILE_TYPE_REG) { 855 reg = def->stage[stage].reg_mem_id[0]; 856 rval = 0; 857 switch (reg) { 858 case ING_IPFIX_PORT_RECORD_LIMIT_SETr: 859 case EGR_IPFIX_PORT_RECORD_LIMIT_SETr: 860 soc_reg_field_set(unit, reg, &rval, ENTRY_LIMITf, 861 config->entry_limit); 862 break; 863 case ING_IPFIX_MINIMUM_LIVE_TIME_SETr: 864 case EGR_IPFIX_MINIMUM_LIVE_TIME_SETr: 865 soc_reg_field_set(unit, reg, &rval, MIN_RECORD_LIFEf, 866 config->min_time); 867 break; 868 case ING_IPFIX_MAXIMUM_LIVE_TIME_SETr: 869 case EGR_IPFIX_MAXIMUM_LIVE_TIME_SETr: 870 soc_reg_field_set(unit, reg, &rval, MAX_RECORD_LIFEf, 871 config->max_time); 872 break; 873 case ING_IPFIX_MAXIMUM_IDLE_AGE_SETr: 874 case EGR_IPFIX_MAXIMUM_IDLE_AGE_SETr: 875 soc_reg_field_set(unit, reg, &rval, MAX_IDLE_AGEf, 876 config->max_idle_time); 877 break; 878 case ING_IPFIX_SAMPLING_LIMIT_SETr: 879 case EGR_IPFIX_SAMPLING_LIMIT_SETr: 880 soc_reg_field_set(unit, reg, &rval, SAMPLING_LIMITf, 881 config->sample_rate); 882 break; 883 default: 884 continue; 885 } 886 COMPILER_64_SET(rval64, 0, rval); 887 rval64s[0] = &rval64; 888 rv = soc_profile_reg_add(unit, profile, rval64s, 1, &index); 889 } else if (def->type == _BCM_IPFIX_PROFILE_TYPE_MEM) { 890 mems[0] = def->stage[stage].reg_mem_id[0]; 891 mems[1] = def->stage[stage].reg_mem_id[1]; 892 size = 1; 893 switch (mems[0]) { 894 case ING_IPFIX_DSCP_XLATE_TABLEm: 895 sal_memset(&entry0, 0, sizeof(entry0)); 896 size = BCM_IPFIX_DSCP_MASK_COUNT; 897 for (i = 0; i < size; i++) { 898 soc_mem_field32_set(unit, mems[0], 899 &entry0.ing_ipfix_dscp_xlate_table[i], 900 DSCP_KEYf, config->dscp_mask[i]); 901 } 902 break; 903 case EGR_IPFIX_DSCP_XLATE_TABLEm: 904 sal_memset(&entry0, 0, sizeof(entry0)); 905 size = BCM_IPFIX_DSCP_MASK_COUNT; 906 for (i = 0; i < size; i++) { 907 soc_mem_field32_set(unit, mems[0], 908 &entry0.egr_ipfix_dscp_xlate_table[i], 909 DSCP_KEYf, config->dscp_mask[i]); 910 } 911 break; 912 case ING_IPFIX_IPV4_MASK_SET_Am: 913 case EGR_IPFIX_IPV4_MASK_SET_Am: 914 sal_memset(&entry0, 0, sizeof(entry0)); 915 soc_mem_field_set(unit, mems[0], entry0.w, IPV4_SIP_MASKf, 916 (uint32 *)&config->src_ip4_mask); 917 soc_mem_field_set(unit, mems[0], entry0.w, IPV4_DIP_MASKf, 918 (uint32 *)&config->dst_ip4_mask); 919 if (mems[1] != INVALIDm) { 920 sal_memset(&entry1, 0, sizeof(entry1)); 921 soc_mem_field_set(unit, mems[1], entry1.w, 922 TUNNEL_IPV4_SIP_MASKf, 923 (uint32 *)&config->tunnel_src_ip4_mask); 924 soc_mem_field_set(unit, mems[1], entry1.w, 925 TUNNEL_IPV4_DIP_MASKf, 926 (uint32 *)&config->tunnel_dst_ip4_mask); 927 } 928 break; 929 case ING_IPFIX_IPV6_MASK_SET_Am: 930 case EGR_IPFIX_IPV6_MASK_SET_Am: 931 soc_mem_field_set(unit, mems[0], entry0.w, IPV6_SIP_MASKf, 932 (uint32 *)&config->src_ip6_mask); 933 soc_mem_field_set(unit, mems[0], entry0.w, IPV6_DIP_MASKf, 934 (uint32 *)&config->dst_ip6_mask); 935 if (mems[1] != INVALIDm) { 936 sal_memset(&entry1, 0, sizeof(entry1)); 937 soc_mem_field_set(unit, mems[1], entry1.w, 938 TUNNEL_IPV6_SIP_MASKf, 939 (uint32 *)&config->tunnel_src_ip6_mask); 940 soc_mem_field_set(unit, mems[1], entry1.w, 941 TUNNEL_IPV6_DIP_MASKf, 942 (uint32 *)&config->tunnel_dst_ip6_mask); 943 } 944 break; 945 default: 946 continue; 947 } 948 entries[0] = &entry0; 949 entries[1] = &entry1; 950 rv = soc_profile_mem_add(unit, profile, entries, size, &index); 951 index /= size; 952 } 953 if (SOC_FAILURE(rv)) { 954 BCM_IF_ERROR_RETURN(_bcm_ipfix_profile_del(unit, profile_def, 955 id_def, stage, port, 956 count)); 957 return rv; 958 } 959 soc_mem_field32_set(unit, profile_mem, &profile_entry, 960 def->index_field, index); 961 } 962 BCM_IF_ERROR_RETURN 963 (soc_mem_write(unit, profile_mem, MEM_BLOCK_ANY, port, 964 &profile_entry)); 965 966 /* Port config register */ 967 reg = id_def->port_config[stage]; 968 flags = config->flags; 969 rval = 0; 970 for (i = 0; flags_def[i].bit_mask; i++) { 971 if (flags & flags_def[i].bit_mask) { 972 soc_reg_field_set(unit, reg, &rval, flags_def[i].field, 1); 973 } 974 } 975 fval = (flags & BCM_IPFIX_CONFIG_ENABLE_IP4 ? 1 : 0) | 976 (flags & BCM_IPFIX_CONFIG_ENABLE_IP6 ? 2 : 0) | 977 (flags & BCM_IPFIX_CONFIG_ENABLE_NON_IP ? 4 : 0); 978 soc_reg_field_set(unit, reg, &rval, IPFIX_ENABLEf, fval); 979 fval = (flags & BCM_IPFIX_CONFIG_KEY_IP4_USE_L2 ? 0 : 1) | 980 (flags & BCM_IPFIX_CONFIG_KEY_IP6_USE_L2 ? 0 : 2); 981 soc_reg_field_set(unit, reg, &rval, IPFIX_KEY_SELECTf, fval); 982 if (config->sample_rate > 1) { 983 soc_reg_field_set(unit, reg, &rval, IPFIX_SAMPLE_MODEf, 1); 984 } 985 986 if (flags & (BCM_IPFIX_CONFIG_RECORD_DISCARD_PKT | 987 BCM_IPFIX_CONFIG_RECORD_NON_DISCARD_PKT)) { 988 /* Record all packets */ 989 fval = 1; 990 } else if (flags & BCM_IPFIX_CONFIG_RECORD_DISCARD_PKT) { 991 /* Record only discarded packets */ 992 fval = 2; 993 } else if (flags & BCM_IPFIX_CONFIG_RECORD_NON_DISCARD_PKT) { 994 /* Record only non-discarded packets */ 995 fval = 0; 996 } else { 997 /* Don't Record any packets */ 998 fval = 3; 999 } 1000 1001 soc_reg_field_set(unit, reg, &rval, DISCARDED_FLOWS_MODEf, fval); 1002 if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 1003 SOC_IS_VALKYRIE2(unit)|| SOC_IS_TRIUMPH3(unit)) { 1004 if (flags & BCM_IPFIX_CONFIG_KEY_SOURCE_PORT_OR_INTERFACE) { 1005 soc_reg_field_set(unit, reg, &rval, IP_IPFIX_INTF_ENABLEf, 1); 1006 } 1007 if (flags & BCM_IPFIX_CONFIG_TCP_FLAGS_LAST) { 1008 soc_reg_field_set(unit, reg, &rval, TCP_FLAG_MODEf, 1); 1009 } 1010 } 1011 BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, rval)); 1012 1013 return BCM_E_NONE; 1014 #else /* BCM_IPFIX_SUPPORT */ 1015 return BCM_E_UNAVAIL; 1016 #endif /* BCM_IPFIX_SUPPORT */ 1017 } 1018 1019 /* 1020 * Function: 1021 * bcm_esw_ipfix_config_get 1022 * Description: 1023 * To get per port IPFIX configuration 1024 * Parameters: 1025 * unit device number 1026 * stage BCM_IPFIX_STAGE_INGRESS or BCM_IPFIX_STAGE_EGRESS 1027 * port port number 1028 * config pointer to ipfix configuration 1029 * Return: 1030 * BCM_E_NONE 1031 * BCM_E_PARAM 1032 * BCM_E_UNAVAIL 1033 * BCM_E_INIT 1034 * BCM_E_PORT 1035 */ 1036 int 1037 bcm_esw_ipfix_config_get(int unit, 1038 bcm_ipfix_stage_t stage, 1039 bcm_port_t port, 1040 bcm_ipfix_config_t *config) 1041 { 1042 #ifdef BCM_IPFIX_SUPPORT 1043 const _bcm_ipfix_profile_def_t *profile_def = NULL, *def; 1044 const _bcm_ipfix_id_def_t *id_def = NULL; 1045 const _bcm_ipfix_flags_def_t *flags_def = NULL; 1046 union { 1047 ing_ipfix_profile_entry_t ing_ipfix_profile; 1048 egr_ipfix_profile_entry_t egr_ipfix_profile; 1049 } profile_entry; 1050 union { 1051 ing_ipfix_dscp_xlate_table_entry_t ing_ipfix_dscp_xlate_table; 1052 ing_ipfix_ipv4_mask_set_a_entry_t ing_ipfix_ipv4_mask_set_a; 1053 ing_ipfix_ipv4_mask_set_b_entry_t ing_ipfix_ipv4_mask_set_b; 1054 ing_ipfix_ipv6_mask_set_a_entry_t ing_ipfix_ipv6_mask_set_a; 1055 ing_ipfix_ipv6_mask_set_b_entry_t ing_ipfix_ipv6_mask_set_b; 1056 egr_ipfix_dscp_xlate_table_entry_t egr_ipfix_dscp_xlate_table; 1057 egr_ipfix_ipv4_mask_set_a_entry_t egr_ipfix_ipv4_mask_set_a; 1058 egr_ipfix_ipv6_mask_set_a_entry_t egr_ipfix_ipv6_mask_set_a; 1059 uint32 w[1]; 1060 } entry; 1061 soc_reg_t reg; 1062 soc_mem_t mems[2], profile_mem; 1063 uint32 rval, fval, index, flags; 1064 int i; 1065 1066 if (!soc_feature(unit, soc_feature_ipfix)) { 1067 return BCM_E_UNAVAIL; 1068 } 1069 1070 #ifdef BCM_TRIUMPH_SUPPORT 1071 if (SOC_IS_TR_VL(unit)) { 1072 profile_def = _ipfix_tr_profile_def; 1073 id_def = &_ipfix_tr_id_def; 1074 flags_def = _ipfix_tr_port_config_flags_def; 1075 } 1076 #endif /* BCM_TRIUMPH_SUPPORT */ 1077 if (profile_def == NULL || id_def == NULL || flags_def == NULL) { 1078 return BCM_E_INTERNAL; 1079 } 1080 1081 if (_bcm_ipfix_ctrl[unit] == NULL) { 1082 return BCM_E_INIT; 1083 } 1084 1085 if ((stage != BCM_IPFIX_STAGE_INGRESS && stage != BCM_IPFIX_STAGE_EGRESS) 1086 || config == NULL) { 1087 return BCM_E_PARAM; 1088 } 1089 1090 BCM_IF_ERROR_RETURN(_bcm_ipfix_gport_resolve(unit, port, &port)); 1091 1092 profile_mem = id_def->profile[stage]; 1093 1094 /* Profile */ 1095 BCM_IF_ERROR_RETURN 1096 (soc_mem_read(unit, profile_mem, MEM_BLOCK_ANY, port, &profile_entry)); 1097 for (def = profile_def; def->type != _BCM_IPFIX_PROFILE_TYPE_NONE; def++) { 1098 if (!soc_mem_field_valid(unit, profile_mem, def->index_field)) { 1099 continue; 1100 } 1101 index = soc_mem_field32_get(unit, profile_mem, &profile_entry, 1102 def->index_field); 1103 if (def->type == _BCM_IPFIX_PROFILE_TYPE_REG) { 1104 reg = def->stage[stage].reg_mem_id[0]; 1105 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, index, &rval)); 1106 switch (reg) { 1107 case ING_IPFIX_PORT_RECORD_LIMIT_SETr: 1108 case EGR_IPFIX_PORT_RECORD_LIMIT_SETr: 1109 config->entry_limit = soc_reg_field_get(unit, reg, rval, 1110 ENTRY_LIMITf); 1111 break; 1112 case ING_IPFIX_MINIMUM_LIVE_TIME_SETr: 1113 case EGR_IPFIX_MINIMUM_LIVE_TIME_SETr: 1114 config->min_time = soc_reg_field_get(unit, reg, rval, 1115 MIN_RECORD_LIFEf); 1116 break; 1117 case ING_IPFIX_MAXIMUM_LIVE_TIME_SETr: 1118 case EGR_IPFIX_MAXIMUM_LIVE_TIME_SETr: 1119 config->max_time = soc_reg_field_get(unit, reg, rval, 1120 MAX_RECORD_LIFEf); 1121 break; 1122 case ING_IPFIX_MAXIMUM_IDLE_AGE_SETr: 1123 case EGR_IPFIX_MAXIMUM_IDLE_AGE_SETr: 1124 config->max_idle_time = soc_reg_field_get(unit, reg, rval, 1125 MAX_IDLE_AGEf); 1126 break; 1127 case ING_IPFIX_SAMPLING_LIMIT_SETr: 1128 case EGR_IPFIX_SAMPLING_LIMIT_SETr: 1129 config->sample_rate = soc_reg_field_get(unit, reg, rval, 1130 SAMPLING_LIMITf); 1131 break; 1132 default: 1133 continue; 1134 } 1135 } else if (def->type == _BCM_IPFIX_PROFILE_TYPE_MEM) { 1136 mems[0] = def->stage[stage].reg_mem_id[0]; 1137 mems[1] = def->stage[stage].reg_mem_id[1]; 1138 switch (mems[0]) { 1139 case ING_IPFIX_DSCP_XLATE_TABLEm: 1140 case EGR_IPFIX_DSCP_XLATE_TABLEm: 1141 for (i = 0; i < BCM_IPFIX_DSCP_MASK_COUNT; i++) { 1142 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mems[0], 1143 MEM_BLOCK_ANY, index * 64 + i, 1144 &entry)); 1145 config->dscp_mask[i] = 1146 soc_mem_field32_get(unit, mems[0], entry.w, DSCP_KEYf); 1147 } 1148 break; 1149 case ING_IPFIX_IPV4_MASK_SET_Am: 1150 case EGR_IPFIX_IPV4_MASK_SET_Am: 1151 BCM_IF_ERROR_RETURN 1152 (soc_mem_read(unit, mems[0], MEM_BLOCK_ANY, index, 1153 &entry)); 1154 soc_mem_field_get(unit, mems[0], entry.w, IPV4_SIP_MASKf, 1155 (uint32 *)&config->src_ip4_mask); 1156 soc_mem_field_get(unit, mems[0], entry.w, IPV4_DIP_MASKf, 1157 (uint32 *)&config->dst_ip4_mask); 1158 if (mems[1] != INVALIDm) { 1159 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mems[1], 1160 MEM_BLOCK_ANY, index, 1161 &entry)); 1162 soc_mem_field_get(unit, mems[1], entry.w, 1163 TUNNEL_IPV4_SIP_MASKf, 1164 (uint32 *)&config->tunnel_src_ip4_mask); 1165 soc_mem_field_get(unit, mems[1], entry.w, 1166 TUNNEL_IPV4_DIP_MASKf, 1167 (uint32 *)&config->tunnel_dst_ip4_mask); 1168 } 1169 break; 1170 case ING_IPFIX_IPV6_MASK_SET_Am: 1171 case EGR_IPFIX_IPV6_MASK_SET_Am: 1172 BCM_IF_ERROR_RETURN 1173 (soc_mem_read(unit, mems[0], MEM_BLOCK_ANY, index, 1174 &entry)); 1175 soc_mem_field_get(unit, mems[0], entry.w, IPV6_SIP_MASKf, 1176 (uint32 *)&config->src_ip6_mask); 1177 soc_mem_field_get(unit, mems[0], entry.w, IPV6_DIP_MASKf, 1178 (uint32 *)&config->dst_ip6_mask); 1179 if (mems[1] != INVALIDm) { 1180 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mems[1], 1181 MEM_BLOCK_ANY, index, 1182 &entry)); 1183 soc_mem_field_get(unit, mems[1], entry.w, 1184 TUNNEL_IPV6_SIP_MASKf, 1185 (uint32 *)&config->tunnel_src_ip6_mask); 1186 soc_mem_field_get(unit, mems[1], entry.w, 1187 TUNNEL_IPV6_DIP_MASKf, 1188 (uint32 *)&config->tunnel_dst_ip6_mask); 1189 } 1190 break; 1191 default: 1192 continue; 1193 } 1194 } 1195 } 1196 1197 /* Port config register */ 1198 reg = id_def->port_config[stage]; 1199 flags = 0; 1200 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, &rval)); 1201 for (i = 0; flags_def[i].bit_mask; i++) { 1202 if (soc_reg_field_get(unit, reg, rval, flags_def[i].field)) { 1203 flags |= flags_def[i].bit_mask; 1204 } 1205 } 1206 fval = soc_reg_field_get(unit, reg, rval, IPFIX_ENABLEf); 1207 flags |= ((fval & 1 ? BCM_IPFIX_CONFIG_ENABLE_IP4 : 0) | 1208 (fval & 2 ? BCM_IPFIX_CONFIG_ENABLE_IP6 : 0) | 1209 (fval & 4 ? BCM_IPFIX_CONFIG_ENABLE_NON_IP : 0)); 1210 fval = soc_reg_field_get(unit, reg, rval, IPFIX_KEY_SELECTf); 1211 flags |= ((fval & 1 ? 0 : BCM_IPFIX_CONFIG_KEY_IP4_USE_L2) | 1212 (fval & 2 ? 0 : BCM_IPFIX_CONFIG_KEY_IP6_USE_L2)); 1213 fval = soc_reg_field_get(unit, reg, rval, IPFIX_SAMPLE_MODEf); 1214 if (!fval) { 1215 config->sample_rate = 0; 1216 } 1217 fval = soc_reg_field_get(unit, reg, rval, DISCARDED_FLOWS_MODEf); 1218 if (fval == 0) { 1219 flags |= BCM_IPFIX_CONFIG_RECORD_NON_DISCARD_PKT; 1220 } else if (fval == 1) { 1221 flags |= (BCM_IPFIX_CONFIG_RECORD_NON_DISCARD_PKT | 1222 BCM_IPFIX_CONFIG_RECORD_DISCARD_PKT); 1223 } else if (fval == 2) { 1224 flags |= BCM_IPFIX_CONFIG_RECORD_DISCARD_PKT; 1225 } 1226 config->flags = flags; 1227 1228 return BCM_E_NONE; 1229 #else /* BCM_IPFIX_SUPPORT */ 1230 return BCM_E_UNAVAIL; 1231 #endif /* BCM_IPFIX_SUPPORT */ 1232 } 1233 1234 /* 1235 * Function: 1236 * bcm_esw_ipfix_rate_create 1237 * Description: 1238 * Add an IPFIX flow rate meter entry 1239 * Parameters: 1240 * unit device number 1241 * rate_info pointer to rate information 1242 * Return: 1243 * BCM_E_NONE 1244 * BCM_E_PARAM 1245 * BCM_E_RESOURCE 1246 * BCM_E_UNAVAIL 1247 */ 1248 int 1249 bcm_esw_ipfix_rate_create(int unit, 1250 bcm_ipfix_rate_t *rate_info) 1251 { 1252 #ifdef BCM_IPFIX_SUPPORT 1253 _bcm_ipfix_ctrl_t *ipfix_ctrl; 1254 const _bcm_ipfix_profile_def_t *profile_def = NULL; 1255 const _bcm_ipfix_id_def_t *id_def = NULL; 1256 ing_ipfix_flow_rate_meter_table_entry_t entry; 1257 bcm_ipfix_rate_id_t free_rate_id; 1258 int rv, size, bmp_size, i; 1259 uint32 bits, cng, rval; 1260 1261 if (!soc_feature(unit, soc_feature_ipfix_rate)) { 1262 return BCM_E_UNAVAIL; 1263 } 1264 1265 #ifdef BCM_TRIUMPH_SUPPORT 1266 if (SOC_IS_TR_VL(unit)) { 1267 profile_def = _ipfix_tr_profile_def; 1268 id_def = &_ipfix_tr_id_def; 1269 } 1270 #endif /* BCM_TRIUMPH_SUPPORT */ 1271 if (profile_def == NULL || id_def == NULL) { 1272 return BCM_E_INTERNAL; 1273 } 1274 1275 if (_bcm_ipfix_ctrl[unit] == NULL) { 1276 BCM_IF_ERROR_RETURN(_bcm_ipfix_init(unit, profile_def, id_def)); 1277 } 1278 ipfix_ctrl = _bcm_ipfix_ctrl[unit]; 1279 size = soc_mem_index_count(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm); 1280 1281 if (rate_info == NULL) { 1282 return BCM_E_PARAM; 1283 } 1284 1285 if (rate_info->flags & BCM_IPFIX_RATE_VIOLATION_WITH_ID) { 1286 rv = _bcm_ipfix_rate_id_check(unit, rate_info->rate_id); 1287 if (rate_info->flags & BCM_IPFIX_RATE_VIOLATION_REPLACE) { 1288 if (BCM_FAILURE(rv)) { 1289 return rv; 1290 } 1291 } else { 1292 if (BCM_SUCCESS(rv)) { 1293 return BCM_E_EXISTS; 1294 } else if (rv != BCM_E_NOT_FOUND) { 1295 return rv; 1296 } 1297 } 1298 } else { 1299 if (rate_info->flags & BCM_IPFIX_RATE_VIOLATION_REPLACE) { 1300 return BCM_E_PARAM; 1301 } 1302 } 1303 1304 if (rate_info->limit >= 1305 (1 << soc_mem_field_length(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, 1306 BUCKETSIZEf))) { 1307 return BCM_E_PARAM; 1308 } 1309 1310 if (rate_info->rate >= 1311 (1 << soc_mem_field_length(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, 1312 REFRESHCOUNTf))) { 1313 return BCM_E_PARAM; 1314 } 1315 1316 if (rate_info->flags & BCM_IPFIX_RATE_VIOLATION_DSCP_SET) { 1317 if (rate_info->dscp > 63) { 1318 return BCM_E_PARAM; 1319 } 1320 } 1321 1322 if (rate_info->flags & BCM_IPFIX_RATE_VIOLATION_COLOR_SET) { 1323 if (rate_info->color < 0 || rate_info->color >= bcmColorCount) { 1324 return BCM_E_PARAM; 1325 } 1326 } 1327 1328 if (rate_info->flags & BCM_IPFIX_RATE_VIOLATION_PKT_PRI_SET) { 1329 if (rate_info->pkt_pri < 0 || rate_info->pkt_pri > 7) { 1330 return BCM_E_PARAM; 1331 } 1332 } 1333 1334 if (rate_info->flags & BCM_IPFIX_RATE_VIOLATION_INT_PRI_SET) { 1335 if (rate_info->int_pri < 0 || 1336 rate_info->int_pri >= 1337 (1 << soc_mem_field_length(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, 1338 NEW_INT_PRIf))) { 1339 1340 return BCM_E_PARAM; 1341 } 1342 } 1343 1344 if (!(rate_info->flags & BCM_IPFIX_RATE_VIOLATION_WITH_ID)) { 1345 free_rate_id = size; 1346 bmp_size = _SHR_BITDCLSIZE(size); 1347 /* find the index of first zero from rate_used_bmp */ 1348 for (i = 0; i < bmp_size; i++) { 1349 if (ipfix_ctrl->rate_used_bmp[i] == 0xffffffff) { 1350 continue; 1351 } 1352 bits = ipfix_ctrl->rate_used_bmp[i]; 1353 bits &= (bits << 1) | 0x00000001; 1354 bits &= (bits << 2) | 0x00000003; 1355 bits &= (bits << 4) | 0x0000000f; 1356 bits &= (bits << 8) | 0x000000ff; 1357 bits &= (bits << 16) | 0x0000ffff; 1358 free_rate_id = (i << 5) + _shr_popcount(bits); 1359 break; 1360 } 1361 if (free_rate_id >= size) { 1362 return BCM_E_RESOURCE; 1363 } 1364 rate_info->rate_id = free_rate_id; 1365 } 1366 1367 sal_memset(&entry, 0, sizeof(entry)); 1368 soc_mem_field32_set(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry, 1369 BUCKETSIZEf, rate_info->limit); 1370 soc_mem_field32_set(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry, 1371 REFRESHCOUNTf, rate_info->rate); 1372 if (rate_info->flags & BCM_IPFIX_RATE_VIOLATION_DROP) { 1373 soc_mem_field32_set(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry, 1374 DROPf, 1); 1375 } 1376 if (rate_info->flags & BCM_IPFIX_RATE_VIOLATION_COPY_TO_CPU) { 1377 soc_mem_field32_set(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry, 1378 COPY_TO_CPUf, 1); 1379 } 1380 if (rate_info->flags & BCM_IPFIX_RATE_VIOLATION_DSCP_SET) { 1381 soc_mem_field32_set(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry, 1382 CHANGE_DSCPf, 1); 1383 soc_mem_field32_set(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry, 1384 NEW_DSCPf, rate_info->dscp); 1385 } 1386 if (rate_info->flags & BCM_IPFIX_RATE_VIOLATION_COLOR_SET) { 1387 soc_mem_field32_set(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry, 1388 CHANGE_CNGf, 1); 1389 cng = _BCM_COLOR_ENCODING(unit, rate_info->color); 1390 soc_mem_field32_set(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry, 1391 NEW_CNGf, cng); 1392 } 1393 if (rate_info->flags & BCM_IPFIX_RATE_VIOLATION_PKT_PRI_SET) { 1394 soc_mem_field32_set(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry, 1395 CHANGE_PKT_PRIf, 1); 1396 soc_mem_field32_set(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry, 1397 NEW_PRIf, rate_info->pkt_pri); 1398 } 1399 if (rate_info->flags & BCM_IPFIX_RATE_VIOLATION_INT_PRI_SET) { 1400 soc_mem_field32_set(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry, 1401 CHANGE_INT_PRIf, 1); 1402 soc_mem_field32_set(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry, 1403 NEW_INT_PRIf, rate_info->int_pri); 1404 } 1405 BCM_IF_ERROR_RETURN(soc_mem_write(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, 1406 MEM_BLOCK_ANY, rate_info->rate_id, 1407 &entry)); 1408 1409 SHR_BITSET(ipfix_ctrl->rate_used_bmp, rate_info->rate_id); 1410 1411 if (!(rate_info->flags & BCM_IPFIX_RATE_VIOLATION_REPLACE)) { 1412 if (!ipfix_ctrl->rate_used_count) { 1413 BCM_IF_ERROR_RETURN(READ_ING_IPFIX_CONFIGr(unit, &rval)); 1414 soc_reg_field_set(unit, ING_IPFIX_CONFIGr, &rval, 1415 FLOW_RATE_ENABLEf, 1); 1416 BCM_IF_ERROR_RETURN(WRITE_ING_IPFIX_CONFIGr(unit, rval)); 1417 } 1418 ipfix_ctrl->rate_used_count++; 1419 } 1420 1421 return BCM_E_NONE; 1422 #else /* BCM_IPFIX_SUPPORT */ 1423 return BCM_E_UNAVAIL; 1424 #endif /* BCM_IPFIX_SUPPORT */ 1425 } 1426 1427 /* 1428 * Function: 1429 * bcm_esw_ipfix_rate_destroy 1430 * Description: 1431 * Delete an IPFIX flow rate meter entry 1432 * Parameters: 1433 * unit device number 1434 * rate_id rate identifier 1435 * Return: 1436 * BCM_E_NONE 1437 * BCM_E_NOT_FOUND 1438 * BCM_E_BADID 1439 * BCM_E_UNAVAIL 1440 * BCM_E_INIT 1441 */ 1442 int 1443 bcm_esw_ipfix_rate_destroy(int unit, 1444 bcm_ipfix_rate_id_t rate_id) 1445 { 1446 #ifdef BCM_IPFIX_SUPPORT 1447 _bcm_ipfix_ctrl_t *ipfix_ctrl; 1448 uint32 rval; 1449 1450 BCM_IF_ERROR_RETURN(_bcm_ipfix_rate_id_check(unit, rate_id)); 1451 1452 ipfix_ctrl = _bcm_ipfix_ctrl[unit]; 1453 1454 SHR_BITCLR(ipfix_ctrl->rate_used_bmp, rate_id); 1455 1456 ipfix_ctrl->rate_used_count--; 1457 if (!ipfix_ctrl->rate_used_count) { 1458 BCM_IF_ERROR_RETURN(READ_ING_IPFIX_CONFIGr(unit, &rval)); 1459 soc_reg_field_set(unit, ING_IPFIX_CONFIGr, &rval, FLOW_RATE_ENABLEf, 1460 0); 1461 BCM_IF_ERROR_RETURN(WRITE_ING_IPFIX_CONFIGr(unit, rval)); 1462 } 1463 1464 return BCM_E_NONE; 1465 #else /* BCM_IPFIX_SUPPORT */ 1466 return BCM_E_UNAVAIL; 1467 #endif /* BCM_IPFIX_SUPPORT */ 1468 } 1469 1470 /* 1471 * Function: 1472 * bcm_esw_ipfix_rate_get 1473 * Description: 1474 * Get IPFIX flow rate meter entry for the specified id 1475 * Parameters: 1476 * unit device number 1477 * rate_info pointer to rate information carrying rate identifier 1478 * Return: 1479 * BCM_E_NONE 1480 * BCM_E_PARAM 1481 * BCM_E_NOT_FOUND 1482 * BCM_E_BADID 1483 * BCM_E_UNAVAIL 1484 * BCM_E_INIT 1485 */ 1486 int 1487 bcm_esw_ipfix_rate_get(int unit, 1488 bcm_ipfix_rate_t *rate_info) 1489 { 1490 #ifdef BCM_IPFIX_SUPPORT 1491 if (rate_info == NULL) { 1492 return BCM_E_PARAM; 1493 } 1494 1495 BCM_IF_ERROR_RETURN(_bcm_ipfix_rate_id_check(unit, rate_info->rate_id)); 1496 1497 return _bcm_ipfix_rate_get(unit, rate_info->rate_id, rate_info); 1498 #else /* BCM_IPFIX_SUPPORT */ 1499 return BCM_E_UNAVAIL; 1500 #endif /* BCM_IPFIX_SUPPORT */ 1501 } 1502 1503 /* 1504 * Function: 1505 * bcm_esw_ipfix_rate_traverse 1506 * Description: 1507 * Traverse through IPFIX flow rate meter entries 1508 * Parameters: 1509 * unit device number 1510 * cb user callback function 1511 * userdata user data used as argument during callback 1512 * Return: 1513 * BCM_E_NONE 1514 * BCM_E_PARAM 1515 * BCM_E_UNAVAIL 1516 * BCM_E_INIT 1517 */ 1518 int 1519 bcm_esw_ipfix_rate_traverse(int unit, 1520 bcm_ipfix_rate_traverse_cb cb, 1521 void *userdata) 1522 { 1523 #ifdef BCM_IPFIX_SUPPORT 1524 bcm_ipfix_rate_t rate_info; 1525 int size, index; 1526 1527 if (!soc_feature(unit, soc_feature_ipfix_rate)) { 1528 return BCM_E_UNAVAIL; 1529 } 1530 1531 if (_bcm_ipfix_ctrl[unit] == NULL) { 1532 return BCM_E_INIT; 1533 } 1534 1535 if (cb == NULL) { 1536 return BCM_E_PARAM; 1537 } 1538 1539 size = soc_mem_index_count(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm); 1540 for (index = 1; index < size; index++) { 1541 if (!SHR_BITGET(_bcm_ipfix_ctrl[unit]->rate_used_bmp, index)) { 1542 continue; 1543 } 1544 BCM_IF_ERROR_RETURN(_bcm_ipfix_rate_get(unit, index, &rate_info)); 1545 (*cb)(unit, &rate_info, userdata); 1546 } 1547 1548 return BCM_E_NONE; 1549 #else /* BCM_IPFIX_SUPPORT */ 1550 return BCM_E_UNAVAIL; 1551 #endif /* BCM_IPFIX_SUPPORT */ 1552 } 1553 1554 /* 1555 * Function: 1556 * bcm_esw_ipfix_rate_destroy_all 1557 * Description: 1558 * Delete all IPFIX flow rate meter entries 1559 * Parameters: 1560 * unit device number 1561 * Return: 1562 * BCM_E_NONE 1563 * BCM_E_UNAVAIL 1564 * BCM_E_INIT 1565 */ 1566 int 1567 bcm_esw_ipfix_rate_destroy_all(int unit) 1568 { 1569 #ifdef BCM_IPFIX_SUPPORT 1570 _bcm_ipfix_ctrl_t *ipfix_ctrl; 1571 int size; 1572 1573 if (!soc_feature(unit, soc_feature_ipfix_rate)) { 1574 return BCM_E_UNAVAIL; 1575 } 1576 1577 if (_bcm_ipfix_ctrl[unit] == NULL) { 1578 return BCM_E_INIT; 1579 } 1580 ipfix_ctrl = _bcm_ipfix_ctrl[unit]; 1581 size = soc_mem_index_count(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm); 1582 1583 sal_memset(ipfix_ctrl->rate_used_bmp, 0, SHR_BITALLOCSIZE(size)); 1584 SHR_BITSET(ipfix_ctrl->rate_used_bmp, 0); /* index 0 is reserved */ 1585 1586 return BCM_E_NONE; 1587 #else /* BCM_IPFIX_SUPPORT */ 1588 return BCM_E_UNAVAIL; 1589 #endif /* BCM_IPFIX_SUPPORT */ 1590 } 1591 1592 /* 1593 * Function: 1594 * bcm_esw_ipfix_rate_mirror_add 1595 * Description: 1596 * Add a mirror destination to the IPFIX flow rate meter entry 1597 * Parameters: 1598 * unit device number 1599 * rate_id rate identifier 1600 * mirror_dest_id pre-allocated mirror destination identifier 1601 * Return: 1602 * BCM_E_NONE 1603 * BCM_E_NOT_FOUND 1604 * BCM_E_EXISTS 1605 * BCM_E_BADID 1606 * BCM_E_RESOURCE 1607 * BCM_E_UNAVAIL 1608 * BCM_E_INIT 1609 */ 1610 int 1611 bcm_esw_ipfix_rate_mirror_add(int unit, 1612 bcm_ipfix_rate_id_t rate_id, 1613 bcm_gport_t mirror_dest_id) 1614 { 1615 #ifdef BCM_IPFIX_SUPPORT 1616 const _bcm_ipfix_id_def_t *id_def = NULL; 1617 ing_ipfix_flow_rate_meter_table_entry_t entry; 1618 uint32 mirror_bmp; 1619 int mtp_index, free_index, index; 1620 1621 BCM_IF_ERROR_RETURN(_bcm_ipfix_rate_id_check(unit, rate_id)); 1622 1623 #ifdef BCM_TRIUMPH_SUPPORT 1624 if (SOC_IS_TR_VL(unit)) { 1625 id_def = &_ipfix_tr_id_def; 1626 } 1627 #endif /* BCM_TRIUMPH_SUPPORT */ 1628 if (id_def == NULL) { 1629 return BCM_E_INTERNAL; 1630 } 1631 1632 if (!BCM_GPORT_IS_MIRROR(mirror_dest_id)) { 1633 return BCM_E_BADID; 1634 } 1635 mtp_index = BCM_GPORT_MIRROR_GET(mirror_dest_id); 1636 1637 BCM_IF_ERROR_RETURN(soc_mem_read(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, 1638 MEM_BLOCK_ANY, rate_id, &entry)); 1639 mirror_bmp = soc_mem_field32_get(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, 1640 &entry, MIRRORf); 1641 1642 free_index = -1; 1643 for (index = _BCM_IPFIX_RATE_MIRROR_COUNT - 1; index >= 0; index--) { 1644 if (!(mirror_bmp & (1 << index))) { 1645 free_index = index; 1646 continue; 1647 } 1648 if (soc_mem_field32_get(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry, 1649 id_def->mtp_index[index]) == mtp_index) { 1650 return BCM_E_EXISTS; 1651 } 1652 } 1653 if (free_index < 0) { 1654 return BCM_E_RESOURCE; 1655 } 1656 1657 soc_mem_field32_set(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry, 1658 id_def->mtp_index[free_index], mtp_index); 1659 soc_mem_field32_set(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry, 1660 MIRRORf, mirror_bmp | (1 << free_index)); 1661 BCM_IF_ERROR_RETURN(soc_mem_write(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, 1662 MEM_BLOCK_ANY, rate_id, &entry)); 1663 1664 return BCM_E_NONE; 1665 #else /* BCM_IPFIX_SUPPORT */ 1666 return BCM_E_UNAVAIL; 1667 #endif /* BCM_IPFIX_SUPPORT */ 1668 } 1669 1670 /* 1671 * Function: 1672 * bcm_esw_ipfix_rate_mirror_delete 1673 * Description: 1674 * Delete a mirror destination from the IPFIX flow rate meter entry 1675 * Parameters: 1676 * unit device number 1677 * rate_id rate identifier 1678 * mirror_dest_id pre-allocated mirror destination identifier 1679 * Return: 1680 * BCM_E_NONE 1681 * BCM_E_NOT_FOUND 1682 * BCM_E_BADID 1683 * BCM_E_UNAVAIL 1684 * BCM_E_INIT 1685 */ 1686 int 1687 bcm_esw_ipfix_rate_mirror_delete(int unit, 1688 bcm_ipfix_rate_id_t rate_id, 1689 bcm_gport_t mirror_dest_id) 1690 { 1691 #ifdef BCM_IPFIX_SUPPORT 1692 const _bcm_ipfix_id_def_t *id_def = NULL; 1693 ing_ipfix_flow_rate_meter_table_entry_t entry; 1694 uint32 mirror_bmp; 1695 int mtp_index, index; 1696 1697 BCM_IF_ERROR_RETURN(_bcm_ipfix_rate_id_check(unit, rate_id)); 1698 1699 #ifdef BCM_TRIUMPH_SUPPORT 1700 if (SOC_IS_TR_VL(unit)) { 1701 id_def = &_ipfix_tr_id_def; 1702 } 1703 #endif /* BCM_TRIUMPH_SUPPORT */ 1704 if (id_def == NULL) { 1705 return BCM_E_INTERNAL; 1706 } 1707 1708 if (!BCM_GPORT_IS_MIRROR(mirror_dest_id)) { 1709 return BCM_E_BADID; 1710 } 1711 mtp_index = BCM_GPORT_MIRROR_GET(mirror_dest_id); 1712 1713 BCM_IF_ERROR_RETURN(soc_mem_read(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, 1714 MEM_BLOCK_ANY, rate_id, &entry)); 1715 mirror_bmp = soc_mem_field32_get(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, 1716 &entry, MIRRORf); 1717 1718 for (index = 0; index < _BCM_IPFIX_RATE_MIRROR_COUNT; index++) { 1719 if (!(mirror_bmp & (1 << index))) { 1720 continue; 1721 } 1722 if (soc_mem_field32_get(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry, 1723 id_def->mtp_index[index]) == mtp_index) { 1724 break; 1725 } 1726 } 1727 if (index == _BCM_IPFIX_RATE_MIRROR_COUNT) { 1728 return BCM_E_NOT_FOUND; 1729 } 1730 1731 soc_mem_field32_set(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry, 1732 MIRRORf, mirror_bmp ^ (1 << index)); 1733 BCM_IF_ERROR_RETURN(soc_mem_write(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, 1734 MEM_BLOCK_ANY, rate_id, &entry)); 1735 1736 return BCM_E_NONE; 1737 #else /* BCM_IPFIX_SUPPORT */ 1738 return BCM_E_UNAVAIL; 1739 #endif /* BCM_IPFIX_SUPPORT */ 1740 } 1741 1742 /* 1743 * Function: 1744 * bcm_esw_ipfix_rate_mirror_delete_all 1745 * Description: 1746 * Delete all mirror destination associated to the IPFIX flow rate meter 1747 * entry 1748 * Parameters: 1749 * unit device number 1750 * rate_id rate identifier 1751 * Return: 1752 * BCM_E_NONE 1753 * BCM_E_NOT_FOUND 1754 * BCM_E_BADID 1755 * BCM_E_UNAVAIL 1756 * BCM_E_INIT 1757 */ 1758 int 1759 bcm_esw_ipfix_rate_mirror_delete_all(int unit, 1760 bcm_ipfix_rate_id_t rate_id) 1761 { 1762 #ifdef BCM_IPFIX_SUPPORT 1763 ing_ipfix_flow_rate_meter_table_entry_t entry; 1764 1765 BCM_IF_ERROR_RETURN(_bcm_ipfix_rate_id_check(unit, rate_id)); 1766 1767 BCM_IF_ERROR_RETURN(soc_mem_read(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, 1768 MEM_BLOCK_ANY, rate_id, &entry)); 1769 soc_mem_field32_set(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry, 1770 MIRRORf, 0); 1771 BCM_IF_ERROR_RETURN(soc_mem_write(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, 1772 MEM_BLOCK_ANY, rate_id, &entry)); 1773 1774 return BCM_E_NONE; 1775 #else /* BCM_IPFIX_SUPPORT */ 1776 return BCM_E_UNAVAIL; 1777 #endif /* BCM_IPFIX_SUPPORT */ 1778 } 1779 1780 /* 1781 * Function: 1782 * bcm_esw_ipfix_rate_mirror_get 1783 * Description: 1784 * Get all mirror destination from the IPFIX flow rate meter entry 1785 * Parameters: 1786 * unit device number 1787 * rate_id rate identifier 1788 * mirror_dest_size size of mirror_dest_id array 1789 * mirror_dest_id array to store mirror destination identifier 1790 * mirror_dest_count number of entries stored in the mirror_dest_id array 1791 * Return: 1792 * BCM_E_NONE 1793 * BCM_E_NOT_FOUND 1794 * BCM_E_BADID 1795 * BCM_E_UNAVAIL 1796 * BCM_E_INIT 1797 */ 1798 int 1799 bcm_esw_ipfix_rate_mirror_get(int unit, 1800 bcm_ipfix_rate_id_t rate_id, 1801 int mirror_dest_size, 1802 bcm_gport_t *mirror_dest_id, 1803 int *mirror_dest_count) 1804 { 1805 #ifdef BCM_IPFIX_SUPPORT 1806 const _bcm_ipfix_id_def_t *id_def = NULL; 1807 ing_ipfix_flow_rate_meter_table_entry_t entry; 1808 uint32 mirror_bmp; 1809 int mtp_index, index; 1810 1811 BCM_IF_ERROR_RETURN(_bcm_ipfix_rate_id_check(unit, rate_id)); 1812 1813 #ifdef BCM_TRIUMPH_SUPPORT 1814 if (SOC_IS_TR_VL(unit)) { 1815 id_def = &_ipfix_tr_id_def; 1816 } 1817 #endif /* BCM_TRIUMPH_SUPPORT */ 1818 if (id_def == NULL) { 1819 return BCM_E_INTERNAL; 1820 } 1821 1822 if (mirror_dest_id == NULL || mirror_dest_count == NULL) { 1823 return BCM_E_PARAM; 1824 } 1825 1826 BCM_IF_ERROR_RETURN(soc_mem_read(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, 1827 MEM_BLOCK_ANY, rate_id, &entry)); 1828 1829 mirror_bmp = soc_mem_field32_get(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, 1830 &entry, MIRRORf); 1831 1832 *mirror_dest_count = 0; 1833 for (index = 0; index < _BCM_IPFIX_RATE_MIRROR_COUNT; index++) { 1834 if (!(mirror_bmp & (1 << index))) { 1835 continue; 1836 } 1837 if (*mirror_dest_count >= mirror_dest_size) { 1838 break; 1839 } 1840 mtp_index = soc_mem_field32_get(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, 1841 &entry, id_def->mtp_index[index]); 1842 BCM_GPORT_MIRROR_SET(mirror_dest_id[*mirror_dest_count], mtp_index); 1843 (*mirror_dest_count)++; 1844 } 1845 1846 return BCM_E_NONE; 1847 #else /* BCM_IPFIX_SUPPORT */ 1848 return BCM_E_UNAVAIL; 1849 #endif /* BCM_IPFIX_SUPPORT */ 1850 } 1851 1852 /* 1853 * Function: 1854 * bcm_esw_ipfix_mirror_config_set 1855 * Description: 1856 * Set IPFIX mirror control configuration of the specified port 1857 * Parameters: 1858 * unit device number 1859 * stage BCM_IPFIX_STAGE_INGRESS or BCM_IPFIX_STAGE_EGRESS 1860 * port generic port identifier 1861 * config pointer to ipfix mirror configuration 1862 * Return: 1863 * BCM_E_NONE 1864 * BCM_E_PARAM 1865 * BCM_E_UNAVAIL 1866 * BCM_E_INIT 1867 * BCM_E_PORT 1868 */ 1869 int 1870 bcm_esw_ipfix_mirror_config_set(int unit, 1871 bcm_ipfix_stage_t stage, 1872 bcm_gport_t port, 1873 bcm_ipfix_mirror_config_t *config) 1874 { 1875 #ifdef BCM_IPFIX_SUPPORT 1876 const _bcm_ipfix_id_def_t *id_def = NULL; 1877 soc_reg_t reg; 1878 uint64 rval64; 1879 1880 if (!soc_feature(unit, soc_feature_ipfix_flow_mirror)) { 1881 return BCM_E_UNAVAIL; 1882 } 1883 1884 #ifdef BCM_TRIUMPH_SUPPORT 1885 if (SOC_IS_TR_VL(unit)) { 1886 id_def = &_ipfix_tr_id_def; 1887 } 1888 #endif /* BCM_TRIUMPH_SUPPORT */ 1889 if (id_def == NULL) { 1890 return BCM_E_INTERNAL; 1891 } 1892 1893 if (_bcm_ipfix_ctrl[unit] == NULL) { 1894 return BCM_E_INIT; 1895 } 1896 1897 if (stage != BCM_IPFIX_STAGE_INGRESS && stage != BCM_IPFIX_STAGE_EGRESS) { 1898 return BCM_E_PARAM; 1899 } 1900 1901 BCM_IF_ERROR_RETURN(_bcm_ipfix_gport_resolve(unit, port, &port)); 1902 1903 if (config == NULL) { 1904 return BCM_E_PARAM; 1905 } 1906 1907 reg = id_def->mirror_control[stage]; 1908 1909 if (config->pkt_count >= 1910 (1 << soc_reg_field_length(unit, reg, MIRROR_COUNTf))) { 1911 return BCM_E_PARAM; 1912 } 1913 1914 if (config->tcp_flags_mask >= 1915 (1 << soc_reg_field_length(unit, reg, TCP_FLAG_MASKf))) { 1916 return BCM_E_PARAM; 1917 } 1918 1919 if (config->flags & BCM_IPFIX_MIRROR_CONFIG_TTL_OFFSET_MAX) { 1920 if (config->ttl_offset_max >= 1921 (1 << soc_reg_field_length(unit, reg, TTL_RANGE_VALf))) { 1922 return BCM_E_PARAM; 1923 } 1924 } 1925 1926 COMPILER_64_ZERO(rval64); 1927 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &rval64)); 1928 soc_reg64_field32_set(unit, reg, &rval64, MIRROR_COUNTf, 1929 config->pkt_count); 1930 soc_reg64_field32_set(unit, reg, &rval64, TCP_FLAG_MASKf, 1931 config->tcp_flags_mask); 1932 if (config->flags & BCM_IPFIX_MIRROR_CONFIG_TTL_OFFSET_MAX) { 1933 soc_reg64_field32_set(unit, reg, &rval64, TTL_RANGE_CHECK_ENABLEf, 1); 1934 soc_reg64_field32_set(unit, reg, &rval64, TTL_RANGE_VALf, 1935 config->ttl_offset_max); 1936 } 1937 if (config->flags & BCM_IPFIX_MIRROR_CONFIG_FRAGMENT) { 1938 soc_reg64_field32_set(unit, reg, &rval64, FRAGMENT_MASKf, 1); 1939 } 1940 if (config->flags & BCM_IPFIX_MIRROR_CONFIG_NON_FRAGMENT) { 1941 soc_reg64_field32_set(unit, reg, &rval64, NON_FRAGMENT_MASKf, 1); 1942 } 1943 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 1944 1945 return BCM_E_NONE; 1946 #else /* BCM_IPFIX_SUPPORT */ 1947 return BCM_E_UNAVAIL; 1948 #endif /* BCM_IPFIX_SUPPORT */ 1949 } 1950 1951 /* 1952 * Function: 1953 * bcm_esw_ipfix_mirror_config_get 1954 * Description: 1955 * Get IPFIX mirror control configuration of the specified port 1956 * Parameters: 1957 * unit device number 1958 * stage BCM_IPFIX_STAGE_INGRESS or BCM_IPFIX_STAGE_EGRESS 1959 * port generic port identifier 1960 * config pointer to ipfix mirror configuration 1961 * Return: 1962 * BCM_E_NONE 1963 * BCM_E_PARAM 1964 * BCM_E_UNAVAIL 1965 * BCM_E_INIT 1966 * BCM_E_PORT 1967 */ 1968 int 1969 bcm_esw_ipfix_mirror_config_get(int unit, 1970 bcm_ipfix_stage_t stage, 1971 bcm_gport_t port, 1972 bcm_ipfix_mirror_config_t *config) 1973 { 1974 #ifdef BCM_IPFIX_SUPPORT 1975 const _bcm_ipfix_id_def_t *id_def = NULL; 1976 soc_reg_t reg; 1977 uint64 rval64; 1978 1979 if (!soc_feature(unit, soc_feature_ipfix_flow_mirror)) { 1980 return BCM_E_UNAVAIL; 1981 } 1982 1983 #ifdef BCM_TRIUMPH_SUPPORT 1984 if (SOC_IS_TR_VL(unit)) { 1985 id_def = &_ipfix_tr_id_def; 1986 } 1987 #endif /* BCM_TRIUMPH_SUPPORT */ 1988 if (id_def == NULL) { 1989 return BCM_E_INTERNAL; 1990 } 1991 1992 if (_bcm_ipfix_ctrl[unit] == NULL) { 1993 return BCM_E_INIT; 1994 } 1995 1996 if (stage != BCM_IPFIX_STAGE_INGRESS && stage != BCM_IPFIX_STAGE_EGRESS) { 1997 return BCM_E_PARAM; 1998 } 1999 2000 BCM_IF_ERROR_RETURN(_bcm_ipfix_gport_resolve(unit, port, &port)); 2001 2002 if (config == NULL) { 2003 return BCM_E_PARAM; 2004 } 2005 2006 reg = id_def->mirror_control[stage]; 2007 2008 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &rval64)); 2009 config->flags = 0; 2010 config->pkt_count = soc_reg64_field32_get(unit, reg, rval64, 2011 MIRROR_COUNTf); 2012 config->tcp_flags_mask = soc_reg64_field32_get(unit, reg, rval64, 2013 TCP_FLAG_MASKf); 2014 if (soc_reg64_field32_get(unit, reg, rval64, TTL_RANGE_CHECK_ENABLEf)) { 2015 config->flags |= BCM_IPFIX_MIRROR_CONFIG_TTL_OFFSET_MAX; 2016 config->ttl_offset_max = soc_reg64_field32_get(unit, reg, rval64, 2017 TTL_RANGE_VALf); 2018 } 2019 if (soc_reg64_field32_get(unit, reg, rval64, FRAGMENT_MASKf)) { 2020 config->flags |= BCM_IPFIX_MIRROR_CONFIG_FRAGMENT; 2021 } 2022 if (soc_reg64_field32_get(unit, reg, rval64, NON_FRAGMENT_MASKf)) { 2023 config->flags |= BCM_IPFIX_MIRROR_CONFIG_NON_FRAGMENT; 2024 } 2025 2026 return BCM_E_NONE; 2027 #else /* BCM_IPFIX_SUPPORT */ 2028 return BCM_E_UNAVAIL; 2029 #endif /* BCM_IPFIX_SUPPORT */ 2030 } 2031 2032 /* 2033 * Function: 2034 * bcm_esw_ipfix_mirror_port_dest_add 2035 * Description: 2036 * Add an IPFIX mirror destination to the specified port 2037 * Parameters: 2038 * unit device number 2039 * stage BCM_IPFIX_STAGE_INGRESS or BCM_IPFIX_STAGE_EGRESS 2040 * port generic port identifier 2041 * mirror_dest_id pre-allocated mirror destination identifier 2042 * Return: 2043 * BCM_E_NONE 2044 * BCM_E_PARAM 2045 * BCM_E_EXISTS 2046 * BCM_E_BADID 2047 * BCM_E_RESOURCE 2048 * BCM_E_UNAVAIL 2049 * BCM_E_INIT 2050 * BCM_E_PORT 2051 */ 2052 int 2053 bcm_esw_ipfix_mirror_port_dest_add(int unit, 2054 bcm_ipfix_stage_t stage, 2055 bcm_gport_t port, 2056 bcm_gport_t mirror_dest_id) 2057 { 2058 #ifdef BCM_IPFIX_SUPPORT 2059 const _bcm_ipfix_id_def_t *id_def = NULL; 2060 soc_reg_t reg; 2061 uint64 rval64; 2062 uint32 mirror_bmp; 2063 int mtp_index, free_index, index; 2064 #ifdef BCM_TRIUMPH_SUPPORT 2065 uint32 flags = BCM_MIRROR_PORT_INGRESS; 2066 int rv; 2067 #endif /* BCM_TRIUMPH_SUPPORT */ 2068 2069 if (!soc_feature(unit, soc_feature_ipfix_flow_mirror)) { 2070 return BCM_E_UNAVAIL; 2071 } 2072 2073 #ifdef BCM_TRIUMPH_SUPPORT 2074 if (SOC_IS_TR_VL(unit)) { 2075 id_def = &_ipfix_tr_id_def; 2076 } 2077 #endif /* BCM_TRIUMPH_SUPPORT */ 2078 if (id_def == NULL) { 2079 return BCM_E_INTERNAL; 2080 } 2081 2082 if (_bcm_ipfix_ctrl[unit] == NULL) { 2083 return BCM_E_INIT; 2084 } 2085 2086 if (stage != BCM_IPFIX_STAGE_INGRESS && stage != BCM_IPFIX_STAGE_EGRESS) { 2087 return BCM_E_PARAM; 2088 } 2089 2090 BCM_IF_ERROR_RETURN(_bcm_ipfix_gport_resolve(unit, port, &port)); 2091 2092 if (!BCM_GPORT_IS_MIRROR(mirror_dest_id)) { 2093 return BCM_E_BADID; 2094 } 2095 2096 reg = id_def->mirror_control[stage]; 2097 2098 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &rval64)); 2099 2100 #ifdef BCM_TRIUMPH_SUPPORT 2101 if (SOC_IS_TRIUMPH3(unit) || SOC_IS_APOLLO(unit)) { 2102 if (stage == BCM_IPFIX_STAGE_EGRESS) { 2103 flags = BCM_MIRROR_PORT_EGRESS_TRUE; 2104 } 2105 BCM_IF_ERROR_RETURN(_bcm_esw_mirror_mtp_reserve(unit, mirror_dest_id, flags, &mtp_index)); 2106 } else 2107 #endif /* BCM_TRIUMPH_SUPPORT */ 2108 { 2109 mtp_index = BCM_GPORT_MIRROR_GET(mirror_dest_id); 2110 } 2111 2112 mirror_bmp = soc_reg64_field32_get(unit, reg, rval64, MIRRORf); 2113 2114 free_index = -1; 2115 for (index = _BCM_IPFIX_RATE_MIRROR_COUNT - 1; index >= 0; index--) { 2116 if (!(mirror_bmp & (1 << index))) { 2117 free_index = index; 2118 continue; 2119 } 2120 if (soc_reg64_field32_get(unit, reg, rval64, 2121 id_def->mtp_index[index]) == mtp_index) { 2122 return BCM_E_EXISTS; 2123 } 2124 } 2125 if (free_index < 0) { 2126 #ifdef BCM_TRIUMPH_SUPPORT 2127 if (SOC_IS_TRIUMPH3(unit) || SOC_IS_APOLLO(unit)) { 2128 _bcm_esw_mirror_mtp_unreserve(unit, mtp_index, TRUE, flags); 2129 } 2130 #endif /* BCM_TRIUMPH_SUPPORT */ 2131 2132 return BCM_E_RESOURCE; 2133 } 2134 2135 soc_reg64_field32_set(unit, reg, &rval64, id_def->mtp_index[free_index], 2136 mtp_index); 2137 soc_reg64_field32_set(unit, reg, &rval64, MIRRORf, 2138 mirror_bmp | (1 << free_index)); 2139 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 2140 2141 #ifdef BCM_TRIUMPH_SUPPORT 2142 if (SOC_IS_TRIUMPH3(unit) || SOC_IS_APOLLO(unit)) { 2143 rv = soc_reg_set(unit, reg, port, 0, rval64); 2144 if (BCM_FAILURE(rv)) { 2145 _bcm_esw_mirror_mtp_unreserve(unit, mtp_index, TRUE, flags); 2146 return rv; 2147 } 2148 2149 if (stage == BCM_IPFIX_STAGE_INGRESS) { 2150 /*INGRESS rely on MIRROR_CONTROL, EGRSS_TRUE donot rely on this*/ 2151 BCM_IF_ERROR_RETURN(_bcm_esw_mirror_enable_set(unit, port, TRUE)); 2152 } 2153 } else 2154 #endif /* BCM_TRIUMPH_SUPPORT */ 2155 { 2156 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 2157 } 2158 2159 return BCM_E_NONE; 2160 #else /* BCM_IPFIX_SUPPORT */ 2161 return BCM_E_UNAVAIL; 2162 #endif /* BCM_IPFIX_SUPPORT */ 2163 } 2164 2165 /* 2166 * Function: 2167 * bcm_esw_ipfix_mirror_port_dest_delete 2168 * Description: 2169 * Delete an IPFIX mirror destination from the specified port 2170 * Parameters: 2171 * unit device number 2172 * stage BCM_IPFIX_STAGE_INGRESS or BCM_IPFIX_STAGE_EGRESS 2173 * port generic port identifier 2174 * mirror_dest_id pre-allocated mirror destination identifier 2175 * Return: 2176 * BCM_E_NONE 2177 * BCM_E_PARAM 2178 * BCM_E_NOT_FOUND 2179 * BCM_E_BADID 2180 * BCM_E_UNAVAIL 2181 * BCM_E_INIT 2182 * BCM_E_PORT 2183 */ 2184 int 2185 bcm_esw_ipfix_mirror_port_dest_delete(int unit, 2186 bcm_ipfix_stage_t stage, 2187 bcm_gport_t port, 2188 bcm_gport_t mirror_dest_id) 2189 { 2190 #ifdef BCM_IPFIX_SUPPORT 2191 const _bcm_ipfix_id_def_t *id_def = NULL; 2192 soc_reg_t reg; 2193 uint64 rval64; 2194 uint32 mirror_bmp; 2195 int mtp_index, index; 2196 #ifdef BCM_TRIUMPH_SUPPORT 2197 uint32 flags = BCM_MIRROR_PORT_INGRESS; 2198 #endif /* BCM_TRIUMPH_SUPPORT */ 2199 2200 if (!soc_feature(unit, soc_feature_ipfix_flow_mirror)) { 2201 return BCM_E_UNAVAIL; 2202 } 2203 2204 #ifdef BCM_TRIUMPH_SUPPORT 2205 if (SOC_IS_TR_VL(unit)) { 2206 id_def = &_ipfix_tr_id_def; 2207 } 2208 #endif /* BCM_TRIUMPH_SUPPORT */ 2209 if (id_def == NULL) { 2210 return BCM_E_INTERNAL; 2211 } 2212 2213 if (_bcm_ipfix_ctrl[unit] == NULL) { 2214 return BCM_E_INIT; 2215 } 2216 2217 if (stage != BCM_IPFIX_STAGE_INGRESS && stage != BCM_IPFIX_STAGE_EGRESS) { 2218 return BCM_E_PARAM; 2219 } 2220 2221 BCM_IF_ERROR_RETURN(_bcm_ipfix_gport_resolve(unit, port, &port)); 2222 2223 if (!BCM_GPORT_IS_MIRROR(mirror_dest_id)) { 2224 return BCM_E_BADID; 2225 } 2226 2227 #ifdef BCM_TRIUMPH_SUPPORT 2228 if (SOC_IS_TRIUMPH3(unit) || SOC_IS_APOLLO(unit)) { 2229 if (stage == BCM_IPFIX_STAGE_EGRESS) { 2230 flags = BCM_MIRROR_PORT_EGRESS_TRUE; 2231 } 2232 BCM_IF_ERROR_RETURN(_bcm_esw_mirror_mtp_match(unit, mirror_dest_id, flags, &mtp_index)); 2233 } else 2234 #endif /* BCM_TRIUMPH_SUPPORT */ 2235 { 2236 mtp_index = BCM_GPORT_MIRROR_GET(mirror_dest_id); 2237 } 2238 2239 reg = id_def->mirror_control[stage]; 2240 2241 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &rval64)); 2242 mirror_bmp = soc_reg64_field32_get(unit, reg, rval64, MIRRORf); 2243 2244 for (index = 0; index < _BCM_IPFIX_RATE_MIRROR_COUNT; index++) { 2245 if (!(mirror_bmp & (1 << index))) { 2246 continue; 2247 } 2248 if (soc_reg64_field32_get(unit, reg, rval64, 2249 id_def->mtp_index[index]) == mtp_index) { 2250 soc_reg64_field32_set(unit, reg, &rval64, id_def->mtp_index[index], 0); 2251 break; 2252 } 2253 } 2254 if (index == _BCM_IPFIX_RATE_MIRROR_COUNT) { 2255 return BCM_E_NOT_FOUND; 2256 } 2257 2258 soc_reg64_field32_set(unit, reg, &rval64, MIRRORf, 2259 mirror_bmp ^ (1 << index)); 2260 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 2261 2262 #ifdef BCM_TRIUMPH_SUPPORT 2263 if (SOC_IS_TRIUMPH3(unit) || SOC_IS_APOLLO(unit)) { 2264 BCM_IF_ERROR_RETURN(_bcm_esw_mirror_mtp_unreserve(unit, mtp_index, TRUE, flags)); 2265 } 2266 #endif /* BCM_TRIUMPH_SUPPORT */ 2267 2268 return BCM_E_NONE; 2269 #else /* BCM_IPFIX_SUPPORT */ 2270 return BCM_E_UNAVAIL; 2271 #endif /* BCM_IPFIX_SUPPORT */ 2272 } 2273 2274 /* 2275 * Function: 2276 * bcm_esw_ipfix_mirror_port_dest_delete_all 2277 * Description: 2278 * Delete all IPFIX mirror destination from the specified port 2279 * Parameters: 2280 * unit device number 2281 * stage BCM_IPFIX_STAGE_INGRESS or BCM_IPFIX_STAGE_EGRESS 2282 * port generic port identifier 2283 * Return: 2284 * BCM_E_NONE 2285 * BCM_E_PARAM 2286 * BCM_E_UNAVAIL 2287 * BCM_E_INIT 2288 * BCM_E_PORT 2289 */ 2290 int 2291 bcm_esw_ipfix_mirror_port_dest_delete_all(int unit, 2292 bcm_ipfix_stage_t stage, 2293 bcm_gport_t port) 2294 { 2295 #ifdef BCM_IPFIX_SUPPORT 2296 const _bcm_ipfix_id_def_t *id_def = NULL; 2297 soc_reg_t reg; 2298 uint64 rval64; 2299 #ifdef BCM_TRIUMPH_SUPPORT 2300 uint32 mirror_bmp; 2301 int mtp_index, index; 2302 #endif /* BCM_TRIUMPH_SUPPORT */ 2303 2304 if (!soc_feature(unit, soc_feature_ipfix_flow_mirror)) { 2305 return BCM_E_UNAVAIL; 2306 } 2307 2308 #ifdef BCM_TRIUMPH_SUPPORT 2309 if (SOC_IS_TR_VL(unit)) { 2310 id_def = &_ipfix_tr_id_def; 2311 } 2312 #endif /* BCM_TRIUMPH_SUPPORT */ 2313 if (id_def == NULL) { 2314 return BCM_E_INTERNAL; 2315 } 2316 2317 if (_bcm_ipfix_ctrl[unit] == NULL) { 2318 return BCM_E_INIT; 2319 } 2320 2321 if (stage != BCM_IPFIX_STAGE_INGRESS && stage != BCM_IPFIX_STAGE_EGRESS) { 2322 return BCM_E_PARAM; 2323 } 2324 2325 BCM_IF_ERROR_RETURN(_bcm_ipfix_gport_resolve(unit, port, &port)); 2326 2327 reg = id_def->mirror_control[stage]; 2328 2329 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &rval64)); 2330 2331 #ifdef BCM_TRIUMPH_SUPPORT 2332 if (SOC_IS_TRIUMPH3(unit) || SOC_IS_APOLLO(unit)) { 2333 mirror_bmp = soc_reg64_field32_get(unit, reg, rval64, MIRRORf); 2334 for (index = 0; index < _BCM_IPFIX_RATE_MIRROR_COUNT; index++) { 2335 if (!(mirror_bmp & (1 << index))) { 2336 continue; 2337 } 2338 2339 mtp_index = soc_reg64_field32_get(unit, reg, rval64, 2340 id_def->mtp_index[index]); 2341 2342 if (stage == BCM_IPFIX_STAGE_INGRESS) { 2343 BCM_IF_ERROR_RETURN(_bcm_esw_mirror_mtp_unreserve(unit, mtp_index, 2344 TRUE, BCM_MIRROR_PORT_INGRESS)); 2345 } else { 2346 BCM_IF_ERROR_RETURN(_bcm_esw_mirror_mtp_unreserve(unit, mtp_index, 2347 TRUE, BCM_MIRROR_PORT_EGRESS_TRUE)); 2348 } 2349 2350 soc_reg64_field32_set(unit, reg, &rval64, id_def->mtp_index[index], 0); 2351 } 2352 } 2353 #endif /* BCM_TRIUMPH_SUPPORT */ 2354 2355 soc_reg64_field32_set(unit, reg, &rval64, MIRRORf, 0); 2356 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 2357 2358 return BCM_E_NONE; 2359 #else /* BCM_IPFIX_SUPPORT */ 2360 return BCM_E_UNAVAIL; 2361 #endif /* BCM_IPFIX_SUPPORT */ 2362 } 2363 2364 /* 2365 * Function: 2366 * bcm_esw_ipfix_mirror_port_dest_get 2367 * Description: 2368 * Get all IPFIX mirror destination of the specified port 2369 * Parameters: 2370 * unit device number 2371 * stage BCM_IPFIX_STAGE_INGRESS or BCM_IPFIX_STAGE_EGRESS 2372 * port generic port identifier 2373 * mirror_dest_size size of mirror_dest_id array 2374 * mirror_dest_id array to store mirror destination identifier 2375 * mirror_dest_count number of entries stored in the mirror_dest_id array 2376 * Return: 2377 * BCM_E_NONE 2378 * BCM_E_PARAM 2379 * BCM_E_UNAVAIL 2380 * BCM_E_INIT 2381 * BCM_E_PORT 2382 */ 2383 int 2384 bcm_esw_ipfix_mirror_port_dest_get(int unit, 2385 bcm_ipfix_stage_t stage, 2386 bcm_gport_t port, 2387 int mirror_dest_size, 2388 bcm_gport_t *mirror_dest_id, 2389 int *mirror_dest_count) 2390 { 2391 #ifdef BCM_IPFIX_SUPPORT 2392 const _bcm_ipfix_id_def_t *id_def = NULL; 2393 soc_reg_t reg; 2394 uint64 rval64; 2395 uint32 mirror_bmp; 2396 int mtp_index, index; 2397 2398 if (!soc_feature(unit, soc_feature_ipfix_flow_mirror)) { 2399 return BCM_E_UNAVAIL; 2400 } 2401 2402 #ifdef BCM_TRIUMPH_SUPPORT 2403 if (SOC_IS_TR_VL(unit)) { 2404 id_def = &_ipfix_tr_id_def; 2405 } 2406 #endif /* BCM_TRIUMPH_SUPPORT */ 2407 if (id_def == NULL) { 2408 return BCM_E_INTERNAL; 2409 } 2410 2411 if (_bcm_ipfix_ctrl[unit] == NULL) { 2412 return BCM_E_INIT; 2413 } 2414 2415 if (stage != BCM_IPFIX_STAGE_INGRESS && stage != BCM_IPFIX_STAGE_EGRESS) { 2416 return BCM_E_PARAM; 2417 } 2418 2419 BCM_IF_ERROR_RETURN(_bcm_ipfix_gport_resolve(unit, port, &port)); 2420 2421 if (mirror_dest_id == NULL || mirror_dest_count == NULL) { 2422 return BCM_E_PARAM; 2423 } 2424 2425 reg = id_def->mirror_control[stage]; 2426 2427 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &rval64)); 2428 mirror_bmp = soc_reg64_field32_get(unit, reg, rval64, MIRRORf); 2429 2430 for (index = 0; index < _BCM_IPFIX_RATE_MIRROR_COUNT; index++) { 2431 if (!(mirror_bmp & (1 << index))) { 2432 continue; 2433 } 2434 if (*mirror_dest_count >= mirror_dest_size) { 2435 break; 2436 } 2437 mtp_index = soc_reg64_field32_get(unit, reg, rval64, 2438 id_def->mtp_index[index]); 2439 BCM_GPORT_MIRROR_SET(mirror_dest_id[*mirror_dest_count], mtp_index); 2440 (*mirror_dest_count)++; 2441 } 2442 2443 return BCM_E_NONE; 2444 #else /* BCM_IPFIX_SUPPORT */ 2445 return BCM_E_UNAVAIL; 2446 #endif /* BCM_IPFIX_SUPPORT */ 2447 } 2448 2449 /* 2450 * Function: 2451 * bcm_ipfix_dump_export_entry 2452 * Description: 2453 * To print export entry 2454 * Parameters: 2455 * unit Device number 2456 * data Pointer to converted data in API format 2457 * Return: 2458 * None 2459 */ 2460 void 2461 bcm_ipfix_dump_export_entry(int unit, bcm_ipfix_data_t *data) 2462 { 2463 #ifdef BCM_IPFIX_SUPPORT 2464 char *stage_str, *type_str, *reason_str; 2465 2466 if (data->stage == BCM_IPFIX_STAGE_INGRESS) { 2467 stage_str = "ingress"; 2468 } else if (data->stage == BCM_IPFIX_STAGE_EGRESS) { 2469 stage_str = "egress"; 2470 } else { 2471 stage_str = "unknown stage"; 2472 } 2473 2474 if (data->flags & BCM_IPFIX_DATA_TYPE_L2) { 2475 type_str = "(L2)"; 2476 } else if (data->flags & BCM_IPFIX_DATA_TYPE_IP4) { 2477 type_str = "(IPv4)"; 2478 } else if (data->flags & BCM_IPFIX_DATA_TYPE_IP6) { 2479 type_str = "(IPv6)"; 2480 } else { 2481 type_str = "(Unknown)"; 2482 } 2483 2484 if (data->flags & BCM_IPFIX_DATA_REASON_FLOW_TIMEOUT) { 2485 reason_str = "flow expired"; 2486 } else if (data->flags & BCM_IPFIX_DATA_REASON_FLOW_END) { 2487 reason_str = "flow end"; 2488 } else if (data->flags & BCM_IPFIX_DATA_REASON_FLOW) { 2489 reason_str = "early export"; 2490 } else if (data->flags & BCM_IPFIX_DATA_REASON_COUNT) { 2491 reason_str = "counter overflow"; 2492 } else if (data->flags & BCM_IPFIX_DATA_REASON_TIMESTAMP) { 2493 reason_str = "timestamp overflow"; 2494 } else { 2495 reason_str = "unknown"; 2496 } 2497 2498 LOG_CLI((BSL_META_U(unit, 2499 "\t%s %s port %d reason=%s\n"), 2500 type_str, stage_str, data->port, reason_str)); 2501 LOG_CLI((BSL_META_U(unit, 2502 "\tstart_timestamp=%d last_timestamp=%d" 2503 " byte_count=%d pkt_count=%d\n"), 2504 data->start_timestamp, data->last_timestamp, 2505 data->byte_count, data->pkt_count)); 2506 LOG_CLI((BSL_META_U(unit, 2507 "\tnon_fragment_pkt_detected=%d fragmented_pkt_detected=%d\n"), 2508 data->flags & BCM_IPFIX_DATA_NON_FRAGMENT_PKT_DETECTED ? 1: 0, 2509 data->flags & BCM_IPFIX_DATA_FRAGMENT_PKT_DETECTED ? 1: 0)); 2510 LOG_CLI((BSL_META_U(unit, 2511 "\tttl_changed_detected=%d ttl=%d tcp_flags=0x%x\n"), 2512 data->flags & BCM_IPFIX_DATA_TTL_CHANGED_DETECTED ? 1: 0, 2513 data->ttl, data->tcp_flags)); 2514 LOG_CLI((BSL_META_U(unit, 2515 "\tdrop_detected=%d dest_port=0x%x egress_vlan=%d " 2516 "dest_multicast=0x%x\n"), 2517 data->flags & BCM_IPFIX_DATA_DROP_DETECTED ? 1: 0, 2518 data->dest_port, data->egress_vlan, data->dest_multicast)); 2519 2520 if (data->flags & BCM_IPFIX_DATA_TYPE_L2) { 2521 LOG_CLI((BSL_META_U(unit, 2522 "\tvlan_tagged=%d vlan=%d vlan_prio=0x%x " 2523 "ether_type=0x%x\n"), 2524 data->flags & BCM_IPFIX_DATA_VLAN_TAGGED ? 1 : 0, 2525 data->vlan, data->vlan_prio, data->ether_type)); 2526 LOG_CLI((BSL_META_U(unit, 2527 "\tsrc_mac_addr=%02x-%02x-%02x-%02x-%02x-%02x" 2528 " dst_mac_addr=%02x-%02x-%02x-%02x-%02x-%02x\n"), 2529 data->src_mac_addr[0], data->src_mac_addr[1], 2530 data->src_mac_addr[2], data->src_mac_addr[3], 2531 data->src_mac_addr[4], data->src_mac_addr[5], 2532 data->dst_mac_addr[0], data->dst_mac_addr[1], 2533 data->dst_mac_addr[2], data->dst_mac_addr[3], 2534 data->dst_mac_addr[4], data->dst_mac_addr[5])); 2535 } else if (data->flags & BCM_IPFIX_DATA_TYPE_IP4) { 2536 LOG_CLI((BSL_META_U(unit, 2537 "\tsrc_ip4_addr=%d.%d.%d.%d dst_ip4_addr=%d.%d.%d.%d\n"), 2538 (data->src_ip4_addr >> 24) & 0xff, 2539 (data->src_ip4_addr >> 16) & 0xff, 2540 (data->src_ip4_addr >> 8) & 0xff, 2541 data->src_ip4_addr & 0xff, 2542 (data->dst_ip4_addr >> 24) & 0xff, 2543 (data->dst_ip4_addr >> 16) & 0xff, 2544 (data->dst_ip4_addr >> 8) & 0xff, 2545 data->dst_ip4_addr & 0xff)); 2546 LOG_CLI((BSL_META_U(unit, 2547 "\tip_protocol=0x%x tos=0x%x\n"), 2548 data->ip_protocol, data->tos)); 2549 LOG_CLI((BSL_META_U(unit, 2550 "\tl4_src_port=%d l4_dst_port=%d source_port=0x%x " 2551 "vlan=%d\n"), 2552 data->l4_src_port, data->l4_dst_port, data->source_port, 2553 data->vlan)); 2554 } else if (data->flags & BCM_IPFIX_DATA_TYPE_IP6) { 2555 LOG_CLI((BSL_META_U(unit, 2556 "\tsrc_ip6_addr=%02x%02x:%02x%02x:%02x%02x:%02x%02x:" 2557 "%02x%02x:%02x%02x:%02x%02x:%02x%02x\n"), 2558 data->src_ip6_addr[0], data->src_ip6_addr[1], 2559 data->src_ip6_addr[2], data->src_ip6_addr[3], 2560 data->src_ip6_addr[4], data->src_ip6_addr[5], 2561 data->src_ip6_addr[6], data->src_ip6_addr[7], 2562 data->src_ip6_addr[8], data->src_ip6_addr[9], 2563 data->src_ip6_addr[10], data->src_ip6_addr[11], 2564 data->src_ip6_addr[12], data->src_ip6_addr[13], 2565 data->src_ip6_addr[14], data->src_ip6_addr[15])); 2566 LOG_CLI((BSL_META_U(unit, 2567 "\tdst_ip6_addr=%02x%02x:%02x%02x:%02x%02x:%02x%02x:" 2568 "%02x%02x:%02x%02x:%02x%02x:%02x%02x\n"), 2569 data->dst_ip6_addr[0], data->dst_ip6_addr[1], 2570 data->dst_ip6_addr[2], data->dst_ip6_addr[3], 2571 data->dst_ip6_addr[4], data->dst_ip6_addr[5], 2572 data->dst_ip6_addr[6], data->dst_ip6_addr[7], 2573 data->dst_ip6_addr[8], data->dst_ip6_addr[9], 2574 data->dst_ip6_addr[10], data->dst_ip6_addr[11], 2575 data->dst_ip6_addr[12], data->dst_ip6_addr[13], 2576 data->dst_ip6_addr[14], data->dst_ip6_addr[15])); 2577 LOG_CLI((BSL_META_U(unit, 2578 "\tip_protocol=0x%x tos=0x%x ip6_flow_label=0x%x\n"), 2579 data->ip_protocol, data->tos, data->ip6_flow_label)); 2580 LOG_CLI((BSL_META_U(unit, 2581 "\tl4_src_port=%d l4_dst_port=%d source_port=0x%x " 2582 "vlan=%d\n"), 2583 data->l4_src_port, data->l4_dst_port, data->source_port, 2584 data->vlan)); 2585 } 2586 #endif /* BCM_IPFIX_SUPPORT */ 2587 } 2588 2589 #ifdef BCM_IPFIX_SUPPORT 2590 /* 2591 * Function: 2592 * _bcm_ipfix_get_field 2593 * Description: 2594 * A generic routine to extract a fragment of bits from source bit stream 2595 * Parameters: 2596 * str Source bit stream, bit 0 is the LSB at LS word offset 2597 * minbit Bit number of the first bit of the extracted data 2598 * maxbit Bit number of the last bit of the extracted data 2599 * data_vp Pointer to array for the extracted data 2600 * Return: 2601 * None 2602 */ 2603 STATIC void 2604 _bcm_ipfix_get_field(uint32 *str, 2605 uint32 minbit, 2606 uint32 maxbit, 2607 void *data_vp) 2608 { 2609 int len, str_index, data_index, right_shift_count, left_shift_count; 2610 uint32 *data = data_vp; 2611 2612 len = maxbit - minbit + 1; 2613 str_index = minbit >> 5; 2614 data_index = 0; 2615 right_shift_count = minbit & 0x1f; 2616 left_shift_count = 32 - right_shift_count; 2617 2618 if (right_shift_count) { 2619 for (; len > 0; len -= 32) { 2620 data[data_index] = str[str_index++] >> right_shift_count; 2621 data[data_index++] |= str[str_index] << left_shift_count; 2622 } 2623 } else { 2624 for (; len > 0; len -= 32) { 2625 data[data_index++] = str[str_index++]; 2626 } 2627 } 2628 if (len & 0x1f) { 2629 data[data_index - 1] &= (1 << (len & 0x1f)) - 1; 2630 } 2631 } 2632 2633 /* 2634 * Function: 2635 * _bcm_ipfix_set_field 2636 * Description: 2637 * A generic routine to implant a fragment of bits into target bit stream 2638 * Parameters: 2639 * str Target bit stream, bit 0 is the LSB at LS word offset 2640 * minbit Bit number of the first bit of the extracted data 2641 * maxbit Bit number of the last bit of the extracted data 2642 * data_vp Pointer to array for the source data 2643 * Return: 2644 * None 2645 */ 2646 STATIC void 2647 _bcm_ipfix_set_field(uint32 *str, 2648 uint32 minbit, 2649 uint32 maxbit, 2650 void *data_vp) 2651 { 2652 int len, str_index, data_index, right_shift_count, left_shift_count; 2653 uint32 *data = data_vp; 2654 uint32 mask; 2655 2656 len = maxbit - minbit + 1; 2657 str_index = minbit >> 5; 2658 data_index = 0; 2659 left_shift_count = minbit & 0x1f; 2660 right_shift_count = 32 - left_shift_count; 2661 2662 if (left_shift_count) { 2663 mask = 0xffffffff; 2664 for (; len >= 32; len -= 32) { 2665 str[str_index] &= ~(mask << left_shift_count); 2666 str[str_index++] |= data[data_index] << left_shift_count; 2667 str[str_index] &= ~(mask >> right_shift_count); 2668 str[str_index] |= data[data_index++] >> right_shift_count; 2669 } 2670 if (len) { 2671 mask = (1 << len) - 1; 2672 str[str_index] &= ~(mask << left_shift_count); 2673 str[str_index++] |= data[data_index] << left_shift_count; 2674 str[str_index] &= ~(mask >> right_shift_count); 2675 str[str_index] |= data[data_index] >> right_shift_count; 2676 } 2677 } else { 2678 for (; len >= 32; len -= 32) { 2679 str[str_index++] = data[data_index++]; 2680 } 2681 if (len) { 2682 mask = (1 << len) - 1; 2683 str[str_index] &= ~mask; 2684 str[str_index] |= data[data_index]; 2685 } 2686 } 2687 } 2688 2689 /* 2690 * Function: 2691 * _bcm_ipfix_process_export_entry 2692 * Description: 2693 * To unpack export entry and convert into API format 2694 * Parameters: 2695 * unit Device number 2696 * stage BCM_IPFIX_STAGE_INGRESS or BCM_IPFIX_STAGE_EGRESS 2697 * entry Export entry from hardware 2698 * data Pointer to converted data in API format 2699 * Return: 2700 * BCM_E_NONE 2701 * BCM_E_INTERNAL 2702 * BCM_E_BUSY Type is IPV6 upper, convert when IPV6 lower is seen 2703 * BCM_E_NOT_FOUND Export entry does not have valid bit set 2704 */ 2705 STATIC int 2706 _bcm_ipfix_process_export_entry(int unit, 2707 bcm_ipfix_stage_t stage, 2708 void *entry, 2709 bcm_ipfix_data_t *data) 2710 { 2711 const _bcm_ipfix_id_def_t *id_def = NULL; 2712 soc_mem_t mem; 2713 uint32 type, flags; 2714 bcm_module_t modid; 2715 bcm_port_t port; 2716 #if defined(BCM_TRIUMPH2_SUPPORT) && defined(INCLUDE_L3) 2717 uint32 intf_type, intf, tunnel; 2718 tunnel_entry_t tunnel_entry; 2719 #endif /* BCM_TRIUMPH2_SUPPORT && INCLUDE_L3 */ 2720 static struct { 2721 int type; 2722 uint32 reason; 2723 uint32 session[3]; /* 95 bits */ 2724 uint32 data[2]; /* 34 bits */ 2725 uint32 key[11]; /* 340 bits */ 2726 } fields[2]; 2727 uint32 fval[12]; 2728 2729 #ifdef BCM_TRIUMPH_SUPPORT 2730 if (SOC_IS_TR_VL(unit)) { 2731 id_def = &_ipfix_tr_id_def; 2732 } 2733 #endif /* BCM_TRIUMPH_SUPPORT */ 2734 if (id_def == NULL) { 2735 return BCM_E_INTERNAL; 2736 } 2737 2738 mem = id_def->export_fifo[stage]; 2739 2740 if (!soc_mem_field32_get(unit, mem, entry, VALIDf)) { 2741 fields[stage].type = -1; 2742 return BCM_E_NOT_FOUND; 2743 } 2744 2745 type = soc_mem_field32_get(unit, mem, entry, KEY_TYPEf); 2746 if (type != 3) { 2747 fields[stage].reason = soc_mem_field32_get(unit, mem, entry, 2748 FIFO_REASON_CODEf); 2749 soc_mem_field_get(unit, mem, entry, DATA_INFOf, 2750 fields[stage].data); 2751 soc_mem_field_get(unit, mem, entry, SESSION_INFOf, 2752 fields[stage].session); 2753 } 2754 switch (type) { 2755 case 0: /* L2 */ 2756 soc_mem_field_get(unit, mem, entry, L2_KEYf, fields[stage].key); 2757 sal_memset(data, 0, sizeof(bcm_ipfix_data_t)); 2758 flags = BCM_IPFIX_DATA_TYPE_L2; 2759 _bcm_ipfix_get_field(fields[stage].key, 6, 21, fval); 2760 data->ether_type = fval[0]; 2761 _bcm_ipfix_get_field(fields[stage].key, 22, 22, fval); 2762 if (fval[0]) { 2763 flags |= BCM_IPFIX_DATA_VLAN_TAGGED; 2764 } 2765 _bcm_ipfix_get_field(fields[stage].key, 23, 25, fval); 2766 data->vlan_prio = fval[0]; 2767 _bcm_ipfix_get_field(fields[stage].key, 26, 37, fval); 2768 data->vlan = fval[0]; 2769 _bcm_ipfix_get_field(fields[stage].key, 38, 85, fval); 2770 SAL_MAC_ADDR_FROM_UINT32(data->dst_mac_addr, fval); 2771 _bcm_ipfix_get_field(fields[stage].key, 86, 133, fval); 2772 SAL_MAC_ADDR_FROM_UINT32(data->src_mac_addr, fval); 2773 break; 2774 case 1: /* IPv4 */ 2775 soc_mem_field_get(unit, mem, entry, IPV4_KEYf, fields[stage].key); 2776 sal_memset(data, 0, sizeof(bcm_ipfix_data_t)); 2777 flags = BCM_IPFIX_DATA_TYPE_IP4; 2778 if (SOC_IS_TRIUMPH(unit)) { 2779 _bcm_ipfix_get_field(fields[stage].key, 64, 95, 2780 &data->dst_ip4_addr); 2781 _bcm_ipfix_get_field(fields[stage].key, 96, 127, 2782 &data->src_ip4_addr); 2783 } else if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 2784 SOC_IS_VALKYRIE2(unit)) { 2785 _bcm_ipfix_get_field(fields[stage].key, 69, 100, 2786 &data->dst_ip4_addr); 2787 _bcm_ipfix_get_field(fields[stage].key, 101, 132, 2788 &data->src_ip4_addr); 2789 } else if (SOC_IS_TRIUMPH3(unit)) { 2790 _bcm_ipfix_get_field(fields[stage].key, 72, 103, 2791 &data->dst_ip4_addr); 2792 _bcm_ipfix_get_field(fields[stage].key, 104, 135, 2793 &data->src_ip4_addr); 2794 } 2795 break; 2796 case 2: /* IPv6 Upper half */ 2797 if (SOC_IS_TRIUMPH(unit)) { 2798 soc_mem_field_get(unit, mem, entry, IPV6_UPPER_KEYf, 2799 &fields[stage].key[7]); 2800 } else if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 2801 SOC_IS_VALKYRIE2(unit)) { 2802 soc_mem_field_get(unit, mem, entry, IPV6_UPPER_KEYf, fval); 2803 _bcm_ipfix_set_field(fields[stage].key, 229, 344, fval); 2804 } else if (SOC_IS_TRIUMPH3(unit)) { 2805 soc_mem_field_get(unit, mem, entry, IPV6_UPPER_KEYf, fval); 2806 _bcm_ipfix_set_field(fields[stage].key, 232, 347, fval); 2807 } 2808 fields[stage].type = type; 2809 return BCM_E_BUSY; 2810 case 3: /* IPv6 Lower half, key only */ 2811 if (fields[stage].type != 2) { 2812 return BCM_E_NOT_FOUND; 2813 } 2814 sal_memset(data, 0, sizeof(bcm_ipfix_data_t)); 2815 flags = BCM_IPFIX_DATA_TYPE_IP6; 2816 if (SOC_IS_TRIUMPH(unit)) { 2817 soc_mem_field_get(unit, mem, entry, IPV6_LOWER_KEYf, 2818 fields[stage].key); 2819 } else if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 2820 SOC_IS_VALKYRIE2(unit)) { 2821 soc_mem_field_get(unit, mem, entry, IPV6_LOWER_KEYf, fval); 2822 _bcm_ipfix_set_field(fields[stage].key, 0, 228, fval); 2823 } else if (SOC_IS_TRIUMPH3(unit)) { 2824 soc_mem_field_get(unit, mem, entry, IPV6_LOWER_KEYf, fval); 2825 _bcm_ipfix_set_field(fields[stage].key, 0, 231, fval); 2826 } 2827 if (SOC_IS_TRIUMPH(unit)) { 2828 _bcm_ipfix_get_field(fields[stage].key, 64, 83, 2829 &data->ip6_flow_label); 2830 _bcm_ipfix_get_field(fields[stage].key, 84, 211, fval); 2831 SAL_IP6_ADDR_FROM_UINT32(data->dst_ip6_addr, fval); 2832 _bcm_ipfix_get_field(fields[stage].key, 212, 339, fval); 2833 SAL_IP6_ADDR_FROM_UINT32(data->src_ip6_addr, fval); 2834 } else if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 2835 SOC_IS_VALKYRIE2(unit)) { 2836 _bcm_ipfix_get_field(fields[stage].key, 69, 88, 2837 &data->ip6_flow_label); 2838 _bcm_ipfix_get_field(fields[stage].key, 89, 216, fval); 2839 SAL_IP6_ADDR_FROM_UINT32(data->dst_ip6_addr, fval); 2840 _bcm_ipfix_get_field(fields[stage].key, 217, 344, fval); 2841 SAL_IP6_ADDR_FROM_UINT32(data->src_ip6_addr, fval); 2842 } else if (SOC_IS_TRIUMPH3(unit)) { 2843 _bcm_ipfix_get_field(fields[stage].key, 72, 91, 2844 &data->ip6_flow_label); 2845 _bcm_ipfix_get_field(fields[stage].key, 92, 219, fval); 2846 SAL_IP6_ADDR_FROM_UINT32(data->dst_ip6_addr, fval); 2847 _bcm_ipfix_get_field(fields[stage].key, 220, 347, fval); 2848 SAL_IP6_ADDR_FROM_UINT32(data->src_ip6_addr, fval); 2849 } 2850 break; 2851 default: 2852 return BCM_E_INTERNAL; 2853 } 2854 fields[stage].type = type; 2855 _bcm_ipfix_get_field(fields[stage].key, 0, 5, fval); 2856 data->port = fval[0]; 2857 if (fields[stage].type) { /* Common IP key fields */ 2858 _bcm_ipfix_get_field(fields[stage].key, 6, 13, fval); 2859 data->ip_protocol = fval[0]; 2860 _bcm_ipfix_get_field(fields[stage].key, 14, 21, fval); 2861 data->tos = fval[0]; 2862 _bcm_ipfix_get_field(fields[stage].key, 22, 37, fval); 2863 data->l4_src_port = fval[0]; 2864 _bcm_ipfix_get_field(fields[stage].key, 38, 53, fval); 2865 data->l4_dst_port = fval[0]; 2866 #if defined(BCM_TRIUMPH2_SUPPORT) && defined(INCLUDE_L3) 2867 if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 2868 SOC_IS_VALKYRIE2(unit)) { 2869 _bcm_ipfix_get_field(fields[stage].key, 54, 55, &intf_type); 2870 _bcm_ipfix_get_field(fields[stage].key, 56, 68, &intf); 2871 switch (intf_type) { 2872 case 0: /* VLAN */ 2873 data->vlan = intf; 2874 break; 2875 case 1: /* L3_IIF */ 2876 if (intf < 4096) { /* vlan id */ 2877 data->vlan = intf; 2878 } else if (intf < 4096 + 512) { /* L3_TUNNEL index */ 2879 if (SOC_MEM_FIELD_VALID(unit, L3_TUNNELm, TUNNEL_IDf)) { 2880 BCM_IF_ERROR_RETURN 2881 (soc_mem_read(unit, L3_TUNNELm, MEM_BLOCK_ANY, 2882 intf - 4096, &tunnel_entry)); 2883 tunnel = soc_mem_field32_get 2884 (unit, L3_TUNNELm, &tunnel_entry, TUNNEL_IDf); 2885 if (tunnel) { 2886 BCM_GPORT_TUNNEL_ID_SET(data->source_port, tunnel); 2887 } 2888 } 2889 } else { /* MPLS */ 2890 /* vrf = intf - 4096 - 512 */ 2891 } 2892 break; 2893 case 2: /* SVP */ 2894 if (_bcm_vp_used_get(unit, intf, _bcmVpTypeMpls)) { 2895 BCM_GPORT_MPLS_PORT_ID_SET(data->source_port, intf); 2896 } else if (_bcm_vp_used_get(unit, intf, _bcmVpTypeMim)) { 2897 BCM_GPORT_MIM_PORT_ID_SET(data->source_port, intf); 2898 } else if (_bcm_vp_used_get(unit, intf, _bcmVpTypeSubport)) { 2899 BCM_GPORT_SUBPORT_GROUP_SET(data->source_port, intf); 2900 } else if (_bcm_vp_used_get(unit, intf, _bcmVpTypeWlan)) { 2901 BCM_GPORT_WLAN_PORT_ID_SET(data->source_port, intf); 2902 } 2903 } 2904 } 2905 #endif /* BCM_TRIUMPH2_SUPPORT && INCLUDE_L3 */ 2906 } 2907 2908 data->stage = stage; 2909 #ifdef BCM_TRIUMPH3_SUPPORT 2910 if (SOC_IS_TRIUMPH3(unit)) { 2911 _bcm_ipfix_get_field(fields[stage].data, 35, 35, fval); 2912 if (fval[0]) { 2913 flags |= BCM_IPFIX_DATA_NON_FRAGMENT_PKT_DETECTED; 2914 } 2915 _bcm_ipfix_get_field(fields[stage].data, 34, 34, fval); 2916 if (fval[0]) { 2917 flags |= BCM_IPFIX_DATA_FRAGMENT_PKT_DETECTED; 2918 } 2919 _bcm_ipfix_get_field(fields[stage].data, 33, 33, fval); 2920 if (fval[0]) { 2921 flags |= BCM_IPFIX_DATA_TTL_CHANGED_DETECTED; 2922 } 2923 _bcm_ipfix_get_field(fields[stage].data, 18, 18, fval); 2924 if (fval[0]) { 2925 flags |= BCM_IPFIX_DATA_DROP_DETECTED; 2926 } 2927 _bcm_ipfix_get_field(fields[stage].data, 25, 32, &data->ttl); 2928 _bcm_ipfix_get_field(fields[stage].data, 19, 24, &data->tcp_flags); 2929 } else 2930 #endif /* BCM_TRIUMPH3_SUPPORT */ 2931 { 2932 _bcm_ipfix_get_field(fields[stage].data, 33, 33, fval); 2933 if (fval[0]) { 2934 flags |= BCM_IPFIX_DATA_NON_FRAGMENT_PKT_DETECTED; 2935 } 2936 _bcm_ipfix_get_field(fields[stage].data, 32, 32, fval); 2937 if (fval[0]) { 2938 flags |= BCM_IPFIX_DATA_FRAGMENT_PKT_DETECTED; 2939 } 2940 _bcm_ipfix_get_field(fields[stage].data, 31, 31, fval); 2941 if (fval[0]) { 2942 flags |= BCM_IPFIX_DATA_TTL_CHANGED_DETECTED; 2943 } 2944 _bcm_ipfix_get_field(fields[stage].data, 16, 16, fval); 2945 if (fval[0]) { 2946 flags |= BCM_IPFIX_DATA_DROP_DETECTED; 2947 } 2948 _bcm_ipfix_get_field(fields[stage].data, 23, 30, &data->ttl); 2949 _bcm_ipfix_get_field(fields[stage].data, 17, 22, &data->tcp_flags); 2950 } 2951 _bcm_ipfix_get_field(fields[stage].data, 0, 2, fval); 2952 switch (fval[0]) { 2953 case 0: /* unicast - modid / port */ 2954 #ifdef BCM_TRIUMPH3_SUPPORT 2955 if (SOC_IS_TRIUMPH3(unit)) { 2956 /* DESTINATIONf: bits 3-9: PORTID, bits 10-17: MODULE */ 2957 _bcm_ipfix_get_field(fields[stage].data, 3, 9, &port); 2958 _bcm_ipfix_get_field(fields[stage].data, 10, 17, &modid); 2959 } else 2960 #endif /* BCM_TRIUMPH3_SUPPORT */ 2961 { 2962 /* DESTINATIONf: bits 3-8: PORTID, bits 9-15: MODULE */ 2963 _bcm_ipfix_get_field(fields[stage].data, 3, 8, &port); 2964 _bcm_ipfix_get_field(fields[stage].data, 9, 15, &modid); 2965 } 2966 BCM_GPORT_MODPORT_SET(data->dest_port, modid, port); 2967 break; 2968 case 1: /* unicast - trunk */ 2969 SOC_GPORT_TRUNK_SET(data->dest_port, fval[0]); 2970 break; 2971 case 2: /* L2 multicast ID */ 2972 _bcm_ipfix_get_field(fields[stage].data, 3, 15, fval); 2973 _BCM_MULTICAST_GROUP_SET 2974 (data->dest_multicast, _BCM_MULTICAST_TYPE_L2, fval[0]); 2975 break; 2976 case 3: /* L3 multicast ID */ 2977 #if defined(BCM_TRX_SUPPORT) && defined(INCLUDE_L3) 2978 #ifdef BCM_TRIUMPH3_SUPPORT 2979 if (SOC_IS_TRIUMPH3(unit)) { 2980 _bcm_ipfix_get_field(fields[stage].data, 3, 17, fval); 2981 } else 2982 #endif /* BCM_TRIUMPH3_SUPPORT */ 2983 { 2984 _bcm_ipfix_get_field(fields[stage].data, 3, 15, fval); 2985 } 2986 if (_bcm_tr_multicast_ipmc_group_type_get 2987 (unit, fval[0], &data->dest_multicast) == BCM_E_NOT_FOUND) { 2988 _BCM_MULTICAST_GROUP_SET 2989 (data->dest_multicast, _BCM_MULTICAST_TYPE_L3, fval[0]); 2990 } 2991 #endif /* BCM_TRX_SUPPORT && INCLUDE_L3 */ 2992 break; 2993 case 4: /* L2 broadcast (VLAN ID) */ 2994 case 5: /* L2 DLF at time of first packet (VLAN ID) */ 2995 _bcm_ipfix_get_field(fields[stage].data, 3, 15, fval); 2996 data->egress_vlan = fval[0]; 2997 break; 2998 default: 2999 break; 3000 } 3001 3002 _bcm_ipfix_get_field(fields[stage].session, 0, 15, &data->start_timestamp); 3003 _bcm_ipfix_get_field(fields[stage].session, 16, 31, &data->last_timestamp); 3004 _bcm_ipfix_get_field(fields[stage].session, 32, 63, &data->byte_count); 3005 _bcm_ipfix_get_field(fields[stage].session, 64, 89, &data->pkt_count); 3006 if (soc_feature(unit, soc_feature_ipfix_rate)) { 3007 _bcm_ipfix_get_field(fields[stage].session, 90, 90, fval); 3008 if (fval[0]) { 3009 flags |= BCM_IPFIX_DATA_RATE_VIOLATION; 3010 } 3011 } 3012 3013 switch(fields[stage].reason) { 3014 case 1: 3015 flags |= BCM_IPFIX_DATA_REASON_FLOW_END; 3016 break; 3017 case 2: 3018 flags |= BCM_IPFIX_DATA_REASON_FLOW_TIMEOUT; 3019 break; 3020 case 3: 3021 flags |= BCM_IPFIX_DATA_REASON_FLOW; 3022 break; 3023 case 4: 3024 flags |= BCM_IPFIX_DATA_REASON_COUNT; 3025 break; 3026 case 5: 3027 flags |= BCM_IPFIX_DATA_REASON_TIMESTAMP; 3028 break; 3029 default: 3030 break; 3031 } 3032 3033 data->flags = flags; 3034 3035 return BCM_E_NONE; 3036 } 3037 3038 /* 3039 * Function: 3040 * _bcm_ipfix_fifo_dma_thread 3041 * Description: 3042 * A task thread to process IPFIX export FIFOs via FIFO DMA 3043 * Parameters: 3044 * unit_vp Device number 3045 * Return: 3046 * None 3047 */ 3048 STATIC void 3049 _bcm_ipfix_fifo_dma_thread(void *unit_vp) 3050 { 3051 int unit = PTR_TO_INT(unit_vp); 3052 _bcm_ipfix_ctrl_t *ipfix_ctrl = _bcm_ipfix_ctrl[unit]; 3053 _bcm_ipfix_callback_entry_t *cb_entry; 3054 const _bcm_ipfix_id_def_t *id_def = NULL; 3055 bcm_ipfix_data_t data; 3056 int rv, entries_per_buf, adv_threshold, interval, count, i, j, non_empty; 3057 int stage, chan, entry_words[2]; 3058 void *host_buf[2], *export_entry[2]; 3059 #ifdef BCM_CMICM_SUPPORT 3060 uint32 rval = 0; 3061 uint8 overflow_ch2 = 0, overflow_ch3 = 0; 3062 uint8 timeout_ch2 = 0, timeout_ch3 = 0; 3063 int cmc = SOC_PCI_CMC(unit); 3064 #endif /* BCM_CMICM_SUPPORT */ 3065 3066 #ifdef BCM_TRIUMPH_SUPPORT 3067 if (SOC_IS_TR_VL(unit)) { 3068 id_def = &_ipfix_tr_id_def; 3069 } 3070 #endif /* BCM_TRIUMPH_SUPPORT */ 3071 if (id_def == NULL) { 3072 ipfix_ctrl->pid = SAL_THREAD_ERROR; 3073 soc_event_generate(unit, SOC_SWITCH_EVENT_THREAD_ERROR, 3074 SOC_SWITCH_EVENT_THREAD_IPFIX, __LINE__, 3075 BCM_E_INTERNAL); 3076 sal_thread_exit(0); 3077 return; 3078 } 3079 3080 entries_per_buf = soc_property_get(unit, spn_IPFIX_HOSTBUF_SIZE, 1024); 3081 adv_threshold = entries_per_buf / 2; 3082 3083 entry_words[0] = soc_mem_entry_words(unit, id_def->export_fifo[0]); 3084 host_buf[0] = 3085 soc_cm_salloc(unit, entries_per_buf * entry_words[0] * sizeof(uint32), 3086 "Ingress IPFIX DMA Buffer"); 3087 if (host_buf[0] == NULL) { 3088 soc_event_generate(unit, SOC_SWITCH_EVENT_THREAD_ERROR, 3089 SOC_SWITCH_EVENT_THREAD_IPFIX, __LINE__, 3090 BCM_E_MEMORY); 3091 goto cleanup_exit; 3092 } 3093 3094 entry_words[1] = soc_mem_entry_words(unit, id_def->export_fifo[1]); 3095 host_buf[1] = 3096 soc_cm_salloc(unit, entries_per_buf * entry_words[1] * sizeof(uint32), 3097 "Egress IPFIX DMA Buffer"); 3098 if (host_buf[1] == NULL) { 3099 soc_event_generate(unit, SOC_SWITCH_EVENT_THREAD_ERROR, 3100 SOC_SWITCH_EVENT_THREAD_IPFIX, __LINE__, 3101 BCM_E_MEMORY); 3102 goto cleanup_exit; 3103 } 3104 3105 for (stage = 0; stage < 2; stage++) { 3106 rv = soc_mem_fifo_dma_start(unit, ipfix_ctrl->dma_chan[stage], 3107 id_def->export_fifo[stage], 3108 MEM_BLOCK_ANY, entries_per_buf, 3109 host_buf[stage]); 3110 if (BCM_FAILURE(rv)) { 3111 soc_event_generate(unit, SOC_SWITCH_EVENT_THREAD_ERROR, 3112 SOC_SWITCH_EVENT_THREAD_IPFIX, __LINE__, rv); 3113 goto cleanup_exit; 3114 } 3115 #ifdef BCM_CMICM_SUPPORT 3116 export_entry[stage] = host_buf[stage]; 3117 #endif 3118 } 3119 3120 while ((interval = ipfix_ctrl->interval)) { 3121 if (SOC_CONTROL(unit)->ipfixIntrEnb) { 3122 #ifdef BCM_TRIUMPH3_SUPPORT 3123 if (SOC_IS_TRIUMPH3(unit)) { 3124 (void)soc_cmicm_intr0_enable 3125 (unit, 3126 IRQ_CMCx_FIFO_CH_DMA(SOC_MEM_FIFO_DMA_CHANNEL_2) | 3127 IRQ_CMCx_FIFO_CH_DMA(SOC_MEM_FIFO_DMA_CHANNEL_3)); 3128 } else 3129 #endif /* BCM_TRIUMPH3_SUPPORT */ 3130 { 3131 (void)soc_intr_enable(unit, (IRQ_FIFO_CH0_DMA | IRQ_FIFO_CH3_DMA)); 3132 } 3133 3134 #ifdef BCM_CMICM_SUPPORT 3135 if (soc_feature(unit, soc_feature_cmicm)) { 3136 /* check for timeout & overflow */ 3137 rval = soc_pci_read(unit, 3138 CMIC_CMCx_FIFO_CHy_RD_DMA_STAT_OFFSET(cmc, 3139 SOC_MEM_FIFO_DMA_CHANNEL_2)); 3140 overflow_ch2 = soc_reg_field_get(unit, 3141 CMIC_CMC0_FIFO_CH2_RD_DMA_STATr, rval, 3142 HOSTMEM_OVERFLOWf); 3143 timeout_ch2 = soc_reg_field_get(unit, 3144 CMIC_CMC0_FIFO_CH2_RD_DMA_STATr, rval, 3145 HOSTMEM_TIMEOUTf); 3146 overflow_ch2 |= timeout_ch2; 3147 3148 rval = soc_pci_read(unit, 3149 CMIC_CMCx_FIFO_CHy_RD_DMA_STAT_OFFSET(cmc, 3150 SOC_MEM_FIFO_DMA_CHANNEL_3)); 3151 overflow_ch3 = soc_reg_field_get(unit, 3152 CMIC_CMC0_FIFO_CH3_RD_DMA_STATr, rval, 3153 HOSTMEM_OVERFLOWf); 3154 timeout_ch3 = soc_reg_field_get(unit, 3155 CMIC_CMC0_FIFO_CH3_RD_DMA_STATr, rval, 3156 HOSTMEM_TIMEOUTf); 3157 overflow_ch3 |= timeout_ch3; 3158 } 3159 #endif /* BCM_CMICM_SUPPORT */ 3160 } 3161 3162 if (sal_sem_take(SOC_CONTROL(unit)->ipfixIntr, interval) < 0) { 3163 LOG_VERBOSE(BSL_LS_BCM_DMA, 3164 (BSL_META_U(unit, 3165 "IPFIX polling timeout\n"))); 3166 } else { 3167 LOG_VERBOSE(BSL_LS_BCM_DMA, 3168 (BSL_META_U(unit, 3169 "IPFIX woken up\n"))); 3170 } 3171 3172 for (i = 0; i < _BCM_IPFIX_CB_MAX; i++) { 3173 cb_entry = &ipfix_ctrl->callback_entry[i]; 3174 switch (cb_entry->state) { 3175 case _BCM_IPFIX_CALLBACK_STATE_REGISTERED: 3176 cb_entry->state = _BCM_IPFIX_CALLBACK_STATE_ACTIVE; 3177 break; 3178 case _BCM_IPFIX_CALLBACK_STATE_UNREGISTERED: 3179 cb_entry->state = _BCM_IPFIX_CALLBACK_STATE_INVALID; 3180 break; 3181 default: 3182 break; 3183 } 3184 } 3185 3186 do { 3187 non_empty = FALSE; 3188 for (stage = 0; stage < 2; stage++) { 3189 chan = ipfix_ctrl->dma_chan[stage]; 3190 #ifdef BCM_CMICM_SUPPORT 3191 if (soc_feature(unit, soc_feature_cmicm)) { 3192 rv = soc_mem_fifo_dma_get_num_entries(unit, chan, &count); 3193 } else 3194 #endif 3195 { 3196 rv = soc_mem_fifo_dma_get_read_ptr(unit, chan, &export_entry[0], 3197 &count); 3198 } 3199 if (SOC_SUCCESS(rv)) { 3200 non_empty = TRUE; 3201 if (count > adv_threshold) { 3202 count = adv_threshold; 3203 } 3204 for (i = 0; i < count; i++) { 3205 #ifdef BCM_CMICM_SUPPORT 3206 rv = _bcm_ipfix_process_export_entry(unit, stage, 3207 export_entry[stage], 3208 &data); 3209 export_entry[stage] = 3210 (uint32 *)export_entry[stage] + entry_words[stage]; 3211 /*From the begining of host buffer*/ 3212 if (((uint32 *)export_entry[stage] - (uint32 *)host_buf[stage])/entry_words[stage] 3213 == entries_per_buf) { 3214 export_entry[stage] = host_buf[stage]; 3215 } 3216 #else 3217 rv = _bcm_ipfix_process_export_entry(unit, stage, 3218 export_entry[0], 3219 &data); 3220 export_entry[0] = 3221 (uint32 *)export_entry[0] + entry_words[stage]; 3222 #endif 3223 if (rv < 0) { 3224 continue; 3225 } 3226 3227 3228 if (bsl_check(bslLayerBcm, bslSourceDma, bslSeverityVerbose, unit)) { 3229 bcm_ipfix_dump_export_entry(unit, &data); 3230 } 3231 for (j = 0; j < _BCM_IPFIX_CB_MAX; j++) { 3232 cb_entry = &ipfix_ctrl->callback_entry[j]; 3233 if (cb_entry->state == 3234 _BCM_IPFIX_CALLBACK_STATE_ACTIVE) { 3235 cb_entry->callback(unit, &data, 3236 cb_entry->userdata); 3237 } 3238 } 3239 } 3240 #ifdef BCM_CMICM_SUPPORT 3241 if (soc_feature(unit, soc_feature_cmicm)) { 3242 (void)_soc_mem_sbus_fifo_dma_set_entries_read(unit, chan, count); 3243 } else 3244 #endif 3245 { 3246 (void)soc_mem_fifo_dma_advance_read_ptr(unit, chan, count); 3247 } 3248 } 3249 } 3250 } while (non_empty); 3251 /* clearing of the FIFO_CH_DMA_INT interrupt by resetring 3252 overflow & timeout status in FIFO_CHx_RD_DMA_STAT_CLR reg */ 3253 #ifdef BCM_CMICM_SUPPORT 3254 if (soc_feature(unit, soc_feature_cmicm)) { 3255 if (overflow_ch2) { 3256 rval = 0; 3257 soc_reg_field_set(unit, 3258 CMIC_CMC0_FIFO_CH2_RD_DMA_STAT_CLRr, &rval, 3259 HOSTMEM_OVERFLOWf, 1); 3260 soc_reg_field_set(unit, 3261 CMIC_CMC0_FIFO_CH2_RD_DMA_STAT_CLRr, &rval, 3262 HOSTMEM_TIMEOUTf, 1); 3263 soc_pci_write(unit, 3264 CMIC_CMCx_FIFO_CHy_RD_DMA_STAT_CLR_OFFSET(cmc, 3265 SOC_MEM_FIFO_DMA_CHANNEL_2), rval); 3266 } 3267 if (overflow_ch3) { 3268 rval = 0; 3269 soc_reg_field_set(unit, 3270 CMIC_CMC0_FIFO_CH3_RD_DMA_STAT_CLRr, &rval, 3271 HOSTMEM_OVERFLOWf, 1); 3272 soc_reg_field_set(unit, 3273 CMIC_CMC0_FIFO_CH3_RD_DMA_STAT_CLRr, &rval, 3274 HOSTMEM_TIMEOUTf, 1); 3275 soc_pci_write(unit, 3276 CMIC_CMCx_FIFO_CHy_RD_DMA_STAT_CLR_OFFSET(cmc, 3277 SOC_MEM_FIFO_DMA_CHANNEL_3), rval); 3278 } 3279 } 3280 #endif /* BCM_CMICM_SUPPORT */ 3281 } 3282 3283 cleanup_exit: 3284 (void)soc_mem_fifo_dma_stop(unit, ipfix_ctrl->dma_chan[0]); 3285 (void)soc_mem_fifo_dma_stop(unit, ipfix_ctrl->dma_chan[1]); 3286 3287 if (host_buf[0] != NULL) { 3288 soc_cm_sfree(unit, host_buf[0]); 3289 } 3290 if (host_buf[1] != NULL) { 3291 soc_cm_sfree(unit, host_buf[1]); 3292 } 3293 ipfix_ctrl->pid = SAL_THREAD_ERROR; 3294 sal_thread_exit(0); 3295 } 3296 #endif /* BCM_IPFIX_SUPPORT */ 3297 3298 #ifdef BCM_WARM_BOOT_SUPPORT 3299 /* 3300 * Function: 3301 * _bcm_esw_ipfix_sync 3302 * Purpose: 3303 * Record ipfix module persisitent info for Level 2 Warm Boot 3304 * Parameters: 3305 * unit - StrataSwitch unit number. 3306 * Returns: 3307 * BCM_E_XXX 3308 */ 3309 int 3310 _bcm_esw_ipfix_sync(int unit) 3311 { 3312 #ifdef BCM_IPFIX_SUPPORT 3313 _bcm_ipfix_ctrl_t *ipfix_ctrl = _bcm_ipfix_ctrl[unit]; 3314 soc_scache_handle_t scache_handle; 3315 uint8 *ipfix_scache = NULL; 3316 int size; 3317 int arry_size; 3318 3319 if (soc_feature(unit, soc_feature_ipfix_rate)) { 3320 /* 3321 * Return error if IPFIX is not initialized. 3322 */ 3323 if (_bcm_ipfix_ctrl[unit] == NULL) { 3324 return BCM_E_INIT; 3325 } 3326 3327 sal_memset(&scache_handle, 0, sizeof(soc_scache_handle_t)); 3328 /* 3329 * Get ipfix base address handle and start writing 3330 * Level-2 recovery data to memory. 3331 */ 3332 size = soc_mem_index_count(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm); 3333 arry_size = _SHR_BITDCLSIZE(size); 3334 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_IPFIX, 0); 3335 BCM_IF_ERROR_RETURN(_bcm_esw_scache_ptr_get(unit, scache_handle, 3336 FALSE, 0, 3337 &ipfix_scache, 3338 BCM_WB_DEFAULT_VERSION, 3339 NULL)); 3340 sal_memcpy(ipfix_scache, &ipfix_ctrl->rate_used_count, 3341 sizeof(ipfix_ctrl->rate_used_count)); 3342 ipfix_scache += sizeof(ipfix_ctrl->rate_used_count); 3343 sal_memcpy(ipfix_scache, ipfix_ctrl->rate_used_bmp, arry_size); 3344 } 3345 #endif /* !BCM_IPFIX_SUPPORT */ 3346 return BCM_E_NONE; 3347 } 3348 #endif /* !BCM_WARM_BOOT_SUPPORT */ 3349 3350 /* 3351 * Function: 3352 * bcm_ipfix_export_fifo_control 3353 * Description: 3354 * To start/stop ipfix export fifo processing thread 3355 * Parameters: 3356 * unit device number 3357 * sal_usecs_t polling interval, set to 0 to stop the thread 3358 * Return: 3359 * BCM_E_NONE 3360 * BCM_E_MEMORY 3361 * BCM_E_UNAVAIL 3362 */ 3363 int 3364 bcm_ipfix_export_fifo_control(int unit, sal_usecs_t interval) 3365 { 3366 #ifdef BCM_IPFIX_SUPPORT 3367 _bcm_ipfix_ctrl_t *ipfix_ctrl = _bcm_ipfix_ctrl[unit]; 3368 const _bcm_ipfix_profile_def_t *profile_def = NULL; 3369 const _bcm_ipfix_id_def_t *id_def = NULL; 3370 int pri; 3371 char name[16]; 3372 3373 if (!soc_feature(unit, soc_feature_ipfix) || 3374 !soc_feature(unit, soc_feature_fifo_dma)) { 3375 return BCM_E_UNAVAIL; 3376 } 3377 3378 #ifdef BCM_TRIUMPH_SUPPORT 3379 if (SOC_IS_TR_VL(unit)) { 3380 profile_def = _ipfix_tr_profile_def; 3381 id_def = &_ipfix_tr_id_def; 3382 } 3383 #endif /* BCM_TRIUMPH_SUPPORT */ 3384 if (profile_def == NULL || id_def == NULL) { 3385 return BCM_E_INTERNAL; 3386 } 3387 3388 if (ipfix_ctrl == NULL) { 3389 BCM_IF_ERROR_RETURN(_bcm_ipfix_init(unit, profile_def, id_def)); 3390 ipfix_ctrl = _bcm_ipfix_ctrl[unit]; 3391 } 3392 3393 sal_snprintf(name, sizeof(name), "bcmIpfixDma.%d", unit); 3394 3395 ipfix_ctrl->interval = interval; 3396 if (interval) { 3397 if (ipfix_ctrl->pid == SAL_THREAD_ERROR) { 3398 pri = soc_property_get(unit, spn_IPFIX_THREAD_PRI, 100); 3399 ipfix_ctrl->pid = sal_thread_create(name, SAL_THREAD_STKSZ, pri, 3400 _bcm_ipfix_fifo_dma_thread, 3401 INT_TO_PTR(unit)); 3402 if (ipfix_ctrl->pid == SAL_THREAD_ERROR) { 3403 LOG_ERROR(BSL_LS_BCM_IPFIX, 3404 (BSL_META_U(unit, 3405 "Could not start thread\n"))); 3406 return BCM_E_MEMORY; 3407 } 3408 } 3409 } else { 3410 /* Wake up thread so it will check the changed interval value */ 3411 sal_sem_give(SOC_CONTROL(unit)->ipfixIntr); 3412 } 3413 3414 return BCM_E_NONE; 3415 #else /* BCM_IPFIX_SUPPORT */ 3416 return BCM_E_UNAVAIL; 3417 #endif /* BCM_IPFIX_SUPPORT */ 3418 } 3419 3420 int _bcm_esw_ipfix_deinit(int unit) 3421 { 3422 #ifdef BCM_IPFIX_SUPPORT 3423 soc_timeout_t timeout; 3424 _bcm_ipfix_ctrl_t *ipfix_ctrl = _bcm_ipfix_ctrl[unit]; 3425 int i; 3426 #ifdef BCM_TRIUMPH3_SUPPORT 3427 uint32 rval; 3428 #endif 3429 3430 if (NULL == ipfix_ctrl) { 3431 return (BCM_E_NONE); 3432 } 3433 3434 bcm_ipfix_export_fifo_control(unit, 0); 3435 3436 soc_timeout_init(&timeout, SAL_BOOT_BCMSIM ? 30000000 : 10000000, 0); 3437 3438 while (ipfix_ctrl->pid != SAL_THREAD_ERROR) 3439 { 3440 if (soc_timeout_check(&timeout) != 0) 3441 { 3442 LOG_ERROR(BSL_LS_BCM_IPFIX, 3443 (BSL_META_U(unit, 3444 "IPFIX thread did not exit.\n"))); 3445 3446 return BCM_E_INTERNAL; 3447 } 3448 } 3449 3450 for (i = 0; i < _BCM_IPFIX_CB_MAX; i++) { 3451 ipfix_ctrl->callback_entry[i].state = 3452 _BCM_IPFIX_CALLBACK_STATE_INVALID; 3453 } 3454 3455 #ifdef BCM_TRIUMPH3_SUPPORT 3456 if (SOC_IS_TRIUMPH3(unit)) { 3457 BCM_IF_ERROR_RETURN(READ_AUX_ARB_CONTROL_2r(unit, &rval)); 3458 soc_reg_field_set(unit, AUX_ARB_CONTROL_2r, &rval, 3459 IPFIX_REFRESH_ENABLEf, 0); 3460 BCM_IF_ERROR_RETURN(WRITE_AUX_ARB_CONTROL_2r(unit, rval)); 3461 } 3462 #endif 3463 3464 return BCM_E_NONE; 3465 #else /* BCM_IPFIX_SUPPORT */ 3466 return BCM_E_UNAVAIL; 3467 #endif /* BCM_IPFIX_SUPPORT */ 3468 } 3469 3470 #ifdef BCM_WARM_BOOT_SUPPORT_SW_DUMP 3471 /* 3472 * Function: 3473 * _bcm_ipfix_sw_dump 3474 * Description: 3475 * Displays IPFIX information maintained in software. 3476 * Parameters: 3477 * unit - Device unit number. 3478 * Return: 3479 * None 3480 */ 3481 void _bcm_ipfix_sw_dump(int unit) 3482 { 3483 #ifdef BCM_IPFIX_SUPPORT 3484 _bcm_ipfix_ctrl_t *ipfix_ctrl = _bcm_ipfix_ctrl[unit]; 3485 int size; 3486 int rate_id; 3487 int rate_id_exists = 0; 3488 3489 if (NULL == ipfix_ctrl) { 3490 LOG_ERROR(BSL_LS_BCM_IPFIX, 3491 (BSL_META_U(unit, 3492 "IPFIX module not initialized.\n"))); 3493 return; 3494 } 3495 size = soc_mem_index_count(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm); 3496 LOG_CLI((BSL_META_U(unit, 3497 "\n SW Information IPFIX - Unit %d\n"), unit)); 3498 LOG_CLI((BSL_META_U(unit, 3499 "\n\tIPFIX Flow Rate Meter ID Info\n"))); 3500 LOG_CLI((BSL_META_U(unit, 3501 "\t-----------------------------\n"))); 3502 for (rate_id = 1; rate_id < size; rate_id++) { 3503 if (SHR_BITGET(_bcm_ipfix_ctrl[unit]->rate_used_bmp, rate_id)) { 3504 LOG_CLI((BSL_META_U(unit, 3505 "\t\tMeterId:%d - exists\n"), rate_id)); 3506 rate_id_exists = 1; 3507 } 3508 } 3509 if (rate_id_exists == 0) { 3510 LOG_CLI((BSL_META_U(unit, 3511 "\t\tNone.\n"))); 3512 } 3513 if (ipfix_ctrl->rate_used_count == 0) { 3514 LOG_CLI((BSL_META_U(unit, 3515 "\n\tFlow Rate Meter config - Disabled\n"))); 3516 } else { 3517 LOG_CLI((BSL_META_U(unit, 3518 "\n\tFlow Rate Meter config - Enabled\n"))); 3519 } 3520 #endif /* !BCM_IPFIX_SUPPORT */ 3521 return; 3522 } 3523 #endif /* !BCM_WARM_BOOT_SUPPORT_SW_DUMP */