field_presel.c (17836B)
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: field_presel.c 8 * Purpose: Field Processor routines Specific to Preselector Module 9 * in Helix5. 10 */ 11 12 #include <soc/defs.h> 13 14 #if defined (BCM_HELIX5_SUPPORT) && defined(BCM_FIELD_SUPPORT) 15 16 #include <bcm/error.h> 17 #include <bcm/field.h> 18 #include <shared/bsl.h> 19 20 #include <bcm_int/esw/field.h> 21 #include <bcm_int/esw/tomahawk.h> 22 #include <bcm_int/esw/helix5.h> 23 #include <bcm_int/esw/keygen_api.h> 24 25 /* 26 * Function: 27 * _field_hx5_ft_lt_entry_hw_remove 28 * 29 * Purpose: 30 * Remove preselector Entry from hardware at given index 31 * 32 * Parameters: 33 * unit - (IN) BCM device number. 34 * f_presel - (IN/OUT) Preselector entry. 35 * tcam_idx - (IN) Hardware index 36 * 37 * Returns: 38 * BCM_E_XXX 39 */ 40 STATIC int 41 _field_hx5_ft_lt_entry_hw_remove(int unit, 42 _field_presel_entry_t *f_presel, 43 int tcam_idx) 44 { 45 int rv = BCM_E_NONE; 46 _field_stage_t *stage_fc = NULL; 47 soc_mem_t lt_tcam_mem = INVALIDm; 48 soc_mem_t lt_data_mem = INVALIDm; 49 50 /* Get device stage control structure. */ 51 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, 52 f_presel->group->stage_id, &stage_fc)); 53 54 /* Get TCAM/DATA memory */ 55 rv = _bcm_field_th_lt_tcam_policy_mem_get(unit, stage_fc, 56 f_presel->group->instance, 57 _BCM_FIELD_MEM_TYPE_FT_LT, 58 _BCM_FIELD_MEM_VIEW_TYPE_TCAM | _BCM_FIELD_MEM_VIEW_TYPE_DATA, 59 <_tcam_mem, <_data_mem); 60 BCM_IF_ERROR_RETURN(rv); 61 62 BCM_IF_ERROR_RETURN(soc_mem_write(unit, lt_tcam_mem, MEM_BLOCK_ALL, 63 tcam_idx, soc_mem_entry_null(unit, lt_tcam_mem))); 64 BCM_IF_ERROR_RETURN(soc_mem_write(unit, lt_data_mem, MEM_BLOCK_ALL, 65 tcam_idx, soc_mem_entry_null(unit, lt_data_mem))); 66 67 /* Keygen Remove */ 68 BCM_IF_ERROR_RETURN(_field_hx5_ft_group_keygen_remove(unit, 69 f_presel, tcam_idx)); 70 71 return rv; 72 } 73 /* 74 * Function: 75 * _field_hx5_ft_presel_qualifiers_init 76 * 77 * Purpose: 78 * Initializes flowtracker stage presel qualifiers. 79 * 80 * Parameters: 81 * unit - (IN) BCM device number. 82 * stage_fc - (IN) Field stage control structure. 83 * 84 * Returns: 85 * BCM_E_PARAM - Null field stage control structure. 86 * BCM_E_MEMORY - Allocation failure. 87 * BCM_E_INTERNAL - Invalid CAP Stage ID. 88 * BCM_E_NONE - Success. 89 */ 90 int 91 _field_hx5_ft_presel_qualifiers_init(int unit, 92 _field_stage_t *stage_fc) 93 { 94 uint16 key_base_off; 95 uint16 z1_uc_bp = 0; 96 uint16 z2_uc_bp = 0; 97 soc_mem_t mem = INVALIDm; 98 soc_field_info_t *field_info = NULL; 99 _FP_QUAL_DECL; 100 101 if (stage_fc->f_presel_qual_arr == 0) { 102 return (BCM_E_INTERNAL); 103 } 104 105 mem = BSK_FTFP_LTS_LOGICAL_TBL_SEL_TCAMm; 106 107 field_info = soc_mem_fieldinfo_get(unit, mem, KEYf); 108 if (field_info == NULL) { 109 return BCM_E_PARAM; 110 } 111 key_base_off = field_info->bp; 112 113 /* PARSER1_L4_VALID */ 114 field_info = soc_mem_fieldinfo_get(unit, mem, PARSER1_L4_VALIDf); 115 if (field_info != NULL) { 116 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL4Ports, 117 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 118 field_info->bp - key_base_off , 1); 119 } 120 121 /* PARSER2_L4_VALID */ 122 field_info = soc_mem_fieldinfo_get(unit, mem, PARSER2_L4_VALIDf); 123 if (field_info != NULL) { 124 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInnerL4Ports, 125 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 126 field_info->bp - key_base_off , 1); 127 } 128 129 /* PARSER1_IP_FRAG_INFO */ 130 field_info = soc_mem_fieldinfo_get(unit, mem, PARSER1_IP_FRAG_INFOf); 131 if (field_info != NULL) { 132 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpFrag, 133 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 134 field_info->bp - key_base_off , 2); 135 } 136 137 /* PARSER2_IP_FRAG_INFO */ 138 field_info = soc_mem_fieldinfo_get(unit, mem, PARSER2_IP_FRAG_INFOf); 139 if (field_info != NULL) { 140 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInnerIpFrag, 141 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 142 field_info->bp - key_base_off , 2); 143 } 144 145 /* HVE_RESULTS_1_Z1_UC */ 146 /* HVE_RESULTS_1_Z1_BC */ 147 /* HVE_RESULTS_1_Z2_UC */ 148 /* HVE_RESULTS_1_Z2_BC */ 149 field_info = soc_mem_fieldinfo_get(unit, mem, HVE_RESULTS_1_Z1_UCf); 150 if (field_info != NULL) { 151 z1_uc_bp = field_info->bp - key_base_off; 152 } 153 field_info = soc_mem_fieldinfo_get(unit, mem, HVE_RESULTS_1_Z2_UCf); 154 if (field_info != NULL) { 155 z2_uc_bp = field_info->bp - key_base_off; 156 } 157 if (z2_uc_bp != 0) { 158 _FP_PRESEL_QUAL_TWO_ADD(unit, stage_fc, bcmFieldQualifyPktDstAddrType, 159 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 160 z1_uc_bp, 2, z2_uc_bp, 2); 161 } 162 163 /* HVE_RESULTS_2_Z1_UC */ 164 /* HVE_RESULTS_2_Z1_BC */ 165 /* HVE_RESULTS_2_Z2_UC */ 166 /* HVE_RESULTS_2_Z2_BC */ 167 field_info = soc_mem_fieldinfo_get(unit, mem, HVE_RESULTS_2_Z1_UCf); 168 if (field_info != NULL) { 169 z1_uc_bp = field_info->bp - key_base_off; 170 } 171 field_info = soc_mem_fieldinfo_get(unit, mem, HVE_RESULTS_2_Z2_UCf); 172 if (field_info != NULL) { 173 z2_uc_bp = field_info->bp - key_base_off; 174 } 175 if (z2_uc_bp != 0) { 176 _FP_PRESEL_QUAL_TWO_ADD(unit, stage_fc, bcmFieldQualifyPktInnerDstAddrType, 177 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 178 z1_uc_bp, 2, z2_uc_bp, 2); 179 } 180 181 /* PARSER1_DOS_ATTACK */ 182 field_info = soc_mem_fieldinfo_get(unit, mem, PARSER1_DOS_ATTACKf); 183 if (field_info != NULL) { 184 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDosAttack, 185 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 186 field_info->bp - key_base_off , 1); 187 } 188 189 /* PARSER2_DOS_ATTACK */ 190 field_info = soc_mem_fieldinfo_get(unit, mem, PARSER2_DOS_ATTACKf); 191 if (field_info != NULL) { 192 _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInnerDosAttack, 193 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel, 194 field_info->bp - key_base_off , 1); 195 } 196 197 return (BCM_E_NONE); 198 } 199 200 /* 201 * Function: 202 * _bcm_field_hx5_ft_lt_entry_data_value_set 203 * 204 * Purpose: 205 * Set presel entry data to sw copy of entry. 206 * 207 * Parameters: 208 * unit - (IN) BCM device number. 209 * stage_fc - (IN) Stage field control structure. 210 * fg - (IN) Field group structure. 211 * index - (IN) 212 * lt_data_mem- (IN) presel sram hw table 213 * data - (IN/OUT) entry data 214 * 215 * Returns: 216 * BCM_E_PARAM - Null field stage control structure. 217 * BCM_E_INTERNAL - Invalid CAP Stage ID. 218 * BCM_E_NONE - Success. 219 */ 220 int 221 _bcm_field_hx5_ft_lt_entry_data_value_set(int unit, 222 _field_stage_t *stage_fc, 223 _field_group_t *fg, 224 int index, 225 soc_mem_t lt_data_mem, 226 uint32 *data) 227 { 228 uint32 keytype = 0; 229 int group_key_mode = 0; 230 231 if ((fg == NULL) || (stage_fc == NULL)) { 232 return BCM_E_PARAM; 233 } 234 235 /* Set main SRAM as in lt_data_mem */ 236 if (fg->flags & _FP_GROUP_DW_DEPTH_EXPANDED) { 237 group_key_mode = 1; 238 } else { 239 group_key_mode = 0; 240 } 241 soc_mem_field32_set(unit, lt_data_mem, 242 data, GROUP_KEY_MODEf, group_key_mode); 243 244 soc_mem_field32_set(unit, lt_data_mem, data, GROUP_LOOKUP_ENABLEf, 245 (fg->flags & _FP_GROUP_LOOKUP_ENABLED) ? 1 : 0); 246 247 keytype = (fg->lt_id >> _FP_GROUP_FT_KEYTYPE_SHIFT) & 248 (_FP_GROUP_FT_KEYTYPE_MASK); 249 soc_mem_field32_set(unit, lt_data_mem, data, GROUP_KEY_TYPEf, keytype); 250 251 return BCM_E_NONE; 252 } 253 254 /* 255 * Function: 256 * _bcm_field_hx5_ft_lt_entry_install 257 * 258 * Purpose: 259 * Install preselector entry for flowtracker stage in hw. 260 * 261 * Parameters: 262 * unit - (IN) BCM device number. 263 * f_presel - (IN) Preselector entry. 264 * lt_fs - (IN) Logical table field slice. 265 * 266 * Returns: 267 * BCM_E_PARAM - Null field stage control structure. 268 * BCM_E_INTERNAL - Invalid CAP Stage ID. 269 * BCM_E_NONE - Success. 270 */ 271 int 272 _bcm_field_hx5_ft_lt_entry_install(int unit, 273 _field_presel_entry_t *f_presel, 274 _field_lt_slice_t *lt_fs) 275 { 276 int rv = BCM_E_NONE; 277 _field_stage_t *stage_fc = NULL; 278 int valid = 0; 279 int tcam_idx = 0; 280 soc_mem_t lt_tcam_mem = INVALIDm; 281 soc_mem_t lt_data_mem = INVALIDm; 282 uint32 tcam_entry[SOC_MAX_MEM_FIELD_WORDS] = {0}; /* TCAM Entry buffer.*/ 283 uint32 data_entry[SOC_MAX_MEM_FIELD_WORDS] = {0}; /* DATA Entry buffer. */ 284 285 /* Validate input params */ 286 if ((f_presel == NULL) || (lt_fs == NULL)) { 287 return BCM_E_INTERNAL; 288 } 289 if ((f_presel->lt_tcam.key == NULL) || 290 (f_presel->lt_tcam.mask == NULL) || 291 (f_presel->lt_data.data == NULL)) { 292 return BCM_E_PARAM; 293 } 294 295 /* Get device stage control structure. */ 296 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, 297 f_presel->group->stage_id, &stage_fc)); 298 299 BCM_IF_ERROR_RETURN(_bcm_field_presel_entry_tcam_idx_get(unit, 300 f_presel, lt_fs, &tcam_idx)); 301 302 /* Call Group Keygen Install */ 303 BCM_IF_ERROR_RETURN(_field_hx5_ft_group_keygen_install(unit, f_presel)); 304 305 /* Get TCAM/DATA memory */ 306 rv = _bcm_field_th_lt_tcam_policy_mem_get(unit, stage_fc, 307 f_presel->group->instance, 308 _BCM_FIELD_MEM_TYPE_FT_LT, 309 _BCM_FIELD_MEM_VIEW_TYPE_TCAM | _BCM_FIELD_MEM_VIEW_TYPE_DATA, 310 <_tcam_mem, <_data_mem); 311 BCM_IF_ERROR_RETURN(rv); 312 313 valid = (f_presel->group->flags & _FP_GROUP_LOOKUP_ENABLED) ? 3: 0; 314 315 BCM_IF_ERROR_RETURN(soc_mem_write(unit, lt_tcam_mem, MEM_BLOCK_ALL, 316 tcam_idx, tcam_entry)); 317 BCM_IF_ERROR_RETURN(soc_mem_write(unit, lt_data_mem, MEM_BLOCK_ALL, 318 tcam_idx, data_entry)); 319 320 BCM_IF_ERROR_RETURN(soc_mem_read(unit, lt_tcam_mem, MEM_BLOCK_ANY, tcam_idx, 321 tcam_entry)); 322 BCM_IF_ERROR_RETURN(soc_mem_read(unit, lt_data_mem, MEM_BLOCK_ANY, tcam_idx, 323 data_entry)); 324 325 soc_mem_field_set(unit, lt_tcam_mem, tcam_entry, KEYf, f_presel->lt_tcam.key); 326 soc_mem_field_set(unit, lt_tcam_mem, tcam_entry, MASKf, f_presel->lt_tcam.mask); 327 soc_mem_field_set(unit, lt_data_mem, data_entry, DATAf, f_presel->lt_data.data); 328 329 /* Set entry valid bit status. */ 330 soc_mem_field32_set(unit, lt_tcam_mem, tcam_entry, VALIDf, valid); 331 332 /* Install entry in hardware. */ 333 BCM_IF_ERROR_RETURN(soc_mem_write(unit, lt_data_mem, MEM_BLOCK_ALL, 334 tcam_idx, data_entry)); 335 BCM_IF_ERROR_RETURN(soc_mem_write(unit, lt_tcam_mem, MEM_BLOCK_ALL, 336 tcam_idx, tcam_entry)); 337 338 f_presel->flags &= ~_FP_ENTRY_DIRTY; 339 f_presel->flags |= _FP_ENTRY_INSTALLED; 340 f_presel->flags |= _FP_ENTRY_ENABLED; 341 342 return BCM_E_NONE; 343 } 344 345 /* 346 * Function: 347 * _bcm_field_hx5_ft_lt_entry_hw_remove 348 * 349 * Purpose: 350 * Remove preselector Entry from hardware. 351 * 352 * Parameters: 353 * unit - (IN) BCM device number. 354 * f_presel - (IN/OUT) Preselector entry. 355 * 356 * Returns: 357 * BCM_E_PARAM - Null field stage control structure. 358 * BCM_E_MEMORY - Allocation failure. 359 * BCM_E_INTERNAL - Invalid CAP Stage ID. 360 * BCM_E_NONE - Success. 361 */ 362 int 363 _bcm_field_hx5_ft_lt_entry_hw_remove(int unit, 364 _field_presel_entry_t *f_presel) 365 { 366 int rv = BCM_E_NONE; 367 int tcam_idx = 0; 368 369 /* Validate input params */ 370 if (f_presel == NULL) { 371 return BCM_E_INTERNAL; 372 } 373 374 if ((f_presel->flags & _FP_ENTRY_INSTALLED) == 0) { 375 /* Entry is not installed in hw */ 376 return BCM_E_NONE; 377 } 378 379 /* Get Tcam Index */ 380 BCM_IF_ERROR_RETURN(_bcm_field_presel_entry_tcam_idx_get(unit, 381 f_presel, f_presel->lt_fs, &tcam_idx)); 382 383 BCM_IF_ERROR_RETURN(_field_hx5_ft_lt_entry_hw_remove(unit, 384 f_presel, tcam_idx)); 385 386 f_presel->flags |= _FP_ENTRY_DIRTY; 387 f_presel->flags &= ~(_FP_ENTRY_INSTALLED); 388 f_presel->flags &= ~(_FP_ENTRY_ENABLED); 389 390 return rv; 391 } 392 393 /* 394 * Function: 395 * _field_hx5_ft_presel_delete_last_entry_hw 396 * 397 * Purpose: 398 * Remove preselector Entry at last index in lt slice 399 * 400 * Parameters: 401 * unit - (IN) BCM device number. 402 * f_presel - (IN/OUT) Preselector entry. 403 * last_hw_index - (IN) Hardware index 404 * 405 * Returns: 406 * BCM_E_XXX 407 */ 408 int 409 _field_hx5_ft_presel_delete_last_entry_hw(int unit, 410 _field_presel_entry_t *f_presel, 411 int last_hw_index) 412 { 413 int rv = BCM_E_NONE; 414 int tcam_idx = 0; 415 416 tcam_idx = f_presel->lt_fs->start_tcam_idx + last_hw_index; 417 418 BCM_IF_ERROR_RETURN(_field_hx5_ft_lt_entry_hw_remove(unit, 419 f_presel, tcam_idx)); 420 421 f_presel->lt_fs->p_entries[last_hw_index] = NULL; 422 423 return rv; 424 } 425 426 #define _BCM_FIELD_PKT_DST_ADDR_TYPE_MAC_MASK \ 427 (BCM_FIELD_PKT_DST_ADDR_TYPE_UCAST_MAC | \ 428 BCM_FIELD_PKT_DST_ADDR_TYPE_MCAST_MAC | \ 429 BCM_FIELD_PKT_DST_ADDR_TYPE_BCAST_MAC) 430 431 #define _BCM_FIELD_PKT_DST_ADDR_TYPE_IP_MASK \ 432 (BCM_FIELD_PKT_DST_ADDR_TYPE_UCAST_IP | \ 433 BCM_FIELD_PKT_DST_ADDR_TYPE_MCAST_IP | \ 434 BCM_FIELD_PKT_DST_ADDR_TYPE_BCAST_IP) 435 436 int 437 _bcm_field_hx5_qualify_PktDstAddrType(int unit, 438 bcm_field_qualify_t qual, 439 uint32 dst_addr_type, 440 uint32 *hw_data, 441 uint32 *hw_mask) 442 { 443 uint32 dst_mac_type = 0; 444 uint32 dst_ip_type = 0; 445 uint32 dst_mac_flags = 0; 446 uint32 dst_ip_flags = 0; 447 uint32 bit = 0, flag = 0; 448 uint32 mac_hw_data = 0, mac_hw_mask = 0; 449 uint32 ip_hw_data = 0, ip_hw_mask = 0; 450 uint32 dst_addr_type_arr[1] = {0}; 451 452 /* Validate input args */ 453 if ((hw_data == NULL) || (hw_mask == NULL)) { 454 return BCM_E_PARAM; 455 } 456 457 dst_mac_type = dst_addr_type & _BCM_FIELD_PKT_DST_ADDR_TYPE_MAC_MASK; 458 dst_ip_type = dst_addr_type & _BCM_FIELD_PKT_DST_ADDR_TYPE_IP_MASK; 459 460 dst_mac_flags = _shr_popcount(dst_mac_type); 461 dst_ip_flags = _shr_popcount(dst_ip_type); 462 463 if ((dst_mac_flags > 1) || (dst_ip_flags > 1)) { 464 return BCM_E_PARAM; 465 } 466 467 dst_addr_type_arr[0] = dst_addr_type; 468 SHR_BIT_ITER(dst_addr_type_arr, 32, bit) { 469 flag = (1 << bit); 470 switch(flag) { 471 case BCM_FIELD_PKT_DST_ADDR_TYPE_UCAST_MAC: 472 mac_hw_data = 0x1; 473 mac_hw_mask = 0x3; 474 break; 475 case BCM_FIELD_PKT_DST_ADDR_TYPE_MCAST_MAC: 476 mac_hw_data = 0x0; 477 mac_hw_mask = 0x3; 478 break; 479 case BCM_FIELD_PKT_DST_ADDR_TYPE_BCAST_MAC: 480 mac_hw_data = 0x2; 481 mac_hw_mask = 0x3; 482 break; 483 case BCM_FIELD_PKT_DST_ADDR_TYPE_UCAST_IP: 484 ip_hw_data = 0x1; 485 ip_hw_mask = 0x3; 486 break; 487 case BCM_FIELD_PKT_DST_ADDR_TYPE_MCAST_IP: 488 ip_hw_data = 0x0; 489 ip_hw_mask = 0x3; 490 break; 491 case BCM_FIELD_PKT_DST_ADDR_TYPE_BCAST_IP: 492 ip_hw_data = 0x2; 493 ip_hw_mask = 0x3; 494 break; 495 default: 496 return BCM_E_PARAM; 497 } 498 } 499 500 *hw_data = (ip_hw_data << 2) + mac_hw_data; 501 *hw_mask = (ip_hw_mask << 2) + mac_hw_mask; 502 503 return BCM_E_NONE; 504 } 505 506 int 507 _bcm_field_hx5_qualify_PktDstAddrType_get(int unit, 508 bcm_field_qualify_t qual, 509 uint32 hw_data, 510 uint32 hw_mask, 511 uint32 *dst_addr_type) 512 { 513 uint32 ip_hw_data = 0; 514 uint32 ip_hw_mask = 0; 515 uint32 mac_hw_data = 0; 516 uint32 mac_hw_mask = 0; 517 518 ip_hw_data = (hw_data >> 2) & 0x3; 519 ip_hw_mask = (hw_mask >> 2) & 0x3; 520 mac_hw_data = hw_data & 0x3; 521 mac_hw_mask = hw_mask & 0x3; 522 523 *dst_addr_type = 0; 524 525 if (mac_hw_mask != 0) { 526 switch (mac_hw_data) { 527 case 0: 528 *dst_addr_type |= BCM_FIELD_PKT_DST_ADDR_TYPE_MCAST_MAC; 529 break; 530 case 1: 531 *dst_addr_type |= BCM_FIELD_PKT_DST_ADDR_TYPE_UCAST_MAC; 532 break; 533 case 2: 534 *dst_addr_type |= BCM_FIELD_PKT_DST_ADDR_TYPE_BCAST_MAC; 535 break; 536 default: 537 *dst_addr_type |= 0; 538 } 539 } 540 541 if (ip_hw_mask != 0) { 542 switch (ip_hw_data) { 543 case 0: 544 *dst_addr_type |= BCM_FIELD_PKT_DST_ADDR_TYPE_MCAST_IP; 545 break; 546 case 1: 547 *dst_addr_type |= BCM_FIELD_PKT_DST_ADDR_TYPE_UCAST_IP; 548 break; 549 case 2: 550 *dst_addr_type |= BCM_FIELD_PKT_DST_ADDR_TYPE_BCAST_IP; 551 break; 552 default: 553 *dst_addr_type |= 0; 554 } 555 } 556 557 return BCM_E_NONE; 558 } 559 560 #endif