ft_export.c (133486B)
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: ft_export.c 8 * Purpose: Implementation of Flowtracker Export APIs. 9 * Requires: 10 */ 11 12 13 #include <bcm_int/esw/flowtracker/ft_group.h> 14 #include <bcm_int/esw/flowtracker/ft_export.h> 15 #include <bcm_int/esw/flowtracker/ft_field.h> 16 17 #if defined(BCM_FLOWTRACKER_SUPPORT) 18 19 #include <soc/cmicm.h> 20 21 22 #ifdef BCM_WARM_BOOT_SUPPORT 23 #include <bcm_int/esw/switch.h> 24 25 #define BCM_WB_FT_EXPORT_VERSION_1_1 SOC_SCACHE_VERSION(1,1) 26 27 /* Default warmboot version */ 28 #define BCM_WB_FT_EXPORT_DEFAULT_VERSION BCM_WB_FT_EXPORT_VERSION_1_1 29 30 #endif 31 32 /* Export software state. */ 33 bcmi_ft_export_state_t *bcmi_ft_export_state[BCM_MAX_NUM_UNITS] = {0}; 34 35 36 37 #define BCMI_FT_XLATE_PARAM(_name, _size) \ 38 bcmFlowtrackerTrackingParamType##_name, \ 39 bcmFlowtrackerExportElementType##_name, \ 40 _size, \ 41 #_name 42 43 typedef struct bcmi_fte_template_record_elem_info_s { 44 int length; 45 bcm_flowtracker_export_element_type_t info_elem; 46 bcm_flowtracker_tracking_param_type_t tracking_param; 47 bcm_flowtracker_check_t check_id; 48 } bcmi_fte_template_record_elem_info_t; 49 50 typedef struct bcmi_fte_template_record_info_s { 51 int info_depth; 52 int total_bits; 53 int flow_key_offset; 54 int flow_key_length; 55 int flow_data_offset; 56 int flow_data_length; 57 bcmi_fte_template_record_elem_info_t *info; 58 } bcmi_fte_template_record_info_t; 59 60 #define BCMI_FTE_RECORD_ELEM_IDX_GET(_start_, _offset_, _len_, _idx_) \ 61 _idx_ = ((_start_) - ((_offset_) + (_len_)))/ 8 62 63 #define BCMI_FTE_RECORD_ELEM_SET(_record_, _idx_, _info_elem_) \ 64 (_record_)->info[(_idx_)].info_elem = (_info_elem_) 65 66 #define BCMI_FTE_RECORD_TRACKING_PARAM_SET(_record_, _idx_, _tracking_p_) \ 67 (_record_)->info[(_idx_)].tracking_param = (_tracking_p_) 68 69 #define BCMI_FTE_RECORD_LENGTH_SET(_record_, _idx_, _length_) \ 70 do { \ 71 int reset_count = 0; \ 72 (_record_)->info[(_idx_)].length = (_length_); \ 73 reset_count = (_length_ - 8) / 8; \ 74 while (reset_count > 0) { \ 75 (_record_)->info[(_idx_) + reset_count].length = 0; \ 76 reset_count--; \ 77 } \ 78 } while(0) 79 80 #define BCMI_FTE_RECORD_FLOW_CHECK_SET(_record_, _idx_, _check_id_) \ 81 (_record_)->info[(_idx_)].check_id = (_check_id_) 82 83 typedef struct bcmi_ft_export_elements_map_s { 84 bcm_flowtracker_tracking_param_type_t tracking_param; 85 bcm_flowtracker_export_element_type_t export_element; 86 int default_data_size; 87 char element_name[BCMI_FT_EXPORT_ELEMENT_NAME_LEN_MAX]; 88 } bcmi_ft_export_elements_map_t; 89 90 91 static bcmi_ft_export_elements_map_t bcmi_ft_export_elements_map[] = { 92 { BCMI_FT_XLATE_PARAM(SrcIPv4, 4 ) }, 93 { BCMI_FT_XLATE_PARAM(DstIPv4, 4 ) }, 94 { BCMI_FT_XLATE_PARAM(L4SrcPort, 2 ) }, 95 { BCMI_FT_XLATE_PARAM(L4DstPort, 2 ) }, 96 { BCMI_FT_XLATE_PARAM(SrcIPv6, 16 ) }, 97 { BCMI_FT_XLATE_PARAM(DstIPv6, 16 ) }, 98 { BCMI_FT_XLATE_PARAM(IPProtocol, 1 ) }, 99 { BCMI_FT_XLATE_PARAM(PktCount, 4 ) }, 100 { BCMI_FT_XLATE_PARAM(ByteCount, 4 ) }, 101 { BCMI_FT_XLATE_PARAM(VRF, 2 ) }, 102 { BCMI_FT_XLATE_PARAM(TTL, 1 ) }, 103 { BCMI_FT_XLATE_PARAM(IPLength, 2 ) }, 104 { BCMI_FT_XLATE_PARAM(IP6Length, 2 ) }, 105 { BCMI_FT_XLATE_PARAM(TcpWindowSize, 2 ) }, 106 { BCMI_FT_XLATE_PARAM(DosAttack, 4 ) }, 107 { BCMI_FT_XLATE_PARAM(VxlanNetworkId, 3 ) }, 108 { BCMI_FT_XLATE_PARAM(NextHeader, 1 ) }, 109 { BCMI_FT_XLATE_PARAM(HopLimit, 1 ) }, 110 { BCMI_FT_XLATE_PARAM(InnerSrcIPv4, 4 ) }, 111 { BCMI_FT_XLATE_PARAM(InnerDstIPv4, 4 ) }, 112 { BCMI_FT_XLATE_PARAM(InnerL4SrcPort, 2 ) }, 113 { BCMI_FT_XLATE_PARAM(InnerL4DstPort, 2 ) }, 114 { BCMI_FT_XLATE_PARAM(InnerSrcIPv6, 16 ) }, 115 { BCMI_FT_XLATE_PARAM(InnerDstIPv6, 16 ) }, 116 { BCMI_FT_XLATE_PARAM(InnerIPProtocol, 1 ) }, 117 { BCMI_FT_XLATE_PARAM(InnerTTL, 1 ) }, 118 { BCMI_FT_XLATE_PARAM(InnerIPLength, 2 ) }, 119 { BCMI_FT_XLATE_PARAM(InnerNextHeader, 1 ) }, 120 { BCMI_FT_XLATE_PARAM(InnerHopLimit, 1 ) }, 121 { BCMI_FT_XLATE_PARAM(InnerIP6Length, 2 ) }, 122 { BCMI_FT_XLATE_PARAM(TcpFlags, 1 ) }, 123 { BCMI_FT_XLATE_PARAM(OuterVlanTag, 2 ) }, 124 { BCMI_FT_XLATE_PARAM(TimestampNewLearn, 6 ) }, 125 { BCMI_FT_XLATE_PARAM(TimestampFlowStart, 6 ) }, 126 { BCMI_FT_XLATE_PARAM(TimestampFlowEnd, 6 ) }, 127 { BCMI_FT_XLATE_PARAM(TimestampCheckEvent1, 6 ) }, 128 { BCMI_FT_XLATE_PARAM(TimestampCheckEvent2, 6 ) }, 129 { BCMI_FT_XLATE_PARAM(InnerDosAttack, 4 ) }, 130 { BCMI_FT_XLATE_PARAM(TunnelClass, 3 ) }, 131 { BCMI_FT_XLATE_PARAM(FlowtrackerCheck, 4 ) }, 132 133 { bcmFlowtrackerTrackingParamTypeNone, bcmFlowtrackerExportElementTypeExportReasons, 2, "ExportReasons"}, 134 { bcmFlowtrackerTrackingParamTypeNone, bcmFlowtrackerExportElementTypeExportFlags, 1, "ExportFlags"}, 135 { bcmFlowtrackerTrackingParamTypeNone, bcmFlowtrackerExportElementTypeFlowtrackerGroup, 1, "FlowtrackerGroup"}, 136 { bcmFlowtrackerTrackingParamTypeNone, bcmFlowtrackerExportElementTypeReserved, 1, "Reserved"} 137 }; 138 139 /* FT Export internal routines. */ 140 141 STATIC int 142 bcmi_ft_export_cb_init(int unit) 143 { 144 bcmi_ft_export_cb_ctrl_t *ft_export_cb_ctrl = BCMI_FT_CB_CTRL(unit); 145 146 if (ft_export_cb_ctrl == NULL) { 147 ft_export_cb_ctrl = sal_alloc(sizeof(bcmi_ft_export_cb_ctrl_t), 148 "IPFIX Control Data"); 149 if (ft_export_cb_ctrl == NULL) { 150 return BCM_E_MEMORY; 151 } 152 sal_memset(ft_export_cb_ctrl, 0, sizeof(bcmi_ft_export_cb_ctrl_t)); 153 154 BCMI_FT_EXPORT_INFO(unit)->export_cb_ctrl = ft_export_cb_ctrl; 155 156 ft_export_cb_ctrl->pid = SAL_THREAD_ERROR; 157 ft_export_cb_ctrl->dma_chan = SOC_MEM_FIFO_DMA_CHANNEL_2; 158 159 } 160 161 return BCM_E_NONE; 162 } 163 164 165 STATIC int 166 bcmi_ft_export_cb_deinit(int unit) 167 { 168 soc_timeout_t timeout; 169 bcmi_ft_export_cb_ctrl_t *ft_export_cb_ctrl = BCMI_FT_CB_CTRL(unit); 170 int i; 171 172 if (NULL == ft_export_cb_ctrl) { 173 return (BCM_E_NONE); 174 } 175 176 bcma_ft_export_fifo_control(unit, 0); 177 178 soc_timeout_init(&timeout, SAL_BOOT_BCMSIM ? 30000000 : 10000000, 0); 179 180 while (ft_export_cb_ctrl->pid != SAL_THREAD_ERROR) { 181 if (soc_timeout_check(&timeout) != 0) { 182 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 183 (BSL_META_U(unit, 184 "IPFIX thread did not exit.\n"))); 185 186 return BCM_E_INTERNAL; 187 } 188 } 189 190 for (i = 0; i < BCMI_FT_CB_MAX; i++) { 191 ft_export_cb_ctrl->callback_entry[i].state = 192 BCMI_FT_CALLBACK_STATE_INVALID; 193 } 194 195 196 sal_free(ft_export_cb_ctrl); 197 ft_export_cb_ctrl = NULL; 198 199 return BCM_E_NONE; 200 } 201 202 #define BCMI_FTE_IPFIX_HDR_VERSION 0xa 203 #define BCMI_FTE_IPFIX_HDR_LENGTH 0x10 204 #define BCMI_FTE_IPFIX_HDR_TIMESTAMP 0x0 205 #define BCMI_FTE_IPFIX_HDR_SEQNUM 0x0 206 #define BCMI_FTE_IPFIX_HDR_OBS_DOMAIN 0x1 207 208 /* IpV4 based IPFIX encap header */ 209 #define BCMI_FTE_IPV4_HDR_CTRL_IP_CHKSUM 0 210 #define BCMI_FTE_IPV4_HDR_CTRL_IP_LENGTH 1 211 #define BCMI_FTE_UDP_HDR_CTRL_LENGTH 2 212 #define BCMI_FTE_UDP_HDR_CTRL_CHKSUM 3 213 #define BCMI_FTE_IPFIX_HDR_CTRL_LENGTH 4 214 #define BCMI_FTE_IPFIX_HDR_CTRL_TIMESTAMP 5 215 #define BCMI_FTE_IPFIX_HDR_CTRL_SEQ_NUM 6 216 #define BCMI_FTE_IPV6_HDR_CTRL_IP_LENGTH 7 217 218 typedef struct bcmi_fte_flex_hdr_upd_info_s { 219 uint32 double_for_chksum; 220 uint32 edit_type; 221 uint32 num_bytes; 222 uint32 offset_type; 223 uint32 offset; 224 uint32 payload_chksum; 225 uint32 chksum_type; 226 } bcmi_fte_flex_hdr_upd_info_t; 227 228 /* HDR UPD CTRL EDIT TYPE hardware values. DO NOT MODIFY */ 229 #define BCMI_FTE_HDR_UDP_CTRL_EDIT_TYPE_LENGTH 0 230 #define BCMI_FTE_HDR_UDP_CTRL_EDIT_TYPE_CHKSUM 1 231 #define BCMI_FTE_HDR_UDP_CTRL_EDIT_TYPE_TIMESTAMP 2 232 #define BCMI_FTE_HDR_UDP_CTRL_EDIT_TYPE_SEQ_NUM 3 233 234 /* Offset Type */ 235 #define BCMI_FTE_HDR_UPD_CTRL_OFFSET_TYPE_IP 1 236 #define BCMI_FTE_HDR_UPD_CTRL_OFFSET_TYPE_UDP 2 237 #define BCMI_FTE_HDR_UPD_CTRL_OFFSET_TYPE_IPFIX 3 238 239 /* CheckSum Type */ 240 #define BCMI_FTE_HDR_UPD_CTRL_CHKSUM_TYPE_NONE 0 241 #define BCMI_FTE_HDR_UPD_CTRL_CHKSUM_TYPE_BIT_OR 1 242 #define BCMI_FTE_HDR_UPD_CTRL_CHKSUM_TYPE_SET 2 243 244 static bcmi_fte_flex_hdr_upd_info_t flex_hdr_upd_info_array[] = { 245 /* BCMI_FTE_IPV4_HDR_CTRL_IP_CHKSUM */ 246 {0, BCMI_FTE_HDR_UDP_CTRL_EDIT_TYPE_CHKSUM, 0x2, 247 BCMI_FTE_HDR_UPD_CTRL_OFFSET_TYPE_IP, 10, 248 0, BCMI_FTE_HDR_UPD_CTRL_CHKSUM_TYPE_SET}, 249 250 /* BCMI_FTE_IPV4_HDR_CTRL_IP_LENGTH */ 251 {0, BCMI_FTE_HDR_UDP_CTRL_EDIT_TYPE_LENGTH, 0x2, 252 BCMI_FTE_HDR_UPD_CTRL_OFFSET_TYPE_IP, 2, 253 0, BCMI_FTE_HDR_UPD_CTRL_CHKSUM_TYPE_BIT_OR}, 254 255 /* BCMI_FTE_UDP_HDR_CTRL_LENGTH */ 256 {1, BCMI_FTE_HDR_UDP_CTRL_EDIT_TYPE_LENGTH, 0x2, 257 BCMI_FTE_HDR_UPD_CTRL_OFFSET_TYPE_UDP, 4, 258 0, BCMI_FTE_HDR_UPD_CTRL_CHKSUM_TYPE_BIT_OR}, 259 260 /* BCMI_FTE_UDP_HDR_CTRL_CHKSUM */ 261 {0, BCMI_FTE_HDR_UDP_CTRL_EDIT_TYPE_CHKSUM, 0x2, 262 BCMI_FTE_HDR_UPD_CTRL_OFFSET_TYPE_UDP, 6, 263 1, BCMI_FTE_HDR_UPD_CTRL_CHKSUM_TYPE_SET}, 264 265 /* BCMI_FTE_IPFIX_HDR_CTRL_LENGTH */ 266 {0, BCMI_FTE_HDR_UDP_CTRL_EDIT_TYPE_LENGTH, 0x2, 267 BCMI_FTE_HDR_UPD_CTRL_OFFSET_TYPE_IPFIX, 2, 268 0, BCMI_FTE_HDR_UPD_CTRL_CHKSUM_TYPE_BIT_OR}, 269 270 /* BCMI_FTE_IPFIX_HDR_CTRL_TIMESTAMP */ 271 {0, BCMI_FTE_HDR_UDP_CTRL_EDIT_TYPE_TIMESTAMP, 0x4, 272 BCMI_FTE_HDR_UPD_CTRL_OFFSET_TYPE_IPFIX, 4, 273 0, BCMI_FTE_HDR_UPD_CTRL_CHKSUM_TYPE_BIT_OR}, 274 275 /* BCMI_FTE_IPFIX_HDR_CTRL_SEQ_NUM */ 276 {0, BCMI_FTE_HDR_UDP_CTRL_EDIT_TYPE_SEQ_NUM, 0x4, 277 BCMI_FTE_HDR_UPD_CTRL_OFFSET_TYPE_IPFIX, 8, 278 0, BCMI_FTE_HDR_UPD_CTRL_CHKSUM_TYPE_BIT_OR}, 279 280 /* BCMI_FTE_IPV6_HDR_CTRL_IP_LENGTH */ 281 {0, BCMI_FTE_HDR_UDP_CTRL_EDIT_TYPE_LENGTH, 0x2, 282 BCMI_FTE_HDR_UPD_CTRL_OFFSET_TYPE_IP, 4, 283 0, BCMI_FTE_HDR_UPD_CTRL_CHKSUM_TYPE_NONE} 284 }; 285 286 STATIC int 287 bcmi_ft_ipfix_header_get(int unit, 288 bcmi_ft_collector_info_t *ft_coll_info, 289 shr_ipfix_header_t *ipfix) 290 { 291 /* Set IPFIX */ 292 sal_memset(ipfix, 0, sizeof(*ipfix)); 293 294 ipfix->version = ft_coll_info->ipfix_hdr.version; 295 ipfix->length = BCMI_FTE_IPFIX_HDR_LENGTH; 296 ipfix->export_time = BCMI_FTE_IPFIX_HDR_TIMESTAMP; 297 ipfix->sequence_num = ft_coll_info->ipfix_hdr.initial_sequence_num; 298 ipfix->observation_id = BCMI_FT_EXPORT_INFO(unit)->ipfix_observation_domain_id; 299 300 return BCM_E_NONE; 301 } 302 303 STATIC int 304 bcmi_ft_udp_header_get(int unit, 305 bcm_flowtracker_collector_info_t *collector_info, 306 shr_udp_header_t *udp) 307 { 308 /* Set UDP */ 309 sal_memset(udp, 0, sizeof(*udp)); 310 udp->src = collector_info->udp.src_port; 311 udp->dst = collector_info->udp.dst_port; 312 313 /* To be calculated later. */ 314 udp->sum = 0; 315 udp->length = 0; 316 317 return BCM_E_NONE; 318 } 319 320 321 STATIC int 322 bcmi_ft_ipv4_header_get(int unit, 323 bcm_flowtracker_collector_info_t *collector_info, 324 uint16 *etype, 325 shr_ipv4_header_t *ipv4) 326 { 327 328 *etype = SHR_L2_ETYPE_IPV4; 329 330 sal_memset(ipv4, 0, sizeof(*ipv4)); 331 332 ipv4->version = SHR_IPV4_VERSION; 333 ipv4->h_length = SHR_IPV4_HEADER_LENGTH_WORDS; 334 ipv4->dscp = collector_info->ipv4.dscp; 335 ipv4->ecn = 0; 336 337 /* Length populated by EDIT_CTRL function. 338 */ 339 ipv4->length = 0; 340 ipv4->id = 0; 341 ipv4->flags = 0; 342 ipv4->f_offset = 0; 343 ipv4->ttl = collector_info->ipv4.ttl; 344 ipv4->protocol = SHR_IP_PROTOCOL_UDP; 345 ipv4->sum = 0; 346 ipv4->src = collector_info->ipv4.src_ip; 347 ipv4->dst = collector_info->ipv4.dst_ip; 348 349 /* Calculate IP header checksum. */ 350 ipv4->sum = 0; 351 352 return BCM_E_NONE; 353 } 354 355 STATIC int 356 bcmi_ft_ipv6_header_get(int unit, 357 bcm_flowtracker_collector_info_t *collector_info, 358 uint16 *etype, 359 shr_ipv6_header_t *ipv6) 360 { 361 *etype = SHR_L2_ETYPE_IPV6; 362 363 sal_memset(ipv6, 0, sizeof(*ipv6)); 364 365 ipv6->version = SHR_IPV6_VERSION; 366 ipv6->t_class = collector_info->ipv6.traffic_class; 367 ipv6->f_label = collector_info->ipv6.flow_label; 368 ipv6->next_header = SHR_IP_PROTOCOL_UDP; 369 ipv6->hop_limit = collector_info->ipv6.hop_limit; 370 sal_memcpy(ipv6->src, collector_info->ipv6.src_ip, sizeof(bcm_ip6_t)); 371 sal_memcpy(ipv6->dst, collector_info->ipv6.dst_ip, sizeof(bcm_ip6_t)); 372 373 /* To be calculated by EDIT_CTRL function */ 374 ipv6->p_length = 0; 375 376 return BCM_E_NONE; 377 } 378 379 STATIC int 380 bcmi_ft_l2_header_get(int unit, 381 bcm_flowtracker_collector_info_t *collector_info, 382 uint16 etype, shr_l2_header_t *l2) 383 { 384 sal_memset(l2, 0, sizeof(*l2)); 385 386 /* Destination and Source MAC */ 387 sal_memcpy(l2->dst_mac, collector_info->eth.dst_mac, SHR_MAC_ADDR_LENGTH); 388 sal_memcpy(l2->src_mac, collector_info->eth.src_mac, SHR_MAC_ADDR_LENGTH); 389 390 /* 391 * VLAN Tag(s) 392 */ 393 if (collector_info->eth.vlan_tag_structure == 394 BCM_FLOWTRACKER_COLLECTOR_ETH_HDR_UNTAGGED) { 395 396 /* Set to 0 to indicate untagged */ 397 l2->outer_vlan_tag.tpid = 0; 398 l2->inner_vlan_tag.tpid = 0; 399 } else { 400 401 /* Fill outer vlan */ 402 if ((collector_info->eth.vlan_tag_structure == 403 BCM_FLOWTRACKER_COLLECTOR_ETH_HDR_SINGLE_TAGGED) || 404 (collector_info->eth.vlan_tag_structure == 405 BCM_FLOWTRACKER_COLLECTOR_ETH_HDR_DOUBLE_TAGGED)) 406 { 407 l2->outer_vlan_tag.tpid = 408 collector_info->eth.outer_tpid; 409 l2->outer_vlan_tag.tci.prio = 410 BCM_VLAN_CTRL_PRIO(collector_info->eth.outer_vlan_tag); 411 l2->outer_vlan_tag.tci.cfi = 412 BCM_VLAN_CTRL_CFI(collector_info->eth.outer_vlan_tag); 413 l2->outer_vlan_tag.tci.vid = 414 BCM_VLAN_CTRL_ID(collector_info->eth.outer_vlan_tag); 415 } else { 416 /* Set to 0 to indicate not inner tagged */ 417 l2->inner_vlan_tag.tpid = 0; 418 } 419 } 420 421 /* Ether Type */ 422 l2->etype = etype; 423 424 return BCM_E_NONE; 425 } 426 427 STATIC int 428 bcmi_ft_collector_packet_build(int unit, 429 bcmi_ft_collector_info_t *ft_coll_info, 430 bcmi_ft_pkt_build_t *pkt_build) 431 { 432 int rv; 433 uint8 *cur_ptr; 434 uint8 *buffer; 435 436 bcm_ethertype_t etype; 437 shr_ipfix_header_t ipfix; 438 shr_udp_header_t udp; 439 shr_ipv4_header_t ipv4; 440 shr_ipv6_header_t ipv6; 441 shr_l2_header_t l2; 442 uint16 flex_offset; 443 444 bcm_flowtracker_collector_info_t *collector_info; 445 446 collector_info = &(ft_coll_info->collector_info); 447 448 etype = 0; 449 sal_memset(&ipfix, 0, sizeof(ipfix)); 450 sal_memset(&udp, 0, sizeof(udp)); 451 sal_memset(&ipv4, 0, sizeof(ipv4)); 452 sal_memset(&ipv6, 0, sizeof(ipv6)); 453 sal_memset(&l2, 0, sizeof(l2)); 454 455 switch(collector_info->transport_type) { 456 case bcmFlowtrackerCollectorTransportTypeIpfixIpv4Udp: 457 458 /* Get IPFIX Header fields */ 459 rv = bcmi_ft_ipfix_header_get(unit, ft_coll_info, &ipfix); 460 BCM_IF_ERROR_RETURN(rv); 461 462 /* Get UDP Header Fields */ 463 rv = bcmi_ft_udp_header_get(unit, collector_info, &udp); 464 BCM_IF_ERROR_RETURN(rv); 465 466 /* Get IPv4 Header Fields */ 467 rv = bcmi_ft_ipv4_header_get(unit, collector_info, &etype, &ipv4); 468 BCM_IF_ERROR_RETURN(rv); 469 470 /* Get L2 Header Fields */ 471 rv = bcmi_ft_l2_header_get(unit, collector_info, etype, &l2); 472 break; 473 474 case bcmFlowtrackerCollectorTransportTypeIpfixIpv6Udp: 475 476 /* Get IPFIX Header fields */ 477 rv = bcmi_ft_ipfix_header_get(unit, ft_coll_info, &ipfix); 478 BCM_IF_ERROR_RETURN(rv); 479 480 /* Get UDP Header Fields */ 481 rv = bcmi_ft_udp_header_get(unit, collector_info, &udp); 482 BCM_IF_ERROR_RETURN(rv); 483 484 /* Get IPv6 Header Fields */ 485 rv = bcmi_ft_ipv6_header_get(unit, collector_info, &etype, &ipv6); 486 BCM_IF_ERROR_RETURN(rv); 487 488 /* Get L2 Header Fields */ 489 rv = bcmi_ft_l2_header_get(unit, collector_info, etype, &l2); 490 break; 491 492 default: 493 return BCM_E_PARAM; 494 } 495 496 BCM_IF_ERROR_RETURN(rv); 497 498 /* 499 * Pack header/labels into given buffer (network packet format). 500 * 501 * Following packing order must be followed to correctly 502 * build the packet encapsulation. 503 */ 504 buffer = pkt_build->encap; 505 cur_ptr = buffer; 506 507 switch(collector_info->transport_type) { 508 case bcmFlowtrackerCollectorTransportTypeIpfixIpv4Udp: 509 510 cur_ptr = shr_l2_header_pack(cur_ptr, &l2); 511 512 /* Set Flowtracker export pkt IP base offset */ 513 pkt_build->ip_offset = cur_ptr - buffer; 514 cur_ptr = shr_ipv4_header_pack(cur_ptr, &ipv4); 515 516 /* Set Flowtracker export pkt UDP base offset */ 517 pkt_build->udp_offset = cur_ptr - buffer; 518 cur_ptr = shr_udp_header_pack(cur_ptr, &udp); 519 520 /* Set Flowtracker export pkt IPFIX base offset */ 521 pkt_build->ipfix_offset = cur_ptr - buffer; 522 cur_ptr = shr_ipfix_header_pack(cur_ptr, &ipfix); 523 524 /* Set Flowtracker export pkt encapsulation length */ 525 pkt_build->encap_length = cur_ptr - buffer; 526 527 /* Set Flowtracker Export pkt UDP Length */ 528 udp.length = pkt_build->encap_length - pkt_build->udp_offset; 529 530 /* pack udp length */ 531 flex_offset = pkt_build->udp_offset + 532 flex_hdr_upd_info_array[BCMI_FTE_UDP_HDR_CTRL_LENGTH].offset; 533 cur_ptr = buffer + flex_offset; 534 SHR_PKT_PACK_U16(cur_ptr, udp.length); 535 536 /* Set Flowtracker export pkt UDP Base checksum */ 537 cur_ptr = buffer + pkt_build->ipfix_offset; 538 pkt_build->udp_base_checksum = 539 shr_udp_initial_checksum_get(0, &ipv4, NULL, cur_ptr, &udp); 540 541 /* Initial Udp checksum calculation */ 542 udp.sum = (pkt_build->udp_base_checksum >> 16) & 0xffff; 543 udp.sum += (pkt_build->udp_base_checksum & 0xffff); 544 udp.sum = (~udp.sum); 545 546 /* pack UDP checksum */ 547 flex_offset = pkt_build->udp_offset + 548 flex_hdr_upd_info_array[BCMI_FTE_UDP_HDR_CTRL_CHKSUM].offset; 549 cur_ptr = buffer + flex_offset; 550 SHR_PKT_PACK_U16(cur_ptr, udp.sum); 551 552 /* Set Flowtracker export pkt IP Length */ 553 ipv4.length = pkt_build->encap_length - pkt_build->ip_offset; 554 555 /* pack ip length */ 556 flex_offset = pkt_build->ip_offset + 557 flex_hdr_upd_info_array[BCMI_FTE_IPV4_HDR_CTRL_IP_LENGTH].offset; 558 cur_ptr = buffer + flex_offset; 559 SHR_PKT_PACK_U16(cur_ptr, ipv4.length); 560 561 /* Set Flowtracker export pkt IP Base checksum */ 562 cur_ptr = buffer + pkt_build->ip_offset; 563 pkt_build->ip_base_checksum = 564 shr_initial_chksum_get(SHR_IPV4_HEADER_LENGTH, cur_ptr); 565 566 /* Initial Ip Header checksum calculation */ 567 ipv4.sum = (pkt_build->ip_base_checksum >> 16) & 0xffff; 568 ipv4.sum += (pkt_build->ip_base_checksum & 0xffff); 569 ipv4.sum = (~ipv4.sum); 570 571 /* pack checksum */ 572 flex_offset = pkt_build->ip_offset + 573 flex_hdr_upd_info_array[BCMI_FTE_IPV4_HDR_CTRL_IP_CHKSUM].offset; 574 cur_ptr = buffer + flex_offset; 575 SHR_PKT_PACK_U16(cur_ptr, ipv4.sum); 576 break; 577 578 case bcmFlowtrackerCollectorTransportTypeIpfixIpv6Udp: 579 580 cur_ptr = shr_l2_header_pack(cur_ptr, &l2); 581 582 /* Set Flowtracker export pkt IP base offset */ 583 pkt_build->ip_offset = cur_ptr - buffer; 584 cur_ptr = shr_ipv6_header_pack(cur_ptr, &ipv6); 585 586 /* Set Flowtracker export pkt UDP base offset */ 587 pkt_build->udp_offset = cur_ptr - buffer; 588 cur_ptr = shr_udp_header_pack(cur_ptr, &udp); 589 590 /* Set Flowtracker export pkt IPFIX base offset */ 591 pkt_build->ipfix_offset = cur_ptr - buffer; 592 cur_ptr = shr_ipfix_header_pack(cur_ptr, &ipfix); 593 594 /* Set Flowtracker export pkt encapsulation length */ 595 pkt_build->encap_length = cur_ptr - buffer; 596 597 /* Set Flowtracker Export pkt UDP Length */ 598 udp.length = pkt_build->encap_length - pkt_build->udp_offset; 599 600 /* pack udp length */ 601 flex_offset = pkt_build->udp_offset + 602 flex_hdr_upd_info_array[BCMI_FTE_UDP_HDR_CTRL_LENGTH].offset; 603 cur_ptr = buffer + flex_offset; 604 SHR_PKT_PACK_U16(cur_ptr, udp.length); 605 606 /* Set Flowtracker export pkt UDP Base checksum */ 607 cur_ptr = buffer + pkt_build->ipfix_offset; 608 pkt_build->udp_base_checksum = 609 shr_udp_initial_checksum_get(1, NULL, &ipv6, cur_ptr, &udp); 610 611 /* Initial UDP Checksum calculation */ 612 udp.sum = (pkt_build->udp_base_checksum >> 16) & 0xffff; 613 udp.sum += (pkt_build->udp_base_checksum & 0xffff); 614 udp.sum = (~udp.sum); 615 616 /* pack UDP checksum */ 617 flex_offset = pkt_build->udp_offset + 618 flex_hdr_upd_info_array[BCMI_FTE_UDP_HDR_CTRL_CHKSUM].offset; 619 cur_ptr = buffer + flex_offset; 620 SHR_PKT_PACK_U16(cur_ptr, udp.sum); 621 622 /* Set Flowtracker export pkt IP payload Length */ 623 ipv6.p_length = pkt_build->encap_length - pkt_build->udp_offset; 624 625 /* pack ip length */ 626 flex_offset = pkt_build->ip_offset + 627 flex_hdr_upd_info_array[BCMI_FTE_IPV6_HDR_CTRL_IP_LENGTH].offset; 628 cur_ptr = buffer + flex_offset; 629 SHR_PKT_PACK_U16(cur_ptr, ipv6.p_length); 630 break; 631 632 default: 633 return BCM_E_PARAM; 634 } 635 636 return BCM_E_NONE; 637 } 638 639 STATIC int 640 bcmi_ft_collector_flex_hdr_upd_ctrl_set(int unit, 641 soc_mem_t mem, 642 uint32 ctrl, 643 int ctrl_bin, 644 bcmi_ft_pkt_build_t *pkt_build, 645 bsc_ex_hdr_construct_cfg_entry_t *hdr, 646 uint32 *chksum_bin_map) 647 { 648 int offset; 649 uint32 hdr_upd_ctrl; 650 soc_field_t hdr_upd_fld; 651 soc_format_t collector_fmt; 652 bcmi_fte_flex_hdr_upd_info_t *flex_hdr_upd_info = NULL; 653 654 soc_field_t fte_flx_hdr_upd_flds[] = { 655 HDR_UPDATE_CTRL_0f, HDR_UPDATE_CTRL_1f, 656 HDR_UPDATE_CTRL_2f, HDR_UPDATE_CTRL_3f, 657 HDR_UPDATE_CTRL_4f, HDR_UPDATE_CTRL_5f, 658 HDR_UPDATE_CTRL_6f, HDR_UPDATE_CTRL_7f 659 }; 660 661 collector_fmt = HDR_UPDATE_CTRLfmt; 662 663 offset = 0; 664 hdr_upd_ctrl = 0x0; 665 hdr_upd_fld = fte_flx_hdr_upd_flds[ctrl_bin]; 666 flex_hdr_upd_info = &flex_hdr_upd_info_array[ctrl]; 667 668 if (flex_hdr_upd_info->offset_type == 669 BCMI_FTE_HDR_UPD_CTRL_OFFSET_TYPE_IP) { 670 offset = pkt_build->ip_offset; 671 } else if (flex_hdr_upd_info->offset_type == 672 BCMI_FTE_HDR_UPD_CTRL_OFFSET_TYPE_UDP) { 673 offset = pkt_build->udp_offset; 674 } else if (flex_hdr_upd_info->offset_type == 675 BCMI_FTE_HDR_UPD_CTRL_OFFSET_TYPE_IPFIX) { 676 offset = pkt_build->ipfix_offset; 677 } 678 offset += flex_hdr_upd_info->offset; 679 680 soc_format_field32_set(unit, collector_fmt, &hdr_upd_ctrl, 681 FLEX_HDR_EDIT_TYPEf, flex_hdr_upd_info->edit_type); 682 soc_format_field32_set(unit, collector_fmt, &hdr_upd_ctrl, 683 FLEX_HDR_EDIT_OFFSETf, offset); 684 soc_format_field32_set(unit, collector_fmt, &hdr_upd_ctrl, 685 FLEX_HDR_EDIT_NUM_BYTESf, flex_hdr_upd_info->num_bytes); 686 soc_format_field32_set(unit, collector_fmt, &hdr_upd_ctrl, 687 FLEX_HDR_EDIT_VALIDf, 1); 688 689 if (flex_hdr_upd_info->double_for_chksum == 1) { 690 soc_format_field32_set(unit, collector_fmt, &hdr_upd_ctrl, 691 DOUBLE_FOR_CHKSUMf, 0x1); 692 } 693 if (flex_hdr_upd_info->payload_chksum == 1) { 694 soc_format_field32_set(unit, collector_fmt, &hdr_upd_ctrl, 695 PAYLOAD_CHKSUM_ENf, 0x1); 696 } 697 if (flex_hdr_upd_info->chksum_type == 698 BCMI_FTE_HDR_UPD_CTRL_CHKSUM_TYPE_BIT_OR) { 699 (*chksum_bin_map) |= (1 << ctrl_bin); 700 } else if (flex_hdr_upd_info->chksum_type == 701 BCMI_FTE_HDR_UPD_CTRL_CHKSUM_TYPE_SET) { 702 soc_format_field32_set(unit, collector_fmt, &hdr_upd_ctrl, 703 CHKSUM_EN_BITMAPf, *chksum_bin_map); 704 *chksum_bin_map = 0; 705 } 706 707 soc_mem_field32_set(unit, mem, hdr, hdr_upd_fld, hdr_upd_ctrl); 708 709 return BCM_E_NONE; 710 } 711 712 STATIC int 713 bcmi_ft_collector_hdr_construct(int unit, 714 bcm_flowtracker_collector_t coll_hw_id, 715 bcm_flowtracker_collector_info_t *collector_info, 716 bcmi_ft_pkt_build_t *pkt_build) 717 { 718 int rv; 719 int index = 0; 720 int ctrl_count = 0; 721 uint32 chksum_bin_map; 722 uint32 ctrl_array[8]; 723 uint32 ctrl_bin_array[8]; 724 soc_mem_t mem; 725 bsc_ex_hdr_construct_cfg_entry_t hdr; 726 727 mem = BSC_EX_HDR_CONSTRUCT_CFGm; 728 sal_memset(&hdr, 0, sizeof(bsc_ex_hdr_construct_cfg_entry_t)); 729 chksum_bin_map = 0; 730 731 switch(collector_info->transport_type) { 732 case bcmFlowtrackerCollectorTransportTypeIpfixIpv4Udp: 733 734 /* Do Not Change Order */ 735 ctrl_array[0] = BCMI_FTE_IPFIX_HDR_CTRL_LENGTH; 736 ctrl_bin_array[0] = 1; 737 ctrl_array[1] = BCMI_FTE_IPFIX_HDR_CTRL_TIMESTAMP; 738 ctrl_bin_array[1] = 2; 739 ctrl_array[2] = BCMI_FTE_IPFIX_HDR_CTRL_SEQ_NUM; 740 ctrl_bin_array[2] = 3; 741 ctrl_array[3] = BCMI_FTE_UDP_HDR_CTRL_LENGTH; 742 ctrl_bin_array[3] = 4; 743 ctrl_array[4] = BCMI_FTE_UDP_HDR_CTRL_CHKSUM; 744 ctrl_bin_array[4] = 5; 745 ctrl_array[5] = BCMI_FTE_IPV4_HDR_CTRL_IP_LENGTH; 746 ctrl_bin_array[5] = 6; 747 ctrl_array[6] = BCMI_FTE_IPV4_HDR_CTRL_IP_CHKSUM; 748 ctrl_bin_array[6] = 0; 749 ctrl_count = 7; 750 751 for (index = 0; index < ctrl_count; index++) { 752 rv = bcmi_ft_collector_flex_hdr_upd_ctrl_set(unit, 753 mem, ctrl_array[index], ctrl_bin_array[index], 754 pkt_build, &hdr, &chksum_bin_map); 755 BCM_IF_ERROR_RETURN(rv); 756 } 757 break; 758 759 case bcmFlowtrackerCollectorTransportTypeIpfixIpv6Udp: 760 761 /* Do Not Change Order */ 762 ctrl_array[0] = BCMI_FTE_IPFIX_HDR_CTRL_LENGTH; 763 ctrl_bin_array[0] = 0; 764 ctrl_array[1] = BCMI_FTE_IPFIX_HDR_CTRL_TIMESTAMP; 765 ctrl_bin_array[1] = 1; 766 ctrl_array[2] = BCMI_FTE_IPFIX_HDR_CTRL_SEQ_NUM; 767 ctrl_bin_array[2] = 2; 768 ctrl_array[3] = BCMI_FTE_UDP_HDR_CTRL_LENGTH; 769 ctrl_bin_array[3] = 3; 770 ctrl_array[4] = BCMI_FTE_UDP_HDR_CTRL_CHKSUM; 771 ctrl_bin_array[4] = 4; 772 ctrl_array[5] = BCMI_FTE_IPV6_HDR_CTRL_IP_LENGTH; 773 ctrl_bin_array[5] = 5; 774 ctrl_count = 6; 775 776 for (index = 0; index < ctrl_count; index++) { 777 rv = bcmi_ft_collector_flex_hdr_upd_ctrl_set(unit, 778 mem, ctrl_array[index], ctrl_bin_array[index], 779 pkt_build, &hdr, &chksum_bin_map); 780 BCM_IF_ERROR_RETURN(rv); 781 } 782 break; 783 784 default: 785 return BCM_E_PARAM; 786 } 787 788 /* Encap length. */ 789 soc_mem_field32_set(unit, mem, &hdr, HDR_BYTE_LENGTHf, 790 pkt_build->encap_length); 791 792 soc_mem_write(unit, mem, COPYNO_ALL, coll_hw_id, &hdr); 793 794 return BCM_E_NONE; 795 } 796 797 int 798 bcmi_ft_num_records_enc_get(int unit, int val, uint32 *num_rec_enc) 799 { 800 int idx = 0; 801 802 uint32 record_enc_array[] = { 0, 1, 4, 8, 12, 16, 20, 24, 803 28, 32, 40, 48, 56, 64, 96, 128}; 804 805 if (num_rec_enc == NULL) { 806 return BCM_E_PARAM; 807 } 808 809 /* Round off to lower nearest encoding */ 810 for (idx = 0; idx < (COUNTOF(record_enc_array) - 1); idx++) { 811 if ((val >= record_enc_array[idx]) && 812 (val < record_enc_array[idx + 1])) { 813 break; 814 } 815 } 816 *num_rec_enc = idx; 817 818 return BCM_E_NONE; 819 } 820 821 822 823 /* Routine to install FT collector hardware. */ 824 STATIC int 825 bcmi_ft_collector_hw_install(int unit, 826 bcm_flowtracker_collector_t coll_hw_id, 827 int coll_enable) 828 { 829 int ix, rv; 830 int m_idx, m_bytes, m_entries; 831 int min_ptr; 832 int fifo_depth; 833 int coll_depth; 834 int num_collectors; 835 int init_seq; 836 int num_records; 837 uint32 num_records_enc; 838 839 uint8 *buffer; 840 uint32 rval = 0; 841 uint32 dma_en, dma_coll_id; 842 uint32 m_entry_val[2]; 843 bcmi_ft_pkt_build_t pkt_build; 844 845 soc_mem_t collector_mem; 846 soc_reg_t collector_reg; 847 848 bsc_ex_collector_ipfix_packet_build_entry_t m_entry; 849 bsc_ex_collector_config_entry_t config; 850 851 bcmi_ft_collector_info_t *ft_coll_info; 852 bcm_flowtracker_collector_info_t *collector_info; 853 854 855 /* Init pkt_build. */ 856 sal_memset(&pkt_build, 0, sizeof(bcmi_ft_pkt_build_t)); 857 858 ft_coll_info = BCMI_FT_COLLECTOR_INFO(unit, coll_hw_id); 859 collector_info = &(ft_coll_info->collector_info); 860 861 num_records = 1; 862 num_collectors = BCMI_FT_EXPORT_INFO(unit)->max_collectors; 863 fifo_depth = (soc_mem_index_count(unit, BSC_EX_EXPORT_FIFOm) / 2); 864 coll_depth = (fifo_depth / num_collectors); 865 min_ptr = (coll_depth * coll_hw_id); 866 m_entries = (soc_mem_index_count(unit, BSC_EX_COLLECTOR_IPFIX_PACKET_BUILDm) / 867 soc_mem_index_count(unit, BSC_EX_COLLECTOR_CONFIGm)); 868 869 init_seq = (ft_coll_info->ipfix_hdr).initial_sequence_num; 870 871 /* Flush Collector before enabling. */ 872 collector_mem = BSC_EX_COLLECTOR_CONFIGm; 873 sal_memset(&config, 0, sizeof(config)); 874 soc_mem_field32_set(unit, collector_mem, 875 &config, FLUSHf, 0x1); 876 soc_mem_write(unit, collector_mem, COPYNO_ALL, coll_hw_id, &config); 877 878 879 880 /* Disable DMA for Local collector */ 881 collector_reg = BSC_EX_EXPORT_CONTROLr; 882 rv = soc_reg32_get(unit, collector_reg, REG_PORT_ANY, 0, &rval); 883 BCM_IF_ERROR_RETURN(rv); 884 885 dma_en = soc_reg_field_get(unit, collector_reg, rval, DMA_ENf); 886 dma_coll_id = soc_reg_field_get(unit, collector_reg, rval, DMA_COLLECTOR_IDf); 887 888 if ((dma_en == 1) && (coll_hw_id == dma_coll_id)) { 889 soc_reg_field_set(unit, collector_reg, &rval, DMA_ENf, 0x0); 890 soc_reg_field_set(unit, collector_reg, &rval, DMA_COLLECTOR_IDf, 0x0); 891 892 rv = soc_reg32_set(unit, collector_reg, REG_PORT_ANY, 0, rval); 893 BCM_IF_ERROR_RETURN(rv); 894 } 895 896 897 /* For uninstalling, flush collector, disable and return */ 898 if (coll_enable == 0) { 899 return BCM_E_NONE; 900 } 901 902 /* Populate PACKET_BUILD. */ 903 if (collector_info->collector_type == bcmFlowtrackerCollectorRemote) { 904 collector_mem = BSC_EX_COLLECTOR_IPFIX_PACKET_BUILDm; 905 906 sal_memset(&pkt_build, 0, sizeof(pkt_build)); 907 908 rv = bcmi_ft_collector_packet_build(unit, ft_coll_info, &pkt_build); 909 BCM_IF_ERROR_RETURN(rv); 910 911 num_records = ft_coll_info->num_records; 912 if (num_records == -1) { 913 num_records = ((collector_info->max_packet_length - 914 pkt_build.encap_length) / 915 (BCMI_FT_IPFIX_RECORD_SIZE)); 916 } 917 918 /* Populate PACKET_BUILD */ 919 buffer = &(pkt_build.encap[0]); 920 m_bytes = soc_mem_entry_bytes(unit, collector_mem); 921 m_idx = (coll_hw_id * m_entries); 922 923 for (ix = 0; ix < (m_entries * m_bytes); ix += m_bytes) { 924 /* 64 bit FIELDS field is to be written in Network byte order */ 925 SHR_PKT_UNPACK_U32(buffer, m_entry_val[1]); 926 SHR_PKT_UNPACK_U32(buffer, m_entry_val[0]); 927 928 soc_mem_field_set(unit, collector_mem, (uint32 *)&m_entry, 929 FIELDSf, m_entry_val); 930 soc_mem_write(unit, collector_mem, 931 COPYNO_ALL, (m_idx + (ix / m_bytes)), &m_entry); 932 } 933 934 /* Configure HDR_CONSTRUCT fields. */ 935 rv = bcmi_ft_collector_hdr_construct(unit, 936 coll_hw_id, collector_info, &pkt_build); 937 BCM_IF_ERROR_RETURN(rv); 938 } 939 940 rv = bcmi_ft_num_records_enc_get(unit, num_records, &num_records_enc); 941 BCM_IF_ERROR_RETURN(rv); 942 943 /* Reset sequence number. */ 944 rval = 0; 945 soc_reg_field_set(unit, BSC_EX_SEQ_NUMr, &rval, SEQ_NUMf, init_seq); 946 rv = soc_reg32_set(unit, BSC_EX_SEQ_NUMr, REG_PORT_ANY, coll_hw_id, rval); 947 BCM_IF_ERROR_RETURN(rv); 948 949 /* Enable Collector. */ 950 collector_mem = BSC_EX_COLLECTOR_CONFIGm; 951 soc_mem_field32_set(unit, collector_mem, 952 &config, FLUSHf, 0x0); 953 soc_mem_field32_set(unit, collector_mem, 954 &config, ENABLEf, 0x1); 955 soc_mem_field32_set(unit, collector_mem, 956 &config, MAX_POINTERf, (min_ptr + coll_depth - 1)); 957 soc_mem_field32_set(unit, collector_mem, 958 &config, MIN_POINTERf, min_ptr); 959 soc_mem_field32_set(unit, collector_mem, 960 &config, MAX_RECORDS_PER_PACKETf, num_records_enc); 961 soc_mem_field32_set(unit, collector_mem, 962 &config, TIME_INTERVAL_ENABLEf, 0x1); 963 soc_mem_field32_set(unit, collector_mem, 964 &config, TIME_INTERVALf, 0x1); 965 966 967 /* Enable threshold based drain. */ 968 if (SAL_BOOT_BCMSIM) { 969 soc_mem_field32_set(unit, collector_mem, 970 &config, MAX_RECORDS_PER_PACKETf, 0x1); 971 soc_mem_field32_set(unit, collector_mem, 972 &config, TIME_INTERVAL_ENABLEf, 0x0); 973 soc_mem_field32_set(unit, collector_mem, 974 &config, TIME_INTERVALf, 0x0); 975 } 976 977 if (collector_info->collector_type == bcmFlowtrackerCollectorRemote) { 978 soc_mem_field32_set(unit, collector_mem, 979 &config, PACKET_BUILD_ENABLEf, 0x1); 980 } else { 981 /* Local collector */ 982 rval = 0; 983 collector_reg = BSC_EX_EXPORT_CONTROLr; 984 985 soc_reg_field_set(unit, collector_reg, &rval, DMA_ENf, 0x1); 986 soc_reg_field_set(unit, collector_reg, &rval, DMA_COLLECTOR_IDf, coll_hw_id); 987 988 rv = soc_reg32_set(unit, collector_reg, REG_PORT_ANY, 0, rval); 989 BCM_IF_ERROR_RETURN(rv); 990 } 991 soc_mem_write(unit, collector_mem, COPYNO_ALL, coll_hw_id, &config); 992 993 return BCM_E_NONE; 994 } 995 996 /* Routine to validate collector params. */ 997 STATIC int 998 bcmi_ft_collector_info_validate(int unit, 999 bcm_flowtracker_collector_info_t *info) 1000 { 1001 int min_frame_size = 0, max_frame_size = 0; 1002 1003 /* Check if the encap mode is supported. */ 1004 if (info->collector_type == bcmFlowtrackerCollectorRemote) { 1005 switch (info->transport_type) { 1006 case bcmFlowtrackerCollectorTransportTypeIpfixIpv4Udp: 1007 case bcmFlowtrackerCollectorTransportTypeIpfixIpv6Udp: 1008 /* Currently supported encap types for remote collector. */ 1009 break; 1010 default: 1011 return BCM_E_PARAM; 1012 } 1013 } else if (info->collector_type == bcmFlowtrackerCollectorLocal) { 1014 switch (info->transport_type) { 1015 case bcmFlowtrackerCollectorTransportTypeRaw: 1016 /* Only rawmode transport is supported for local collector. */ 1017 break; 1018 default: 1019 return BCM_E_PARAM; 1020 } 1021 } else { 1022 /* Unknown collector type */ 1023 return BCM_E_PARAM; 1024 } 1025 1026 /* Calculate min_frame_size and max_frame_size - TBD */ 1027 if (info->collector_type == bcmFlowtrackerCollectorRemote) { 1028 /* 1029 * IpfixIpv4Udp: L2_HDR + IPV4_HDR + UDP_HDR 1030 * IpfixIpv6Udp: L2_HDR + IPV6_HDR + UDP_HDR 1031 * 1032 * L2_HDR: MACDA (6) + MACSA (6) + TPID (2) = 14 Bytes. 1033 * IPV4_HDR = 20 Bytes. 1034 * IPV6_HDR = 40 Bytes. 1035 * UDP_HDR = 8 Bytes. 1036 */ 1037 if (info->transport_type == 1038 bcmFlowtrackerCollectorTransportTypeIpfixIpv4Udp) { 1039 min_frame_size = 46; 1040 } else if (info->transport_type == 1041 bcmFlowtrackerCollectorTransportTypeIpfixIpv6Udp) { 1042 min_frame_size = 66; 1043 } else { 1044 return BCM_E_PARAM; 1045 } 1046 1047 max_frame_size = (BCMI_FT_IPFIX_PACKET_BUILD_MAX_SIZE + 1048 (BCMI_FT_IPFIX_MAX_RECORDS_PER_PACKET * 1049 BCMI_FT_IPFIX_RECORD_SIZE) 1050 ); 1051 1052 if ((info->max_packet_length < min_frame_size) || 1053 (info->max_packet_length > max_frame_size)) { 1054 return BCM_E_PARAM; 1055 } 1056 } 1057 1058 return BCM_E_NONE; 1059 } 1060 1061 #if 0 1062 int hx5_supported_elems[BCMI_FT_MAX_TEMPLATES] = { 1063 bcmFlowtrackerExportElementTypeSrcIPv4, 1064 bcmFlowtrackerExportElementTypeDstIPv4, 1065 bcmFlowtrackerExportElementTypeSrcIPv6, 1066 bcmFlowtrackerExportElementTypeDstIPv6, 1067 bcmFlowtrackerExportElementTypeL4SrcPort, 1068 bcmFlowtrackerExportElementTypeL4DstPort, 1069 bcmFlowtrackerExportElementTypeIPProtocol, 1070 bcmFlowtrackerExportElementTypePktCount, 1071 bcmFlowtrackerExportElementTypeByteCount, 1072 bcmFlowtrackerExportElementTypeFlowtrackerGroup, 1073 bcmFlowtrackerExportElementTypeReserved 1074 }; 1075 1076 struct hx5_support_elem_s { 1077 bcm_flowtracker_export_element_type_t elem; 1078 char elem_name[20]; 1079 } hx5_supported_elems[BCMI_FT_MAX_TEMPLATES] = { 1080 {bcmFlowtrackerExportElementTypeSrcIPv4, 1081 "SrcIpv4"}, 1082 {bcmFlowtrackerExportElementTypeDstIPv4, 1083 "DstIpv4"}, 1084 {bcmFlowtrackerExportElementTypeSrcIPv6, 1085 "SrcIpv6"}, 1086 {bcmFlowtrackerExportElementTypeDstIPv6, 1087 "DstIpv6"}, 1088 {bcmFlowtrackerExportElementTypeL4SrcPort, 1089 "SrcL4Port"}, 1090 {bcmFlowtrackerExportElementTypeL4DstPort, 1091 "DstL4Port"}, 1092 {bcmFlowtrackerExportElementTypeIPProtocol, 1093 "IpProto"}, 1094 {bcmFlowtrackerExportElementTypePktCount, 1095 "PktCount"}, 1096 {bcmFlowtrackerExportElementTypeByteCount, 1097 "ByteCount"}, 1098 {bcmFlowtrackerExportElementTypeFlowtrackerGroup, 1099 "FlowGroup"}, 1100 {bcmFlowtrackerExportElementTypeReserved, 1101 "Reserved"}, 1102 }; 1103 #endif 1104 1105 1106 /* Routine to validate template params. */ 1107 STATIC int 1108 bcmi_ft_template_validate(int unit, 1109 int num_elems, 1110 bcm_flowtracker_export_element_info_t *elem_list) 1111 { 1112 int ix, jx; 1113 bcm_flowtracker_export_element_info_t *elem; 1114 1115 if ((num_elems <= 0) || 1116 (num_elems >= BCMI_FT_EXPORT_INFO(unit)->max_elements)) { 1117 return BCM_E_PARAM; 1118 } 1119 1120 1121 for (jx = 0; jx < num_elems; jx++) { 1122 elem = elem_list +jx; 1123 1124 for (ix = 0; ix < COUNTOF(bcmi_ft_export_elements_map); ix++) { 1125 if (elem->element == bcmi_ft_export_elements_map[ix].export_element) { 1126 /* Break the loop when found. */ 1127 break; 1128 } 1129 } 1130 1131 /* Reached end of supported list. Not found. */ 1132 if (ix >= COUNTOF(bcmi_ft_export_elements_map)) { 1133 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 1134 (BSL_META_U(unit, 1135 "Could not find name for element %d\n"), elem->element)); 1136 return BCM_E_PARAM; 1137 } 1138 } 1139 1140 return BCM_E_NONE; 1141 } 1142 1143 /* 1144 * Function: 1145 * bcmi_ft_template_id_alloc 1146 * Purpose: 1147 * get free index for template id. 1148 * Parameters: 1149 * unit - (IN) BCM device id 1150 * alloc - (IN) Allocate a fresh id. 1151 * template_id - (OUT) FT export template id. 1152 * 1153 * Returns: 1154 * BCM_E_XXX. 1155 */ 1156 STATIC int 1157 bcmi_ft_template_id_alloc(int unit, int alloc, int *template_id) 1158 { 1159 1160 int idx, num_templates; 1161 1162 num_templates = BCMI_FT_EXPORT_INFO(unit)->max_templates; 1163 1164 1165 if (!alloc) { 1166 idx = *template_id; 1167 if ((idx >= num_templates) || 1168 (idx <= BCMI_FT_TEMPLATE_ID_INVALID)) { 1169 return BCM_E_PARAM; 1170 } 1171 1172 if ((SHR_BITGET(BCMI_FT_TEMPLATE_BITMAP(unit), idx))) { 1173 return BCM_E_EXISTS; 1174 } 1175 1176 /* Reserve new id. */ 1177 SHR_BITSET(BCMI_FT_TEMPLATE_BITMAP(unit), idx); 1178 1179 return BCM_E_NONE; 1180 } 1181 1182 for (idx = 0; idx < num_templates; idx++) { 1183 1184 if (!(SHR_BITGET(BCMI_FT_TEMPLATE_BITMAP(unit), idx))) { 1185 1186 /* Found an unused template id. */ 1187 SHR_BITSET(BCMI_FT_TEMPLATE_BITMAP(unit), idx); 1188 1189 *template_id = idx; 1190 return BCM_E_NONE; 1191 } 1192 } 1193 1194 return BCM_E_RESOURCE; 1195 } 1196 1197 1198 1199 1200 /* 1201 * Function: 1202 * bcmi_ft_export_state_clear 1203 * Purpose: 1204 * Clear Flowtracker export state. 1205 * Parameters: 1206 * unit - (IN) BCM device id 1207 * 1208 * Returns: 1209 * None. 1210 */ 1211 int 1212 bcmi_ft_export_state_clear(int unit) 1213 { 1214 int ix; 1215 bcmi_ft_template_info_t *template_info; 1216 1217 if (NULL == BCMI_FT_EXPORT_INFO(unit)) { 1218 return (BCM_E_NONE); 1219 } 1220 1221 for (ix = 0; ix < BCMI_FT_EXPORT_INFO(unit)->max_templates; ix++) { 1222 template_info = BCMI_FT_TEMPLATE_INFO(unit, ix); 1223 1224 if (template_info != NULL) { 1225 sal_free(template_info); 1226 template_info = NULL; 1227 } 1228 } 1229 1230 1231 if (bcmi_ft_export_state[unit] != NULL) { 1232 sal_free(bcmi_ft_export_state[unit]); 1233 bcmi_ft_export_state[unit] = NULL; 1234 } 1235 1236 return BCM_E_NONE; 1237 } 1238 1239 /* 1240 * Function: 1241 * bcmi_ft_export_state_init 1242 * Purpose: 1243 * Initialize Flowtracker export state. 1244 * Parameters: 1245 * unit - (IN) BCM device id 1246 * 1247 * Returns: 1248 * None. 1249 */ 1250 int 1251 bcmi_ft_export_state_init(int unit) 1252 { 1253 int ix; 1254 int num_collectors; 1255 int record_length; 1256 soc_mem_t collector_config_mem; 1257 bcmi_ft_collector_info_t *collector_info; 1258 bcmi_ft_template_info_t *template_info; 1259 1260 collector_config_mem = BSC_EX_COLLECTOR_CONFIGm; 1261 1262 /* Allocate export software state. */ 1263 bcmi_ft_export_state[unit] = 1264 sal_alloc(sizeof(bcmi_ft_export_state_t), 1265 "flowtracker export sw state"); 1266 1267 if (bcmi_ft_export_state[unit] == NULL) { 1268 return BCM_E_MEMORY; 1269 } 1270 sal_memset(bcmi_ft_export_state[unit], 0, sizeof(bcmi_ft_export_state_t)); 1271 1272 /* total number of collectors. */ 1273 num_collectors = soc_mem_index_count(unit, collector_config_mem); 1274 BCMI_FT_EXPORT_INFO(unit)->max_collectors = num_collectors; 1275 1276 /* Max number of templates cannot be greater than the max groups. 1277 * Note: EXPORT_FIFO will have half of the record in each entry. 1278 */ 1279 record_length = (soc_mem_entry_words(unit, BSC_EX_EXPORT_FIFOm) * 2) * 4; 1280 BCMI_FT_EXPORT_INFO(unit)->record_length = record_length; 1281 1282 BCMI_FT_EXPORT_INFO(unit)->max_templates = 1283 soc_mem_index_count(unit, BSC_KG_GROUP_TABLEm); 1284 1285 /* Max number of elements in a template cannot be more than the 1286 * number of octets in a record. */ 1287 BCMI_FT_EXPORT_INFO(unit)->max_elements = 1288 BCMI_FT_EXPORT_INFO(unit)->record_length; 1289 1290 /* Initialize independent collector_info structures. */ 1291 for (ix = 0; ix < num_collectors; ix++) { 1292 collector_info = BCMI_FT_COLLECTOR_INFO(unit, ix); 1293 collector_info->coll_hw_id = BCMI_FT_COLLECTOR_ID_INVALID; 1294 collector_info->cmn_coll_id = BCMI_FT_COLLECTOR_ID_INVALID; 1295 collector_info->num_records = -1; 1296 } 1297 1298 /* Allocate memory for each template_info struct. */ 1299 for (ix = 0; ix < BCMI_FT_EXPORT_INFO(unit)->max_templates; ix++) { 1300 1301 template_info = sal_alloc(sizeof(*template_info), "template info"); 1302 if (template_info == NULL) { 1303 return BCM_E_MEMORY; 1304 } 1305 1306 sal_memset(template_info, 0, sizeof(*template_info)); 1307 template_info->template_id = BCMI_FT_TEMPLATE_ID_INVALID; 1308 1309 BCMI_FT_TEMPLATE_INFO(unit, ix) = template_info; 1310 } 1311 1312 return BCM_E_NONE; 1313 } 1314 1315 1316 int 1317 bcmi_ft_export_init(int unit) 1318 { 1319 int rv; 1320 int ipfix_obs_domain_id; 1321 uint32 fld_len, interval, high_val; 1322 uint32 interval_usecs, interval_secs; 1323 uint64 val64; 1324 1325 rv = bcmi_ft_export_cleanup(unit); 1326 BCM_IF_ERROR_RETURN(rv); 1327 1328 rv = bcmi_ft_export_state_init(unit); 1329 BCM_IF_ERROR_RETURN(rv); 1330 1331 if (soc_feature(unit, soc_feature_bscan_ft_fifodma_support)) { 1332 rv = bcmi_ft_export_cb_init(unit); 1333 BCM_IF_ERROR_RETURN(rv); 1334 } 1335 1336 ipfix_obs_domain_id = soc_property_get(unit, 1337 spn_FLOWTRACKER_IPFIX_OBSERVATION_DOMAIN_ID, 1338 BCMI_FTE_IPFIX_HDR_OBS_DOMAIN); 1339 BCMI_FT_EXPORT_INFO(unit)->ipfix_observation_domain_id = 1340 ipfix_obs_domain_id; 1341 1342 interval_secs = soc_property_get(unit, 1343 spn_FLOWTRACKER_EXPORT_INTERVAL_SECS, 0); 1344 interval_usecs = soc_property_get(unit, 1345 spn_FLOWTRACKER_EXPORT_INTERVAL_USECS, 0); 1346 1347 /* Export Interval in seconds */ 1348 COMPILER_64_SET(val64, 0, interval_secs); 1349 1350 /* Export Interval in 100 msecs */ 1351 COMPILER_64_UMUL_32(val64, 10); 1352 1353 /* Converting usecs to 100 msecs */ 1354 interval = interval_usecs / 1000; 1355 interval = interval / 100; 1356 1357 /* Add to get export interval in 100 msecs */ 1358 COMPILER_64_ADD_32(val64, interval); 1359 1360 COMPILER_64_TO_32_HI(high_val, val64); 1361 if (high_val != 0) { 1362 interval = 0xFFFFFFFF; 1363 } else { 1364 COMPILER_64_TO_32_LO(interval, val64); 1365 } 1366 /* In case user have configured export interval value less than 100 ms, 1367 * but not zero. here user intention is to set least value of export 1368 * interval, so set interval=1 (100 ms) */ 1369 if ((interval == 0) && (interval_usecs != 0)) { 1370 interval = 1; 1371 } 1372 1373 fld_len = soc_reg_field_length(unit, BSC_AG_PERIODIC_EXPORTr, EXPORT_PERIODf); 1374 1375 /* Do not exceed field length */ 1376 interval = MIN(interval, ((1 << fld_len) - 1)); 1377 1378 rv = soc_reg_field32_modify(unit, BSC_AG_PERIODIC_EXPORTr, 1379 REG_PORT_ANY, EXPORT_PERIODf, interval); 1380 1381 return rv; 1382 } 1383 1384 int 1385 bcmi_ft_export_cleanup(int unit) 1386 { 1387 int rv; 1388 1389 if (soc_feature(unit, soc_feature_bscan_ft_fifodma_support)) { 1390 rv = bcmi_ft_export_cb_deinit(unit); 1391 BCM_IF_ERROR_RETURN(rv); 1392 } 1393 1394 rv = bcmi_ft_export_state_clear(unit); 1395 BCM_IF_ERROR_RETURN(rv); 1396 1397 return rv; 1398 } 1399 1400 1401 1402 /* 1403 * Function: 1404 * bcmi_ft_collector_create 1405 * Purpose: 1406 * Create flowtracker collector id. 1407 * Description : 1408 * Routine to create a flowtracker collector 1409 * Parameters: 1410 * unit - (IN) BCM device id 1411 * options - (IN) options for group creation 1412 * coll_hw_id - (OUT) FT collector id. 1413 * collector_info - (IN) Collector info. 1414 * 1415 * Returns: 1416 * BCM_E_XXX 1417 */ 1418 int 1419 bcmi_ft_collector_create( 1420 int unit, 1421 uint32 options, 1422 bcm_flowtracker_collector_t *coll_hw_id, 1423 bcm_flowtracker_collector_info_t *collector_info) 1424 { 1425 int rv; 1426 int idx; 1427 bcm_flowtracker_collector_info_t old_collector_info; 1428 bcmi_ft_collector_info_t *ft_coll_info; 1429 bcm_collector_ipfix_header_t *ipfix_hdr; 1430 1431 /* Check if remote collector is supported. */ 1432 if (collector_info->collector_type == 1433 bcmFlowtrackerCollectorRemote) { 1434 1435 if (!(soc_feature(unit, 1436 soc_feature_flowtracker_ver_1_ipfix_remote_collector))) { 1437 return BCM_E_UNAVAIL; 1438 } 1439 } 1440 1441 /* 1442 * Validate collector_info for any unsupported encap or 1443 * export length etc. 1444 */ 1445 rv = bcmi_ft_collector_info_validate(unit, collector_info); 1446 BCM_IF_ERROR_RETURN(rv); 1447 1448 1449 /* REPLACE should be set along with WITH_ID. */ 1450 if ((options & BCM_FLOWTRACKER_COLLECTOR_REPLACE) && 1451 !(options & BCM_FLOWTRACKER_COLLECTOR_WITH_ID)) { 1452 return BCM_E_PARAM; 1453 } 1454 1455 /* While replacing, original entry should be already created. */ 1456 if (options & BCM_FLOWTRACKER_COLLECTOR_REPLACE) { 1457 sal_memset(&old_collector_info, 0, sizeof(old_collector_info)); 1458 1459 rv = bcmi_ft_collector_get(unit, *coll_hw_id, &old_collector_info); 1460 BCM_IF_ERROR_RETURN(rv); 1461 } 1462 1463 /* WITH_ID and not replacing. */ 1464 if (options & BCM_FLOWTRACKER_COLLECTOR_WITH_ID) { 1465 1466 if (options & BCM_FLOWTRACKER_COLLECTOR_REPLACE) { 1467 /* Reserve Id. */ 1468 ft_coll_info = BCMI_FT_COLLECTOR_INFO(unit, *coll_hw_id); 1469 ft_coll_info->coll_hw_id = *coll_hw_id; 1470 } 1471 1472 } else { 1473 for (idx = 0; idx < BCMI_FT_MAX_COLLECTORS; idx++) { 1474 ft_coll_info = BCMI_FT_COLLECTOR_INFO(unit, idx); 1475 if (ft_coll_info->coll_hw_id == 1476 BCMI_FT_COLLECTOR_ID_INVALID) { 1477 break; 1478 } 1479 } 1480 if (idx < BCMI_FT_MAX_COLLECTORS) { 1481 *coll_hw_id = idx; 1482 ft_coll_info = BCMI_FT_COLLECTOR_INFO(unit, *coll_hw_id); 1483 ft_coll_info->coll_hw_id = *coll_hw_id; 1484 } else { 1485 return BCM_E_PARAM; 1486 } 1487 } 1488 1489 /* Copy the collector info to system cache. */ 1490 ft_coll_info = BCMI_FT_COLLECTOR_INFO(unit, *coll_hw_id); 1491 sal_memcpy(&(ft_coll_info->collector_info), 1492 collector_info, sizeof(*collector_info)); 1493 1494 if (!(ft_coll_info->ipfix_hdr_use_custom)) { 1495 1496 ipfix_hdr = &(ft_coll_info->ipfix_hdr); 1497 ipfix_hdr->version = BCMI_FTE_IPFIX_HDR_VERSION; 1498 ipfix_hdr->initial_sequence_num = 0; 1499 } 1500 1501 /* Install in hardware. */ 1502 rv = bcmi_ft_collector_hw_install(unit, *coll_hw_id, TRUE); 1503 1504 if (BCM_SUCCESS(rv)) { 1505 ft_coll_info->coll_hw_id = *coll_hw_id; 1506 } 1507 1508 return rv; 1509 } 1510 1511 1512 /* 1513 * Function: 1514 * bcmi_ft_collector_get 1515 * Purpose: 1516 * Fetch flowtracker collector info. 1517 * Description : 1518 * Routine to create a flowtracker collector 1519 * Parameters: 1520 * unit - (IN) BCM device id 1521 * coll_hw_id - (OUT) FT collector id. 1522 * collector_info - (IN) Collector info. 1523 * 1524 * Returns: 1525 * BCM_E_XXX 1526 */ 1527 int 1528 bcmi_ft_collector_get( 1529 int unit, 1530 bcm_flowtracker_collector_t coll_hw_id, 1531 bcm_flowtracker_collector_info_t *collector_info) 1532 { 1533 bcmi_ft_collector_info_t *ft_coll_info; 1534 1535 if (collector_info == NULL) { 1536 return BCM_E_PARAM; 1537 } 1538 if ((coll_hw_id <= BCMI_FT_COLLECTOR_ID_INVALID) || 1539 (coll_hw_id >= BCMI_FT_MAX_COLLECTORS)) { 1540 return BCM_E_PARAM; 1541 } 1542 1543 ft_coll_info = BCMI_FT_COLLECTOR_INFO(unit, coll_hw_id); 1544 1545 if (ft_coll_info->coll_hw_id == BCMI_FT_COLLECTOR_ID_INVALID) { 1546 return BCM_E_PARAM; 1547 } 1548 1549 sal_memcpy(collector_info, 1550 &(ft_coll_info->collector_info), 1551 sizeof(*collector_info)); 1552 1553 return BCM_E_NONE; 1554 } 1555 1556 1557 /* 1558 * Function: 1559 * bcmi_ft_collector_get_all 1560 * Purpose: 1561 * Fetch all flowtracker collectors info. 1562 * Description : 1563 * Routine to create a flowtracker collector 1564 * Parameters: 1565 * unit - (IN) BCM device id 1566 * max_size - (OUT) Max collectors to read. 1567 * collector_list - (OUT) Collector id list. 1568 * list_size (OUT) - Num of collectors read. 1569 * 1570 * Returns: 1571 * BCM_E_XXX 1572 */ 1573 int 1574 bcmi_ft_collector_get_all( 1575 int unit, 1576 int max_size, 1577 bcm_flowtracker_collector_t *collector_list, 1578 int *list_size) 1579 { 1580 int idx, cnt; 1581 bcm_flowtracker_collector_t *coll_hw_id; 1582 bcmi_ft_collector_info_t *ft_coll_info; 1583 1584 if ((max_size != 0) && (collector_list == NULL)) { 1585 return BCM_E_PARAM; 1586 } 1587 if (list_size == NULL) { 1588 return BCM_E_PARAM; 1589 } 1590 1591 if ((max_size <= BCMI_FT_COLLECTOR_ID_INVALID) || 1592 (max_size >= BCMI_FT_MAX_COLLECTORS)) { 1593 return BCM_E_PARAM; 1594 } 1595 1596 *list_size = cnt = 0; 1597 1598 for (idx = 0; idx < BCMI_FT_MAX_COLLECTORS; idx++) { 1599 ft_coll_info = BCMI_FT_COLLECTOR_INFO(unit, idx); 1600 coll_hw_id = &(collector_list[(*list_size)]); 1601 1602 if (ft_coll_info->coll_hw_id == BCMI_FT_COLLECTOR_ID_INVALID) { 1603 continue; 1604 } 1605 1606 if (cnt < max_size) { 1607 *coll_hw_id = ft_coll_info->coll_hw_id; 1608 cnt++; 1609 } 1610 1611 (*list_size) += 1; 1612 } 1613 1614 if (max_size == 0) { 1615 *list_size = cnt; 1616 } 1617 1618 return BCM_E_NONE; 1619 } 1620 1621 /* 1622 * Function: 1623 * bcmi_ft_collector_destroy 1624 * Purpose: 1625 * Destroy flowtracker collector. 1626 * Description : 1627 * Routine to destroy a flowtracker collector 1628 * Parameters: 1629 * unit - (IN) BCM device id 1630 * coll_hw_id - (OUT) FT collector id. 1631 * 1632 * Returns: 1633 * BCM_E_XXX 1634 */ 1635 int 1636 bcmi_ft_collector_destroy( 1637 int unit, 1638 bcm_flowtracker_collector_t coll_hw_id) 1639 { 1640 bcmi_ft_collector_info_t *ft_coll_info; 1641 1642 if ((coll_hw_id <= BCMI_FT_COLLECTOR_ID_INVALID) || 1643 (coll_hw_id >= BCMI_FT_MAX_COLLECTORS)) { 1644 return BCM_E_PARAM; 1645 } 1646 1647 ft_coll_info = BCMI_FT_COLLECTOR_INFO(unit, coll_hw_id); 1648 if (ft_coll_info->coll_hw_id == BCMI_FT_COLLECTOR_ID_INVALID) { 1649 return BCM_E_NOT_FOUND; 1650 } 1651 1652 /* Allow destroying collector only if it is detached from all groups. */ 1653 if (ft_coll_info->in_use != 0) { 1654 return BCM_E_BUSY; 1655 } 1656 1657 sal_memset(&(ft_coll_info->collector_info), 0, 1658 sizeof(ft_coll_info->collector_info)); 1659 ft_coll_info->coll_hw_id = BCMI_FT_COLLECTOR_ID_INVALID; 1660 ft_coll_info->cmn_coll_id = BCMI_FT_COLLECTOR_ID_INVALID; 1661 ft_coll_info->num_records = -1; 1662 1663 BCM_IF_ERROR_RETURN(bcmi_ft_collector_hw_install(unit, coll_hw_id, FALSE)); 1664 1665 return BCM_E_NONE; 1666 } 1667 1668 1669 #if 0 1670 STATIC int 1671 bcmi_ft_templ_fill_elem(int unit, int num_bits, int elem_size, 1672 bcm_flowtracker_export_element_type_t elem_type, 1673 bcm_flowtracker_export_element_info_t *out_elems, 1674 int *num_elems) 1675 { 1676 bcm_flowtracker_export_element_info_t *l_elem_list; 1677 1678 *num_elems = 0; 1679 while (num_bits) { 1680 l_elem_list = out_elems; 1681 1682 l_elem_list->element = elem_type; 1683 l_elem_list->data_size = 1; 1684 1685 num_bits -= elem_size; 1686 out_elems++; 1687 (*num_elems)++; 1688 } 1689 1690 return BCM_E_NONE; 1691 } 1692 #endif 1693 1694 STATIC int 1695 bcmi_ft_tracking_param_xlate(int unit, 1696 bcm_flowtracker_tracking_param_type_t elem, 1697 int *size, 1698 bcm_flowtracker_export_element_type_t *info_elem) 1699 { 1700 int ix; 1701 1702 for (ix = 0; ix < COUNTOF(bcmi_ft_export_elements_map); ix++) { 1703 if (bcmi_ft_export_elements_map[ix].tracking_param == elem) { 1704 if (size) { 1705 *size = bcmi_ft_export_elements_map[ix].default_data_size; 1706 } 1707 if (info_elem) { 1708 *info_elem = bcmi_ft_export_elements_map[ix].export_element; 1709 } 1710 1711 break; 1712 } 1713 } 1714 1715 1716 return BCM_E_NONE; 1717 } 1718 1719 1720 1721 #if 0 1722 typedef enum pdd_field_type_e { 1723 bcmiFtePddFldTypeAlu32, 1724 bcmiFtePddFldTypeLoad16, 1725 bcmiFtePddFldTypeAlu16, 1726 bcmiFtePddFldTypeLoad8, 1727 bcmiFtePddFldTypeReserved, 1728 } pdd_field_type_t; 1729 1730 struct bcmi_fte_pdd_fields_s { 1731 int length; 1732 pdd_field_type_t field_type; 1733 soc_field_t pdd_field; 1734 } bcmi_fte_flex_pdd_action_list[] = { 1735 {4, bcmiFtePddFldTypeReserved, BSD_FLEX_TIMESTAMP_0f, }, 1736 {4, bcmiFtePddFldTypeReserved, BSD_FLEX_TIMESTAMP_1f, }, 1737 {4, bcmiFtePddFldTypeReserved, BSD_FLEX_TIMESTAMP_2f, }, 1738 {4, bcmiFtePddFldTypeReserved, BSD_FLEX_TIMESTAMP_3f, }, 1739 {4, bcmiFtePddFldTypeReserved, BSD_FLEX_FLOW_METERf, }, 1740 {4, bcmiFtePddFldTypeAlu32, BSD_FLEX_ALU32_TRACKING_PARAM_0f, }, 1741 {4, bcmiFtePddFldTypeAlu32, BSD_FLEX_ALU32_TRACKING_PARAM_1f, }, 1742 {4, bcmiFtePddFldTypeAlu32, BSD_FLEX_ALU32_TRACKING_PARAM_2f, }, 1743 {4, bcmiFtePddFldTypeAlu32, BSD_FLEX_ALU32_TRACKING_PARAM_3f, }, 1744 {4, bcmiFtePddFldTypeAlu32, BSD_FLEX_ALU32_TRACKING_PARAM_4f, }, 1745 {4, bcmiFtePddFldTypeAlu32, BSD_FLEX_ALU32_TRACKING_PARAM_5f, }, 1746 {4, bcmiFtePddFldTypeAlu32, BSD_FLEX_ALU32_TRACKING_PARAM_6f, }, 1747 {4, bcmiFtePddFldTypeAlu32, BSD_FLEX_ALU32_TRACKING_PARAM_7f, }, 1748 {4, bcmiFtePddFldTypeAlu32, BSD_FLEX_ALU32_TRACKING_PARAM_8f, }, 1749 {4, bcmiFtePddFldTypeAlu32, BSD_FLEX_ALU32_TRACKING_PARAM_9f, }, 1750 {4, bcmiFtePddFldTypeAlu32, BSD_FLEX_ALU32_TRACKING_PARAM_10f, }, 1751 {4, bcmiFtePddFldTypeAlu32, BSD_FLEX_ALU32_TRACKING_PARAM_11f, }, 1752 {2, bcmiFtePddFldTypeLoad16, BSD_FLEX_LOAD16_TRACKING_PARAM_0f, }, 1753 {2, bcmiFtePddFldTypeLoad16, BSD_FLEX_LOAD16_TRACKING_PARAM_1f, }, 1754 {2, bcmiFtePddFldTypeLoad16, BSD_FLEX_LOAD16_TRACKING_PARAM_2f, }, 1755 {2, bcmiFtePddFldTypeLoad16, BSD_FLEX_LOAD16_TRACKING_PARAM_3f, }, 1756 {2, bcmiFtePddFldTypeLoad16, BSD_FLEX_LOAD16_TRACKING_PARAM_4f, }, 1757 {2, bcmiFtePddFldTypeLoad16, BSD_FLEX_LOAD16_TRACKING_PARAM_5f, }, 1758 {2, bcmiFtePddFldTypeLoad16, BSD_FLEX_LOAD16_TRACKING_PARAM_6f, }, 1759 {2, bcmiFtePddFldTypeLoad16, BSD_FLEX_LOAD16_TRACKING_PARAM_7f, }, 1760 {2, bcmiFtePddFldTypeLoad16, BSD_FLEX_LOAD16_TRACKING_PARAM_8f, }, 1761 {2, bcmiFtePddFldTypeLoad16, BSD_FLEX_LOAD16_TRACKING_PARAM_9f, }, 1762 {2, bcmiFtePddFldTypeLoad16, BSD_FLEX_LOAD16_TRACKING_PARAM_10f, }, 1763 {2, bcmiFtePddFldTypeLoad16, BSD_FLEX_LOAD16_TRACKING_PARAM_11f, }, 1764 {2, bcmiFtePddFldTypeLoad16, BSD_FLEX_LOAD16_TRACKING_PARAM_12f, }, 1765 {2, bcmiFtePddFldTypeLoad16, BSD_FLEX_LOAD16_TRACKING_PARAM_13f, }, 1766 {2, bcmiFtePddFldTypeLoad16, BSD_FLEX_LOAD16_TRACKING_PARAM_14f, }, 1767 {2, bcmiFtePddFldTypeLoad16, BSD_FLEX_LOAD16_TRACKING_PARAM_15f, }, 1768 {2, bcmiFtePddFldTypeAlu16, BSD_FLEX_ALU16_TRACKING_PARAM_0f, }, 1769 {2, bcmiFtePddFldTypeAlu16, BSD_FLEX_ALU16_TRACKING_PARAM_1f, }, 1770 {2, bcmiFtePddFldTypeAlu16, BSD_FLEX_ALU16_TRACKING_PARAM_2f, }, 1771 {2, bcmiFtePddFldTypeAlu16, BSD_FLEX_ALU16_TRACKING_PARAM_3f, }, 1772 {2, bcmiFtePddFldTypeAlu16, BSD_FLEX_ALU16_TRACKING_PARAM_4f, }, 1773 {2, bcmiFtePddFldTypeAlu16, BSD_FLEX_ALU16_TRACKING_PARAM_5f, }, 1774 {2, bcmiFtePddFldTypeAlu16, BSD_FLEX_ALU16_TRACKING_PARAM_6f, }, 1775 {2, bcmiFtePddFldTypeAlu16, BSD_FLEX_ALU16_TRACKING_PARAM_7f, }, 1776 {2, bcmiFtePddFldTypeReserved, BSD_FLEX_FLOW_COUNT_TO_CPUf, }, 1777 {1, bcmiFtePddFldTypeLoad8, BSD_FLEX_LOAD8_TRACKING_PARAM_0f, }, 1778 {1, bcmiFtePddFldTypeLoad8, BSD_FLEX_LOAD8_TRACKING_PARAM_1f, }, 1779 {1, bcmiFtePddFldTypeLoad8, BSD_FLEX_LOAD8_TRACKING_PARAM_2f, }, 1780 {1, bcmiFtePddFldTypeLoad8, BSD_FLEX_LOAD8_TRACKING_PARAM_3f, }, 1781 {1, bcmiFtePddFldTypeLoad8, BSD_FLEX_LOAD8_TRACKING_PARAM_4f, }, 1782 {1, bcmiFtePddFldTypeLoad8, BSD_FLEX_LOAD8_TRACKING_PARAM_5f, }, 1783 {1, bcmiFtePddFldTypeLoad8, BSD_FLEX_LOAD8_TRACKING_PARAM_6f, }, 1784 {1, bcmiFtePddFldTypeLoad8, BSD_FLEX_LOAD8_TRACKING_PARAM_7f, }, 1785 {1, bcmiFtePddFldTypeReserved, BSD_FLEX_FLOW_STATEf, }, 1786 {0, bcmiFtePddFldTypeReserved, INVALIDf, }, 1787 }; 1788 #endif 1789 1790 STATIC int 1791 bcmi_ft_export_elem_name_get(int unit, 1792 bcm_flowtracker_export_element_type_t info_elem, 1793 int *data_size, 1794 char *elem_name) 1795 { 1796 int ix; 1797 1798 for (ix = 0; ix < COUNTOF(bcmi_ft_export_elements_map); ix++) { 1799 if (bcmi_ft_export_elements_map[ix].export_element == info_elem) { 1800 if (elem_name) { 1801 sal_strncpy(elem_name, bcmi_ft_export_elements_map[ix].element_name, 1802 BCMI_FT_EXPORT_ELEMENT_NAME_LEN_MAX); 1803 } 1804 if (data_size) { 1805 *data_size = bcmi_ft_export_elements_map[ix].default_data_size; 1806 } 1807 break; 1808 } 1809 } 1810 1811 if (ix == COUNTOF(bcmi_ft_export_elements_map)) { 1812 return BCM_E_PARAM; 1813 } 1814 1815 return BCM_E_NONE; 1816 } 1817 1818 STATIC int 1819 bcmi_fte_template_record_flow_key_populate(int unit, 1820 bcm_flowtracker_group_t flow_group, 1821 bcmi_fte_template_record_info_t *record) 1822 { 1823 int rv = BCM_E_NONE; 1824 int idx = 0; 1825 int key_idx = 0; 1826 int offset = 0; 1827 int num_key_info = 0; 1828 int rec_total_bits = 0; 1829 int flow_key_offset = 0; 1830 bcmi_ft_alu_key_t *key_alu = NULL; 1831 bcmi_ft_group_alu_info_t *key_ext_info = NULL; 1832 bcm_flowtracker_export_element_type_t info_elem; 1833 char info_name[BCMI_FT_EXPORT_ELEMENT_NAME_LEN_MAX]; 1834 1835 /* Get Session Key info from FT Group */ 1836 key_ext_info = BCMI_FT_GROUP_EXT_KEY_INFO(unit, flow_group); 1837 num_key_info = BCMI_FT_GROUP_EXT_INFO(unit, flow_group).num_key_info; 1838 1839 rec_total_bits = record->total_bits; 1840 flow_key_offset = record->flow_key_offset; 1841 1842 /* 1st Byte at Flow_key_offset is skipped as it represent KeyType + Mode */ 1843 flow_key_offset += 8; 1844 1845 for (key_idx = 0; key_idx < num_key_info; key_idx++) { 1846 key_alu = &(key_ext_info->key1); 1847 offset = flow_key_offset + key_alu->location; 1848 1849 info_elem = bcmFlowtrackerExportElementTypeReserved; 1850 rv = bcmi_ft_tracking_param_xlate(unit, 1851 key_ext_info->element_type1, NULL, &info_elem); 1852 BCM_IF_ERROR_RETURN(rv); 1853 1854 BCMI_FTE_RECORD_ELEM_IDX_GET(rec_total_bits, offset, key_alu->length, idx); 1855 BCMI_FTE_RECORD_ELEM_SET(record, idx, info_elem); 1856 BCMI_FTE_RECORD_LENGTH_SET(record, idx, key_alu->length); 1857 BCMI_FTE_RECORD_TRACKING_PARAM_SET(record, idx, key_ext_info->element_type1); 1858 1859 sal_memset(info_name, 0, sizeof(char) * BCMI_FT_EXPORT_ELEMENT_NAME_LEN_MAX); 1860 (void) bcmi_ft_export_elem_name_get(unit, info_elem, NULL, info_name); 1861 LOG_DEBUG(BSL_LS_BCM_FLOWTRACKER, (BSL_META_U(unit, 1862 "[TemplateValidate]Element Record_Idx: %2d | Id: %2d (%20s) |" 1863 " Size: %02d\n\r"), idx, info_elem, info_name, key_alu->length)); 1864 key_ext_info++; 1865 } 1866 1867 return BCM_E_NONE; 1868 } 1869 1870 STATIC int 1871 bcmi_fte_template_record_flow_data_polpulate(int unit, 1872 bcm_flowtracker_group_t flow_group, 1873 bcmi_fte_template_record_info_t *record) 1874 { 1875 int rv = BCM_E_NONE; 1876 int idx = 0; 1877 int offset = 0; 1878 int length = 0; 1879 int rec_total_bits = 0; 1880 int flow_data_offset = 0; 1881 bcm_flowtracker_check_t check_id; 1882 bcm_flowtracker_export_element_type_t info_elem; 1883 bcm_flowtracker_tracking_param_type_t tracking_param; 1884 bcmi_ft_group_template_list_t *ftg_template = NULL; 1885 char info_name[BCMI_FT_EXPORT_ELEMENT_NAME_LEN_MAX]; 1886 1887 /* Flow Data is populated from higher bits to lower bits */ 1888 rec_total_bits = record->total_bits; 1889 flow_data_offset = record->flow_data_offset + record->flow_data_length; 1890 1891 ftg_template = ((BCMI_FT_GROUP(unit, flow_group))->template_head); 1892 while(ftg_template) { 1893 switch(ftg_template->info.param_type) { 1894 case bcmiFtGroupParamTypeTracking: 1895 tracking_param = 1896 ftg_template->info.param; 1897 break; 1898 1899 case bcmiFtGroupParamTypeTsNewLearn: 1900 tracking_param = 1901 bcmFlowtrackerTrackingParamTypeTimestampNewLearn; 1902 break; 1903 case bcmiFtGroupParamTypeTsFlowStart: 1904 tracking_param = 1905 bcmFlowtrackerTrackingParamTypeTimestampFlowStart; 1906 break; 1907 case bcmiFtGroupParamTypeTsFlowEnd: 1908 tracking_param = 1909 bcmFlowtrackerTrackingParamTypeTimestampFlowEnd; 1910 break; 1911 case bcmiFtGroupParamTypeTsCheckEvent1: 1912 tracking_param = 1913 bcmFlowtrackerTrackingParamTypeTimestampCheckEvent1; 1914 break; 1915 case bcmiFtGroupParamTypeTsCheckEvent2: 1916 tracking_param = 1917 bcmFlowtrackerTrackingParamTypeTimestampCheckEvent2; 1918 break; 1919 case bcmiFtGroupParamTypeFlowchecker: 1920 tracking_param = 1921 bcmFlowtrackerTrackingParamTypeFlowtrackerCheck; 1922 break; 1923 1924 default: 1925 tracking_param = 1926 bcmFlowtrackerTrackingParamTypeCount; 1927 break; 1928 } 1929 check_id = ftg_template->info.check_id; 1930 info_elem = bcmFlowtrackerExportElementTypeReserved; 1931 rv = bcmi_ft_tracking_param_xlate(unit, 1932 tracking_param, NULL, &info_elem); 1933 BCM_IF_ERROR_RETURN(rv); 1934 1935 length = ftg_template->info.cont_width; 1936 1937 if (ftg_template->info.flags & BCMI_FT_ALU_LOAD_NEXT_ATTACH) { 1938 /* Special case for dos attack. */ 1939 length += ftg_template->next->info.cont_width; 1940 } 1941 1942 if (ftg_template->info.data_shift != 0) { 1943 length -= ftg_template->info.data_shift; 1944 } 1945 offset = ftg_template->info.cont_offset; 1946 offset = flow_data_offset - (offset + length); 1947 1948 BCMI_FTE_RECORD_ELEM_IDX_GET(rec_total_bits, offset, length, idx); 1949 BCMI_FTE_RECORD_ELEM_SET(record, idx, info_elem); 1950 BCMI_FTE_RECORD_LENGTH_SET(record, idx, length); 1951 BCMI_FTE_RECORD_TRACKING_PARAM_SET(record, idx, tracking_param); 1952 BCMI_FTE_RECORD_FLOW_CHECK_SET(record, idx, check_id); 1953 1954 sal_memset(info_name, 0, sizeof(char) * BCMI_FT_EXPORT_ELEMENT_NAME_LEN_MAX); 1955 (void) bcmi_ft_export_elem_name_get(unit, info_elem, NULL, info_name); 1956 LOG_DEBUG(BSL_LS_BCM_FLOWTRACKER, (BSL_META_U(unit, 1957 "[TemplateValidate]Element Record_Idx: %2d | Id: %2d (%20s) |" 1958 " Size: %02d (0x%x)\n\r"), idx, info_elem, info_name, length, 1959 check_id)); 1960 1961 if (ftg_template->info.flags & BCMI_FT_ALU_LOAD_NEXT_ATTACH) { 1962 /* This is surely at least second last. so we can blindly go next.*/ 1963 ftg_template = ftg_template->next; 1964 } 1965 1966 ftg_template = ftg_template->next; 1967 } 1968 1969 return BCM_E_NONE; 1970 } 1971 1972 STATIC int 1973 bcmi_fte_template_record_info_populate(int unit, 1974 bcm_flowtracker_group_t flow_group, 1975 bcmi_fte_template_record_info_t *record) 1976 { 1977 int rv = BCM_E_NONE; 1978 int idx = 0; 1979 int offset = 0; 1980 int length = 0; 1981 int rec_total_bits = 0; 1982 soc_field_info_t *field_info = NULL; 1983 soc_format_t format; 1984 bcm_flowtracker_export_element_type_t info_elem; 1985 char info_name[BCMI_FT_EXPORT_ELEMENT_NAME_LEN_MAX]; 1986 1987 format = BSC_EX_EXPORT_RECORDfmt; 1988 1989 /* Get record total bits, base offset of SET HEADER */ 1990 field_info = NULL; 1991 field_info = soc_format_fieldinfo_get(unit, format, SET_HEADERf); 1992 if (field_info != NULL) { 1993 rec_total_bits = field_info->bp; 1994 } 1995 record->total_bits = rec_total_bits; 1996 record->info_depth = (record->total_bits / 8); 1997 1998 /* Allocate memory for record */ 1999 record->info = sal_alloc(record->info_depth * 2000 sizeof(bcmi_fte_template_record_elem_info_t), 2001 "Export Record element info"); 2002 if (record->info == NULL) { 2003 return BCM_E_MEMORY; 2004 } 2005 2006 /* Initialize with 'Reserved' element */ 2007 for (idx = 0; idx < record->info_depth; idx++) { 2008 record->info[idx].info_elem = bcmFlowtrackerExportElementTypeReserved; 2009 record->info[idx].length = 8; 2010 record->info[idx].check_id = 0; 2011 } 2012 2013 /* Insert hardware extracted default elements */ 2014 /* FT_INDEX */ 2015 field_info = NULL; 2016 field_info = soc_format_fieldinfo_get(unit, format, FLOW_INDEXf); 2017 if (field_info != NULL) { 2018 offset = field_info->bp; 2019 length = field_info->len; 2020 info_elem = bcmFlowtrackerExportElementTypeReserved; 2021 BCMI_FTE_RECORD_ELEM_IDX_GET(rec_total_bits, offset, length, idx); 2022 BCMI_FTE_RECORD_ELEM_SET(record, idx, info_elem); 2023 BCMI_FTE_RECORD_LENGTH_SET(record, idx, length); 2024 2025 sal_memset(info_name, 0, sizeof(char) * BCMI_FT_EXPORT_ELEMENT_NAME_LEN_MAX); 2026 (void) bcmi_ft_export_elem_name_get(unit, info_elem, NULL, info_name); 2027 LOG_DEBUG(BSL_LS_BCM_FLOWTRACKER, (BSL_META_U(unit, 2028 "[TemplateValidate]Element Record_Idx: %2d | Id: %2d (%20s) |" 2029 " Size: %02d\n\r"), idx, info_elem, info_name, length)); 2030 } 2031 2032 /* FT_Group */ 2033 field_info = NULL; 2034 field_info = soc_format_fieldinfo_get(unit, format, GROUP_IDf); 2035 if (field_info != NULL) { 2036 offset = field_info->bp; 2037 length = field_info->len; 2038 info_elem = bcmFlowtrackerExportElementTypeFlowtrackerGroup; 2039 BCMI_FTE_RECORD_ELEM_IDX_GET(rec_total_bits, offset, length, idx); 2040 BCMI_FTE_RECORD_ELEM_SET(record, idx, info_elem); 2041 BCMI_FTE_RECORD_LENGTH_SET(record, idx, length); 2042 2043 sal_memset(info_name, 0, sizeof(char) * BCMI_FT_EXPORT_ELEMENT_NAME_LEN_MAX); 2044 (void) bcmi_ft_export_elem_name_get(unit, info_elem, NULL, info_name); 2045 LOG_DEBUG(BSL_LS_BCM_FLOWTRACKER, (BSL_META_U(unit, 2046 "[TemplateValidate]Element Record_Idx: %2d | Id: %2d (%20s) |" 2047 " Size: %02d\n\r"), idx, info_elem, info_name, length)); 2048 } 2049 2050 /* FT_EXPORT_REASON */ 2051 field_info = NULL; 2052 field_info = soc_format_fieldinfo_get(unit, format, EXPORT_REASONf); 2053 if (field_info != NULL) { 2054 offset = field_info->bp; 2055 length = field_info->len; 2056 info_elem = bcmFlowtrackerExportElementTypeExportReasons; 2057 BCMI_FTE_RECORD_ELEM_IDX_GET(rec_total_bits, offset, length, idx); 2058 BCMI_FTE_RECORD_ELEM_SET(record, idx, info_elem); 2059 BCMI_FTE_RECORD_LENGTH_SET(record, idx, length); 2060 2061 sal_memset(info_name, 0, sizeof(char) * BCMI_FT_EXPORT_ELEMENT_NAME_LEN_MAX); 2062 (void) bcmi_ft_export_elem_name_get(unit, info_elem, NULL, info_name); 2063 LOG_DEBUG(BSL_LS_BCM_FLOWTRACKER, (BSL_META_U(unit, 2064 "[TemplateValidate]Element Record_Idx: %2d | Id: %2d (%20s) |" 2065 " Size: %02d\n\r"), idx, info_elem, info_name, length)); 2066 } 2067 2068 /* EXPORT_FLAGS */ 2069 field_info = NULL; 2070 field_info = soc_format_fieldinfo_get(unit, format, EXPORT_FLAGSf); 2071 if (field_info != NULL) { 2072 offset = field_info->bp; 2073 length = field_info->len; 2074 info_elem = bcmFlowtrackerExportElementTypeExportFlags; 2075 BCMI_FTE_RECORD_ELEM_IDX_GET(rec_total_bits, offset, length, idx); 2076 BCMI_FTE_RECORD_ELEM_SET(record, idx, info_elem); 2077 BCMI_FTE_RECORD_LENGTH_SET(record, idx, length); 2078 2079 sal_memset(info_name, 0, sizeof(char) * BCMI_FT_EXPORT_ELEMENT_NAME_LEN_MAX); 2080 (void) bcmi_ft_export_elem_name_get(unit, info_elem, NULL, info_name); 2081 LOG_DEBUG(BSL_LS_BCM_FLOWTRACKER, (BSL_META_U(unit, 2082 "[TemplateValidate]Element Record_Idx: %2d | Id: %2d (%20s) |" 2083 " Size: %02d\n\r"), idx, info_elem, info_name, length)); 2084 } 2085 2086 /* TIMESTAMP */ 2087 field_info = NULL; 2088 field_info = soc_format_fieldinfo_get(unit, format, TIMESTAMPf); 2089 if (field_info != NULL) { 2090 offset = field_info->bp; 2091 length = field_info->len; 2092 info_elem = bcmFlowtrackerExportElementTypeReserved; 2093 BCMI_FTE_RECORD_ELEM_IDX_GET(rec_total_bits, offset, length, idx); 2094 BCMI_FTE_RECORD_ELEM_SET(record, idx, info_elem); 2095 BCMI_FTE_RECORD_LENGTH_SET(record, idx, length); 2096 2097 sal_memset(info_name, 0, sizeof(char) * BCMI_FT_EXPORT_ELEMENT_NAME_LEN_MAX); 2098 (void) bcmi_ft_export_elem_name_get(unit, info_elem, NULL, info_name); 2099 LOG_DEBUG(BSL_LS_BCM_FLOWTRACKER, (BSL_META_U(unit, 2100 "[TemplateValidate]Element Record_Idx: %2d | Id: %2d (%20s) |" 2101 " Size: %02d\n\r"), idx, info_elem, info_name, length)); 2102 } 2103 2104 /* FLOW_KEY */ 2105 field_info = NULL; 2106 field_info = soc_format_fieldinfo_get(unit, format, FLOW_KEYf); 2107 if (field_info != NULL) { 2108 record->flow_key_offset = field_info->bp; 2109 record->flow_key_length = field_info->len; 2110 } 2111 rv = bcmi_fte_template_record_flow_key_populate(unit, flow_group, record); 2112 if(BCM_FAILURE(rv)) { 2113 goto cleanup; 2114 } 2115 2116 /* FLOW_DATA */ 2117 field_info = NULL; 2118 field_info = soc_format_fieldinfo_get(unit, format, FLOW_DATAf); 2119 if (field_info != NULL) { 2120 record->flow_data_offset = field_info->bp; 2121 record->flow_data_length = field_info->len; 2122 } 2123 rv = bcmi_fte_template_record_flow_data_polpulate(unit, flow_group, record); 2124 2125 cleanup: 2126 2127 if (BCM_FAILURE(rv)) { 2128 if (record->info != NULL) { 2129 sal_free(record->info); 2130 record->info = NULL; 2131 } 2132 } 2133 2134 return rv; 2135 } 2136 2137 /* 2138 * Function: 2139 * bcmi_ft_export_elements_check_search 2140 * Purpose: 2141 * Search flowcheck in export elements list. 2142 * Parameters: 2143 * unit - (IN) BCM device id 2144 * check_id - (IN) Flowtracker Check 2145 * list - (IN) list of export elements. 2146 * count - (IN) number of export elements. 2147 * 2148 * Returns: 2149 * TRUE if found FALSE otherwise 2150 */ 2151 int 2152 bcmi_ft_export_elements_check_search( 2153 int unit, 2154 bcm_flowtracker_check_t check_id, 2155 void *list, 2156 int count) 2157 { 2158 int idx = 0; 2159 bcm_flowtracker_export_element_info_t *export_elements = NULL; 2160 2161 if ((list == NULL) || (count == 0)) { 2162 return FALSE; 2163 } 2164 export_elements = (bcm_flowtracker_export_element_info_t *) list; 2165 2166 for (idx = 0; idx < count; idx++) { 2167 if ((export_elements[idx].element == 2168 bcmFlowtrackerExportElementTypeFlowtrackerCheck) && 2169 (export_elements[idx].check_id == check_id)) { 2170 return TRUE; 2171 } 2172 } 2173 return FALSE; 2174 } 2175 2176 /* 2177 * Function: 2178 * bcmi_fte_template_create_validate 2179 * Purpose: 2180 * Validate the template and return the list supported by the 2181 * device. 2182 * Parameters: 2183 * unit - (IN) Unit number. 2184 * flow_group_id - (IN) Flowtracker flow group software ID. 2185 * num_in_export_elements - (IN) Number of export elements intended in the tempate. 2186 * in_export_elements - (IN) List of export elements intended to be in the template. 2187 * num_out_export_elements - (IN/OUT) Number of export elements in the supportable tempate. 2188 * out_export_elements - (OUT) List of export elements in the template supportable by hardware. 2189 * Returns: 2190 * BCM_E_xxx 2191 * Notes: 2192 */ 2193 STATIC int 2194 bcmi_fte_template_create_validate( 2195 int unit, 2196 bcm_flowtracker_group_t flow_group_id, 2197 int num_in_export_elements, 2198 bcm_flowtracker_export_element_info_t *in_export_elements, 2199 int num_out_export_elements, 2200 bcm_flowtracker_export_element_info_t *out_export_elements, 2201 int *actual_out_export_elements) 2202 { 2203 int rv = BCM_E_NONE; 2204 int ix_in = 0, ix_out = 0, in_c = 0; 2205 int idx = 0; 2206 int info_size = 0; 2207 char info_name[BCMI_FT_EXPORT_ELEMENT_NAME_LEN_MAX]; 2208 bcm_flowtracker_check_t check_id; 2209 bcmi_fte_template_record_info_t record; 2210 bcm_flowtracker_export_element_type_t info_elem; 2211 bcm_flowtracker_export_element_info_t *info_elem_in = NULL; 2212 bcm_flowtracker_export_element_info_t *info_elem_out = NULL; 2213 2214 if ((num_in_export_elements <= 0) || (in_export_elements == NULL)) { 2215 return BCM_E_PARAM; 2216 } 2217 if ((num_out_export_elements > 0) && (out_export_elements == NULL)) { 2218 return BCM_E_PARAM; 2219 } 2220 2221 /* Validate export element list of the group */ 2222 rv = bcmi_ft_group_export_checks_validate(unit, 2223 flow_group_id, num_in_export_elements, in_export_elements); 2224 BCM_IF_ERROR_RETURN(rv); 2225 2226 sal_memset(&record, 0, sizeof(bcmi_fte_template_record_info_t)); 2227 rv = bcmi_fte_template_record_info_populate(unit, flow_group_id, &record); 2228 BCM_IF_ERROR_RETURN(rv); 2229 2230 if (record.info_depth == 0) { 2231 /* Faied to populate template info */ 2232 return BCM_E_INTERNAL; 2233 } 2234 2235 /* Mark info elements not requested by user as 'Reserved' */ 2236 for (idx = 0; idx < record.info_depth; idx++) { 2237 2238 if (record.info[idx].info_elem != 2239 bcmFlowtrackerExportElementTypeReserved) { 2240 for (ix_in = 0; ix_in < num_in_export_elements; ix_in++) { 2241 info_elem_in = &(in_export_elements[ix_in]); 2242 2243 /* If non-primary check, skip */ 2244 if (info_elem_in->element == 2245 bcmFlowtrackerExportElementTypeFlowtrackerCheck) { 2246 check_id = info_elem_in->check_id; 2247 2248 if (!BCMI_FT_IDX_IS_PRIMARY_CHECK(check_id)) { 2249 in_c++; 2250 break; 2251 } 2252 } 2253 2254 if ((record.info[idx].info_elem == info_elem_in->element) && 2255 (record.info[idx].check_id == info_elem_in->check_id)) { 2256 in_c++; 2257 break; 2258 } 2259 } 2260 if (ix_in == num_in_export_elements) { 2261 record.info[idx].info_elem = 2262 bcmFlowtrackerExportElementTypeReserved; 2263 record.info[idx].check_id = 0; 2264 } 2265 } 2266 } 2267 2268 idx = 0; 2269 ix_out = 0; 2270 info_elem = bcmFlowtrackerExportElementTypeReserved; 2271 2272 /* Form out export elements list */ 2273 while(idx < record.info_depth) { 2274 2275 check_id = 0; 2276 info_size = 0; 2277 info_elem = record.info[idx].info_elem; 2278 2279 if (info_elem == bcmFlowtrackerExportElementTypeReserved) { 2280 info_size = record.info[idx].length; 2281 2282 /* Add up all adjacent 'Reserved' element */ 2283 while(((idx + 1) < record.info_depth) && 2284 (record.info[idx + 1].info_elem == 2285 bcmFlowtrackerExportElementTypeReserved)) { 2286 info_size += record.info[idx + 1].length; 2287 idx++; 2288 } 2289 } else { 2290 info_size = record.info[idx].length; 2291 check_id = record.info[idx].check_id; 2292 2293 /* Skip next $info_size 'Reserved' elements */ 2294 idx += ((info_size / 8) - 1); 2295 } 2296 info_size = info_size / 8; 2297 2298 /* Dump FT export element list */ 2299 (void) bcmi_ft_export_elem_name_get(unit, info_elem, NULL, info_name); 2300 LOG_INFO(BSL_LS_BCM_FLOWTRACKER, (BSL_META_U(unit, 2301 "[TemplateValidate]Element Id: %2d (%20s)" 2302 " | Size: %02d (0x%x)\n\r"), info_elem, info_name, 2303 info_size, check_id)); 2304 2305 info_elem_out = NULL; 2306 if (ix_out < num_out_export_elements) { 2307 info_elem_out = &(out_export_elements[ix_out]); 2308 2309 info_elem_out->element = info_elem; 2310 info_elem_out->data_size = info_size; 2311 info_elem_out->check_id = check_id; 2312 } 2313 idx++; 2314 ix_out++; 2315 } 2316 2317 *actual_out_export_elements = ix_out; 2318 2319 if (in_c < num_in_export_elements) { 2320 /* Export element list contains extra elements */ 2321 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, (BSL_META_U(unit, 2322 "In-Export Elements array contain" 2323 " additional elements which are not present" 2324 " in FT Group tracking list.\n\r"))); 2325 rv = BCM_E_CONFIG; 2326 } else if ((num_out_export_elements != 0) && 2327 (num_out_export_elements < ix_out)) { 2328 2329 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, (BSL_META_U(unit, 2330 "Size of Out-Export Elements array is insufficient." 2331 " Required=(%d) but given Size=(%d)\n\r"), 2332 ix_out, num_out_export_elements)); 2333 rv = BCM_E_PARAM; 2334 } 2335 2336 /* Cleanup table */ 2337 if (record.info != NULL) { 2338 sal_free(record.info); 2339 } 2340 2341 return rv; 2342 } 2343 2344 /* 2345 * Function: 2346 * bcmi_ft_export_template_validate 2347 * Purpose: 2348 * Validate the template and return the list supported by the 2349 * device. 2350 * Parameters: 2351 * unit - (IN) Unit number. 2352 * flow_group_id - (IN) Flowtracker flow group software ID. 2353 * num_in_export_elements - (IN) Number of export elements intended in the tempate. 2354 * in_export_elements - (IN) List of export elements intended to be in the template. 2355 * num_out_export_elements - (IN/OUT) Number of export elements in the supportable tempate. 2356 * out_export_elements - (OUT) List of export elements in the template supportable by hardware. 2357 * Returns: 2358 * BCM_E_xxx 2359 * Notes: 2360 */ 2361 int 2362 bcmi_ft_export_template_validate( 2363 int unit, 2364 bcm_flowtracker_group_t flow_group_id, 2365 int num_in_export_elements, 2366 bcm_flowtracker_export_element_info_t *in_export_elements, 2367 int num_out_export_elements, 2368 bcm_flowtracker_export_element_info_t *out_export_elements, 2369 int *actual_out_export_elements) 2370 { 2371 int rv = BCM_E_NONE; 2372 int ft_group_installed = FALSE; 2373 2374 if ((num_in_export_elements <= 0) || (in_export_elements == NULL)) { 2375 return BCM_E_PARAM; 2376 } 2377 if ((num_out_export_elements > 0) && (out_export_elements == NULL)) { 2378 return BCM_E_PARAM; 2379 } 2380 2381 /* If FT Group is not created, fail */ 2382 rv = bcmi_ft_group_is_invalid(unit, flow_group_id); 2383 BCM_IF_ERROR_RETURN(rv); 2384 2385 /* If FT Group is installed, fail */ 2386 if (BCMI_FT_GROUP_IS_BUSY(unit, flow_group_id)) { 2387 return BCM_E_BUSY; 2388 } 2389 2390 /* If FT Group is validated, uninstall */ 2391 if (BCMI_FT_GROUP_IS_VALIDATED(unit, flow_group_id)) { 2392 rv = bcmi_esw_ft_group_hw_uninstall(unit, flow_group_id); 2393 BCM_IF_ERROR_RETURN(rv); 2394 } 2395 2396 /* Extract FT Group tracking params and flow checks */ 2397 rv = _bcm_field_ft_group_tracking_info_process(unit, flow_group_id, 1); 2398 2399 /* Validate and Install FT Group to Hw */ 2400 if (BCM_SUCCESS(rv)) { 2401 rv = bcmi_esw_ft_group_hw_install(unit, flow_group_id); 2402 } 2403 2404 /* Validate and Create Export template */ 2405 if (BCM_SUCCESS(rv)) { 2406 ft_group_installed = TRUE; 2407 rv = bcmi_fte_template_create_validate(unit, 2408 flow_group_id, num_in_export_elements, in_export_elements, 2409 num_out_export_elements, out_export_elements, 2410 actual_out_export_elements); 2411 } 2412 2413 /* Cleanup in case of failure */ 2414 if (BCM_FAILURE(rv)) { 2415 /* Uninstalled FT Group */ 2416 if (ft_group_installed == TRUE) { 2417 (void) bcmi_esw_ft_group_hw_uninstall(unit, flow_group_id); 2418 } 2419 2420 /* Cleanup FT Group Extraction information */ 2421 (void) _bcm_field_ft_group_extraction_clear(unit, flow_group_id); 2422 } 2423 2424 return rv; 2425 } 2426 2427 /* 2428 * Function: 2429 * bcmi_ft_template_create 2430 * Purpose: 2431 * Create flowtracker export template. 2432 * Description : 2433 * Routine to create a flowtracker template 2434 * Parameters: 2435 * unit - (IN) BCM device id 2436 * options - (IN) options for template creation 2437 * template_id - (OUT) FT template id. 2438 * set_id - (IN) IPFIX template set id 2439 * num_elements - (IN) Number of information elements. 2440 * list_of_export_elements - (IN) List of IPFIX information elems. 2441 * 2442 * Returns: 2443 * BCM_E_XXX 2444 */ 2445 int 2446 bcmi_ft_template_create( 2447 int unit, 2448 uint32 options, 2449 bcm_flowtracker_export_template_t *template_id, 2450 uint16 set_id, 2451 int num_elements, 2452 bcm_flowtracker_export_element_info_t *list_of_export_elements) 2453 { 2454 int rv; 2455 bcm_flowtracker_export_template_t index = 0; 2456 bcmi_ft_template_info_t template_info; 2457 2458 /* 2459 * Validate info elems 2460 */ 2461 rv = bcmi_ft_template_validate(unit, 2462 num_elements, 2463 list_of_export_elements); 2464 BCM_IF_ERROR_RETURN(rv); 2465 2466 2467 /* If WITH_ID, reserve the ID */ 2468 if (options & BCM_FLOWTRACKER_EXPORT_TEMPLATE_WITH_ID) { 2469 index = *template_id; 2470 2471 rv = bcmi_ft_template_id_alloc(unit, FALSE, &index); 2472 BCM_IF_ERROR_RETURN(rv); 2473 2474 } else { 2475 2476 rv = bcmi_ft_template_id_alloc(unit, TRUE, &index); 2477 BCM_IF_ERROR_RETURN(rv); 2478 } 2479 2480 /* Init template_info. */ 2481 sal_memset(&template_info, 0, sizeof(bcmi_ft_template_info_t)); 2482 2483 template_info.template_id = index; 2484 template_info.set_id = set_id; 2485 template_info.num_elements = num_elements; 2486 2487 sal_memcpy(template_info.export_elements, 2488 list_of_export_elements, 2489 (num_elements * sizeof(bcm_flowtracker_export_element_info_t))); 2490 2491 sal_memcpy(BCMI_FT_TEMPLATE_INFO(unit, index), 2492 &template_info, sizeof(template_info)); 2493 2494 *template_id = index; 2495 2496 return rv; 2497 } 2498 2499 /* 2500 * Function: 2501 * bcmi_ft_template_get 2502 * Purpose: 2503 * Ftech flowtracker export template. 2504 * Description : 2505 * Routine to get flowtracker template info. 2506 * Parameters: 2507 * unit - (IN) BCM device id 2508 * template_id - (IN) FT template id. 2509 * *set_id - (OUT) IPFIX template set id 2510 * max_size - (IN) Max num of elements 2511 * list_of_export_elements - (OUT) List of IPFIX information elems. 2512 * num_elements - (OUT) Actual Number of information elements. 2513 * 2514 * Returns: 2515 * BCM_E_XXX 2516 */ 2517 int 2518 bcmi_ft_template_get( 2519 int unit, 2520 bcm_flowtracker_export_template_t template_id, 2521 uint16 *set_id, 2522 int max_elems, 2523 bcm_flowtracker_export_element_info_t *list_of_elems, 2524 int *num_elems) 2525 { 2526 int idx; 2527 bcm_flowtracker_export_element_info_t *elem; 2528 bcmi_ft_template_info_t *template_info; 2529 2530 if (max_elems != 0 && list_of_elems == NULL) { 2531 return BCM_E_PARAM; 2532 } 2533 if (num_elems == NULL) { 2534 return BCM_E_PARAM; 2535 } 2536 2537 if ((template_id > BCMI_FT_EXPORT_INFO(unit)->max_templates) || 2538 (template_id <= BCMI_FT_TEMPLATE_ID_INVALID)) { 2539 return BCM_E_PARAM; 2540 } 2541 2542 if (!SHR_BITGET(BCMI_FT_TEMPLATE_BITMAP(unit), template_id)) { 2543 return BCM_E_NOT_FOUND; 2544 } 2545 2546 template_info = BCMI_FT_TEMPLATE_INFO(unit, template_id); 2547 *set_id = template_info->set_id; 2548 *num_elems = template_info->num_elements; 2549 2550 for (idx = 0; idx < max_elems; idx++) { 2551 elem = &(list_of_elems[idx]); 2552 sal_memcpy(elem, 2553 &(template_info->export_elements[idx]), 2554 sizeof(*elem)); 2555 } 2556 2557 if ((max_elems != 0) && (max_elems <= *num_elems)) { 2558 *num_elems = max_elems; 2559 } 2560 2561 return BCM_E_NONE; 2562 } 2563 2564 /* 2565 * Function: 2566 * bcmi_ft_template_destroy 2567 * Purpose: 2568 * Destroy flowtracker export template. 2569 * Description : 2570 * Routine to destroy a flowtracker template 2571 * Parameters: 2572 * unit - (IN) BCM device id 2573 * id - (OUT) FT template id. 2574 * 2575 * Returns: 2576 * BCM_E_XXX 2577 */ 2578 int 2579 bcmi_ft_template_destroy( 2580 int unit, 2581 bcm_flowtracker_export_template_t template_id) 2582 { 2583 bcmi_ft_template_info_t *template_info; 2584 2585 if ((template_id > BCMI_FT_EXPORT_INFO(unit)->max_templates) || 2586 (template_id <= BCMI_FT_TEMPLATE_ID_INVALID)) { 2587 return BCM_E_PARAM; 2588 } 2589 2590 if (!SHR_BITGET(BCMI_FT_TEMPLATE_BITMAP(unit), template_id)) { 2591 return BCM_E_NOT_FOUND; 2592 } 2593 2594 template_info = BCMI_FT_TEMPLATE_INFO(unit, template_id); 2595 2596 /* Allow destroying template only if it is detached from all groups. */ 2597 if (template_info->in_use != 0) { 2598 return BCM_E_BUSY; 2599 } 2600 2601 sal_memset(template_info->export_elements, 0, 2602 (template_info->num_elements * 2603 sizeof(bcm_flowtracker_export_element_info_t))); 2604 2605 template_info->template_id = template_id; 2606 template_info->set_id = 0; 2607 template_info->num_elements = 0; 2608 2609 /* Reset bit in template bitmap */ 2610 SHR_BITCLR(BCMI_FT_TEMPLATE_BITMAP(unit), template_id); 2611 2612 return BCM_E_NONE; 2613 } 2614 2615 /* 2616 * Function: 2617 * bcmi_ft_flow_group_collector_add 2618 * Purpose: 2619 * Attach a collector a flow group. 2620 * Description : 2621 * Routine to associate a collector to an flowtracker group. 2622 * Parameters: 2623 * unit - (IN) BCM device id 2624 * group_id- (IN) FT group Id. 2625 * coll_hw_id - (OUT) FT Collector Id. 2626 * template_id - (IN) IPFIX template Id. 2627 * 2628 * Returns: 2629 * BCM_E_XXX 2630 */ 2631 int 2632 bcmi_ft_flow_group_collector_add( 2633 int unit, 2634 bcm_flowtracker_group_t flow_group_id, 2635 bcm_flowtracker_collector_t coll_hw_id, 2636 bcm_flowtracker_export_template_t template_id) 2637 { 2638 uint16 set_id; 2639 bcmi_ft_collector_info_t *ft_coll_info; 2640 2641 /* 2642 * Validate group id 2643 */ 2644 if (bcmi_ft_group_is_invalid(unit, flow_group_id)) { 2645 return BCM_E_NOT_FOUND; 2646 } 2647 2648 /* Validate Template Id. */ 2649 if ((template_id > BCMI_FT_EXPORT_INFO(unit)->max_templates) || 2650 (template_id <= BCMI_FT_TEMPLATE_ID_INVALID)) { 2651 return BCM_E_PARAM; 2652 } 2653 2654 if (!SHR_BITGET(BCMI_FT_TEMPLATE_BITMAP(unit), template_id)) { 2655 return BCM_E_NOT_FOUND; 2656 } 2657 2658 if ((coll_hw_id <= BCMI_FT_COLLECTOR_ID_INVALID) || 2659 (coll_hw_id >= BCMI_FT_MAX_COLLECTORS)) { 2660 return BCM_E_PARAM; 2661 } 2662 2663 ft_coll_info = BCMI_FT_COLLECTOR_INFO(unit, coll_hw_id); 2664 2665 if (ft_coll_info->coll_hw_id == BCMI_FT_COLLECTOR_ID_INVALID) { 2666 return BCM_E_NOT_FOUND; 2667 } 2668 2669 if (BCMI_FT_TEMPLATE_ID_INVALID != 2670 BCMI_FT_GROUP(unit, flow_group_id)->template_id) { 2671 return BCM_E_BUSY; 2672 } 2673 2674 if (BCMI_FT_COLLECTOR_ID_INVALID != 2675 BCMI_FT_GROUP(unit, flow_group_id)->collector_id) { 2676 return BCM_E_BUSY; 2677 } 2678 2679 /* Update Group table with collector Id. */ 2680 soc_mem_field32_modify(unit, BSC_KG_GROUP_TABLEm, flow_group_id, 2681 COLLECTOR_IDf, coll_hw_id); 2682 ft_coll_info->in_use += 1; 2683 BCMI_FT_GROUP(unit, flow_group_id)->collector_id = coll_hw_id; 2684 2685 /* Update Group table with template SET Id. */ 2686 set_id = BCMI_FT_TEMPLATE_INFO(unit, template_id)->set_id; 2687 soc_mem_field32_modify(unit, BSC_KG_GROUP_TABLEm, flow_group_id, 2688 SET_IDf, set_id); 2689 BCMI_FT_TEMPLATE_INFO(unit, template_id)->in_use += 1; 2690 BCMI_FT_GROUP(unit, flow_group_id)->template_id = template_id; 2691 2692 2693 return BCM_E_NONE; 2694 } 2695 2696 /* 2697 * Function: 2698 * bcmi_ft_flow_group_collector_delete_check 2699 * Purpose: 2700 * Check the conditions that needs to be satisfied 2701 * before a collector is removed from Flowtracker_group. 2702 * Parameters: 2703 * unit - (IN) BCM device id 2704 * id - (IN) FT group Id. 2705 * coll_hw_id - (IN) FT Collector Id. 2706 * 2707 * Returns: 2708 * BCM_E_XXX 2709 */ 2710 int 2711 bcmi_ft_flow_group_collector_delete_check( 2712 int unit, 2713 bcm_flowtracker_group_t id, 2714 bcm_flowtracker_collector_t coll_hw_id) 2715 { 2716 int rv; 2717 int ft_enable; 2718 int is_busy; 2719 int user_entry; 2720 uint32 flow_limit; 2721 uint64 age_out_count; 2722 uint64 flow_learnt_count; 2723 2724 user_entry = (BCMI_FT_GROUP(unit, id)->flags 2725 & BCM_FLOWTRACKER_GROUP_USER_ENTRIES_ONLY); 2726 is_busy = BCMI_FT_GROUP_IS_BUSY(unit, id); 2727 ft_enable = BCMI_FT_GROUP_FTFP_DATA(unit, id).flowtrack; 2728 rv = bcmi_ft_group_flow_limit_get(unit, id, &flow_limit); 2729 if (rv != BCM_E_NONE) { 2730 flow_limit = 0; 2731 } 2732 2733 /* 2734 * For sw managed groups, is_busy and ft_enable are valid, flow_limit is 2735 * not significant. Where as for hw managed groups, is_busy,ft_enable and 2736 * flow_limit are verified. 2737 */ 2738 if (((user_entry == TRUE) && (is_busy == TRUE) && (ft_enable == TRUE)) || 2739 ((is_busy == TRUE) && (ft_enable == TRUE) && (flow_limit != 0))) { 2740 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 2741 (BSL_META_U(unit, 2742 "FLOWTRACKER(unit %d) Error: FT Group is installed in" 2743 " Field Entry or Flowtracking is enabled\r\n"), unit)); 2744 return BCM_E_BUSY; 2745 } 2746 2747 if (SAL_BOOT_BCMSIM) { 2748 return BCM_E_NONE; 2749 } 2750 2751 COMPILER_64_SET(age_out_count, 0, 0); 2752 COMPILER_64_SET(flow_learnt_count, 0, 0); 2753 BCM_IF_ERROR_RETURN(soc_counter_sync_get(unit, REG_PORT_ANY, 2754 SOC_COUNTER_NON_DMA_FT_GROUP_FLOW_AGE_OUT_CNT, id, &age_out_count)); 2755 2756 BCM_IF_ERROR_RETURN(soc_counter_sync_get(unit, REG_PORT_ANY, 2757 SOC_COUNTER_NON_DMA_FT_GROUP_FLOW_LEARNT_CNT, id, &flow_learnt_count)); 2758 2759 if (COMPILER_64_LT(age_out_count, flow_learnt_count)) { 2760 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 2761 (BSL_META_U(unit, 2762 "FLOWTRACKER(unit %d) Error: FT Group" 2763 " has active flows\r\n"), unit)); 2764 return BCM_E_BUSY; 2765 } 2766 2767 return BCM_E_NONE; 2768 } 2769 2770 /* 2771 * Function: 2772 * bcmi_ft_flow_group_collector_delete 2773 * Purpose: 2774 * Detach a collector a flow group. 2775 * Description : 2776 * Routine to dissociate a collector to an flowtracker group. 2777 * Parameters: 2778 * unit - (IN) BCM device id 2779 * group_id- (IN) FT group Id. 2780 * coll_hw_id - (OUT) FT Collector Id. 2781 * template_id - (IN) IPFIX template Id. 2782 * 2783 * Returns: 2784 * BCM_E_XXX 2785 */ 2786 int 2787 bcmi_ft_flow_group_collector_delete( 2788 int unit, 2789 bcm_flowtracker_group_t flow_group_id, 2790 bcm_flowtracker_collector_t coll_hw_id, 2791 bcm_flowtracker_export_template_t template_id) 2792 { 2793 bcmi_ft_collector_info_t *ft_coll_info; 2794 2795 /* 2796 * Validate group id 2797 */ 2798 if (bcmi_ft_group_is_invalid(unit, flow_group_id)) { 2799 return BCM_E_NOT_FOUND; 2800 } 2801 2802 /* Validate Template Id. */ 2803 if ((template_id > BCMI_FT_EXPORT_INFO(unit)->max_templates) || 2804 (template_id <= BCMI_FT_TEMPLATE_ID_INVALID)) { 2805 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 2806 (BSL_META_U(unit, 2807 "FLOWTRACKER(unit %d) Error: Incorrect" 2808 " template Id\r\n"), unit)); 2809 return BCM_E_PARAM; 2810 } 2811 2812 if (!SHR_BITGET(BCMI_FT_TEMPLATE_BITMAP(unit), template_id)) { 2813 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 2814 (BSL_META_U(unit, 2815 "FLOWTRACKER(unit %d) Error: template Id" 2816 " not found\r\n"), unit)); 2817 return BCM_E_NOT_FOUND; 2818 } 2819 2820 if ((coll_hw_id <= BCMI_FT_COLLECTOR_ID_INVALID) || 2821 (coll_hw_id >= BCMI_FT_MAX_COLLECTORS)) { 2822 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 2823 (BSL_META_U(unit, 2824 "FLOWTRACKER(unit %d) Error: Incorrect" 2825 " collector\r\n"), unit)); 2826 return BCM_E_PARAM; 2827 } 2828 2829 ft_coll_info = BCMI_FT_COLLECTOR_INFO(unit, coll_hw_id); 2830 2831 if (ft_coll_info->coll_hw_id == BCMI_FT_COLLECTOR_ID_INVALID) { 2832 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 2833 (BSL_META_U(unit, 2834 "FLOWTRACKER(unit %d) Error: Collector" 2835 " is not associated with Flowtracker Group \r\n"), unit)); 2836 return BCM_E_NOT_FOUND; 2837 } 2838 2839 if (template_id != 2840 BCMI_FT_GROUP(unit, flow_group_id)->template_id) { 2841 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 2842 (BSL_META_U(unit, 2843 "FLOWTRACKER(unit %d) Error: Template" 2844 " is not associated with Flowtracker Group\r\n"), unit)); 2845 return BCM_E_NOT_FOUND; 2846 } 2847 2848 if (coll_hw_id != 2849 BCMI_FT_GROUP(unit, flow_group_id)->collector_id) { 2850 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 2851 (BSL_META_U(unit, 2852 "FLOWTRACKER(unit %d) Error: Collector" 2853 " is not associated with Flowtracker Group \r\n"), unit)); 2854 return BCM_E_NOT_FOUND; 2855 } 2856 2857 /* Update Group table with collector Id. */ 2858 BCM_IF_ERROR_RETURN(bcmi_ft_flow_group_collector_delete_check(unit, 2859 flow_group_id, coll_hw_id)); 2860 2861 soc_mem_field32_modify(unit, BSC_KG_GROUP_TABLEm, flow_group_id, 2862 COLLECTOR_IDf, 0); 2863 ft_coll_info->in_use -= 1; 2864 BCMI_FT_GROUP(unit, flow_group_id)->collector_id = BCMI_FT_COLLECTOR_ID_INVALID; 2865 2866 /* Update Group table with template SET Id. */ 2867 soc_mem_field32_modify(unit, BSC_KG_GROUP_TABLEm, flow_group_id, 2868 SET_IDf, 0); 2869 BCMI_FT_TEMPLATE_INFO(unit, template_id)->in_use -= 1; 2870 BCMI_FT_GROUP(unit, flow_group_id)->template_id = BCMI_FT_TEMPLATE_ID_INVALID; 2871 2872 return BCM_E_NONE; 2873 } 2874 2875 2876 /* 2877 * Function: 2878 * bcmi_ft_flow_group_collector_get_all 2879 * Purpose: 2880 * Get collector attached to a flow group. 2881 * Description : 2882 * Routine to fetch collector and template id 2883 * associated a flowtracker group. 2884 * Parameters: 2885 * unit - (IN) BCM device id 2886 * group_id - (IN) FT group Id. 2887 * max_list_size - (IN) max list of collectors 2888 * list_of_collectors - (OUT) FT Collector Id list. 2889 * list_of_templates - (OUT) FT Template Id list. 2890 * list_size - (IN) Actual list size. 2891 * 2892 * Returns: 2893 * BCM_E_XXX 2894 */ 2895 int 2896 bcmi_ft_flow_group_collector_get_all( 2897 int unit, 2898 bcm_flowtracker_group_t flow_group_id, 2899 int max_list_size, 2900 bcm_flowtracker_collector_t *list_of_collectors, 2901 bcm_flowtracker_export_template_t *list_of_templates, 2902 int *list_size) 2903 { 2904 2905 if (list_size == NULL) { 2906 return BCM_E_PARAM; 2907 } 2908 2909 /* 2910 * Validate group id 2911 */ 2912 if (bcmi_ft_group_is_invalid(unit, flow_group_id)) { 2913 return BCM_E_NOT_FOUND; 2914 } 2915 2916 /* HX5 Hardware supports only one collector id and templat per group */ 2917 if (max_list_size > 0) { 2918 if (list_of_collectors != NULL) { 2919 list_of_collectors[0] = BCMI_FT_GROUP(unit, flow_group_id)->collector_id; 2920 } 2921 2922 if (list_of_templates != NULL) { 2923 list_of_templates[0] = BCMI_FT_GROUP(unit, flow_group_id)->template_id; 2924 } 2925 } 2926 2927 *list_size = 1; 2928 2929 return BCM_E_NONE; 2930 } 2931 2932 /* 2933 * Function: 2934 * bcmi_ft_group_collector_attach 2935 * Purpose: 2936 * Associate flow group to a collector with an export template. 2937 * Parameters: 2938 * unit - (IN) BCM device number 2939 * flow_group_id - (IN) Flow group Id 2940 * collector_id - (IN) Collector Id 2941 * template_id - (IN) Template Id 2942 * Returns: 2943 * BCM_E_XXX - BCM error code. 2944 */ 2945 int bcmi_ft_group_collector_attach( 2946 int unit, 2947 bcm_flowtracker_group_t flow_group_id, 2948 bcm_collector_t collector_id, 2949 int export_profile_id, 2950 bcm_flowtracker_export_template_t template_id) 2951 { 2952 int rv; 2953 bcmi_ft_collector_info_t *ft_coll_info; 2954 bcm_flowtracker_collector_t ix, first_free; 2955 2956 bcm_flowtracker_collector_info_t collector_info; 2957 bcm_collector_export_profile_t export_profile_info; 2958 bcm_collector_info_t cmn_collector_info; 2959 2960 first_free = BCMI_FT_COLLECTOR_ID_INVALID; 2961 2962 for (ix = 0; ix < BCMI_FT_EXPORT_INFO(unit)->max_collectors; ix++) { 2963 ft_coll_info = BCMI_FT_COLLECTOR_INFO(unit, ix); 2964 if ((first_free == BCMI_FT_COLLECTOR_ID_INVALID) && 2965 (ft_coll_info->coll_hw_id == BCMI_FT_COLLECTOR_ID_INVALID)) { 2966 first_free = ix; 2967 } 2968 2969 if (ft_coll_info->cmn_coll_id == collector_id) { 2970 if (ft_coll_info->cmn_export_prof_id != export_profile_id) { 2971 /* Export profile associated earlier is not same */ 2972 return BCM_E_PARAM; 2973 } 2974 break; 2975 } 2976 } 2977 2978 if (ix == BCMI_FT_EXPORT_INFO(unit)->max_collectors) { 2979 if (first_free == BCMI_FT_COLLECTOR_ID_INVALID) { 2980 /* Free hw collector not available. */ 2981 return BCM_E_RESOURCE; 2982 } 2983 2984 /* Collector not installed yet */ 2985 bcm_collector_info_t_init(&cmn_collector_info); 2986 bcm_collector_export_profile_t_init(&export_profile_info); 2987 bcm_flowtracker_collector_info_t_init(&collector_info); 2988 2989 rv = _bcm_xgs5_collector_export_profile_get(unit, 2990 export_profile_id, 2991 &export_profile_info); 2992 BCM_IF_ERROR_RETURN(rv); 2993 2994 if (export_profile_info.wire_format != bcmCollectorWireFormatIpfix) { 2995 return BCM_E_CONFIG; 2996 } 2997 2998 if (_bcm_esw_collector_check_user_is_other(unit, collector_id, 2999 _BCM_COLLECTOR_EXPORT_APP_FT_IPFIX)) { 3000 return BCM_E_CONFIG; 3001 } 3002 3003 rv = _bcm_xgs5_collector_get(unit, collector_id, &cmn_collector_info); 3004 BCM_IF_ERROR_RETURN(rv); 3005 3006 switch (cmn_collector_info.collector_type) { 3007 case bcmCollectorLocal: 3008 collector_info.collector_type = bcmFlowtrackerCollectorLocal; 3009 break; 3010 case bcmCollectorRemote: 3011 collector_info.collector_type = bcmFlowtrackerCollectorRemote; 3012 break; 3013 default: 3014 return (BCM_E_PARAM); 3015 } 3016 3017 switch (cmn_collector_info.transport_type) { 3018 case bcmCollectorTransportTypeIpv4Udp: 3019 collector_info.transport_type = bcmFlowtrackerCollectorTransportTypeIpfixIpv4Udp; 3020 break; 3021 case bcmCollectorTransportTypeIpv6Udp: 3022 collector_info.transport_type = bcmFlowtrackerCollectorTransportTypeIpfixIpv6Udp; 3023 break; 3024 case bcmCollectorTransportTypeRaw: 3025 collector_info.transport_type = bcmFlowtrackerCollectorTransportTypeRaw; 3026 break; 3027 default: 3028 return (BCM_E_PARAM); 3029 } 3030 3031 3032 3033 sal_memcpy(&(collector_info.eth.src_mac), 3034 &(cmn_collector_info.eth.src_mac), sizeof(bcm_mac_t)); 3035 sal_memcpy(&(collector_info.eth.dst_mac), 3036 &(cmn_collector_info.eth.dst_mac), sizeof(bcm_mac_t)); 3037 collector_info.eth.vlan_tag_structure = cmn_collector_info.eth.vlan_tag_structure; 3038 collector_info.eth.outer_tpid = cmn_collector_info.eth.outer_tpid; 3039 collector_info.eth.inner_tpid = cmn_collector_info.eth.inner_tpid; 3040 collector_info.eth.outer_vlan_tag = cmn_collector_info.eth.outer_vlan_tag; 3041 collector_info.eth.inner_vlan_tag = cmn_collector_info.eth.inner_vlan_tag; 3042 3043 collector_info.ipv4.src_ip = cmn_collector_info.ipv4.src_ip; 3044 collector_info.ipv4.dst_ip = cmn_collector_info.ipv4.dst_ip; 3045 collector_info.ipv4.dscp = cmn_collector_info.ipv4.dscp; 3046 collector_info.ipv4.ttl = cmn_collector_info.ipv4.ttl; 3047 3048 sal_memcpy(&(collector_info.ipv6.src_ip), 3049 &(cmn_collector_info.ipv6.src_ip), sizeof(bcm_ip6_t)); 3050 sal_memcpy(&(collector_info.ipv6.dst_ip), 3051 &(cmn_collector_info.ipv6.dst_ip), sizeof(bcm_ip6_t)); 3052 collector_info.ipv6.traffic_class = cmn_collector_info.ipv6.traffic_class; 3053 collector_info.ipv6.flow_label = cmn_collector_info.ipv6.flow_label; 3054 collector_info.ipv6.hop_limit = cmn_collector_info.ipv6.hop_limit; 3055 3056 collector_info.udp.dst_port = cmn_collector_info.udp.dst_port; 3057 collector_info.udp.src_port = cmn_collector_info.udp.src_port; 3058 3059 collector_info.max_packet_length = export_profile_info.max_packet_length; 3060 3061 ft_coll_info = BCMI_FT_COLLECTOR_INFO(unit, first_free); 3062 ft_coll_info->ipfix_hdr_use_custom = 1; 3063 ft_coll_info->ipfix_hdr = cmn_collector_info.ipfix; 3064 3065 if (export_profile_info.flags & 3066 BCM_COLLECTOR_EXPORT_PROFILE_FLAGS_USE_NUM_RECORDS) { 3067 ft_coll_info->num_records = export_profile_info.num_records; 3068 } 3069 3070 rv = bcmi_ft_collector_create(unit, 3071 BCM_FLOWTRACKER_COLLECTOR_WITH_ID, 3072 &first_free, 3073 &collector_info); 3074 BCM_IF_ERROR_RETURN(rv); 3075 3076 ft_coll_info->cmn_coll_id = collector_id; 3077 3078 if (collector_info.collector_type == bcmFlowtrackerCollectorLocal) { 3079 BCMI_FT_EXPORT_INFO(unit)->dma_collector_id = ft_coll_info->cmn_coll_id; 3080 } 3081 3082 ft_coll_info->cmn_export_prof_id = export_profile_id; 3083 ix = first_free; 3084 } 3085 3086 rv = bcmi_ft_flow_group_collector_add(unit, 3087 flow_group_id, 3088 ix, 3089 template_id); 3090 BCM_IF_ERROR_RETURN(rv); 3091 3092 rv = _bcm_esw_collector_ref_count_update(unit, collector_id, 1); 3093 if (BCM_FAILURE(rv)) { 3094 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 3095 (BSL_META_U(unit, 3096 "FLOWTRACKER(unit %d) Error: collector " 3097 " ref_count update failed %s\n"), unit, bcm_errmsg(rv))); 3098 return rv; 3099 } 3100 rv = _bcm_esw_collector_user_update(unit, collector_id, _BCM_COLLECTOR_EXPORT_APP_FT_IPFIX); 3101 if (BCM_FAILURE(rv)) { 3102 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 3103 (BSL_META_U(unit, 3104 "FLOWTRACKER(unit %d) Error: collector " 3105 " user update failed %s\n"), unit, bcm_errmsg(rv))); 3106 return rv; 3107 } 3108 rv = _bcm_esw_collector_export_profile_ref_count_update(unit, 3109 export_profile_id, 3110 1); 3111 if (BCM_FAILURE(rv)) { 3112 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 3113 (BSL_META_U(unit, 3114 "FLOWTRACKER(unit %d) Error: export profile " 3115 " ref_count update failed %s\n"), unit, bcm_errmsg(rv))); 3116 return rv; 3117 } 3118 3119 return BCM_E_NONE; 3120 } 3121 3122 /* 3123 * Function: 3124 * bcmi_ft_group_collector_detach 3125 * Purpose: 3126 * Dis-associate flow group from a collector with an export template. 3127 * Parameters: 3128 * unit - (IN) BCM device number 3129 * flow_group_id - (IN) Flow group Id 3130 * collector_id - (IN) Collector Id 3131 * template_id - (IN) Template Id 3132 * Returns: 3133 * BCM_E_XXX - BCM error code. 3134 */ 3135 int bcmi_ft_group_collector_detach( 3136 int unit, 3137 bcm_flowtracker_group_t flow_group_id, 3138 bcm_flowtracker_collector_t collector_id, 3139 int export_profile_id, 3140 bcm_flowtracker_export_template_t template_id) 3141 { 3142 int rv; 3143 bcmi_ft_collector_info_t *ft_coll_info = NULL; 3144 bcm_flowtracker_collector_t ix; 3145 3146 for (ix = 0; ix < BCMI_FT_EXPORT_INFO(unit)->max_collectors; ix++) { 3147 ft_coll_info = BCMI_FT_COLLECTOR_INFO(unit, ix); 3148 3149 if (ft_coll_info->cmn_coll_id == collector_id) { 3150 if (ft_coll_info->cmn_export_prof_id != export_profile_id) { 3151 /* Export profile associated earlier is not same */ 3152 return BCM_E_PARAM; 3153 } 3154 break; 3155 } 3156 } 3157 3158 if (ix == BCMI_FT_EXPORT_INFO(unit)->max_collectors) { 3159 return BCM_E_NOT_FOUND; 3160 } 3161 3162 rv = bcmi_ft_flow_group_collector_delete(unit, 3163 flow_group_id, 3164 ix, 3165 template_id); 3166 BCM_IF_ERROR_RETURN(rv); 3167 3168 if (ft_coll_info->in_use == 0) { 3169 /* Destroy collector if not attached to any group. */ 3170 rv = bcmi_ft_collector_destroy(unit, ix); 3171 BCM_IF_ERROR_RETURN(rv); 3172 3173 } 3174 3175 rv = _bcm_esw_collector_ref_count_update(unit, collector_id, -1); 3176 if (BCM_FAILURE(rv)) { 3177 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 3178 (BSL_META_U(unit, 3179 "FLOWTRACKER(unit %d) Error: collector " 3180 " ref_count update failed %s\n"), unit, bcm_errmsg(rv))); 3181 return rv; 3182 } 3183 rv = _bcm_esw_collector_export_profile_ref_count_update(unit, 3184 export_profile_id, 3185 -1); 3186 if (BCM_FAILURE(rv)) { 3187 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 3188 (BSL_META_U(unit, 3189 "FLOWTRACKER(unit %d) Error: export profile " 3190 " ref_count update failed %s\n"), unit, bcm_errmsg(rv))); 3191 return rv; 3192 } 3193 3194 3195 return BCM_E_NONE; 3196 } 3197 3198 /* 3199 * Function: 3200 * bcmi_ft_group_collector_attach_get_all 3201 * Purpose: 3202 * Get list of all collectors, templates attached to a flow group 3203 * Parameters: 3204 * unit - (IN) BCM device number 3205 * flow_group_id - (IN) Flow group Id 3206 * max_list_size - (IN) Size of the list arrays 3207 * list_of_collectors - (OUT) Collector list 3208 * list_of_templates - (OUT) Template list 3209 * list_size - (OUT) Number of elements in the lists 3210 * Returns: 3211 * BCM_E_XXX - BCM error code. 3212 */ 3213 int bcmi_ft_group_collector_attach_get_all( 3214 int unit, 3215 bcm_flowtracker_group_t flow_group_id, 3216 int max_list_size, 3217 bcm_flowtracker_collector_t *list_of_collectors, 3218 int *list_of_export_profile_ids, 3219 bcm_flowtracker_export_template_t *list_of_templates, 3220 int *list_size) 3221 { 3222 int result = BCM_E_UNAVAIL; 3223 3224 return result; 3225 } 3226 3227 3228 3229 3230 3231 /* 3232 * Function: 3233 * bcmi_ft_export_record_register 3234 * Description: 3235 * To register the callback function for flow info export 3236 * Parameters: 3237 * unit device number 3238 * callback user callback function 3239 * userdata user data used as argument during callback 3240 * Return: 3241 * BCM_E_NONE 3242 * BCM_E_PARAM 3243 * BCM_E_RESOURCE 3244 * BCM_E_UNAVAIL 3245 */ 3246 int 3247 bcmi_ft_export_record_register( 3248 int unit, 3249 bcm_flowtracker_collector_t collector_id, 3250 bcm_flowtracker_collector_callback_options_t callback_options, 3251 bcm_flowtracker_export_record_cb_f callback_fn, 3252 void *userdata) 3253 { 3254 int free_index, i; 3255 bcmi_ft_export_cb_ctrl_t *ft_export_cb_ctrl; 3256 bcmi_ft_cb_entry_t *entry; 3257 3258 3259 if (!soc_feature(unit, soc_feature_bscan_ft_fifodma_support)) { 3260 return BCM_E_UNAVAIL; 3261 } 3262 3263 if (callback_fn == NULL) { 3264 return BCM_E_PARAM; 3265 } 3266 3267 if (BCMI_FT_CB_CTRL(unit) == NULL) { 3268 BCM_IF_ERROR_RETURN(bcmi_ft_export_cb_init(unit)); 3269 } 3270 ft_export_cb_ctrl = BCMI_FT_CB_CTRL(unit); 3271 3272 if (BCMI_FT_EXPORT_INFO(unit)->dma_collector_id != collector_id) { 3273 return BCM_E_PARAM; 3274 } 3275 3276 free_index = -1; 3277 for (i = 0; i < BCMI_FT_CB_MAX; i++) { 3278 entry = &ft_export_cb_ctrl->callback_entry[i]; 3279 if (entry->state == BCMI_FT_CALLBACK_STATE_INVALID || 3280 (ft_export_cb_ctrl->pid == SAL_THREAD_ERROR && 3281 entry->state == BCMI_FT_CALLBACK_STATE_UNREGISTERED)) { 3282 if (free_index < 0) { 3283 free_index = i; 3284 } 3285 } else if ((entry->state == BCMI_FT_CALLBACK_STATE_ACTIVE) || 3286 (entry->state == BCMI_FT_CALLBACK_STATE_REGISTERED)) { 3287 if (entry->callback == callback_fn && entry->userdata == userdata) { 3288 return BCM_E_NONE; 3289 } 3290 } 3291 } 3292 3293 if (free_index < 0) { 3294 return BCM_E_RESOURCE; 3295 } 3296 3297 entry = &ft_export_cb_ctrl->callback_entry[free_index]; 3298 entry->callback = callback_fn; 3299 entry->callback_options = callback_options; 3300 entry->userdata = userdata; 3301 entry->state = BCMI_FT_CALLBACK_STATE_REGISTERED; 3302 3303 (void)bcma_ft_export_fifo_control(unit, ft_export_cb_ctrl->interval); 3304 3305 return BCM_E_NONE; 3306 } 3307 3308 3309 /* 3310 * Function: 3311 * bcmi_ft_export_record_unregister 3312 * Description: 3313 * To unregister the callback function for flow info export 3314 * Parameters: 3315 * unit device number 3316 * callback user callback function 3317 * userdata user data used as argument during callback 3318 * Return: 3319 * BCM_E_NONE 3320 * BCM_E_NOT_FOUND 3321 * BCM_E_UNAVAIL 3322 * BCM_E_INIT 3323 */ 3324 int 3325 bcmi_ft_export_record_unregister( 3326 int unit, 3327 bcm_flowtracker_collector_t collector_id, 3328 bcm_flowtracker_collector_callback_options_t callback_options, 3329 bcm_flowtracker_export_record_cb_f callback_fn) 3330 { 3331 int i; 3332 bcmi_ft_export_cb_ctrl_t *ft_export_cb_ctrl; 3333 bcmi_ft_cb_entry_t *entry; 3334 3335 if (!soc_feature(unit, soc_feature_bscan_ft_fifodma_support)) { 3336 return BCM_E_UNAVAIL; 3337 } 3338 3339 if (BCMI_FT_CB_CTRL(unit) == NULL) { 3340 return BCM_E_INIT; 3341 } 3342 ft_export_cb_ctrl = BCMI_FT_CB_CTRL(unit); 3343 3344 for (i = 0; i < BCMI_FT_CB_MAX; i++) { 3345 entry = &ft_export_cb_ctrl->callback_entry[i]; 3346 3347 if (entry->callback == callback_fn) { 3348 entry->state = BCMI_FT_CALLBACK_STATE_UNREGISTERED; 3349 3350 (void)bcma_ft_export_fifo_control(unit, ft_export_cb_ctrl->interval); 3351 return BCM_E_NONE; 3352 } 3353 } 3354 3355 return BCM_E_NOT_FOUND; 3356 } 3357 3358 3359 STATIC int 3360 _bcm_ft_process_export_entry(int unit, 3361 void *entry, 3362 bcm_flowtracker_export_record_t *data) 3363 { 3364 int ix, count, num_words; 3365 static int first_half = 1; 3366 static uint8 data_rec[BCM_FLOWTRACKER_EXPORT_RECORD_LENGTH] = {0}; 3367 uint32 *entry_p, *data_p; 3368 3369 count = (BCM_FLOWTRACKER_EXPORT_RECORD_LENGTH / 2); 3370 num_words = count / 4; 3371 3372 entry_p = entry; 3373 3374 if (first_half) { 3375 data_p = (uint32 *) &(data_rec[0]); 3376 for (ix = 0; ix < num_words; ix++) { 3377 data_p[num_words - ix - 1] = soc_htonl(entry_p[ix]); 3378 } 3379 first_half = 0; 3380 3381 return SOC_E_BUSY; 3382 } else { 3383 3384 data_p = (uint32 *) &(data_rec[count]); 3385 for (ix = 0; ix < num_words; ix++) { 3386 data_p[num_words - ix - 1] = soc_htonl(*entry_p); 3387 entry_p++; 3388 } 3389 3390 sal_memset(data, 0, sizeof(*data)); 3391 data->size = BCM_FLOWTRACKER_EXPORT_RECORD_LENGTH; 3392 sal_memcpy(data->data_record, data_rec, 3393 data->size); 3394 3395 first_half = 1; 3396 sal_memset(&data_rec[0], 0, (BCM_FLOWTRACKER_EXPORT_RECORD_LENGTH)); 3397 3398 return SOC_E_NONE; 3399 } 3400 3401 return SOC_E_NONE; 3402 } 3403 3404 3405 3406 /* 3407 * Function: 3408 * bcmi_ft_export_dma 3409 * Description: 3410 * A task thread to process IPFIX export FIFOs via FIFO DMA 3411 * Parameters: 3412 * unit_vp Device number 3413 * Return: 3414 * None 3415 */ 3416 STATIC void 3417 bcmi_ft_export_dma(void *unit_vp) 3418 { 3419 soc_mem_t export_fifo; 3420 bcmi_ft_cb_entry_t *cb_entry; 3421 bcmi_ft_export_cb_ctrl_t *ft_export_cb_ctrl; 3422 bcm_flowtracker_export_record_t export_record; 3423 3424 int unit; 3425 int handled; 3426 int rv, cb_rv; 3427 int entries_per_buf, adv_threshold; 3428 int interval, count, i, j, non_empty; 3429 int chan, entry_words; 3430 uint32 *buff_max; 3431 void *host_buf, *export_entry; 3432 uint32 rval, hostmem_timeout, overflow_ch, done, error, fail; 3433 3434 unit = PTR_TO_INT(unit_vp); 3435 ft_export_cb_ctrl = BCMI_FT_CB_CTRL(unit); 3436 export_fifo = BSC_EX_EXPORT_FIFOm; 3437 3438 entries_per_buf = soc_property_get(unit, 3439 spn_FLOWTRACKER_EXPORT_FIFO_HOSTBUF_SIZE, 1024); 3440 adv_threshold = entries_per_buf / 2; 3441 3442 chan = ft_export_cb_ctrl->dma_chan; 3443 3444 entry_words = soc_mem_entry_words(unit, export_fifo); 3445 host_buf = soc_cm_salloc(unit, entries_per_buf * entry_words * sizeof(uint32), 3446 "FT EXPORT DMA Buffer"); 3447 3448 if (host_buf == NULL) { 3449 soc_event_generate(unit, SOC_SWITCH_EVENT_THREAD_ERROR, 3450 SOC_SWITCH_EVENT_THREAD_IPFIX, __LINE__, 3451 BCM_E_MEMORY); 3452 goto cleanup_exit; 3453 } 3454 3455 soc_fifodma_stop(unit, chan); 3456 3457 rv = soc_fifodma_masks_get(unit, &hostmem_timeout, &overflow_ch, &error, &done); 3458 if (SOC_FAILURE(rv)) { 3459 goto cleanup_exit; 3460 } 3461 3462 rv = soc_fifodma_start(unit, chan, TRUE, export_fifo, 0, 3463 MEM_BLOCK_ANY, 0, entries_per_buf, 3464 host_buf); 3465 if (BCM_FAILURE(rv)) { 3466 soc_event_generate(unit, SOC_SWITCH_EVENT_THREAD_ERROR, 3467 SOC_SWITCH_EVENT_THREAD_IPFIX, __LINE__, rv); 3468 goto cleanup_exit; 3469 } 3470 3471 export_entry = host_buf; 3472 buff_max = (uint32 *)export_entry + (entries_per_buf * entry_words); 3473 3474 3475 while ((interval = ft_export_cb_ctrl->interval)) { 3476 fail = FALSE; 3477 if (SOC_CONTROL(unit)->ftExportIntrEnb) { 3478 3479 soc_fifodma_intr_enable(unit, chan); 3480 3481 3482 if (sal_sem_take(SOC_CONTROL(unit)->ftExportIntr, interval) < 0) { 3483 LOG_VERBOSE(BSL_LS_SOC_INTR, 3484 (BSL_META_U(unit, 3485 "FT Export DMA polling timeout\n"))); 3486 } else { 3487 LOG_VERBOSE(BSL_LS_SOC_INTR, 3488 (BSL_META_U(unit, 3489 "FT Export DMA woken up\n"))); 3490 3491 soc_fifodma_status_get(unit, chan, &rval); 3492 fail = ((rval & hostmem_timeout) | (rval & overflow_ch)); 3493 } 3494 } else { 3495 /* Polling mode: Sleep for thread interval */ 3496 sal_usleep(interval); 3497 } 3498 3499 /* Update current Callback Function Status */ 3500 for (i = 0; i < BCMI_FT_CB_MAX; i++) { 3501 cb_entry = &ft_export_cb_ctrl->callback_entry[i]; 3502 switch (cb_entry->state) { 3503 case BCMI_FT_CALLBACK_STATE_REGISTERED: 3504 cb_entry->state = BCMI_FT_CALLBACK_STATE_ACTIVE; 3505 break; 3506 case BCMI_FT_CALLBACK_STATE_UNREGISTERED: 3507 cb_entry->state = BCMI_FT_CALLBACK_STATE_INVALID; 3508 break; 3509 default: 3510 break; 3511 } 3512 } 3513 3514 3515 do { 3516 non_empty = FALSE; 3517 3518 rv = soc_fifodma_num_entries_get(unit, chan, &count); 3519 if (SOC_SUCCESS(rv)) { 3520 non_empty = TRUE; 3521 if (count > adv_threshold) { 3522 count = adv_threshold; 3523 } 3524 3525 /* Invalidate DMA memory to read */ 3526 if (((uint32 *)export_entry + count * entry_words) > buff_max) { 3527 /* roll-over cases */ 3528 soc_cm_sinval(unit, export_entry, 3529 (buff_max - (uint32 *)export_entry) * sizeof(uint32)); 3530 soc_cm_sinval(unit, host_buf, 3531 ((count * entry_words) - (buff_max - (uint32 *)export_entry)) * sizeof(uint32)); 3532 } 3533 else { 3534 soc_cm_sinval(unit, export_entry, (count * entry_words) * sizeof(uint32)); 3535 } 3536 3537 3538 for (i = 0; i < count; i++) { 3539 3540 rv = _bcm_ft_process_export_entry(unit, export_entry, &export_record); 3541 3542 export_entry = (uint32 *)export_entry + entry_words; 3543 3544 /* From the begining of host buffer */ 3545 if ((((uint32 *)export_entry - (uint32 *)host_buf) / 3546 entry_words) == entries_per_buf) { 3547 export_entry = host_buf; 3548 } 3549 3550 if (rv < 0) { 3551 /* Skip calling CB functions for 3552 * first half records - i.e, when rv != SOC_E_NONE. 3553 */ 3554 continue; 3555 } 3556 3557 3558 handled = FALSE; 3559 3560 for (j = 0; j < BCMI_FT_CB_MAX; j++) { 3561 cb_entry = &ft_export_cb_ctrl->callback_entry[j]; 3562 if (cb_entry->state == BCMI_FT_CALLBACK_STATE_ACTIVE) { 3563 cb_rv = cb_entry->callback(unit, 3564 BCMI_FT_EXPORT_INFO(unit)->dma_collector_id, 3565 &export_record, cb_entry->userdata); 3566 3567 switch (cb_rv) { 3568 case BCM_FLOWTRACKER_EXPORT_RECORD_NOT_HANDLED: 3569 break; 3570 case BCM_FLOWTRACKER_EXPORT_RECORD_HANDLED: 3571 handled = TRUE; 3572 break; 3573 case BCM_FLOWTRACKER_EXPORT_RECORD_HANDLED_OWNED: 3574 handled = TRUE; 3575 BCMI_FT_CB_CTRL(unit)->owned++; 3576 break; 3577 default: 3578 BCMI_FT_CB_CTRL(unit)->bad_handled++; 3579 break; 3580 } 3581 3582 if (handled) { 3583 break; 3584 } 3585 } 3586 } 3587 } 3588 3589 /* Mark entries read in fifo dma channel */ 3590 soc_fifodma_set_entries_read(unit, chan, count); 3591 } 3592 3593 /* check and clear error */ 3594 soc_fifodma_status_get(unit, chan, &rval); 3595 if (rval & done) { 3596 LOG_ERROR(BSL_LS_SOC_COMMON, 3597 (BSL_META_U(unit, 3598 "FIFO DMA engine terminated for chan[%d]\n"), 3599 chan)); 3600 if (rval & error) { 3601 LOG_ERROR(BSL_LS_SOC_COMMON, 3602 (BSL_META_U(unit, 3603 "FIFO DMA engine encountered error: [0x%x]\n"), 3604 rval)); 3605 } 3606 goto cleanup_exit; 3607 } 3608 3609 } while (non_empty); 3610 3611 if (fail) { 3612 /* Clearing of the FIFO_CH_DMA_INT interrupt by resetting 3613 * overflow & timeout status in FIFO_CHx_RD_DMA_STAT_CLR reg 3614 */ 3615 soc_fifodma_status_clear(unit, chan); 3616 } 3617 } 3618 3619 cleanup_exit: 3620 (void)soc_mem_fifo_dma_stop(unit, chan); 3621 3622 if (host_buf != NULL) { 3623 soc_cm_sfree(unit, host_buf); 3624 } 3625 ft_export_cb_ctrl->pid = SAL_THREAD_ERROR; 3626 sal_thread_exit(0); 3627 } 3628 3629 3630 /* Functions called from diag shell */ 3631 3632 /* 3633 * Function: 3634 * bcma_ft_export_fifo_control 3635 * Description: 3636 * To start/stop ipfix export fifo processing thread 3637 * Parameters: 3638 * unit device number 3639 * sal_usecs_t polling interval, set to 0 to stop the thread 3640 * Return: 3641 * BCM_E_NONE 3642 * BCM_E_MEMORY 3643 * BCM_E_UNAVAIL 3644 */ 3645 int 3646 bcma_ft_export_fifo_control(int unit, sal_usecs_t interval) 3647 { 3648 bcmi_ft_export_cb_ctrl_t *ft_export_cb_ctrl = BCMI_FT_CB_CTRL(unit); 3649 int pri; 3650 char name[16]; 3651 3652 if (!soc_feature(unit, soc_feature_bscan_ft_fifodma_support)) { 3653 return BCM_E_UNAVAIL; 3654 } 3655 3656 3657 if (ft_export_cb_ctrl == NULL) { 3658 BCM_IF_ERROR_RETURN(bcmi_ft_export_cb_init(unit)); 3659 ft_export_cb_ctrl = BCMI_FT_CB_CTRL(unit); 3660 if (ft_export_cb_ctrl == NULL) { 3661 return BCM_E_INTERNAL; 3662 } 3663 } 3664 3665 sal_snprintf(name, sizeof(name), "bcmFtExportDma.%d", unit); 3666 3667 ft_export_cb_ctrl->interval = interval; 3668 3669 if (interval) { 3670 if (ft_export_cb_ctrl->pid == SAL_THREAD_ERROR) { 3671 pri = soc_property_get(unit, 3672 spn_FLOWTRACKER_EXPORT_FIFO_THREAD_PRI, 100); 3673 ft_export_cb_ctrl->pid = sal_thread_create(name, 3674 SAL_THREAD_STKSZ, 3675 pri, 3676 bcmi_ft_export_dma, 3677 INT_TO_PTR(unit)); 3678 if (ft_export_cb_ctrl->pid == SAL_THREAD_ERROR) { 3679 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 3680 (BSL_META_U(unit, 3681 "Could not start thread\n"))); 3682 return BCM_E_MEMORY; 3683 } 3684 } 3685 } else { 3686 /* Wake up thread so it will check the changed interval value */ 3687 sal_sem_give(SOC_CONTROL(unit)->ftExportIntr); 3688 } 3689 3690 return BCM_E_NONE; 3691 } 3692 3693 3694 int 3695 bcma_ft_export_dma_collector_get(int unit, 3696 bcm_collector_t *id) 3697 { 3698 bcm_collector_t collector_id; 3699 3700 collector_id = BCMI_FT_EXPORT_INFO(unit)->dma_collector_id; 3701 3702 if (collector_id == BCMI_FT_COLLECTOR_ID_INVALID) { 3703 return BCM_E_PARAM; 3704 } 3705 3706 *id = collector_id; 3707 3708 return BCM_E_NONE; 3709 } 3710 3711 int 3712 bcma_ft_setid_template_id_get(int unit, uint16 setid, 3713 bcm_flowtracker_export_template_t *template_id) 3714 { 3715 int ix; 3716 bcmi_ft_template_info_t *template_info; 3717 3718 for (ix = 0; ix < BCMI_FT_MAX_TEMPLATES; ix++) { 3719 template_info = BCMI_FT_TEMPLATE_INFO(unit, ix); 3720 3721 if (setid == template_info->set_id) { 3722 break; 3723 } 3724 3725 } 3726 3727 if (ix < BCMI_FT_MAX_TEMPLATES) { 3728 *template_id = ix; 3729 return BCM_E_NONE; 3730 } 3731 3732 return BCM_E_NOT_FOUND; 3733 } 3734 3735 3736 3737 #ifdef BCM_WARM_BOOT_SUPPORT 3738 3739 #define BCMI_FT_WB_SCACHE_SIZE(_data_) sizeof(*(_data_)) 3740 3741 3742 #define BCMI_FT_WB_SCACHE_SYNC(_scache_, _data_) \ 3743 do { \ 3744 sal_memcpy((_scache_), (_data_), sizeof(*(_data_)));\ 3745 (_scache_) += sizeof(*(_data_)); \ 3746 } while (0) 3747 3748 #define BCMI_FT_WB_SCACHE_RECOVER(_scache_, _data_) \ 3749 do { \ 3750 sal_memcpy((_data_), (_scache_), sizeof(*(_data_)));\ 3751 (_scache_) += sizeof(*(_data_)); \ 3752 } while (0) 3753 3754 3755 /* 3756 * Function: 3757 * bcmi_ft_export_wb_alloc_size 3758 * Purpose: 3759 * Allocate persistent info memory for flowtracker module 3760 * Parameters: 3761 * unit - StrataSwitch unit number. 3762 * Returns: 3763 * BCM_E_XXX 3764 */ 3765 STATIC void 3766 bcmi_ft_export_wb_alloc_size(int unit, int *size) 3767 { 3768 int ix, jx; 3769 int alloc_size; 3770 bcmi_ft_collector_info_t *coll_info; 3771 bcmi_ft_template_info_t *template_info; 3772 3773 alloc_size = 0; 3774 3775 /* DMA collector Id */ 3776 alloc_size += BCMI_FT_WB_SCACHE_SIZE(&(BCMI_FT_EXPORT_INFO(unit)->dma_collector_id)); 3777 3778 /* Sync collector_info structs. */ 3779 for (ix = 0; ix < BCMI_FT_EXPORT_INFO(unit)->max_collectors; ix++) { 3780 coll_info = BCMI_FT_COLLECTOR_INFO(unit, ix); 3781 3782 alloc_size += BCMI_FT_WB_SCACHE_SIZE(&(coll_info->cmn_coll_id)); 3783 alloc_size += BCMI_FT_WB_SCACHE_SIZE(&(coll_info->cmn_export_prof_id)); 3784 alloc_size += BCMI_FT_WB_SCACHE_SIZE(&(coll_info->coll_hw_id)); 3785 alloc_size += BCMI_FT_WB_SCACHE_SIZE(&(coll_info->in_use)); 3786 alloc_size += BCMI_FT_WB_SCACHE_SIZE(&(coll_info->collector_info)); 3787 } 3788 3789 /* Sync template_info structs. */ 3790 for (ix = 0; ix < BCMI_FT_EXPORT_INFO(unit)->max_templates; ix++) { 3791 template_info = BCMI_FT_TEMPLATE_INFO(unit, ix); 3792 3793 alloc_size += BCMI_FT_WB_SCACHE_SIZE(&(template_info->template_id)); 3794 alloc_size += BCMI_FT_WB_SCACHE_SIZE(&(template_info->in_use)); 3795 alloc_size += BCMI_FT_WB_SCACHE_SIZE(&(template_info->set_id)); 3796 alloc_size += BCMI_FT_WB_SCACHE_SIZE(&(template_info->num_elements)); 3797 3798 3799 for (jx = 0; jx < BCMI_FT_TEMPLATE_MAX_ELEMS; jx++) { 3800 alloc_size += BCMI_FT_WB_SCACHE_SIZE(&(template_info->export_elements[jx])); 3801 } 3802 } 3803 3804 /* Return the calculated size. */ 3805 *size = alloc_size; 3806 3807 return; 3808 } 3809 3810 int 3811 bcmi_ft_export_warmboot_alloc(int unit, soc_scache_handle_t scache_handle) 3812 { 3813 3814 uint8 *ft_scache_ptr; 3815 int size = 0; 3816 int rv = BCM_E_NONE; 3817 3818 bcmi_ft_export_wb_alloc_size(unit, &size); 3819 3820 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE, 3821 size, &ft_scache_ptr, 3822 BCM_WB_FT_EXPORT_DEFAULT_VERSION, NULL); 3823 3824 if (BCM_E_NOT_FOUND == rv) { 3825 /* Proceed with Level 1 Warm Boot */ 3826 rv = BCM_E_NONE; 3827 } 3828 3829 return rv; 3830 } 3831 3832 3833 3834 /* 3835 * Function: 3836 * bcmi_ft_export_warmboot_sync 3837 * Purpose: 3838 * Sync flowtracker export state. 3839 * Parameters: 3840 * unit - (IN) BCM device id 3841 * 3842 * Returns: 3843 * BCM_E_XXX 3844 */ 3845 int 3846 bcmi_ft_export_warmboot_sync(int unit, soc_scache_handle_t scache_handle) 3847 { 3848 int ix, jx; 3849 int size; 3850 bcmi_ft_collector_info_t *coll_info; 3851 bcmi_ft_template_info_t *template_info; 3852 uint8 *ft_scache_ptr; 3853 3854 /* Get the size to save ft export module warmboot state. */ 3855 bcmi_ft_export_wb_alloc_size(unit, &size); 3856 3857 BCM_IF_ERROR_RETURN 3858 (_bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 3859 size, &ft_scache_ptr, 3860 BCM_WB_FT_EXPORT_DEFAULT_VERSION, NULL)); 3861 3862 /* DMA collector Id */ 3863 BCMI_FT_WB_SCACHE_SYNC(ft_scache_ptr, &(BCMI_FT_EXPORT_INFO(unit)->dma_collector_id)); 3864 3865 /* Sync collector_info structs. */ 3866 for (ix = 0; ix < BCMI_FT_EXPORT_INFO(unit)->max_collectors; ix++) { 3867 coll_info = BCMI_FT_COLLECTOR_INFO(unit, ix); 3868 3869 BCMI_FT_WB_SCACHE_SYNC(ft_scache_ptr, &(coll_info->cmn_coll_id)); 3870 BCMI_FT_WB_SCACHE_SYNC(ft_scache_ptr, &(coll_info->cmn_export_prof_id)); 3871 BCMI_FT_WB_SCACHE_SYNC(ft_scache_ptr, &(coll_info->coll_hw_id)); 3872 BCMI_FT_WB_SCACHE_SYNC(ft_scache_ptr, &(coll_info->in_use)); 3873 BCMI_FT_WB_SCACHE_SYNC(ft_scache_ptr, &(coll_info->collector_info)); 3874 } 3875 3876 /* Sync template_info structs. */ 3877 for (ix = 0; ix < BCMI_FT_EXPORT_INFO(unit)->max_templates; ix++) { 3878 template_info = BCMI_FT_TEMPLATE_INFO(unit, ix); 3879 3880 BCMI_FT_WB_SCACHE_SYNC(ft_scache_ptr, &(template_info->template_id)); 3881 BCMI_FT_WB_SCACHE_SYNC(ft_scache_ptr, &(template_info->in_use)); 3882 BCMI_FT_WB_SCACHE_SYNC(ft_scache_ptr, &(template_info->set_id)); 3883 BCMI_FT_WB_SCACHE_SYNC(ft_scache_ptr, &(template_info->num_elements)); 3884 3885 3886 for (jx = 0; jx < BCMI_FT_TEMPLATE_MAX_ELEMS; jx++) { 3887 BCMI_FT_WB_SCACHE_SYNC(ft_scache_ptr, &(template_info->export_elements[jx])); 3888 } 3889 } 3890 3891 return BCM_E_NONE; 3892 } 3893 3894 STATIC int 3895 bcmi_ft_export_reinit(int unit) 3896 { 3897 3898 int ix, rv; 3899 bcmi_ft_template_info_t *template_info; 3900 bcmi_ft_collector_info_t *coll_info; 3901 3902 for (ix = 0; ix < BCMI_FT_EXPORT_INFO(unit)->max_collectors; ix++) { 3903 coll_info = BCMI_FT_COLLECTOR_INFO(unit, ix); 3904 3905 if (coll_info->in_use) { 3906 rv = _bcm_esw_collector_ref_count_update(unit, 3907 coll_info->cmn_coll_id, 3908 coll_info->in_use); 3909 BCM_IF_ERROR_RETURN(rv); 3910 rv = _bcm_esw_collector_user_update(unit, 3911 coll_info->cmn_coll_id, 3912 _BCM_COLLECTOR_EXPORT_APP_FT_IPFIX); 3913 BCM_IF_ERROR_RETURN(rv); 3914 3915 rv = _bcm_esw_collector_export_profile_ref_count_update(unit, 3916 coll_info->cmn_export_prof_id, coll_info->in_use); 3917 BCM_IF_ERROR_RETURN(rv); 3918 3919 } 3920 } 3921 3922 for (ix = 0; ix < BCMI_FT_EXPORT_INFO(unit)->max_templates; ix++) { 3923 template_info = BCMI_FT_TEMPLATE_INFO(unit, ix); 3924 if (template_info->template_id != BCMI_FT_TEMPLATE_ID_INVALID) { 3925 SHR_BITSET(BCMI_FT_TEMPLATE_BITMAP(unit), ix); 3926 } 3927 } 3928 3929 return BCM_E_NONE; 3930 } 3931 3932 3933 /* 3934 * Function: 3935 * bcmi_ft_export_warmboot_recover 3936 * Purpose: 3937 * Recover flowtracker export state. 3938 * Parameters: 3939 * unit - (IN) BCM device id 3940 * 3941 * Returns: 3942 * BCM_E_XXX 3943 */ 3944 3945 int 3946 bcmi_ft_export_warmboot_recover(int unit, soc_scache_handle_t scache_handle) 3947 { 3948 int ix, jx; 3949 int size; 3950 bcmi_ft_collector_info_t *coll_info; 3951 bcmi_ft_template_info_t *template_info; 3952 uint8 *ft_scache_ptr; 3953 3954 /* Get the size to save ft export module warmboot state. */ 3955 bcmi_ft_export_wb_alloc_size(unit, &size); 3956 3957 3958 BCM_IF_ERROR_RETURN 3959 (_bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 3960 size, &ft_scache_ptr, 3961 BCM_WB_FT_EXPORT_DEFAULT_VERSION, NULL)); 3962 3963 /* DMA collector Id */ 3964 BCMI_FT_WB_SCACHE_RECOVER(ft_scache_ptr, &(BCMI_FT_EXPORT_INFO(unit)->dma_collector_id)); 3965 3966 /* Sync collector_info structs. */ 3967 for (ix = 0; ix < BCMI_FT_EXPORT_INFO(unit)->max_collectors; ix++) { 3968 coll_info = BCMI_FT_COLLECTOR_INFO(unit, ix); 3969 3970 BCMI_FT_WB_SCACHE_RECOVER(ft_scache_ptr, &(coll_info->cmn_coll_id)); 3971 BCMI_FT_WB_SCACHE_RECOVER(ft_scache_ptr, &(coll_info->cmn_export_prof_id)); 3972 BCMI_FT_WB_SCACHE_RECOVER(ft_scache_ptr, &(coll_info->coll_hw_id)); 3973 BCMI_FT_WB_SCACHE_RECOVER(ft_scache_ptr, &(coll_info->in_use)); 3974 BCMI_FT_WB_SCACHE_RECOVER(ft_scache_ptr, &(coll_info->collector_info)); 3975 } 3976 3977 /* Sync template_info structs. */ 3978 for (ix = 0; ix < BCMI_FT_EXPORT_INFO(unit)->max_templates; ix++) { 3979 template_info = BCMI_FT_TEMPLATE_INFO(unit, ix); 3980 3981 BCMI_FT_WB_SCACHE_RECOVER(ft_scache_ptr, &(template_info->template_id)); 3982 BCMI_FT_WB_SCACHE_RECOVER(ft_scache_ptr, &(template_info->in_use)); 3983 BCMI_FT_WB_SCACHE_RECOVER(ft_scache_ptr, &(template_info->set_id)); 3984 BCMI_FT_WB_SCACHE_RECOVER(ft_scache_ptr, &(template_info->num_elements)); 3985 3986 3987 for (jx = 0; jx < BCMI_FT_TEMPLATE_MAX_ELEMS; jx++) { 3988 BCMI_FT_WB_SCACHE_RECOVER(ft_scache_ptr, &(template_info->export_elements[jx])); 3989 } 3990 } 3991 3992 3993 /* Export reinit */ 3994 BCM_IF_ERROR_RETURN(bcmi_ft_export_reinit(unit)); 3995 3996 return BCM_E_NONE; 3997 } 3998 3999 #endif /* BCM_WARM_BOOT_SUPPORT */ 4000 4001 #else /* BCM_FLOWTRCAKER_SUPPORT*/ 4002 int bcmi_ft_export_not_empty; 4003 #endif /* BCM_FLOWTRCAKER_SUPPORT */ 4004