hash.c (74927B)
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: hash.c 8 * Purpose: Implement Trident3 specific hash flex bin selection APIs. 9 * Trident3 enhanced the RTAG7 hash module with the flexible bin selection 10 * logic. It can overwrite the existing fixed bin selection logic. The flexible 11 * logic uses a 128 entry deep TCAM. Each entry consists of the key and 12 * policy. The key uses number of flex objects defined in the dynamically loaded 13 * Cancun CEH. User will need to use the bcm_hash_flex_field_t parameter to 14 * pass into the API. 15 */ 16 17 #include <soc/drv.h> 18 #include <soc/scache.h> 19 20 #include <shared/bsl.h> 21 #include <assert.h> 22 #include <bcm/types.h> 23 #include <bcm/error.h> 24 #include <soc/drv.h> 25 #include <soc/format.h> 26 #include <soc/esw/cancun.h> 27 #include <bcm/hash.h> 28 #include <bcm_int/esw/switch.h> 29 #include <bcm_int/esw/hash.h> 30 #include <bcm_int/esw_dispatch.h> 31 32 #if defined(BCM_TRIDENT3_SUPPORT) 33 34 /* fixed packet type's corresponding fields and value */ 35 typedef struct { 36 int pkt_type; 37 soc_format_t fmt; 38 soc_field_t fld1; 39 int val1; 40 soc_field_t fld2; 41 int val2; 42 } _bcm_hash_pfld_info_t; 43 44 /* fixed packet status corresponding fields and value */ 45 typedef struct { 46 int pkt_status; 47 soc_field_t fld_mask; 48 soc_field_t fld; 49 int bit_pos; 50 int fld_size; 51 } _bcm_hash_sfld_info_t; 52 53 /* TD3 flex objects */ 54 typedef struct { 55 uint64 match_id; 56 uint16 flow_id0; 57 uint16 flow_id1; 58 uint16 flow_id2; 59 uint8 hve_ctrl1; 60 uint8 hve_ctrl2; 61 } _bcm_hash_td3_flex_obj_t; 62 63 /* Flex field ID: object and field name id */ 64 #define FIELD_OBJ_ID(_id) ((_id) >> 24) 65 #define FIELD_NAME_ID(_id) ((_id) & 0xFFFFFF) 66 #define FIELD_OBJ_ID_SET(_id, _obj) ((_id) | ((_obj) << 24)) 67 68 /* TD3 profile mem and field */ 69 #define _BCM_HASH_TD3_NUM_BINS_PER_SET 13 70 #define _BCM_HASH_TD3_NUM_PROF_MEM 4 71 72 #define PROF_BASE(_u, _num) \ 73 (soc_mem_index_count((_u), FLEX_BIN_HASH_PROFILE_0m) * \ 74 _BCM_HASH_TD3_NUM_BINS_PER_SET * (_num)) 75 #define BIN_INX(_u, _mn, _ent, _bn) (PROF_BASE((_u),(_mn)) + \ 76 (_ent) * _BCM_HASH_TD3_NUM_BINS_PER_SET + \ 77 (_bn) % _BCM_HASH_TD3_NUM_BINS_PER_SET) 78 79 #define BIN_ID_SIZE8_VALID(_id) ((((_id) >= BCM_HASH_BIN_A_0) && \ 80 ((_id) <= BCM_HASH_BIN_A_MAX)) || \ 81 (((_id) >= BCM_HASH_BIN_A_0_UPPER_HALF) && \ 82 ((_id) <= BCM_HASH_BIN_A_UPPER_HALF_MAX)) || \ 83 (((_id) >= BCM_HASH_BIN_B_0) && \ 84 ((_id) <= BCM_HASH_BIN_B_MAX)) || \ 85 (((_id) >= BCM_HASH_BIN_B_0_UPPER_HALF) && \ 86 ((_id) <= BCM_HASH_BIN_B_UPPER_HALF_MAX))) 87 88 #define BIN_ID_SIZE16_VALID(_id) ((((_id) >= BCM_HASH_BIN_A_0) && \ 89 ((_id) <= BCM_HASH_BIN_A_MAX)) || \ 90 (((_id) >= BCM_HASH_BIN_B_0) && \ 91 ((_id) <= BCM_HASH_BIN_B_MAX))) 92 93 #define BIN_ID_VALID(_cfg, _id) ( \ 94 ((_cfg)->option & BCM_HASH_FLEX_BIN_OPTION_SIZE_8BIT) ? \ 95 BIN_ID_SIZE8_VALID((_id)) : \ 96 BIN_ID_SIZE16_VALID((_id))) 97 98 typedef struct { 99 soc_mem_t mem[_BCM_HASH_TD3_NUM_PROF_MEM]; 100 soc_field_t fld[_BCM_HASH_TD3_NUM_BINS_PER_SET]; 101 } _bcm_hash_prof_info_t; 102 103 104 STATIC _bcm_hash_prof_info_t _bcm_hash_td3_prof_info = { 105 {FLEX_BIN_HASH_PROFILE_0m, FLEX_BIN_HASH_PROFILE_1m, 106 FLEX_BIN_HASH_PROFILE_2m, FLEX_BIN_HASH_PROFILE_3m}, 107 {HASH_BIN_0f, HASH_BIN_1f, HASH_BIN_2f, HASH_BIN_3f, 108 HASH_BIN_4f, HASH_BIN_5f, HASH_BIN_6f, HASH_BIN_7f, 109 HASH_BIN_8f, HASH_BIN_9f, HASH_BIN_10f, HASH_BIN_11f, 110 HASH_BIN_12f} 111 }; 112 113 STATIC _bcm_hash_sfld_info_t _bcm_hash_td3_sfld_info[] = { 114 {BCM_HASH_PKT_STATUS_GTP_ENDPOINT_ID, 115 GTP_ENDPOINT_ID_VALID_MASKf, GTP_ENDPOINT_ID_VALIDf, 0, 1}, 116 117 {BCM_HASH_PKT_STATUS_L3_FORWARDED, 118 L3_FORWARDED_MASKf, L3_FORWARDEDf, 0, 1}, 119 120 {BCM_HASH_PKT_STATUS_TUNNEL_TERM, 121 TUNNEL_TERM_STATUS_MASKf, TUNNEL_TERM_STATUSf, 0, 1}, 122 123 /* end marker */ 124 {BCM_HASH_PKT_STATUS_MAX, INVALIDm, INVALIDm, 0, 0}, 125 }; 126 127 STATIC _bcm_hash_pfld_info_t _bcm_hash_td3_pfld_info[] = { 128 {BCM_HASH_PKT_FLOW_TYPE_FRONT_PANEL, PKT_FLOW_ID_0_FORMATfmt, 129 MACRO_FLOW_ID_FIXEDf, 1, MICRO_FLOW_TYPE_FIXED_FRONT_PANELf, 0}, 130 131 {BCM_HASH_PKT_FLOW_TYPE_FRONT_PANEL_SYSTEM_HDR_PROXY, 132 PKT_FLOW_ID_0_FORMATfmt, 133 MACRO_FLOW_ID_FIXEDf, 1, MICRO_FLOW_TYPE_FIXED_FRONT_PANELf, 1}, 134 135 {BCM_HASH_PKT_FLOW_TYPE_FRONT_PANEL_LOOPBACK_GENERIC, 136 PKT_FLOW_ID_0_FORMATfmt, 137 MACRO_FLOW_ID_FIXEDf, 1, MICRO_FLOW_TYPE_FIXED_FRONT_PANELf, 6}, 138 139 {BCM_HASH_PKT_FLOW_TYPE_FRONT_PANEL_LOOPBACK_TUNNEL_TERM, 140 PKT_FLOW_ID_0_FORMATfmt, 141 MACRO_FLOW_ID_FIXEDf, 1, MICRO_FLOW_TYPE_FIXED_FRONT_PANELf, 7}, 142 143 {BCM_HASH_PKT_FLOW_TYPE_SYSTEM_HDR, 144 PKT_FLOW_ID_0_FORMATfmt, 145 MACRO_FLOW_ID_FIXEDf, 2, MICRO_FLOW_TYPE_FIXED_SYSTEM_HDRf, 0}, 146 147 {BCM_HASH_PKT_FLOW_TYPE_SYSTEM_HDR_CONTROL, 148 PKT_FLOW_ID_0_FORMATfmt, 149 MACRO_FLOW_ID_FIXEDf, 2, MICRO_FLOW_TYPE_FIXED_SYSTEM_HDRf, 0}, 150 151 {BCM_HASH_PKT_FLOW_TYPE_SYSTEM_HDR_UNICAST, 152 PKT_FLOW_ID_0_FORMATfmt, 153 MACRO_FLOW_ID_FIXEDf, 2, MICRO_FLOW_TYPE_FIXED_SYSTEM_HDRf, 1}, 154 155 {BCM_HASH_PKT_FLOW_TYPE_SYSTEM_HDR_FLOOD, 156 PKT_FLOW_ID_0_FORMATfmt, 157 MACRO_FLOW_ID_FIXEDf, 2, MICRO_FLOW_TYPE_FIXED_SYSTEM_HDRf, 2}, 158 159 {BCM_HASH_PKT_FLOW_TYPE_SYSTEM_HDR_L2_MULTICAST, 160 PKT_FLOW_ID_0_FORMATfmt, 161 MACRO_FLOW_ID_FIXEDf, 2, MICRO_FLOW_TYPE_FIXED_SYSTEM_HDRf, 3}, 162 163 {BCM_HASH_PKT_FLOW_TYPE_SYSTEM_HDR_L3_MULTICAST, 164 PKT_FLOW_ID_0_FORMATfmt, 165 MACRO_FLOW_ID_FIXEDf, 2, MICRO_FLOW_TYPE_FIXED_SYSTEM_HDRf, 4}, 166 167 {BCM_HASH_PKT_FLOW_TYPE_TUNNEL_VXLAN, 168 PKT_FLOW_ID_1_FORMATfmt, 169 MACRO_FLOW_ID_FIXEDf, 4, INVALIDf, 0}, 170 171 {BCM_HASH_PKT_FLOW_TYPE_TUNNEL_NVGRE, 172 PKT_FLOW_ID_1_FORMATfmt, 173 MACRO_FLOW_ID_FIXEDf, 3, INVALIDf, 0}, 174 175 {BCM_HASH_PKT_FLOW_TYPE_TUNNEL_MIM, 176 PKT_FLOW_ID_1_FORMATfmt, 177 MACRO_FLOW_ID_FIXEDf, 2, INVALIDf, 0}, 178 179 {BCM_HASH_PKT_FLOW_TYPE_TUNNEL_IPINIP, 180 PKT_FLOW_ID_1_FORMATfmt, 181 MACRO_FLOW_ID_FIXEDf, 5, INVALIDf, 0}, 182 183 {BCM_HASH_PKT_FLOW_TYPE_TUNNEL_MPLS, 184 PKT_FLOW_ID_1_FORMATfmt, 185 MACRO_FLOW_ID_FIXEDf, 6, INVALIDf, 0}, 186 187 {BCM_HASH_PKT_FLOW_TYPE_LAYER_L2, 188 PKT_FLOW_ID_2_FORMATfmt, 189 MACRO_FLOW_ID_FIXEDf, 2, INVALIDf, 0}, 190 191 {BCM_HASH_PKT_FLOW_TYPE_LAYER_L3, 192 PKT_FLOW_ID_2_FORMATfmt, 193 MACRO_FLOW_ID_FIXEDf, 3, INVALIDf, 0}, 194 195 /* end marker */ 196 {BCM_HASH_PKT_TYPE_MAX, INVALIDfmt, INVALIDf, 0, INVALIDf, 0}, 197 }; 198 199 /* TD3 flex object names */ 200 STATIC char *_bcm_hash_td3_obj_names[] = { 201 "Z0_MATCH_ID", 202 "Z1_MATCH_ID", 203 "Z2_MATCH_ID", 204 "Z3_MATCH_ID", 205 "Z4_MATCH_ID", 206 "PKT_FLOW_ID_0", 207 "PKT_FLOW_ID_1", 208 "PKT_FLOW_ID_2", 209 "HVE_CONTROL_1", 210 "HVE_CONTROL_2" 211 }; 212 213 STATIC uint8 _bcm_hash_td3_cmd_offset[BCM_HASH_OBJ_OFFSET_MAX]; 214 STATIC uint8 _bcm_hash_td3_cmd_obj[BCM_HASH_OBJ_ID_MAX]; 215 216 STATIC int _bcm_hash_td3_flex_field_get(int unit, int num_fields, 217 bcm_hash_flex_field_t *flex_field, _bcm_hash_td3_flex_obj_t *flex_obj, 218 _bcm_hash_td3_flex_obj_t *flex_obj_mask); 219 STATIC int _bcm_hash_td3_flex_field_add(int unit, int num_fields, 220 bcm_hash_flex_field_t *flex_field, _bcm_hash_td3_flex_obj_t *flex_obj, 221 _bcm_hash_td3_flex_obj_t *flex_obj_mask); 222 STATIC int _bcm_td3_hash_flex_bin_delete_all(int unit); 223 224 #ifdef BCM_WARM_BOOT_SUPPORT 225 226 #define BCM_WB_VERSION_1_0 SOC_SCACHE_VERSION(1, 0) 227 #define BCM_WB_DEFAULT_VERSION BCM_WB_VERSION_1_0 228 229 /* 230 * Function: 231 * _bcm_hash_td3_fbin_wb_alloc 232 * Purpose: 233 * Alloc persisitent memory for Level 2 Warm Boot scache. 234 * Parameters: 235 * unit - (IN) Device Unit Number. 236 * Returns: 237 * BCM_E_XXX 238 */ 239 240 STATIC int 241 _bcm_hash_td3_fbin_wb_alloc (int unit) 242 { 243 int alloc_sz = 0, rv = BCM_E_NONE; 244 soc_scache_handle_t scache_handle; 245 uint8 *hash_scache_ptr = NULL; 246 int stable_size; 247 248 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 249 250 if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) { 251 return BCM_E_NONE; 252 } 253 254 alloc_sz = soc_mem_index_count(unit, FLEX_BIN_HASH_PROFILE_0m); 255 alloc_sz *= _BCM_HASH_TD3_NUM_PROF_MEM; 256 alloc_sz *= _BCM_HASH_TD3_NUM_BINS_PER_SET; 257 alloc_sz *= sizeof(uint16); 258 259 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_HASH, 0); 260 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE, 261 alloc_sz, (uint8**)&hash_scache_ptr, 262 BCM_WB_DEFAULT_VERSION, NULL); 263 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 264 return rv; 265 } 266 267 return BCM_E_NONE; 268 } 269 270 /* 271 * Function: 272 * _bcm_hash_td3_fbin_wb_recover 273 * Purpose: 274 * Recover hash flex bin module info for Level 2 Warm Boot from 275 * persisitent memory. 276 * Parameters: 277 * unit - (IN) Device Unit Number. 278 * 279 * Returns: 280 * BCM_E_XXX 281 */ 282 283 STATIC int 284 _bcm_hash_td3_fbin_wb_recover (int unit) 285 { 286 int sz = 0, rv = BCM_E_NONE; 287 int stable_size; 288 uint16 recovered_ver = 0; 289 uint8 *hash_scache_ptr = NULL; 290 soc_scache_handle_t scache_handle; 291 bcmi_hash_flex_bin_info_t *info; 292 293 info = &bcmi_hash_flex_bin_info[unit]; 294 295 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 296 297 /* Requires extended scache support level-2 warmboot */ 298 if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) { 299 return BCM_E_NONE; 300 } 301 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_HASH, 0); 302 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 303 0, &hash_scache_ptr, 304 BCM_WB_DEFAULT_VERSION, &recovered_ver); 305 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 306 return rv; 307 } else if (rv == BCM_E_NOT_FOUND) { 308 return _bcm_hash_td3_fbin_wb_alloc(unit); 309 } 310 311 if (hash_scache_ptr != NULL) { 312 sz = soc_mem_index_count(unit, FLEX_BIN_HASH_PROFILE_0m); 313 sz *= _BCM_HASH_TD3_NUM_PROF_MEM; 314 sz *= _BCM_HASH_TD3_NUM_BINS_PER_SET; 315 sz *= sizeof(uint16); 316 317 /* recover bin object id array */ 318 sal_memcpy(info->bin_obj_arr, hash_scache_ptr, sz); 319 hash_scache_ptr += sz; 320 } 321 return BCM_E_NONE; 322 } 323 324 /* 325 * Function: 326 * _bcm_hash_td3_fbin_reinit 327 * Purpose: 328 * Warm boot recovery for the hash flex bin module 329 * Parameters: 330 * unit - Device Number 331 * Returns: 332 * BCM_E_XXX 333 */ 334 335 STATIC int 336 _bcm_hash_td3_fbin_reinit (int unit) 337 { 338 int rv; 339 int i; 340 int size; 341 bcmi_hash_flex_bin_info_t *info; 342 flex_rtag7_hash_tcam_entry_t rule_entry; 343 soc_mem_t mem; 344 345 info = &bcmi_hash_flex_bin_info[unit]; 346 mem = FLEX_RTAG7_HASH_TCAMm; 347 348 /* recover entry usage bitmap from hardware */ 349 size = soc_mem_index_count(unit, mem); 350 for (i = 0; i < size; i++) { 351 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, i, 352 &rule_entry); 353 SOC_IF_ERROR_RETURN(rv); 354 355 if (soc_mem_field32_get(unit, mem, &rule_entry, VALIDf)) { 356 SHR_BITSET(info->entry_bmp, i); 357 } 358 } 359 360 /* Recover L2 scache */ 361 rv = _bcm_hash_td3_fbin_wb_recover(unit); 362 BCM_IF_ERROR_RETURN(rv); 363 364 return BCM_E_NONE; 365 } 366 367 /* 368 * Function: 369 * bcmi_td3_hash_flex_bin_sync 370 * Purpose: 371 * Record hash flex bin module persistent info for Level 2 Warm Boot. 372 * Parameters: 373 * unit - (IN) Device Unit Number. 374 * 375 * Returns: 376 * BCM_E_XXX 377 */ 378 379 int 380 bcmi_td3_hash_flex_bin_sync(int unit) 381 { 382 int sz = 0, rv = BCM_E_NONE; 383 int stable_size; 384 uint8 *hash_scache_ptr = NULL; 385 soc_scache_handle_t scache_handle; 386 bcmi_hash_flex_bin_info_t *info; 387 388 if (!soc_feature(unit, soc_feature_hash_flex_bin)) { 389 return BCM_E_UNAVAIL; 390 } 391 392 info = &bcmi_hash_flex_bin_info[unit]; 393 394 if (info->initialized == FALSE) { 395 return BCM_E_INIT; 396 } 397 398 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 399 400 /* Requires extended scache support level-2 warmboot */ 401 if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) { 402 return BCM_E_NONE; 403 } 404 405 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_HASH, 0); 406 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 407 0, &hash_scache_ptr, 408 BCM_WB_DEFAULT_VERSION, NULL); 409 if (BCM_FAILURE(rv) && (rv != BCM_E_INTERNAL)) { 410 return rv; 411 } 412 413 if (hash_scache_ptr != NULL) { 414 sz = soc_mem_index_count(unit, FLEX_BIN_HASH_PROFILE_0m); 415 sz *= _BCM_HASH_TD3_NUM_PROF_MEM; 416 sz *= _BCM_HASH_TD3_NUM_BINS_PER_SET; 417 sz *= sizeof(uint16); 418 419 /* recover bin object id array */ 420 sal_memcpy(hash_scache_ptr, info->bin_obj_arr, sz); 421 hash_scache_ptr += sz; 422 } 423 return BCM_E_NONE; 424 } 425 426 #endif /* BCM_WARM_BOOT_SUPPORT */ 427 428 /* 429 * Function: 430 * bcmi_td3_hash_flex_bin_init 431 * Purpose: 432 * Initialize the TD3 hash flex bin module. Should only be called during 433 * initialization stage. 434 * 435 * Parameters: 436 * unit - (IN) Unit ID. 437 */ 438 439 int bcmi_td3_hash_flex_bin_init (int unit) 440 { 441 bcmi_hash_flex_bin_info_t *info; 442 uint8 *cmd_offset; 443 uint8 *cmd_obj; 444 int offset; 445 int size; 446 int rv = BCM_E_NONE; 447 448 info = &bcmi_hash_flex_bin_info[unit]; 449 450 if (info->entry_bmp != NULL) { 451 sal_free(info->entry_bmp); 452 info->entry_bmp = NULL; 453 } 454 455 /* allocate the TCAM entry usage bitmap */ 456 size = soc_mem_index_count(unit, FLEX_RTAG7_HASH_TCAMm); 457 size = SHR_BITALLOCSIZE(size); 458 info->entry_bmp = sal_alloc(size, "Hash flex bin TCAM usage bitmap"); 459 if (info->entry_bmp == NULL) { 460 rv = BCM_E_MEMORY; 461 goto exit; 462 } 463 sal_memset(info->entry_bmp, 0, size); 464 465 /* allocate buffer to record the bin command object id 466 * TD3 objects have overlays. Multiple objects can map to the same hardware 467 * value. So the correct object Id cannot be retrieved from hardware. 468 */ 469 if (info->bin_obj_arr != NULL) { 470 sal_free(info->bin_obj_arr); 471 info->bin_obj_arr = NULL; 472 } 473 size = soc_mem_index_count(unit, FLEX_BIN_HASH_PROFILE_0m); 474 size *= _BCM_HASH_TD3_NUM_PROF_MEM; 475 size *= _BCM_HASH_TD3_NUM_BINS_PER_SET; 476 size *= sizeof(uint16); 477 info->bin_obj_arr = sal_alloc(size, "Hash flex bin object id map"); 478 if (info->bin_obj_arr == NULL) { 479 rv = BCM_E_MEMORY; 480 goto exit; 481 } 482 sal_memset(info->bin_obj_arr, 0, size); 483 484 /* This is TD3 specific command offset mapping */ 485 cmd_obj = _bcm_hash_td3_cmd_obj; 486 cmd_offset = _bcm_hash_td3_cmd_offset; 487 488 cmd_offset[BCM_HASH_OBJ_OFFSET_BIT0] = 0; 489 cmd_offset[BCM_HASH_OBJ_OFFSET_BIT4] = 1; 490 cmd_offset[BCM_HASH_OBJ_OFFSET_BIT8] = 2; 491 cmd_offset[BCM_HASH_OBJ_OFFSET_BIT12] = 3; 492 cmd_offset[BCM_HASH_OBJ_OFFSET_BIT16] = 4; 493 cmd_offset[BCM_HASH_OBJ_OFFSET_BIT20] = 5; 494 cmd_offset[BCM_HASH_OBJ_OFFSET_BIT24] = 6; 495 cmd_offset[BCM_HASH_OBJ_OFFSET_BIT28] = 7; 496 cmd_offset[BCM_HASH_OBJ_OFFSET_BIT32] = 8; 497 cmd_offset[BCM_HASH_OBJ_OFFSET_BIT36] = 9; 498 cmd_offset[BCM_HASH_OBJ_OFFSET_BIT40] = 10; 499 cmd_offset[BCM_HASH_OBJ_OFFSET_BIT44] = 11; 500 cmd_offset[BCM_HASH_OBJ_OFFSET_BIT48] = 12; 501 cmd_offset[BCM_HASH_OBJ_OFFSET_BIT52] = 13; 502 cmd_offset[BCM_HASH_OBJ_OFFSET_BIT56] = 14; 503 cmd_offset[BCM_HASH_OBJ_OFFSET_BIT60] = 15; 504 cmd_offset[BCM_HASH_OBJ_OFFSET_BIT64] = 16; 505 cmd_offset[BCM_HASH_OBJ_OFFSET_BIT68] = 17; 506 cmd_offset[BCM_HASH_OBJ_OFFSET_BIT72] = 18; 507 cmd_offset[BCM_HASH_OBJ_OFFSET_BIT76] = 19; 508 cmd_offset[BCM_HASH_OBJ_OFFSET_BIT80] = 20; 509 cmd_offset[BCM_HASH_OBJ_OFFSET_BIT84] = 21; 510 cmd_offset[BCM_HASH_OBJ_OFFSET_BIT88] = 22; 511 cmd_offset[BCM_HASH_OBJ_OFFSET_BIT92] = 23; 512 cmd_offset[BCM_HASH_OBJ_OFFSET_BIT96] = 24; 513 cmd_offset[BCM_HASH_OBJ_OFFSET_BIT100] = 25; 514 cmd_offset[BCM_HASH_OBJ_OFFSET_BIT104] = 26; 515 cmd_offset[BCM_HASH_OBJ_OFFSET_BIT108] = 27; 516 cmd_offset[BCM_HASH_OBJ_OFFSET_BIT112] = 28; 517 cmd_offset[BCM_HASH_OBJ_OFFSET_BIT116] = 29; 518 cmd_offset[BCM_HASH_OBJ_OFFSET_BIT120] = 30; 519 cmd_offset[BCM_HASH_OBJ_OFFSET_BIT124] = 31; 520 521 /* hash object bus container */ 522 cmd_obj[BCM_HASH_OBJ_SGPP] = 96; 523 cmd_obj[BCM_HASH_OBJ_SVP] = 97; 524 cmd_obj[BCM_HASH_OBJ_OUTER_PROTO] = 98; 525 cmd_obj[BCM_HASH_OBJ_HG_LBID] = 99; 526 cmd_obj[BCM_HASH_OBJ_OUTER_SIP] = 100; 527 cmd_obj[BCM_HASH_OBJ_OUTER_DIP] = 101; 528 cmd_obj[BCM_HASH_OBJ_OUTER_SIP_NORMALIZED] = 102; 529 cmd_obj[BCM_HASH_OBJ_OUTER_DIP_NORMALIZED] = 103; 530 cmd_obj[BCM_HASH_OBJ_INNER_SIP] = 104; 531 cmd_obj[BCM_HASH_OBJ_INNER_DIP] = 105; 532 cmd_obj[BCM_HASH_OBJ_INNER_SIP_NORMALIZED] = 106; 533 cmd_obj[BCM_HASH_OBJ_INNER_DIP_NORMALIZED] = 107; 534 cmd_obj[BCM_HASH_OBJ_OUTER_L4_SRC_PORT] = 108; 535 cmd_obj[BCM_HASH_OBJ_OUTER_L4_DEST_PORT] = 109; 536 cmd_obj[BCM_HASH_OBJ_INNER_L4_SRC_PORT] = 110; 537 cmd_obj[BCM_HASH_OBJ_INNER_L4_DEST_PORT] = 111; 538 cmd_obj[BCM_HASH_OBJ_OUTER_L4_SRC_PORT_NORMALIZED] = 112; 539 cmd_obj[BCM_HASH_OBJ_OUTER_L4_DEST_PORT_NORMALIZED] = 113; 540 cmd_obj[BCM_HASH_OBJ_INNER_L4_SRC_PORT_NORMALIZED] = 114; 541 cmd_obj[BCM_HASH_OBJ_INNER_L4_DEST_PORT_NORMALIZED] = 115; 542 cmd_obj[BCM_HASH_OBJ_INNER_PROTO] = 116; 543 cmd_obj[BCM_HASH_OBJ_MPLS_LABEL_1] = 117; 544 cmd_obj[BCM_HASH_OBJ_MPLS_LABEL_2] = 118; 545 cmd_obj[BCM_HASH_OBJ_MPLS_LABEL_3] = 119; 546 cmd_obj[BCM_HASH_OBJ_MPLS_LABEL_4] = 120; 547 cmd_obj[BCM_HASH_OBJ_MPLS_LABEL_5] = 121; 548 549 /* field bus 1 */ 550 cmd_obj[BCM_HASH_OBJ_OUTER_MAC_SA] = 0; 551 cmd_obj[BCM_HASH_OBJ_OUTER_MAC_DA] = 0; 552 cmd_obj[BCM_HASH_OBJ_OUTER_VNTAG_ETAG] = 1; 553 cmd_obj[BCM_HASH_OBJ_OUTER_OTAG] = 2; 554 cmd_obj[BCM_HASH_OBJ_OUTER_ITAG] = 3; 555 cmd_obj[BCM_HASH_OBJ_OUTER_CNTAG] = 4; 556 cmd_obj[BCM_HASH_OBJ_OUTER_ETHTYPE] = 5; 557 cmd_obj[BCM_HASH_OBJ_OUTER_IPV6_SIP] = 6; 558 cmd_obj[BCM_HASH_OBJ_OUTER_IPV4_HEADER] = 6; 559 cmd_obj[BCM_HASH_OBJ_OUTER_IPV4_SIP] = 6; 560 cmd_obj[BCM_HASH_OBJ_OUTER_IPV6_HEADER1] = 7; 561 cmd_obj[BCM_HASH_OBJ_OUTER_IPV4_DIP] = 7; 562 cmd_obj[BCM_HASH_OBJ_OUTER_IPV6_DIP] = 8; 563 cmd_obj[BCM_HASH_OBJ_OUTER_IPV6_HEADER2] = 9; 564 cmd_obj[BCM_HASH_OBJ_OUTER_GRE_HEADER] = 10; 565 cmd_obj[BCM_HASH_OBJ_OUTER_L4] = 10; 566 cmd_obj[BCM_HASH_OBJ_OUTER_L5] = 12; 567 cmd_obj[BCM_HASH_OBJ_OUTER_VXLAN] = 12; 568 cmd_obj[BCM_HASH_OBJ_OUTER_UDF0_0] = 13; 569 cmd_obj[BCM_HASH_OBJ_OUTER_UDF0_1] = 14; 570 cmd_obj[BCM_HASH_OBJ_OUTER_UDF0_2] = 15; 571 cmd_obj[BCM_HASH_OBJ_OUTER_UDF0_3] = 16; 572 cmd_obj[BCM_HASH_OBJ_OUTER_UDF0_4] = 17; 573 cmd_obj[BCM_HASH_OBJ_OUTER_UDF0_5] = 18; 574 cmd_obj[BCM_HASH_OBJ_OUTER_UDF0_6] = 19; 575 cmd_obj[BCM_HASH_OBJ_OUTER_UDF0_7] = 20; 576 cmd_obj[BCM_HASH_OBJ_OUTER_UDF1_0] = 21; 577 cmd_obj[BCM_HASH_OBJ_OUTER_UDF1_1] = 22; 578 cmd_obj[BCM_HASH_OBJ_OUTER_UDF1_2] = 23; 579 cmd_obj[BCM_HASH_OBJ_OUTER_UDF1_3] = 24; 580 cmd_obj[BCM_HASH_OBJ_OUTER_UDF1_4] = 25; 581 cmd_obj[BCM_HASH_OBJ_OUTER_UDF1_5] = 26; 582 cmd_obj[BCM_HASH_OBJ_OUTER_UDF1_6] = 27; 583 cmd_obj[BCM_HASH_OBJ_OUTER_UDF1_7] = 28; 584 cmd_obj[BCM_HASH_OBJ_OUTER_TOS] = 29; 585 cmd_obj[BCM_HASH_OBJ_OUTER_TTL] = 30; 586 cmd_obj[BCM_HASH_OBJ_SUBPORT_TAG] = 31; 587 588 /* field bus 2 */ 589 offset = 48; 590 cmd_obj[BCM_HASH_OBJ_INNER_MAC_SA] = (offset + 0); 591 cmd_obj[BCM_HASH_OBJ_INNER_MAC_DA] = (offset + 0); 592 cmd_obj[BCM_HASH_OBJ_INNER_VNTAG_ETAG] = (offset + 1); 593 cmd_obj[BCM_HASH_OBJ_INNER_OTAG] = (offset + 2); 594 cmd_obj[BCM_HASH_OBJ_INNER_ITAG] = (offset + 3); 595 cmd_obj[BCM_HASH_OBJ_INNER_CNTAG] = (offset + 4); 596 cmd_obj[BCM_HASH_OBJ_INNER_ETHTYPE] = (offset + 5); 597 cmd_obj[BCM_HASH_OBJ_INNER_IPV6_SIP] = (offset + 6); 598 cmd_obj[BCM_HASH_OBJ_INNER_IPV4_HEADER] = (offset + 6); 599 cmd_obj[BCM_HASH_OBJ_INNER_IPV4_SIP] = (offset + 6); 600 cmd_obj[BCM_HASH_OBJ_INNER_IPV6_HEADER1] = (offset + 7); 601 cmd_obj[BCM_HASH_OBJ_INNER_IPV4_DIP] = (offset + 7); 602 cmd_obj[BCM_HASH_OBJ_INNER_IPV6_DIP] = (offset + 8); 603 cmd_obj[BCM_HASH_OBJ_INNER_IPV6_HEADER2] = (offset + 9); 604 cmd_obj[BCM_HASH_OBJ_INNER_GRE_HEADER] = (offset + 10); 605 cmd_obj[BCM_HASH_OBJ_INNER_L4] = (offset + 10); 606 cmd_obj[BCM_HASH_OBJ_INNER_VXLAN] = (offset + 12); 607 cmd_obj[BCM_HASH_OBJ_INNER_L5] = (offset + 12); 608 cmd_obj[BCM_HASH_OBJ_INNER_UDF0_0] = (offset + 13); 609 cmd_obj[BCM_HASH_OBJ_INNER_UDF0_1] = (offset + 14); 610 cmd_obj[BCM_HASH_OBJ_INNER_UDF0_2] = (offset + 15); 611 cmd_obj[BCM_HASH_OBJ_INNER_UDF0_3] = (offset + 16); 612 cmd_obj[BCM_HASH_OBJ_INNER_UDF0_4] = (offset + 17); 613 cmd_obj[BCM_HASH_OBJ_INNER_UDF0_5] = (offset + 18); 614 cmd_obj[BCM_HASH_OBJ_INNER_UDF0_6] = (offset + 19); 615 cmd_obj[BCM_HASH_OBJ_INNER_UDF0_7] = (offset + 20); 616 cmd_obj[BCM_HASH_OBJ_INNER_UDF1_0] = (offset + 21); 617 cmd_obj[BCM_HASH_OBJ_INNER_UDF1_1] = (offset + 22); 618 cmd_obj[BCM_HASH_OBJ_INNER_UDF1_2] = (offset + 23); 619 cmd_obj[BCM_HASH_OBJ_INNER_UDF1_3] = (offset + 24); 620 cmd_obj[BCM_HASH_OBJ_INNER_UDF1_4] = (offset + 25); 621 cmd_obj[BCM_HASH_OBJ_INNER_UDF1_5] = (offset + 26); 622 cmd_obj[BCM_HASH_OBJ_INNER_UDF1_6] = (offset + 27); 623 cmd_obj[BCM_HASH_OBJ_INNER_UDF1_7] = (offset + 28); 624 cmd_obj[BCM_HASH_OBJ_INNER_TOS] = (offset + 29); 625 cmd_obj[BCM_HASH_OBJ_INNER_TTL] = (offset + 30); 626 627 #ifdef BCM_WARM_BOOT_SUPPORT 628 if (SOC_WARM_BOOT(unit)) { 629 rv = _bcm_hash_td3_fbin_reinit(unit); 630 if (BCM_FAILURE(rv)) { 631 goto exit; 632 } 633 } else { 634 rv = _bcm_td3_hash_flex_bin_delete_all(unit); 635 if (BCM_FAILURE(rv)) { 636 goto exit; 637 } 638 rv = _bcm_hash_td3_fbin_wb_alloc(unit); 639 if (BCM_FAILURE(rv)) { 640 goto exit; 641 } 642 } 643 #else 644 rv = _bcm_td3_hash_flex_bin_delete_all(unit); 645 if (BCM_FAILURE(rv)) { 646 goto exit; 647 } 648 #endif /* BCM_WARM_BOOT_SUPPORT */ 649 650 info->initialized = TRUE; 651 return BCM_E_NONE; 652 653 exit: 654 if (info->entry_bmp) { 655 sal_free (info->entry_bmp); 656 info->entry_bmp = NULL; 657 } 658 if (info->bin_obj_arr) { 659 sal_free (info->bin_obj_arr); 660 info->bin_obj_arr = NULL; 661 } 662 return rv; 663 } 664 665 /* 666 * Function: 667 * bcmi_td3_hash_flex_field_id_get 668 * Description: 669 * Get the field_id from the flex object's field name. In Trident3, 670 * the flex objects are defined in the ceh.yml file. Each object defines a 671 * list of flex fields. For example: 672 * Flex object: Z1_MATCH_ID 673 * Field: ETAG 674 * The ceh.yml file is packaged and loaded in the runtime. 675 * 676 * Parameters: 677 * Unit (IN) Unit number 678 * object (IN) Flex object id 679 * field_name (IN) Field name 680 * field_id (OUT) field ID 681 * 682 * Return Value: 683 * BCM_E_XXX 684 * Notes: 685 * This API is used for bcm_hash_flex_bin_add API's flex field. 686 */ 687 688 int 689 bcmi_td3_hash_flex_field_id_get ( 690 int unit, 691 bcm_hash_flex_object_t object, 692 const char *field_name, 693 uint32 *field_id) 694 { 695 int rv; 696 697 *field_id = 0; 698 rv = soc_cancun_ceh_obj_field_id_get(unit, (char *)field_name, field_id); 699 SOC_IF_ERROR_RETURN(rv); 700 701 *field_id |= object << 24; 702 return BCM_E_NONE; 703 } 704 705 /* 706 * Function: 707 * bcmi_td3_hash_flex_field_name_get 708 * Description: 709 * Get the flex object ID and field name from the field_id. In Trident3, 710 * the flex objects are defined in the ceh.yml file. Each object defines a 711 * list of flex fields. For example: 712 * Flex object: Z1_MATCH_ID 713 * Field: ETAG 714 * The ceh.yml file is packaged and loaded in the runtime. 715 * 716 * Parameters: 717 * unit (IN) Unit number 718 * field_id (IN) flex field ID 719 * object (OUT) Flex object id 720 * size (IN) size of the field name buffer 721 * field_name (OUT) Field name buffer 722 * 723 * Return Value: 724 * BCM_E_XXX 725 * Notes: 726 * This API is used for bcm_hash_flex_bin_get API's flex field. 727 */ 728 729 int 730 bcmi_td3_hash_flex_field_name_get ( 731 int unit, 732 uint32 field_id, 733 bcm_hash_flex_object_t *object, 734 int *size, 735 char *field_name) 736 { 737 int rv; 738 739 *object = FIELD_OBJ_ID(field_id); 740 rv = soc_cancun_ceh_obj_field_name_get(unit, FIELD_NAME_ID(field_id), 741 size, field_name); 742 SOC_IF_ERROR_RETURN(rv); 743 744 return BCM_E_NONE; 745 } 746 747 /* 748 * Function: 749 * bcmi_td3_hash_flex_bin_add 750 * Purpose: 751 * Specify the flex bin selection rule and write to the TCAM entry. Higher 752 * entry_id has high priority during TCAM lookup in case of multiple rules 753 * are matched. If entry_id is not specified, i.e. option 754 * BCM_HASH_FLEX_BIN_OPTION_WITH_ID is not given, then a lowest available 755 * entry_id is automatically assigned. 756 * 757 * Parameters: 758 * unit - (IN) Unit ID. 759 * cfg - (INOUT) Key part of selection rule and other parameters 760 * num_bins - (IN) Number of bin cmds. 761 * bin_cmd - (IN) Array of bin commands. Policy data part of rule. 762 * num_fields - (IN) Number of flex fields. 763 * flex_field - (IN) Array of flex fields. 764 */ 765 766 int 767 bcmi_td3_hash_flex_bin_add (int unit, 768 bcm_hash_flex_bin_config_t *cfg, 769 int num_bins, 770 bcm_hash_flex_bin_cmd_t *bin_cmd, 771 int num_fields, 772 bcm_hash_flex_field_t *flex_field) 773 { 774 soc_mem_t mem; 775 int ix,iy; 776 int tcam_size; 777 flex_rtag7_hash_tcam_entry_t rule_entry; 778 flex_bin_hash_profile_0_entry_t prof_entry; 779 flex_bin_hash_profile_0_entry_t prof_entry1; 780 flex_bin_hash_profile_0_entry_t prof_entry2; 781 flex_bin_hash_profile_0_entry_t prof_entry3; 782 flex_bin_hash_profile_0_entry_t *prof[_BCM_HASH_TD3_NUM_PROF_MEM]; 783 int rv = BCM_E_UNAVAIL; 784 uint32 data32; 785 uint32 data1_32; 786 uint32 flow_id0; 787 uint32 flow_id1; 788 uint32 flow_id2; 789 uint32 flow_id0_mask; 790 uint32 flow_id1_mask; 791 uint32 flow_id2_mask; 792 uint32 *data32_p; 793 uint32 *data32_mask_p; 794 _bcm_hash_td3_flex_obj_t flex_obj; 795 _bcm_hash_td3_flex_obj_t flex_obj_mask; 796 int fld_size; 797 _bcm_hash_sfld_info_t *sfld_info; 798 _bcm_hash_pfld_info_t *pfld_info; 799 uint8 *cmd_offset; 800 uint8 *cmd_obj; 801 uint8 offset_val; 802 uint8 obj_val; 803 _bcm_hash_prof_info_t *prof_info; 804 bcmi_hash_flex_bin_info_t *info; 805 int tcam_inx; 806 uint32 tmp_buf[2]; 807 int bin_num; 808 int mem_cnt; 809 int bin_inx; 810 811 info = &bcmi_hash_flex_bin_info[unit]; 812 if (info->initialized == FALSE) { 813 return BCM_E_INIT; 814 } 815 pfld_info = _bcm_hash_td3_pfld_info; 816 sfld_info = _bcm_hash_td3_sfld_info; 817 cmd_offset = _bcm_hash_td3_cmd_offset; 818 cmd_obj = _bcm_hash_td3_cmd_obj; 819 prof_info = &_bcm_hash_td3_prof_info; 820 prof[0] = &prof_entry; 821 prof[1] = &prof_entry1; 822 prof[2] = &prof_entry2; 823 prof[3] = &prof_entry3; 824 825 mem = FLEX_RTAG7_HASH_TCAMm; 826 tcam_size = soc_mem_index_count(unit, mem); 827 sal_memset(&flex_obj, 0, sizeof(flex_obj)); 828 sal_memset(&flex_obj_mask, 0, sizeof(flex_obj_mask)); 829 sal_memset(&rule_entry, 0, sizeof(rule_entry)); 830 flow_id0 = 0; 831 flow_id1 = 0; 832 flow_id2 = 0; 833 flow_id0_mask = 0; 834 flow_id1_mask = 0; 835 flow_id2_mask = 0; 836 837 /* error check */ 838 if (cfg->option & BCM_HASH_FLEX_BIN_OPTION_REPLACE) { 839 if (!(cfg->option & BCM_HASH_FLEX_BIN_OPTION_WITH_ID)) { 840 return BCM_E_PARAM; 841 } 842 } 843 844 /* validate bin_id */ 845 for (ix = 0; ix < num_bins; ix++) { 846 if (!BIN_ID_VALID(cfg, bin_cmd[ix].bin_id)) { 847 return BCM_E_PARAM; 848 } 849 } 850 851 /* find an empty entry */ 852 if (!(cfg->option & BCM_HASH_FLEX_BIN_OPTION_WITH_ID)) { 853 for (tcam_inx = tcam_size - 1; tcam_inx >= 0; tcam_inx--) { 854 if (!SHR_BITGET(info->entry_bmp, tcam_inx)) { 855 break; 856 } 857 } 858 if (tcam_inx < 0) { /* TCAM Full */ 859 return BCM_E_FULL; 860 } 861 cfg->entry_id = tcam_size - 1 - tcam_inx; 862 } else { 863 tcam_inx = tcam_size - 1 - cfg->entry_id; 864 if (tcam_inx < 0) { 865 LOG_ERROR(BSL_LS_BCM_HASH, (BSL_META_U(unit, 866 "Entry ID %d must be less than the hardware table size: %d\n"), 867 cfg->entry_id, tcam_size)); 868 return BCM_E_PARAM; 869 } 870 if (cfg->option & BCM_HASH_FLEX_BIN_OPTION_REPLACE) { 871 if (!SHR_BITGET(info->entry_bmp, tcam_inx)) { 872 return BCM_E_NOT_FOUND; 873 } 874 } else { 875 if (SHR_BITGET(info->entry_bmp, tcam_inx)) { 876 return BCM_E_EXISTS; 877 } 878 } 879 } 880 881 /* handle the pkt_type */ 882 iy = 0; 883 while (pfld_info[iy].pkt_type != BCM_HASH_PKT_TYPE_MAX) { 884 if (BCM_HASH_PKT_TYPE_SET_TEST(cfg->tset, pfld_info[iy].pkt_type)) { 885 if (pfld_info[iy].fmt == PKT_FLOW_ID_2_FORMATfmt) { 886 data32_p = &flow_id2; 887 data32_mask_p = &flow_id2_mask; 888 } else if (pfld_info[iy].fmt == PKT_FLOW_ID_1_FORMATfmt) { 889 data32_p = &flow_id1; 890 data32_mask_p = &flow_id1_mask; 891 } else if (pfld_info[iy].fmt == PKT_FLOW_ID_0_FORMATfmt) { 892 data32_p = &flow_id0; 893 data32_mask_p = &flow_id0_mask; 894 } else { 895 return BCM_E_INTERNAL; 896 } 897 fld_size = soc_format_field_length(unit, 898 pfld_info[iy].fmt, pfld_info[iy].fld1); 899 data32 = 0; 900 soc_format_field32_set(unit, pfld_info[iy].fmt, 901 &data32, pfld_info[iy].fld1, (1 << fld_size) - 1); 902 903 /* indicate error if field is overlapped */ 904 if ((*data32_mask_p) & data32) { 905 LOG_ERROR(BSL_LS_BCM_HASH, (BSL_META_U(unit, 906 "Packet flow type conflict: %d\n"), 907 pfld_info[iy].pkt_type)); 908 return BCM_E_PARAM; 909 } 910 soc_format_field32_set(unit, pfld_info[iy].fmt, 911 data32_mask_p, pfld_info[iy].fld1, (1 << fld_size) - 1); 912 913 soc_format_field32_set(unit, pfld_info[iy].fmt, 914 data32_p, pfld_info[iy].fld1, pfld_info[iy].val1); 915 916 if (pfld_info[iy].fld2 != INVALIDf) { 917 soc_format_field32_set(unit, pfld_info[iy].fmt, 918 data32_p, pfld_info[iy].fld2, pfld_info[iy].val2); 919 fld_size = soc_format_field_length(unit, 920 pfld_info[iy].fmt, pfld_info[iy].fld2); 921 soc_format_field32_set(unit, pfld_info[iy].fmt, 922 data32_mask_p, pfld_info[iy].fld2, 923 (1 << fld_size) - 1); 924 } 925 } 926 iy++; 927 } 928 929 /* handle the pkt status */ 930 iy = 0; 931 while (sfld_info[iy].pkt_status != BCM_HASH_PKT_STATUS_MAX) { 932 ix = sfld_info[iy].pkt_status; 933 if (BCM_HASH_PKT_STATUS_SET_TEST(cfg->sset_mask, ix)) { 934 if (sfld_info[iy].fld_size == 1) { 935 soc_mem_field32_set(unit, mem, &rule_entry, 936 sfld_info[iy].fld_mask, 1); 937 soc_mem_field32_set(unit, mem, &rule_entry, 938 sfld_info[iy].fld, 939 BCM_HASH_PKT_STATUS_SET_TEST(cfg->sset, ix)? 1 :0); 940 } else { 941 return BCM_E_INTERNAL; 942 } 943 } 944 iy++; 945 } 946 947 /* handle flex objects */ 948 rv = _bcm_hash_td3_flex_field_add(unit, num_fields, flex_field, &flex_obj, 949 &flex_obj_mask); 950 BCM_IF_ERROR_RETURN(rv); 951 952 /* check if flex object conflicts with the fixed assignment */ 953 if (flex_obj_mask.flow_id0 & flow_id0_mask) { 954 LOG_ERROR(BSL_LS_BCM_HASH, (BSL_META_U(unit, 955 "Flex object flow_id_0 conflicts with packet flow type\n"))); 956 return BCM_E_PARAM; 957 } else { 958 flow_id0_mask |= flex_obj_mask.flow_id0; 959 flow_id0 |= flex_obj.flow_id0; 960 } 961 962 if (flex_obj_mask.flow_id1 & flow_id1_mask) { 963 LOG_ERROR(BSL_LS_BCM_HASH, (BSL_META_U(unit, 964 "Flex object flow_id_1 conflicts with packet flow type\n"))); 965 return BCM_E_PARAM; 966 } else { 967 flow_id1_mask |= flex_obj_mask.flow_id1; 968 flow_id1 |= flex_obj.flow_id1; 969 } 970 971 if (flex_obj_mask.flow_id2 & flow_id2_mask) { 972 LOG_ERROR(BSL_LS_BCM_HASH, (BSL_META_U(unit, 973 "Flex object flow_id_2 conflicts with packet flow type\n"))); 974 return BCM_E_PARAM; 975 } else { 976 flow_id2_mask |= flex_obj_mask.flow_id2; 977 flow_id2 |= flex_obj.flow_id2; 978 } 979 980 /* set flow ids */ 981 if (flow_id2_mask) { 982 soc_mem_field32_set(unit, mem, &rule_entry, PKT_FLOW_ID_2_MASKf, 983 flow_id2_mask); 984 soc_mem_field32_set(unit, mem, &rule_entry, PKT_FLOW_ID_2f, flow_id2); 985 } 986 if (flow_id1_mask) { 987 soc_mem_field32_set(unit, mem, &rule_entry, PKT_FLOW_ID_1_MASKf, 988 flow_id1_mask); 989 soc_mem_field32_set(unit, mem, &rule_entry, PKT_FLOW_ID_1f, flow_id1); 990 } 991 if (flow_id0_mask) { 992 soc_mem_field32_set(unit, mem, &rule_entry, PKT_FLOW_ID_0_MASKf, 993 flow_id0_mask); 994 soc_mem_field32_set(unit, mem, &rule_entry, PKT_FLOW_ID_0f, flow_id0); 995 } 996 997 /* match_id */ 998 if (!COMPILER_64_IS_ZERO(flex_obj_mask.match_id)) { 999 sal_memcpy(tmp_buf, &flex_obj_mask.match_id, 8); 1000 soc_mem_field_set(unit, mem, (uint32 *)&rule_entry, MATCH_ID_MASKf, 1001 tmp_buf); 1002 sal_memcpy(tmp_buf, &flex_obj.match_id, 8); 1003 soc_mem_field_set(unit, mem, (uint32 *)&rule_entry, MATCH_IDf, 1004 tmp_buf); 1005 } 1006 1007 /* hve control */ 1008 if (flex_obj_mask.hve_ctrl2) { 1009 soc_mem_field32_set(unit, mem, &rule_entry, HVE_CONTROL_2_MASKf, 1010 flex_obj_mask.hve_ctrl2); 1011 soc_mem_field32_set(unit, mem, &rule_entry, HVE_CONTROL_2f, 1012 flex_obj.hve_ctrl2); 1013 } 1014 if (flex_obj_mask.hve_ctrl1) { 1015 soc_mem_field32_set(unit, mem, &rule_entry, HVE_CONTROL_1_MASKf, 1016 flex_obj_mask.hve_ctrl1); 1017 soc_mem_field32_set(unit, mem, &rule_entry, HVE_CONTROL_1f, 1018 flex_obj.hve_ctrl1); 1019 } 1020 1021 /* handle the control fields */ 1022 soc_mem_field32_set(unit, mem, &rule_entry, VALIDf, 3); 1023 1024 soc_mem_field32_set(unit, mem, &rule_entry, VFI_HASH_CTRL_ID_MASKf, 1025 cfg->vfi_ctrl_id_mask); 1026 soc_mem_field32_set(unit, mem, &rule_entry, VFI_HASH_CTRL_IDf, 1027 cfg->vfi_ctrl_id); 1028 1029 soc_mem_field32_set(unit, mem, &rule_entry, VLAN_HASH_CTRL_ID_MASKf, 1030 cfg->vlan_ctrl_id_mask); 1031 soc_mem_field32_set(unit, mem, &rule_entry, VLAN_HASH_CTRL_IDf, 1032 cfg->vlan_ctrl_id); 1033 1034 soc_mem_field32_set(unit, mem, &rule_entry, L3_IIF_HASH_CTRL_ID_MASKf, 1035 cfg->l3iif_ctrl_id_mask); 1036 soc_mem_field32_set(unit, mem, &rule_entry, L3_IIF_HASH_CTRL_IDf, 1037 cfg->l3iif_ctrl_id); 1038 1039 soc_mem_field32_set(unit, mem, &rule_entry, SVP_HASH_CTRL_ID_MASKf, 1040 cfg->svp_ctrl_id_mask); 1041 soc_mem_field32_set(unit, mem, &rule_entry, SVP_HASH_CTRL_IDf, 1042 cfg->svp_ctrl_id); 1043 1044 soc_mem_field32_set(unit, mem, &rule_entry, SGPP_HASH_CTRL_ID_MASKf, 1045 cfg->sgpp_ctrl_id_mask); 1046 soc_mem_field32_set(unit, mem, &rule_entry, SGPP_HASH_CTRL_IDf, 1047 cfg->sgpp_ctrl_id); 1048 1049 soc_mem_field32_set(unit, mem, &rule_entry, 1050 BIN_CONTROL_PROFILEf, tcam_inx); 1051 1052 /* handle policy data command */ 1053 /* In TD3, the bin_cmd profile is 128 deep same as the TCAM. Use 1054 * one-to-one mapping. No need to employ profile mechanism 1055 */ 1056 1057 /* TD3 1058 * FLEX_BIN_HASH_PROFILE_0: LSB 8-bit, A-bin 0-12 1059 * FLEX_BIN_HASH_PROFILE_1: MSB 8-bit, A-bin 0-12 1060 * FLEX_BIN_HASH_PROFILE_2: LSB 8-bit, B-bin 0-12 1061 * FLEX_BIN_HASH_PROFILE_3: MSB 8-bit, B-bin 0-12 1062 */ 1063 for (ix = 0; ix < _BCM_HASH_TD3_NUM_PROF_MEM; ix++) { 1064 sal_memset(prof[ix], 0, sizeof(prof_entry)); 1065 } 1066 for (ix = 0; ix < num_bins; ix++) { 1067 if (cfg->option & BCM_HASH_FLEX_BIN_OPTION_SIZE_8BIT) { 1068 if (bin_cmd[ix].bin_id <= BCM_HASH_BIN_A_MAX) { 1069 bin_num = bin_cmd[ix].bin_id - BCM_HASH_BIN_A_0; 1070 } else if (bin_cmd[ix].bin_id <= BCM_HASH_BIN_A_UPPER_HALF_MAX) { 1071 bin_num = bin_cmd[ix].bin_id - BCM_HASH_BIN_A_0_UPPER_HALF; 1072 bin_num += _BCM_HASH_TD3_NUM_BINS_PER_SET; 1073 } else if (bin_cmd[ix].bin_id <= BCM_HASH_BIN_B_MAX) { 1074 bin_num = bin_cmd[ix].bin_id - BCM_HASH_BIN_B_0; 1075 bin_num += 2 * _BCM_HASH_TD3_NUM_BINS_PER_SET; 1076 } else { /* bin_cmd[ix].bin_id <= BCM_HASH_BIN_B_UPPER_HALF_MAX */ 1077 bin_num = bin_cmd[ix].bin_id - BCM_HASH_BIN_B_0_UPPER_HALF; 1078 bin_num += 3 * _BCM_HASH_TD3_NUM_BINS_PER_SET; 1079 } 1080 } else { 1081 if (bin_cmd[ix].bin_id <= BCM_HASH_BIN_A_MAX) { 1082 bin_num = bin_cmd[ix].bin_id - BCM_HASH_BIN_A_0; 1083 } else { 1084 bin_num = (bin_cmd[ix].bin_id - BCM_HASH_BIN_B_0); 1085 bin_num += _BCM_HASH_TD3_NUM_BINS_PER_SET; 1086 } 1087 } 1088 1089 /* save the object_id for the given bin */ 1090 if (cfg->option & BCM_HASH_FLEX_BIN_OPTION_SIZE_8BIT) { 1091 mem_cnt = bin_num / _BCM_HASH_TD3_NUM_BINS_PER_SET; 1092 bin_inx = BIN_INX(unit, mem_cnt, tcam_inx, bin_num); 1093 info->bin_obj_arr[bin_inx] = bin_cmd[ix].obj_id; 1094 } else { 1095 mem_cnt = 2 * (bin_num / _BCM_HASH_TD3_NUM_BINS_PER_SET); 1096 bin_inx = BIN_INX(unit, mem_cnt, tcam_inx, bin_num); 1097 info->bin_obj_arr[bin_inx] = bin_cmd[ix].obj_id; 1098 bin_inx = BIN_INX(unit, mem_cnt + 1, tcam_inx, bin_num); 1099 info->bin_obj_arr[bin_inx] = bin_cmd[ix].obj_id; 1100 } 1101 1102 /* convert to TD3 specific hardware offset and object value */ 1103 offset_val = cmd_offset[bin_cmd[ix].obj_offset]; 1104 obj_val = cmd_obj[bin_cmd[ix].obj_id]; 1105 1106 switch (bin_cmd[ix].obj_id) { 1107 case BCM_HASH_OBJ_OUTER_MAC_DA: 1108 case BCM_HASH_OBJ_INNER_MAC_DA: 1109 offset_val += cmd_offset[BCM_HASH_OBJ_OFFSET_BIT48]; 1110 break; 1111 case BCM_HASH_OBJ_OUTER_IPV4_SIP: 1112 case BCM_HASH_OBJ_INNER_IPV4_SIP: 1113 offset_val += cmd_offset[BCM_HASH_OBJ_OFFSET_BIT96]; 1114 break; 1115 default: 1116 break; 1117 } 1118 1119 /* LSB 8-bit */ 1120 data32 = 0; 1121 if (bin_cmd[ix].obj_id == BCM_HASH_OBJ_ID_INVALID) { 1122 soc_format_field32_set(unit, FLEX_BIN_HASH_PROFILE_FORMATfmt, 1123 &data32, CMD_VALIDf, 0); 1124 } else { 1125 soc_format_field32_set(unit, FLEX_BIN_HASH_PROFILE_FORMATfmt, 1126 &data32, CMD_VALIDf, 1); 1127 soc_format_field32_set(unit, FLEX_BIN_HASH_PROFILE_FORMATfmt, 1128 &data32, CMD_SRC_CONTAINER_IDf, obj_val); 1129 soc_format_field32_set(unit, FLEX_BIN_HASH_PROFILE_FORMATfmt, 1130 &data32, CMD_SRC_CONTAINER_OFFSETf, offset_val); 1131 soc_format_field32_set(unit, FLEX_BIN_HASH_PROFILE_FORMATfmt, 1132 &data32, CMD_MASKf, (uint8)bin_cmd[ix].bin_mask); 1133 } 1134 1135 if (!(cfg->option & BCM_HASH_FLEX_BIN_OPTION_SIZE_8BIT)) { 1136 /* MSB 8-bit */ 1137 data1_32 = data32; 1138 soc_format_field32_set(unit, FLEX_BIN_HASH_PROFILE_FORMATfmt, 1139 &data1_32, CMD_SRC_CONTAINER_OFFSETf, 1140 offset_val + 2); /* TD3 4-bit gradularity */ 1141 soc_format_field32_set(unit, FLEX_BIN_HASH_PROFILE_FORMATfmt, 1142 &data1_32, CMD_MASKf, (uint8)(bin_cmd[ix].bin_mask >> 8)); 1143 1144 soc_mem_field32_set(unit, 1145 prof_info->mem[2*(bin_num/_BCM_HASH_TD3_NUM_BINS_PER_SET)], 1146 prof[2*(bin_num/_BCM_HASH_TD3_NUM_BINS_PER_SET)], 1147 prof_info->fld[bin_num%_BCM_HASH_TD3_NUM_BINS_PER_SET], 1148 data32); 1149 1150 soc_mem_field32_set(unit, 1151 prof_info->mem[2*(bin_num/_BCM_HASH_TD3_NUM_BINS_PER_SET) + 1], 1152 prof[2*(bin_num/_BCM_HASH_TD3_NUM_BINS_PER_SET) + 1], 1153 prof_info->fld[bin_num%_BCM_HASH_TD3_NUM_BINS_PER_SET], 1154 data1_32); 1155 } else { 1156 soc_mem_field32_set(unit, 1157 prof_info->mem[(bin_num/_BCM_HASH_TD3_NUM_BINS_PER_SET)], 1158 prof[(bin_num/_BCM_HASH_TD3_NUM_BINS_PER_SET)], 1159 prof_info->fld[bin_num%_BCM_HASH_TD3_NUM_BINS_PER_SET], 1160 data32); 1161 } 1162 } 1163 for (ix = 0; ix < _BCM_HASH_TD3_NUM_PROF_MEM; ix++) { 1164 rv = soc_mem_write(unit, prof_info->mem[ix], MEM_BLOCK_ALL, 1165 tcam_inx, prof[ix]); 1166 SOC_IF_ERROR_RETURN(rv); 1167 } 1168 1169 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, tcam_inx, &rule_entry); 1170 SHR_BITSET(info->entry_bmp, tcam_inx); 1171 return rv; 1172 } 1173 1174 /* 1175 * Function: 1176 * bcmi_td3_hash_flex_bin_delete 1177 * Purpose: 1178 * Delete the given entry 1179 * Parameters: 1180 * unit - (IN) Unit ID. 1181 * entry_id - (IN) The entry ID 1182 */ 1183 1184 int bcmi_td3_hash_flex_bin_delete( int unit, int entry_id) 1185 { 1186 soc_mem_t mem; 1187 flex_rtag7_hash_tcam_entry_t rule_entry; 1188 flex_bin_hash_profile_0_entry_t prof_entry; 1189 int rv; 1190 int ix,iy; 1191 _bcm_hash_prof_info_t *prof_info; 1192 int tcam_size; 1193 int tcam_inx; 1194 bcmi_hash_flex_bin_info_t *info; 1195 int bin_inx; 1196 1197 info = &bcmi_hash_flex_bin_info[unit]; 1198 if (info->initialized == FALSE) { 1199 return BCM_E_INIT; 1200 } 1201 mem = FLEX_RTAG7_HASH_TCAMm; 1202 tcam_size = soc_mem_index_count(unit, mem); 1203 tcam_inx = tcam_size - 1 - entry_id; 1204 1205 if (tcam_inx < 0) { 1206 LOG_ERROR(BSL_LS_BCM_HASH, (BSL_META_U(unit, 1207 "Entry ID %d must be less than the hardware table size: %d\n"), 1208 entry_id, tcam_size)); 1209 return BCM_E_PARAM; 1210 } 1211 SHR_BITCLR(info->entry_bmp, tcam_inx); 1212 1213 prof_info = &_bcm_hash_td3_prof_info; 1214 sal_memset(&rule_entry, 0, sizeof(rule_entry)); 1215 sal_memset(&prof_entry, 0, sizeof(prof_entry)); 1216 1217 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, tcam_inx, &rule_entry); 1218 SOC_IF_ERROR_RETURN(rv); 1219 1220 for (ix = 0; ix < _BCM_HASH_TD3_NUM_PROF_MEM; ix++) { 1221 rv = soc_mem_write(unit, prof_info->mem[ix], MEM_BLOCK_ALL, 1222 tcam_inx, &prof_entry); 1223 SOC_IF_ERROR_RETURN(rv); 1224 } 1225 1226 for (iy = 0; iy < _BCM_HASH_TD3_NUM_PROF_MEM; iy++) { 1227 for (ix = 0; ix < _BCM_HASH_TD3_NUM_BINS_PER_SET; ix++) { 1228 bin_inx = BIN_INX(unit, iy, tcam_inx, ix); 1229 info->bin_obj_arr[bin_inx] = 0; 1230 } 1231 } 1232 1233 return rv; 1234 } 1235 1236 /* 1237 * Function: 1238 * bcmi_td3_hash_flex_bin_delete_all 1239 * Purpose: 1240 * Delete all entries 1241 * Parameters: 1242 * unit - (IN) Unit ID. 1243 */ 1244 1245 STATIC int _bcm_td3_hash_flex_bin_delete_all(int unit) 1246 { 1247 soc_mem_t mem; 1248 flex_rtag7_hash_tcam_entry_t rule_entry; 1249 flex_bin_hash_profile_0_entry_t prof_entry; 1250 int rv; 1251 int size; 1252 int ix; 1253 int iy; 1254 _bcm_hash_prof_info_t *prof_info; 1255 bcmi_hash_flex_bin_info_t *info; 1256 1257 info = &bcmi_hash_flex_bin_info[unit]; 1258 mem = FLEX_RTAG7_HASH_TCAMm; 1259 size = soc_mem_index_count(unit, mem); 1260 prof_info = &_bcm_hash_td3_prof_info; 1261 sal_memset(&rule_entry, 0, sizeof(rule_entry)); 1262 sal_memset(&prof_entry, 0, sizeof(prof_entry)); 1263 1264 for (ix = size - 1; ix >= 0; ix--) { 1265 SHR_BITCLR(info->entry_bmp, ix); 1266 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, ix, &rule_entry); 1267 SOC_IF_ERROR_RETURN(rv); 1268 for (iy = 0; iy < _BCM_HASH_TD3_NUM_PROF_MEM; iy++) { 1269 rv = soc_mem_write(unit, prof_info->mem[iy], MEM_BLOCK_ALL, 1270 ix, &prof_entry); 1271 SOC_IF_ERROR_RETURN(rv); 1272 } 1273 } 1274 1275 size = soc_mem_index_count(unit, FLEX_BIN_HASH_PROFILE_0m); 1276 size *= _BCM_HASH_TD3_NUM_PROF_MEM; 1277 size *= _BCM_HASH_TD3_NUM_BINS_PER_SET; 1278 size *= sizeof(uint16); 1279 sal_memset(info->bin_obj_arr, 0, size); 1280 1281 return BCM_E_NONE; 1282 } 1283 1284 int bcmi_td3_hash_flex_bin_delete_all(int unit) 1285 { 1286 bcmi_hash_flex_bin_info_t *info; 1287 1288 info = &bcmi_hash_flex_bin_info[unit]; 1289 if (info->initialized == FALSE) { 1290 return BCM_E_INIT; 1291 } 1292 return _bcm_td3_hash_flex_bin_delete_all(unit); 1293 } 1294 1295 /* 1296 * Function: 1297 * bcmi_td3_hash_flex_bin_get 1298 * Purpose: 1299 * Get the entry configuration parameters for the given entry_id. 1300 * Parameters: 1301 * unit - (IN) Unit ID. 1302 * cfg - (INOUT) Key part of selection rule and other parameters 1303 * num_bins - (IN) Number of bin cmds. 1304 * bin_cmd - (IN) Array of bin commands. Policy part of selection rule. 1305 * num_fields - (IN) Number of flex fields. 1306 * flex_field - (IN) Array of flex fields. 1307 */ 1308 1309 int bcmi_td3_hash_flex_bin_get (int unit, 1310 bcm_hash_flex_bin_config_t *cfg, 1311 int num_bins, 1312 bcm_hash_flex_bin_cmd_t *bin_cmd, 1313 int num_fields, 1314 bcm_hash_flex_field_t *flex_field) 1315 { 1316 soc_mem_t mem; 1317 int ix,iy,inx; 1318 flex_rtag7_hash_tcam_entry_t rule_entry; 1319 flex_bin_hash_profile_0_entry_t prof_entry; 1320 flex_bin_hash_profile_0_entry_t prof_entry1; 1321 flex_bin_hash_profile_0_entry_t prof_entry2; 1322 flex_bin_hash_profile_0_entry_t prof_entry3; 1323 flex_bin_hash_profile_0_entry_t *prof[_BCM_HASH_TD3_NUM_PROF_MEM]; 1324 int rv = BCM_E_UNAVAIL; 1325 uint32 data32; 1326 uint32 *data32_p; 1327 uint32 flow_id0; 1328 uint32 flow_id1; 1329 uint32 flow_id2; 1330 _bcm_hash_td3_flex_obj_t flex_obj; 1331 _bcm_hash_td3_flex_obj_t flex_obj_mask; 1332 _bcm_hash_sfld_info_t *sfld_info; 1333 _bcm_hash_pfld_info_t *pfld_info; 1334 uint8 *cmd_offset; 1335 uint8 offset_val; 1336 _bcm_hash_prof_info_t *prof_info; 1337 int val1; 1338 int val2; 1339 int val1_mask; 1340 uint32 tmp_buf[2]; 1341 int tcam_inx; 1342 int tcam_size; 1343 bcmi_hash_flex_bin_info_t *info; 1344 int num_bin_max; 1345 int bin_inx; 1346 int cmd_inx; 1347 1348 pfld_info = _bcm_hash_td3_pfld_info; 1349 sfld_info = _bcm_hash_td3_sfld_info; 1350 cmd_offset = _bcm_hash_td3_cmd_offset; 1351 prof_info = &_bcm_hash_td3_prof_info; 1352 prof[0] = &prof_entry; 1353 prof[1] = &prof_entry1; 1354 prof[2] = &prof_entry2; 1355 prof[3] = &prof_entry3; 1356 info = &bcmi_hash_flex_bin_info[unit]; 1357 1358 if (info->initialized == FALSE) { 1359 return BCM_E_INIT; 1360 } 1361 1362 mem = FLEX_RTAG7_HASH_TCAMm; 1363 tcam_size = soc_mem_index_count(unit, mem); 1364 sal_memset(&flex_obj, 0, sizeof(flex_obj)); 1365 sal_memset(&flex_obj_mask, 0, sizeof(flex_obj_mask)); 1366 sal_memset(&rule_entry, 0, sizeof(rule_entry)); 1367 flow_id0 = 0; 1368 flow_id1 = 0; 1369 flow_id2 = 0; 1370 1371 if (cfg->entry_id >= tcam_size) { 1372 return BCM_E_PARAM; 1373 } 1374 tcam_inx = tcam_size - cfg->entry_id - 1; 1375 if (tcam_inx < 0) { 1376 LOG_ERROR(BSL_LS_BCM_HASH, (BSL_META_U(unit, 1377 "Entry ID %d must be less than the hardware table size: %d\n"), 1378 cfg->entry_id, tcam_size)); 1379 return BCM_E_PARAM; 1380 } 1381 if (!SHR_BITGET(info->entry_bmp, tcam_inx)) { 1382 return BCM_E_NOT_FOUND; 1383 } 1384 1385 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, tcam_inx, &rule_entry); 1386 SOC_IF_ERROR_RETURN(rv); 1387 1388 if (!soc_mem_field32_get(unit, mem, &rule_entry, VALIDf)) { 1389 return SOC_E_NOT_FOUND; 1390 } 1391 1392 /* get flow ids */ 1393 flow_id2 = soc_mem_field32_get(unit, mem, &rule_entry, PKT_FLOW_ID_2f); 1394 flow_id1 = soc_mem_field32_get(unit, mem, &rule_entry, PKT_FLOW_ID_1f); 1395 flow_id0 = soc_mem_field32_get(unit, mem, &rule_entry, PKT_FLOW_ID_0f); 1396 1397 /* handle the pkt_type */ 1398 for (ix = 0; ix < BCM_HASH_PKT_TYPE_MAX; ix++) { 1399 if (pfld_info[ix].fmt == PKT_FLOW_ID_2_FORMATfmt) { 1400 data32_p = &flow_id2; 1401 } else if (pfld_info[ix].fmt == PKT_FLOW_ID_1_FORMATfmt) { 1402 data32_p = &flow_id1; 1403 } else if (pfld_info[ix].fmt == PKT_FLOW_ID_0_FORMATfmt) { 1404 data32_p = &flow_id0; 1405 } else { 1406 return BCM_E_INTERNAL; 1407 } 1408 val2 = 0; 1409 val1 = soc_format_field32_get(unit, pfld_info[ix].fmt, 1410 data32_p, pfld_info[ix].fld1); 1411 if (pfld_info[ix].fld2 != INVALIDf) { 1412 val2 = soc_format_field32_get(unit, pfld_info[ix].fmt, 1413 data32_p, pfld_info[ix].fld2); 1414 } 1415 if ((val1 == pfld_info[ix].val1) && (val2 == pfld_info[ix].val2)) { 1416 BCM_HASH_PKT_TYPE_SET_ADD(cfg->tset, pfld_info[ix].pkt_type); 1417 } 1418 } 1419 1420 /* handle the pkt status */ 1421 for (iy = 0; iy < BCM_HASH_PKT_STATUS_MAX; iy++) { 1422 if (sfld_info[iy].fld_size == 1) { 1423 val1_mask = soc_mem_field32_get(unit, mem, &rule_entry, 1424 sfld_info[iy].fld_mask); 1425 if (val1_mask) { 1426 BCM_HASH_PKT_STATUS_SET_ADD(cfg->sset_mask, 1427 sfld_info[iy].pkt_status); 1428 } 1429 val1 = soc_mem_field32_get(unit, mem, &rule_entry, 1430 sfld_info[iy].fld); 1431 if (val1) { 1432 BCM_HASH_PKT_STATUS_SET_ADD(cfg->sset,sfld_info[iy].pkt_status); 1433 } 1434 } else { 1435 return BCM_E_INTERNAL; 1436 } 1437 } 1438 1439 soc_mem_field_get(unit, mem, (uint32 *)&rule_entry, MATCH_IDf, tmp_buf); 1440 sal_memcpy(&flex_obj.match_id, tmp_buf, 8); 1441 1442 soc_mem_field_get(unit, mem, (uint32 *)&rule_entry, MATCH_ID_MASKf, 1443 tmp_buf); 1444 sal_memcpy(&flex_obj_mask.match_id, tmp_buf, 8); 1445 1446 flex_obj_mask.flow_id0 = (uint16)soc_mem_field32_get(unit, mem, 1447 &rule_entry, PKT_FLOW_ID_0_MASKf); 1448 flex_obj.flow_id0 = (uint16)soc_mem_field32_get(unit, mem, 1449 &rule_entry, PKT_FLOW_ID_0f); 1450 flex_obj_mask.flow_id0 = (uint16)soc_mem_field32_get(unit, mem, 1451 &rule_entry, PKT_FLOW_ID_0_MASKf); 1452 flex_obj.flow_id1 = (uint16)soc_mem_field32_get(unit, mem, 1453 &rule_entry, PKT_FLOW_ID_1f); 1454 flex_obj_mask.flow_id1 = (uint16)soc_mem_field32_get(unit, mem, 1455 &rule_entry, PKT_FLOW_ID_1_MASKf); 1456 flex_obj.flow_id2 = (uint16)soc_mem_field32_get(unit, mem, 1457 &rule_entry, PKT_FLOW_ID_2f); 1458 flex_obj_mask.flow_id2 = (uint16)soc_mem_field32_get(unit, mem, 1459 &rule_entry, PKT_FLOW_ID_2_MASKf); 1460 flex_obj.hve_ctrl1 = (uint8)soc_mem_field32_get(unit, mem, 1461 &rule_entry, HVE_CONTROL_1f); 1462 flex_obj_mask.hve_ctrl1 = (uint8)soc_mem_field32_get(unit, mem, 1463 &rule_entry, HVE_CONTROL_1_MASKf); 1464 flex_obj.hve_ctrl2 = (uint8)soc_mem_field32_get(unit, mem, 1465 &rule_entry, HVE_CONTROL_2f); 1466 flex_obj_mask.hve_ctrl2 = (uint8)soc_mem_field32_get(unit, mem, 1467 &rule_entry, HVE_CONTROL_2_MASKf); 1468 1469 rv = _bcm_hash_td3_flex_field_get(unit, num_fields, flex_field, 1470 &flex_obj, &flex_obj_mask); 1471 BCM_IF_ERROR_RETURN(rv); 1472 1473 cfg->vfi_ctrl_id_mask = soc_mem_field32_get(unit, mem, &rule_entry, 1474 VFI_HASH_CTRL_ID_MASKf); 1475 cfg->vfi_ctrl_id = soc_mem_field32_get(unit, mem, &rule_entry, 1476 VFI_HASH_CTRL_IDf); 1477 cfg->vlan_ctrl_id_mask = soc_mem_field32_get(unit, mem, &rule_entry, 1478 VLAN_HASH_CTRL_ID_MASKf); 1479 cfg->vlan_ctrl_id = soc_mem_field32_get(unit, mem, &rule_entry, 1480 VLAN_HASH_CTRL_IDf); 1481 cfg->l3iif_ctrl_id_mask = soc_mem_field32_get(unit, mem, &rule_entry, 1482 L3_IIF_HASH_CTRL_ID_MASKf); 1483 cfg->l3iif_ctrl_id = soc_mem_field32_get(unit, mem, &rule_entry, 1484 L3_IIF_HASH_CTRL_IDf); 1485 cfg->svp_ctrl_id_mask = soc_mem_field32_get(unit, mem, &rule_entry, 1486 SVP_HASH_CTRL_ID_MASKf); 1487 cfg->svp_ctrl_id = soc_mem_field32_get(unit, mem, &rule_entry, 1488 SVP_HASH_CTRL_IDf); 1489 cfg->sgpp_ctrl_id_mask = soc_mem_field32_get(unit, mem, &rule_entry, 1490 SGPP_HASH_CTRL_ID_MASKf); 1491 cfg->sgpp_ctrl_id = soc_mem_field32_get(unit, mem, &rule_entry, 1492 SGPP_HASH_CTRL_IDf); 1493 1494 /* handle policy data command */ 1495 /* In TD3, the bin_cmd profile is 128 deep same as the TCAM. Use 1496 * one-to-one mapping. No need to employ profile mechanism 1497 */ 1498 /* TD3 1499 * FLEX_BIN_HASH_PROFILE_0: LSB 8-bit, A-bin 0-12 1500 * FLEX_BIN_HASH_PROFILE_1: MSB 8-bit, A-bin 0-12 1501 * FLEX_BIN_HASH_PROFILE_2: LSB 8-bit, B-bin 0-12 1502 * FLEX_BIN_HASH_PROFILE_3: MSB 8-bit, B-bin 0-12 1503 */ 1504 for (ix = 0; ix < _BCM_HASH_TD3_NUM_PROF_MEM; ix++) { 1505 rv = soc_mem_read(unit, prof_info->mem[ix], MEM_BLOCK_ALL, 1506 tcam_inx, prof[ix]); 1507 SOC_IF_ERROR_RETURN(rv); 1508 } 1509 num_bin_max = cfg->option & BCM_HASH_FLEX_BIN_OPTION_SIZE_8BIT ? 1510 4 * _BCM_HASH_TD3_NUM_BINS_PER_SET: 1511 2 * _BCM_HASH_TD3_NUM_BINS_PER_SET; 1512 1513 for (cmd_inx = 0, ix = 0; ix < num_bin_max; ix++) { 1514 1515 if (cfg->option & BCM_HASH_FLEX_BIN_OPTION_SIZE_8BIT) { 1516 inx = ix/_BCM_HASH_TD3_NUM_BINS_PER_SET; 1517 } else { 1518 inx = 2 * (ix/_BCM_HASH_TD3_NUM_BINS_PER_SET); 1519 } 1520 data32 = soc_mem_field32_get(unit, 1521 prof_info->mem[inx], prof[inx], 1522 prof_info->fld[ix%_BCM_HASH_TD3_NUM_BINS_PER_SET]); 1523 1524 if (!soc_format_field32_get(unit, FLEX_BIN_HASH_PROFILE_FORMATfmt, 1525 &data32, CMD_VALIDf)) { 1526 continue; 1527 } 1528 bin_inx = BIN_INX(unit, inx, tcam_inx, ix); 1529 bin_cmd[cmd_inx].obj_id = info->bin_obj_arr[bin_inx]; 1530 if (cfg->option & BCM_HASH_FLEX_BIN_OPTION_SIZE_8BIT) { 1531 if (ix < _BCM_HASH_TD3_NUM_BINS_PER_SET) { 1532 bin_cmd[cmd_inx].bin_id = BCM_HASH_BIN_A_0 + ix; 1533 } else if (ix < 2*_BCM_HASH_TD3_NUM_BINS_PER_SET) { 1534 bin_cmd[cmd_inx].bin_id = BCM_HASH_BIN_A_0_UPPER_HALF + 1535 ix % _BCM_HASH_TD3_NUM_BINS_PER_SET; 1536 } else if (ix < 3*_BCM_HASH_TD3_NUM_BINS_PER_SET) { 1537 bin_cmd[cmd_inx].bin_id = BCM_HASH_BIN_B_0 + 1538 ix % _BCM_HASH_TD3_NUM_BINS_PER_SET; 1539 } else { 1540 bin_cmd[cmd_inx].bin_id = BCM_HASH_BIN_B_0_UPPER_HALF + 1541 ix % _BCM_HASH_TD3_NUM_BINS_PER_SET; 1542 } 1543 } else { 1544 if (ix < _BCM_HASH_TD3_NUM_BINS_PER_SET) { 1545 bin_cmd[cmd_inx].bin_id = BCM_HASH_BIN_A_0 + ix; 1546 } else { 1547 bin_cmd[cmd_inx].bin_id = BCM_HASH_BIN_B_0 + 1548 ix % _BCM_HASH_TD3_NUM_BINS_PER_SET; 1549 } 1550 } 1551 offset_val = soc_format_field32_get(unit, 1552 FLEX_BIN_HASH_PROFILE_FORMATfmt, 1553 &data32, CMD_SRC_CONTAINER_OFFSETf); 1554 switch (bin_cmd[cmd_inx].obj_id) { 1555 case BCM_HASH_OBJ_OUTER_MAC_DA: 1556 case BCM_HASH_OBJ_INNER_MAC_DA: 1557 offset_val -= cmd_offset[BCM_HASH_OBJ_OFFSET_BIT48]; 1558 break; 1559 case BCM_HASH_OBJ_OUTER_IPV4_SIP: 1560 case BCM_HASH_OBJ_INNER_IPV4_SIP: 1561 offset_val -= cmd_offset[BCM_HASH_OBJ_OFFSET_BIT96]; 1562 break; 1563 default: 1564 break; 1565 } 1566 for (iy = 0; iy < BCM_HASH_OBJ_OFFSET_MAX; iy++) { 1567 if (cmd_offset[iy] == offset_val) { 1568 bin_cmd[cmd_inx].obj_offset = iy; 1569 } 1570 } 1571 1572 bin_cmd[cmd_inx].bin_mask = soc_format_field32_get(unit, 1573 FLEX_BIN_HASH_PROFILE_FORMATfmt, 1574 &data32, CMD_MASKf); 1575 if (!(cfg->option & BCM_HASH_FLEX_BIN_OPTION_SIZE_8BIT)) { 1576 uint16 upper_mask; 1577 1578 data32 = soc_mem_field32_get(unit, 1579 prof_info->mem[inx+1], prof[inx+1], 1580 prof_info->fld[ix%_BCM_HASH_TD3_NUM_BINS_PER_SET]); 1581 upper_mask = soc_format_field32_get(unit, 1582 FLEX_BIN_HASH_PROFILE_FORMATfmt, 1583 &data32, CMD_MASKf); 1584 bin_cmd[cmd_inx].bin_mask |= (upper_mask << 8); 1585 } 1586 cmd_inx++; 1587 } 1588 if (cmd_inx < num_bins) { 1589 /* mark the end if not all entries are filled */ 1590 bin_cmd[cmd_inx].obj_id = BCM_HASH_OBJ_ID_INVALID; 1591 } 1592 return BCM_E_NONE; 1593 } 1594 1595 /* 1596 * Function: 1597 * bcmi_td3_hash_flex_bin_traverse 1598 * Purpose: 1599 * Traverse all added entries in the TCAM. 1600 * Parameters: 1601 * unit - (IN) Unit ID. 1602 * option - (IN) bin_cmd for 8bit data or 16bit. Default 16bit. 1603 * BCM_HASH_FLEX_BIN_OPTION_SIZE_8BIT: 8bit 1604 * cb - (IN) callback function 1605 * user_data - (IN) User context data 1606 */ 1607 1608 int bcmi_td3_hash_flex_bin_traverse( 1609 int unit, 1610 uint32 option, 1611 bcm_hash_flex_bin_traverse_cb cb, 1612 void *user_data) 1613 { 1614 int ix,iy; 1615 int size; 1616 int rv = BCM_E_NONE; 1617 bcm_hash_flex_bin_config_t cfg; 1618 bcm_hash_flex_bin_cmd_t bin_cmd[4 * _BCM_HASH_TD3_NUM_BINS_PER_SET]; 1619 int numBins; 1620 bcm_hash_flex_field_t flex_field[40]; 1621 int num_fields; 1622 int inx; 1623 1624 num_fields = 40; 1625 size = soc_mem_index_count(unit, FLEX_RTAG7_HASH_TCAMm); 1626 if (option & BCM_HASH_FLEX_BIN_OPTION_SIZE_8BIT) { 1627 numBins = 4 * _BCM_HASH_TD3_NUM_BINS_PER_SET; 1628 } else { 1629 numBins = 2 * _BCM_HASH_TD3_NUM_BINS_PER_SET; 1630 } 1631 1632 for (ix = size - 1; ix >= 0; ix--) { 1633 bcm_hash_flex_bin_config_t_init(&cfg); 1634 cfg.option = option; 1635 cfg.entry_id = ix; 1636 for (iy = 0; iy < numBins; iy++) { 1637 bin_cmd[iy].obj_id = BCM_HASH_OBJ_ID_INVALID; 1638 } 1639 rv = bcmi_td3_hash_flex_bin_get(unit, &cfg, numBins, bin_cmd, 1640 num_fields, flex_field); 1641 1642 if (rv == BCM_E_NOT_FOUND) { /* for entries not exposed to user */ 1643 rv = BCM_E_NONE; 1644 continue; 1645 } else if (BCM_FAILURE(rv)) { 1646 break; 1647 } 1648 /* find the actual number of flex field retrieved */ 1649 for (iy = 0; iy < num_fields; iy++) { 1650 if (!flex_field[iy].field_id) { 1651 break; 1652 } 1653 } 1654 /* find the actual number of bin_cmd entries retrieved */ 1655 for (inx = 0; inx < numBins; inx++) { 1656 if (bin_cmd[inx].obj_id == BCM_HASH_OBJ_ID_INVALID) { 1657 break; 1658 } 1659 } 1660 rv = cb(unit, &cfg, inx, bin_cmd, iy, 1661 iy? flex_field: NULL, 1662 user_data); 1663 if (BCM_FAILURE(rv)) { 1664 break; 1665 } 1666 } 1667 return rv; 1668 } 1669 1670 /* 1671 * Function: 1672 * _bcm_hash_td3_flex_field_add 1673 * Purpose: 1674 * Process user inputed flex fields into TD3's Cancun CEH defined flex 1675 * objects such as match_id, flow_id and hve_control. Those objects are part 1676 * of the TCAM's key. 1677 */ 1678 1679 STATIC int _bcm_hash_td3_flex_field_add( 1680 int unit, 1681 int num_fields, /* number of flex fields */ 1682 bcm_hash_flex_field_t *flex_field, /* user provided flex fields */ 1683 _bcm_hash_td3_flex_obj_t *flex_obj, /* Cancun CEH defined flex object */ 1684 _bcm_hash_td3_flex_obj_t *flex_obj_mask) /* flex object's mask */ 1685 { 1686 soc_cancun_ceh_field_info_t fld_info; 1687 soc_cancun_ceh_field_info_t m_zone; 1688 char *flex_obj_name; 1689 uint16 *flow_obj = NULL; 1690 uint16 *flow_obj_mask = NULL; 1691 uint8 *hve_obj = NULL; 1692 uint8 *hve_obj_mask = NULL; 1693 int match_obj = FALSE; 1694 int rv; 1695 uint32 fld_mask; 1696 uint32 obj; 1697 int ix; 1698 int size; 1699 char *field_name = NULL; 1700 int op_flag; 1701 uint64 tmp64; 1702 1703 for (ix = 0; ix < num_fields; ix++) { 1704 match_obj = FALSE; 1705 flow_obj = NULL; 1706 flow_obj_mask = NULL; 1707 hve_obj = NULL; 1708 hve_obj_mask = NULL; 1709 1710 obj = FIELD_OBJ_ID(flex_field[ix].field_id); 1711 flex_obj_name = _bcm_hash_td3_obj_names[obj]; 1712 1713 if (obj == BCM_HASH_FLEX_OBJ_MATCH_ID_ZONE0) { 1714 match_obj = TRUE; 1715 } else if (obj == BCM_HASH_FLEX_OBJ_MATCH_ID_ZONE1) { 1716 match_obj = TRUE; 1717 } else if (obj == BCM_HASH_FLEX_OBJ_MATCH_ID_ZONE2) { 1718 match_obj = TRUE; 1719 } else if (obj == BCM_HASH_FLEX_OBJ_MATCH_ID_ZONE3) { 1720 match_obj = TRUE; 1721 } else if (obj == BCM_HASH_FLEX_OBJ_MATCH_ID_ZONE4) { 1722 match_obj = TRUE; 1723 } else if (obj == BCM_HASH_FLEX_OBJ_FLOW_ID_0) { 1724 flow_obj = &flex_obj->flow_id0; 1725 flow_obj_mask = &flex_obj_mask->flow_id0; 1726 } else if (obj == BCM_HASH_FLEX_OBJ_FLOW_ID_1) { 1727 flow_obj = &flex_obj->flow_id1; 1728 flow_obj_mask = &flex_obj_mask->flow_id1; 1729 } else if (obj == BCM_HASH_FLEX_OBJ_FLOW_ID_2) { 1730 flow_obj = &flex_obj->flow_id2; 1731 flow_obj_mask = &flex_obj_mask->flow_id2; 1732 } else if (obj == BCM_HASH_FLEX_OBJ_HVE_CONTROL_1) { 1733 hve_obj = &flex_obj->hve_ctrl1; 1734 hve_obj_mask = &flex_obj_mask->hve_ctrl1; 1735 } else if (obj == BCM_HASH_FLEX_OBJ_HVE_CONTROL_2) { 1736 hve_obj = &flex_obj->hve_ctrl2; 1737 hve_obj_mask = &flex_obj_mask->hve_ctrl2; 1738 } else { 1739 rv = BCM_E_UNAVAIL; 1740 goto exit; 1741 } 1742 1743 /* get the field_name size first */ 1744 rv = soc_cancun_ceh_obj_field_name_get (unit, 1745 FIELD_NAME_ID(flex_field[ix].field_id), 1746 &size, NULL); 1747 if (BCM_FAILURE(rv)) { 1748 goto exit; 1749 } 1750 1751 field_name = sal_alloc(size, "td3_hash_flex_temp_buffer"); 1752 if (field_name == NULL) { 1753 rv = BCM_E_MEMORY; 1754 goto exit; 1755 } 1756 1757 /* get the field_name */ 1758 rv = soc_cancun_ceh_obj_field_name_get (unit, 1759 FIELD_NAME_ID(flex_field[ix].field_id), 1760 &size, field_name); 1761 if (BCM_FAILURE(rv)) { 1762 goto exit; 1763 } 1764 1765 rv = soc_cancun_ceh_obj_field_get(unit,flex_obj_name, 1766 field_name, &fld_info); 1767 if (BCM_FAILURE(rv)) { 1768 goto exit; 1769 } 1770 1771 /* The Cancun defined Match_id overall width 50 bit. divided 1772 * into 5 zone. 1773 */ 1774 1775 if (match_obj) { 1776 uint64 m_id; 1777 uint64 m_id_mask; 1778 1779 COMPILER_64_ZERO(m_id); 1780 COMPILER_64_ZERO(m_id_mask); 1781 /* Retrieve the match zone value and mask */ 1782 rv = soc_cancun_ceh_obj_field_get(unit,"MATCH_ID",flex_obj_name, 1783 &m_zone); 1784 if (BCM_FAILURE(rv)) { 1785 goto exit; 1786 } 1787 fld_mask = (1 << fld_info.width) - 1; 1788 fld_mask = fld_mask << fld_info.offset; 1789 COMPILER_64_SET(m_id_mask, 0, fld_mask); 1790 COMPILER_64_SHL(m_id_mask, m_zone.offset); 1791 COMPILER_64_SET(m_id, 0, fld_info.value); 1792 COMPILER_64_SHL(m_id, fld_info.offset); 1793 COMPILER_64_SHL(m_id, m_zone.offset); 1794 1795 if (flex_field[ix].mask == 0 || flex_field[ix].value == 0) { 1796 op_flag = 0; 1797 } else { 1798 op_flag = 1; 1799 } 1800 1801 /* add field, check if field collision: mask overlap */ 1802 if (op_flag) { 1803 COMPILER_64_COPY(tmp64, m_id_mask); 1804 COMPILER_64_AND(tmp64, flex_obj_mask->match_id); 1805 if (!COMPILER_64_IS_ZERO(tmp64)) { 1806 LOG_ERROR(BSL_LS_BCM_HASH, (BSL_META_U(unit, 1807 "Flex field conflict: %s\n"), field_name)); 1808 rv = BCM_E_PARAM; 1809 goto exit; 1810 } 1811 COMPILER_64_OR(flex_obj_mask->match_id, m_id_mask); 1812 COMPILER_64_OR(flex_obj->match_id, m_id); 1813 } else { 1814 /* clear the field */ 1815 COMPILER_64_NOT(m_id_mask); 1816 COMPILER_64_AND(flex_obj_mask->match_id, m_id_mask); 1817 COMPILER_64_AND(flex_obj->match_id, m_id_mask); 1818 } 1819 } else if (flow_obj != NULL) { 1820 1821 if (flex_field[ix].mask == 0 || flex_field[ix].value == 0) { 1822 op_flag = 0; 1823 } else { 1824 op_flag = 1; 1825 } 1826 1827 fld_mask = (1 << fld_info.width) - 1; 1828 fld_mask = fld_mask << fld_info.offset; 1829 if (op_flag) { 1830 if (fld_mask & *flow_obj_mask) { 1831 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 1832 "Flex field conflict: %s\n"), field_name)); 1833 rv = BCM_E_PARAM; 1834 goto exit; 1835 } 1836 *flow_obj &= (uint16)(~fld_mask); 1837 *flow_obj |= (uint16)((fld_info.value << fld_info.offset) & 1838 fld_mask); 1839 *flow_obj_mask |= fld_mask; 1840 } else { 1841 *flow_obj &= (uint16)(~fld_mask); 1842 *flow_obj_mask &= (uint16)(~fld_mask); 1843 } 1844 } else if (hve_obj != NULL) { 1845 fld_mask = (1 << fld_info.width) - 1; 1846 fld_mask = fld_mask << fld_info.offset; 1847 if (flex_field[ix].mask == 0) { 1848 *hve_obj_mask &= (uint8)(~fld_mask); 1849 *hve_obj &= (uint8)(~fld_mask); 1850 } else { 1851 *hve_obj_mask |= (uint8)(fld_mask); 1852 *hve_obj |= (uint8)((flex_field[ix].value << fld_info.offset) & 1853 fld_mask); 1854 } 1855 } else { 1856 rv = BCM_E_INTERNAL; 1857 goto exit; 1858 } 1859 sal_free(field_name); 1860 field_name = NULL; 1861 } 1862 return BCM_E_NONE; 1863 1864 exit: 1865 if (field_name != NULL) { 1866 sal_free(field_name); 1867 } 1868 return rv; 1869 } 1870 1871 /* 1872 * Function: 1873 * _bcm_hash_td3_flex_field_get 1874 * Purpose: 1875 * Retrieve data from TD3's Cancun CEH defined flex objects such as 1876 * match_id, flow_id and hve_control. And fill the flex_field buffer array 1877 * provided by user. 1878 */ 1879 1880 STATIC int _bcm_hash_td3_flex_field_get( 1881 int unit, 1882 int num_fields, 1883 bcm_hash_flex_field_t *flex_field, 1884 _bcm_hash_td3_flex_obj_t *flex_obj, 1885 _bcm_hash_td3_flex_obj_t *flex_obj_mask) 1886 { 1887 soc_cancun_ceh_field_info_t fld_info; 1888 soc_cancun_ceh_field_info_t m_zone; 1889 char *flex_obj_name; 1890 uint16 *flow_obj = NULL; 1891 uint16 *flow_obj_mask = NULL; 1892 uint8 *hve_obj = NULL; 1893 uint8 *hve_obj_mask = NULL; 1894 int match_obj = FALSE; 1895 int rv; 1896 uint32 fld_mask; 1897 bcm_hash_flex_object_t obj; 1898 int ix; 1899 int size; 1900 char *field_name = NULL; 1901 uint32 *id_arr = NULL; 1902 int inx; 1903 int fld_size; 1904 uint32 mz_mask; 1905 uint32 fld_value; 1906 int buf_limit = FALSE; 1907 uint64 m_id; 1908 uint64 m_id_mask; 1909 uint64 tmp64; 1910 uint32 tmp32; 1911 1912 COMPILER_64_ZERO(m_id); 1913 COMPILER_64_ZERO(m_id_mask); 1914 inx = 0; 1915 for (obj = BCM_HASH_FLEX_OBJ_MATCH_ID_ZONE0; obj < BCM_HASH_FLEX_OBJ_MAX; 1916 obj++) { 1917 1918 match_obj = FALSE; 1919 flow_obj = NULL; 1920 flow_obj_mask = NULL; 1921 hve_obj = NULL; 1922 hve_obj_mask = NULL; 1923 if (obj == BCM_HASH_FLEX_OBJ_MATCH_ID_ZONE0) { 1924 match_obj = TRUE; 1925 } else if (obj == BCM_HASH_FLEX_OBJ_MATCH_ID_ZONE1) { 1926 match_obj = TRUE; 1927 } else if (obj == BCM_HASH_FLEX_OBJ_MATCH_ID_ZONE2) { 1928 match_obj = TRUE; 1929 } else if (obj == BCM_HASH_FLEX_OBJ_MATCH_ID_ZONE3) { 1930 match_obj = TRUE; 1931 } else if (obj == BCM_HASH_FLEX_OBJ_MATCH_ID_ZONE4) { 1932 match_obj = TRUE; 1933 } else if (obj == BCM_HASH_FLEX_OBJ_FLOW_ID_0) { 1934 flow_obj = &flex_obj->flow_id0; 1935 flow_obj_mask = &flex_obj_mask->flow_id0; 1936 } else if (obj == BCM_HASH_FLEX_OBJ_FLOW_ID_1) { 1937 flow_obj = &flex_obj->flow_id1; 1938 flow_obj_mask = &flex_obj_mask->flow_id1; 1939 } else if (obj == BCM_HASH_FLEX_OBJ_FLOW_ID_2) { 1940 flow_obj = &flex_obj->flow_id2; 1941 flow_obj_mask = &flex_obj_mask->flow_id2; 1942 } else if (obj == BCM_HASH_FLEX_OBJ_HVE_CONTROL_1) { 1943 hve_obj = &flex_obj->hve_ctrl1; 1944 hve_obj_mask = &flex_obj_mask->hve_ctrl1; 1945 } else { /* (obj == BCM_HASH_FLEX_OBJ_HVE_CONTROL_2) */ 1946 hve_obj = &flex_obj->hve_ctrl2; 1947 hve_obj_mask = &flex_obj_mask->hve_ctrl2; 1948 } 1949 1950 flex_obj_name = _bcm_hash_td3_obj_names[obj]; 1951 rv = soc_cancun_ceh_obj_field_id_list_get(unit, flex_obj_name, &size, 1952 NULL); 1953 if (BCM_FAILURE(rv)) { 1954 if (rv == SOC_E_NOT_FOUND) { 1955 continue; 1956 } else { 1957 goto exit; 1958 } 1959 } 1960 1961 id_arr = sal_alloc(size * sizeof(uint32), "td3_hash_flex_temp_buffer"); 1962 if (id_arr == NULL) { 1963 rv = BCM_E_MEMORY; 1964 goto exit; 1965 } 1966 1967 rv = soc_cancun_ceh_obj_field_id_list_get(unit, flex_obj_name, &size, 1968 id_arr); 1969 if (BCM_FAILURE(rv)) { 1970 goto exit; 1971 } 1972 1973 if (match_obj) { 1974 COMPILER_64_ZERO(m_id); 1975 COMPILER_64_ZERO(m_id_mask); 1976 1977 /* Retrieve the match zone value and mask */ 1978 rv = soc_cancun_ceh_obj_field_get(unit,"MATCH_ID", 1979 flex_obj_name, &m_zone); 1980 if (BCM_FAILURE(rv)) { 1981 goto exit; 1982 } 1983 COMPILER_64_COPY(m_id_mask, flex_obj_mask->match_id); 1984 COMPILER_64_SHR(m_id_mask, m_zone.offset); 1985 COMPILER_64_COPY(m_id, flex_obj->match_id); 1986 COMPILER_64_SHR(m_id, m_zone.offset); 1987 mz_mask = (1 << m_zone.width) - 1; 1988 COMPILER_64_SET(tmp64, 0, mz_mask); 1989 COMPILER_64_AND(m_id_mask, tmp64); 1990 COMPILER_64_AND(m_id, tmp64); 1991 } 1992 1993 for (ix = 0; ix < size; ix++) { 1994 /* get the field_name size first */ 1995 rv = soc_cancun_ceh_obj_field_name_get (unit, 1996 id_arr[ix], &fld_size, NULL); 1997 if (BCM_FAILURE(rv)) { 1998 goto exit; 1999 } 2000 2001 field_name = sal_alloc(fld_size, "td3_hash_flex_temp_buffer"); 2002 if (field_name == NULL) { 2003 rv = BCM_E_MEMORY; 2004 goto exit; 2005 } 2006 2007 /* get the field_name */ 2008 rv = soc_cancun_ceh_obj_field_name_get (unit, 2009 id_arr[ix], &fld_size, field_name); 2010 if (BCM_FAILURE(rv)) { 2011 goto exit; 2012 } 2013 2014 rv = soc_cancun_ceh_obj_field_get(unit,flex_obj_name, 2015 field_name, &fld_info); 2016 if (BCM_FAILURE(rv)) { 2017 goto exit; 2018 } 2019 2020 /* The Cancun defined Match_id overall width 50 bit. divided 2021 * into 5 zone. 2022 */ 2023 2024 if (match_obj) { 2025 fld_mask = (1 << fld_info.width) - 1; 2026 fld_mask = fld_mask << fld_info.offset; 2027 COMPILER_64_TO_32_LO(tmp32, m_id_mask); 2028 if ((fld_mask & tmp32) != fld_mask) { 2029 sal_free(field_name); 2030 field_name = NULL; 2031 continue; 2032 } 2033 fld_value = fld_info.value << fld_info.offset; 2034 COMPILER_64_TO_32_LO(tmp32, m_id); 2035 if (fld_value != (tmp32 & fld_mask)) { 2036 sal_free(field_name); 2037 field_name = NULL; 2038 continue; 2039 } 2040 /* found one. remove the mask */ 2041 COMPILER_64_SET(tmp64, 0, ~fld_mask); 2042 COMPILER_64_AND(m_id_mask, tmp64); 2043 2044 if (num_fields <= inx) { 2045 buf_limit = TRUE; 2046 break; 2047 } 2048 flex_field[inx].field_id = FIELD_OBJ_ID_SET(id_arr[ix], obj); 2049 flex_field[inx].mask = 1; 2050 flex_field[inx].value = 1; 2051 inx++; 2052 } else if (flow_obj_mask != NULL) { 2053 2054 fld_mask = (1 << fld_info.width) - 1; 2055 fld_mask = fld_mask << fld_info.offset; 2056 if ((fld_mask & (*flow_obj_mask)) != fld_mask) { 2057 sal_free(field_name); 2058 field_name = NULL; 2059 continue; 2060 } 2061 fld_value = fld_info.value << fld_info.offset; 2062 if (fld_value != ((*flow_obj) & fld_mask)) { 2063 sal_free(field_name); 2064 field_name = NULL; 2065 continue; 2066 } 2067 /* found one. remove the mask */ 2068 *flow_obj_mask = (~fld_mask) & (*flow_obj_mask); 2069 2070 if (num_fields <= inx) { 2071 buf_limit = TRUE; 2072 break; 2073 } 2074 flex_field[inx].field_id = FIELD_OBJ_ID_SET(id_arr[ix], obj); 2075 flex_field[inx].mask = 1; 2076 flex_field[inx].value = 1; 2077 inx++; 2078 } else if (hve_obj_mask != NULL) { 2079 fld_mask = (1 << fld_info.width) - 1; 2080 fld_mask = fld_mask << fld_info.offset; 2081 if ((fld_mask & (*hve_obj_mask)) != fld_mask) { 2082 sal_free(field_name); 2083 field_name = NULL; 2084 continue; 2085 } 2086 /* found one. remove the mask */ 2087 *hve_obj_mask = (~fld_mask) & (*hve_obj_mask); 2088 2089 if (num_fields <= inx) { 2090 buf_limit = TRUE; 2091 break; 2092 } 2093 flex_field[inx].field_id = FIELD_OBJ_ID_SET(id_arr[ix], obj); 2094 flex_field[inx].mask = 1; 2095 if ((*hve_obj) & fld_mask) { 2096 flex_field[inx].value = 1; 2097 } else { 2098 flex_field[inx].value = 0; 2099 } 2100 inx++; 2101 } else { 2102 rv = BCM_E_INTERNAL; 2103 goto exit; 2104 } 2105 sal_free(field_name); 2106 field_name = NULL; 2107 } 2108 if (field_name != NULL) { 2109 sal_free(field_name); 2110 field_name = NULL; 2111 } 2112 sal_free(id_arr); 2113 id_arr = NULL; 2114 if (buf_limit == TRUE) { 2115 break; 2116 } 2117 } 2118 /* clear the remaining buffer */ 2119 for (ix = inx; ix < num_fields; ix++) { 2120 flex_field[inx].field_id = 0; 2121 flex_field[inx].mask = 0; 2122 flex_field[inx].value = 0; 2123 } 2124 return BCM_E_NONE; 2125 2126 exit: 2127 if (id_arr != NULL) { 2128 sal_free(id_arr); 2129 } 2130 if (field_name != NULL) { 2131 sal_free(field_name); 2132 } 2133 return rv; 2134 } 2135 2136 #endif /* #if defined(BCM_TRIDENT3_SUPPORT) */