vlan.c (35979B)
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: vlan.c 8 * Purpose: Handle trident3 specific vlan features. 9 */ 10 11 #include <soc/defs.h> 12 #include <soc/field.h> 13 #include <sal/core/libc.h> 14 #include <shared/bsl.h> 15 16 #if defined(BCM_TRIDENT3_SUPPORT) 17 #include <sal/core/libc.h> 18 #include <soc/drv.h> 19 #include <soc/hash.h> 20 #include <soc/trident2.h> 21 #include <soc/trident3.h> 22 #include <soc/mem.h> 23 #include <bcm/port.h> 24 #include <bcm/error.h> 25 26 #include <bcm_int/esw/port.h> 27 #include <bcm_int/esw/mirror.h> 28 #include <bcm_int/esw/firebolt.h> 29 #include <bcm_int/esw/trident3.h> 30 #include <bcm_int/esw/vpn.h> 31 #include <bcm_int/esw/trx.h> 32 33 /* 34 * Function: 35 * _bcm_td3_vlan_vfi_untag_profile_ptr_get 36 * Purpose: 37 * Given a VLAN/VFI value, get the VLAN/VFI untag profile. 38 * Parameters: 39 * unit - (IN) BCM device number 40 * vlan_vfi - (IN) VLAN/VFI in question 41 * prof_index - (OUT) The associated profile index if all goes well 42 * Returns: 43 * BCM_E_XXX 44 */ 45 46 STATIC int 47 _bcm_td3_vlan_vfi_untag_profile_ptr_get(int unit, 48 bcm_vlan_t vlan_vfi, 49 uint32 *prof_index) 50 { 51 int rv = BCM_E_NONE; 52 uint32 *entry = NULL, index; 53 soc_mem_t mem; 54 55 if (prof_index == NULL) { 56 return BCM_E_PARAM; 57 } 58 59 /* Depending on VLAN/VFI, set relevant memory and index */ 60 if (!_BCM_VPN_VFI_IS_SET(vlan_vfi)) { 61 mem = EGR_VLANm; 62 /* Index in case of a VLAN is same as what is passed in */ 63 index = vlan_vfi; 64 } else { 65 mem = EGR_VFIm; 66 /* Index in case of a VFI is the encoded value */ 67 _BCM_VPN_GET(index, _BCM_VPN_TYPE_VFI, vlan_vfi); 68 } 69 70 /* Allocated the desired size */ 71 entry = sal_alloc(SOC_MEM_BYTES(unit, mem), "Get VLAN/VFI profile index"); 72 if (entry == NULL) { 73 return BCM_E_MEMORY; 74 } 75 76 /* Read the memory and extract the field in question */ 77 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, entry); 78 if (rv < 0) { 79 sal_free(entry); 80 return rv; 81 } 82 83 /* Assign the profile index */ 84 *prof_index = soc_mem_field32_get(unit, mem, entry, UNTAG_PROFILE_PTRf); 85 86 sal_free(entry); 87 88 return rv; 89 } 90 91 /* 92 * Function: 93 * _bcm_td3_vlan_vfi_untag_profile_ptr_set 94 * Purpose: 95 * Given a VLAN/VFI value, prof_index set 96 * the associated VLAN_VFI profile. 97 * Parameters: 98 * unit - (IN) BCM device number 99 * vlan_vfi - (IN) VLAN/VFI value 100 * prof_index - (OUT) The associated profile index if all goes well 101 * Returns: 102 * BCM_E_XXX 103 */ 104 105 STATIC int 106 _bcm_td3_vlan_vfi_untag_profile_ptr_set(int unit, 107 bcm_vlan_t vlan_vfi, 108 int prof_index) 109 { 110 int index = -1; 111 soc_mem_t mem; 112 113 /* Depending on VLAN/VFI, write to relevant memories */ 114 if (!_BCM_VPN_VFI_IS_SET(vlan_vfi)) { 115 mem = EGR_VLANm; 116 index = vlan_vfi; 117 } else { 118 mem = EGR_VFIm; 119 /* Index in case of a VFI is the encoded value */ 120 _BCM_VPN_GET(index, _BCM_VPN_TYPE_VFI, vlan_vfi); 121 } 122 123 LOG_INFO(BSL_LS_BCM_VLAN, 124 (BSL_META_U(unit,"!: mem: %s index: %d prof_index: %d\n"), 125 SOC_MEM_NAME(unit, mem), index, prof_index)); 126 127 SOC_IF_ERROR_RETURN( 128 soc_mem_field32_modify(unit, mem, index, UNTAG_PROFILE_PTRf, prof_index)); 129 130 return BCM_E_NONE; 131 } 132 133 /* 134 * Function: 135 * _bcm_td3_vlan_vfi_profile_entry_set 136 * Purpose: 137 * Given a VLAN/VFI value and a direction (Igr/Egr), set the 138 * data associated with a profile entry and update the VLAN/VFI 139 * with a new profile index 140 * Parameters: 141 * unit - (IN) BCM device number 142 * vlan_vfi - (IN) VLAN/VFI value 143 * egress - (IN) If TRUE, VP handling is for egress, else ingress. 144 * entry_data - (IN) Entry to write 145 * Returns: 146 * BCM_E_XXX 147 */ 148 149 int 150 _bcm_td3_vlan_vfi_profile_entry_set(int unit, bcm_vlan_t vlan_vfi, 151 void *entry_data) 152 { 153 uint32 cur_prof_index = 0, new_prof_index = 0; 154 int32 cur_idx_ref_count = 0, new_idx_ref_count = 0; 155 156 /* Get the profile_idx associated with the VLAN/VFI */ 157 _bcm_td3_vlan_vfi_untag_profile_ptr_get(unit, vlan_vfi, &cur_prof_index); 158 159 /* Gather the ref counts */ 160 BCM_IF_ERROR_RETURN 161 (_bcm_vlan_vfi_untag_profile_ref_count(unit, cur_prof_index, 162 &cur_idx_ref_count)); 163 164 LOG_INFO(BSL_LS_BCM_VLAN, 165 (BSL_META_U(unit,"\n\n!:Enter!Before profile: vlan_vfi: %d Old index %d " 166 "old_ref_cnt %d \n"), 167 vlan_vfi, cur_prof_index, cur_idx_ref_count)); 168 169 /* Depending on the direction, update the relevant profile index, 170 delete the old one */ 171 172 BCM_IF_ERROR_RETURN(_bcm_vlan_vfi_untag_profile_entry_op(unit, &entry_data, 1, 1, 173 (uint32 *)&new_prof_index)); 174 175 /* Write the new index into the VALN/VFI tables */ 176 _bcm_td3_vlan_vfi_untag_profile_ptr_set(unit, vlan_vfi, new_prof_index); 177 178 /* 179 * If the old-profile-index entry is non-zero delete it, note that if the 180 * same index is reallocated, the profile-mgmt would have incremented the 181 * ref-count anyway. 182 */ 183 if (cur_prof_index != 0) { 184 _bcm_vlan_vfi_untag_profile_entry_op(unit, NULL, 1, 0, 185 &cur_prof_index); 186 } 187 188 /* Gather the ref counts */ 189 BCM_IF_ERROR_RETURN 190 (_bcm_vlan_vfi_untag_profile_ref_count(unit, cur_prof_index, 191 &cur_idx_ref_count)); 192 BCM_IF_ERROR_RETURN 193 (_bcm_vlan_vfi_untag_profile_ref_count(unit,new_prof_index, 194 &new_idx_ref_count)); 195 196 LOG_INFO(BSL_LS_BCM_VLAN, 197 (BSL_META_U(unit,"!: After profile: old_index %d " 198 "old_ref_cnt %d new_index %d " 199 "new_ref_count: %d \n"), 200 cur_prof_index, cur_idx_ref_count, 201 new_prof_index, new_idx_ref_count)); 202 203 LOG_INFO(BSL_LS_BCM_VLAN, 204 (BSL_META_U(unit,"!: Old index %d New index %d " 205 "vlan-vfi %d Data0 0x%x Data1 0x%x " 206 "Data2 0x%x Data3 0x%x Data4 0x%x Data5 0x%x Exit!\n\n\n"), 207 cur_prof_index, new_prof_index, vlan_vfi, 208 ((egr_vlan_vfi_untag_entry_t *)entry_data)->entry_data[5], 209 ((egr_vlan_vfi_untag_entry_t *)entry_data)->entry_data[4], 210 ((egr_vlan_vfi_untag_entry_t *)entry_data)->entry_data[3], 211 ((egr_vlan_vfi_untag_entry_t *)entry_data)->entry_data[2], 212 ((egr_vlan_vfi_untag_entry_t *)entry_data)->entry_data[1], 213 ((egr_vlan_vfi_untag_entry_t *)entry_data)->entry_data[0])); 214 215 return BCM_E_NONE; 216 } 217 218 /* 219 * Function: 220 * _bcm_td3_vlan_vfi_profile_entry_get 221 * Purpose: 222 * Given a VLAN/VFI value, return the utag profile entry 223 * Parameters: 224 * unit - (IN) BCM device number 225 * vlan_vfi - (IN) VLAN/VFI value 226 * entry_data - (OUT) Entry returned 227 * Returns: 228 * BCM_E_XXX 229 */ 230 231 int 232 _bcm_td3_vlan_vfi_profile_entry_get(int unit, bcm_vlan_t vlan_vfi, 233 void *entry_data) 234 { 235 int rv = BCM_E_NONE; 236 uint32 prof_index = 0; 237 /* Get the profile_idx associated with the VLAN/VFI */ 238 BCM_IF_ERROR_RETURN(_bcm_td3_vlan_vfi_untag_profile_ptr_get(unit, vlan_vfi, &prof_index)); 239 240 rv = READ_EGR_VLAN_VFI_UNTAGm(unit, MEM_BLOCK_ANY, prof_index, entry_data); 241 return rv; 242 } 243 /* 244 * Function: 245 * bcm_td3_vlan_vfi_untag_init 246 * Purpose: 247 * Program membership port bitmap in vlan vfi membership tables 248 */ 249 int 250 bcm_td3_vlan_vfi_untag_init(int unit, bcm_vlan_t vid, pbmp_t pbmp) 251 { 252 egr_vlan_vfi_untag_entry_t egr_vlan_vfi; 253 egr_vlan_entry_t egr_vtab; 254 uint32 profile_ptr = 0; 255 256 SOC_IF_ERROR_RETURN(READ_EGR_VLANm(unit, MEM_BLOCK_ANY, vid, &egr_vtab)); 257 profile_ptr = soc_EGR_VLANm_field32_get(unit, &egr_vtab, 258 UNTAG_PROFILE_PTRf); 259 260 SOC_IF_ERROR_RETURN 261 (READ_EGR_VLAN_VFI_UNTAGm(unit, MEM_BLOCK_ANY, profile_ptr, 262 &egr_vlan_vfi)); 263 264 soc_mem_pbmp_field_set(unit, EGR_VLAN_VFI_UNTAGm, &egr_vlan_vfi, 265 UT_PORT_BITMAPf, &pbmp); 266 267 SOC_IF_ERROR_RETURN( 268 _bcm_td3_vlan_vfi_profile_entry_set(unit, vid, &egr_vlan_vfi)); 269 270 return BCM_E_NONE; 271 } 272 273 /* 274 * Function: 275 * bcm_td3_vlan_vfi_untag_add 276 * Purpose: 277 * Program membership port bitmap in vlan vfi untag tables 278 */ 279 int 280 bcm_td3_vlan_vfi_untag_add(int unit, bcm_vlan_t vid, pbmp_t pbmp, pbmp_t ubmp) 281 { 282 egr_vlan_vfi_untag_entry_t egr_vlan_vfi; 283 pbmp_t cur_pbmp; 284 uint32 prof_index = 0; 285 286 /* Get the profile_idx associated with the VLAN/VFI */ 287 _bcm_td3_vlan_vfi_untag_profile_ptr_get(unit, vid, &prof_index); 288 289 /* Only allow untagged ports on the vlan. */ 290 SOC_PBMP_AND(ubmp, pbmp); 291 292 /* Draco does not have room for CMIC/IPIC in ubmp */ 293 SOC_PBMP_REMOVE(ubmp, PBMP_CMIC(unit)); 294 SOC_PBMP_REMOVE(ubmp, PBMP_ST_ALL(unit)); 295 296 BCM_IF_ERROR_RETURN 297 (READ_EGR_VLAN_VFI_UNTAGm(unit, MEM_BLOCK_ANY, prof_index, &egr_vlan_vfi)); 298 soc_mem_pbmp_field_get(unit, EGR_VLAN_VFI_UNTAGm, &egr_vlan_vfi, 299 UT_PORT_BITMAPf, &cur_pbmp); 300 BCM_PBMP_REMOVE(cur_pbmp, pbmp); 301 BCM_PBMP_OR(cur_pbmp, ubmp); 302 soc_mem_pbmp_field_set(unit, EGR_VLAN_VFI_UNTAGm, &egr_vlan_vfi, 303 UT_PORT_BITMAPf, &cur_pbmp); 304 305 _bcm_td3_vlan_vfi_profile_entry_set(unit, vid, &egr_vlan_vfi); 306 307 return BCM_E_NONE; 308 } 309 310 /* 311 * Function: 312 * bcm_td3_vlan_vfi_untag_delete 313 * Purpose: 314 * Program membership port bitmap in vlan vfi untag tables 315 */ 316 int 317 bcm_td3_vlan_vfi_untag_delete(int unit, bcm_vlan_t vid, pbmp_t pbmp) 318 { 319 egr_vlan_vfi_untag_entry_t egr_vlan_vfi; 320 pbmp_t cur_pbmp; 321 uint32 prof_index = 0; 322 323 /* Get the profile_idx associated with the VLAN/VFI */ 324 _bcm_td3_vlan_vfi_untag_profile_ptr_get(unit, vid, &prof_index); 325 326 BCM_IF_ERROR_RETURN 327 (READ_EGR_VLAN_VFI_UNTAGm(unit, MEM_BLOCK_ANY, prof_index, &egr_vlan_vfi)); 328 soc_mem_pbmp_field_get(unit, EGR_VLAN_VFI_UNTAGm, &egr_vlan_vfi, 329 UT_PORT_BITMAPf, &cur_pbmp); 330 BCM_PBMP_REMOVE(cur_pbmp, pbmp); 331 soc_mem_pbmp_field_set(unit, EGR_VLAN_VFI_UNTAGm, &egr_vlan_vfi, 332 UT_PORT_BITMAPf, &cur_pbmp); 333 334 _bcm_td3_vlan_vfi_profile_entry_set(unit, vid, &egr_vlan_vfi); 335 336 return BCM_E_NONE; 337 } 338 339 /* 340 * Function: 341 * bcm_td3_egr_vlan_vfi_untag_destroy 342 * Purpose: 343 * Delete the VLAN Vfi membership entry. 344 * Parameters: 345 * unit - (IN) SOC unit number. 346 * vlan - (IN) VLAN ID. 347 * Returns: 348 * BCM_E_XXX 349 */ 350 int 351 bcm_td3_vlan_vfi_untag_destroy(int unit, bcm_vlan_t vlan) 352 { 353 uint32 profile_ptr = 0; 354 egr_vlan_vfi_untag_entry_t ing_vlan_vfi; 355 int cur_ref_count = 0; 356 357 sal_memset(&ing_vlan_vfi, 0, sizeof(egr_vlan_vfi_untag_entry_t)); 358 359 /* Get the MEMBERSHIP_PROFILE_PTR */ 360 _bcm_td3_vlan_vfi_untag_profile_ptr_get(unit, vlan, &profile_ptr); 361 _bcm_vlan_vfi_untag_profile_ref_count(unit, profile_ptr, &cur_ref_count); 362 363 LOG_INFO(BSL_LS_BCM_VLAN, 364 (BSL_META_U(unit,"!: Deleting profile %d for vlan_vfi: %d cur_ref_cnt: %d \n"), 365 profile_ptr, vlan, cur_ref_count)); 366 367 /* Delete the Reference Count, if the profile is non-zero */ 368 if (profile_ptr != 0) { 369 BCM_IF_ERROR_RETURN(_bcm_vlan_vfi_untag_profile_entry_op(unit, NULL, 1, 370 0, &profile_ptr)); 371 } 372 373 return BCM_E_NONE; 374 } 375 376 377 /* 378 * Function: 379 * bcm_td3_vlan_table_utport_get 380 * Purpose: 381 * Read the UT_PORT_BITMAP from a vlan entry. 382 */ 383 int 384 bcm_td3_vlan_table_ut_port_get(int unit, bcm_vlan_t vid, pbmp_t *ut_pbmp) 385 { 386 egr_vlan_vfi_untag_entry_t egr_vlan_vfi; 387 uint32 prof_index = 0; 388 389 /* Upper layer already checks that vid is valid 390 * Get the profile_idx associated with the VLAN/VFI */ 391 _bcm_td3_vlan_vfi_untag_profile_ptr_get(unit, vid, &prof_index); 392 393 SOC_IF_ERROR_RETURN 394 (READ_EGR_VLAN_VFI_UNTAGm(unit, MEM_BLOCK_ANY, prof_index, 395 &egr_vlan_vfi)); 396 soc_mem_pbmp_field_get(unit, EGR_VLAN_VFI_UNTAGm, &egr_vlan_vfi, 397 UT_PORT_BITMAPf, ut_pbmp); 398 399 return BCM_E_NONE; 400 } 401 402 /* 403 * Function: 404 * _bcm_td3_vlan_mac_action_add 405 * Description : 406 * Add association from MAC address to VLAN. 407 * If the entry already exists, update the action. 408 * Parameters : 409 * unit (IN) BCM unit number 410 * mac (IN) MAC address 411 * action (IN) Action for outer and inner tag 412 * Note: 413 * Program VLAN_XLATE_1_DOUBLEm. 414 */ 415 int _bcm_td3_vlan_mac_action_add(int unit, bcm_mac_t mac, 416 bcm_vlan_action_set_t *action) 417 { 418 int rv; 419 uint32 profile_idx; 420 vlan_xlate_2_double_entry_t vx1ent; 421 soc_mem_t mem = VLAN_XLATE_2_DOUBLEm; 422 423 BCM_IF_ERROR_RETURN(_bcm_trx_vlan_action_verify(unit, action)); 424 if (soc_feature(unit, soc_feature_vlan_pri_cfi_action)) { 425 if (action->priority == -1) { 426 return BCM_E_PARAM; /* no default priority action to take*/ 427 } 428 } 429 430 BCM_IF_ERROR_RETURN 431 (_bcm_trx_vlan_action_profile_entry_add(unit, action, &profile_idx)); 432 433 sal_memset(&vx1ent, 0, sizeof(vx1ent)); 434 soc_mem_mac_addr_set(unit, mem, &vx1ent, MAC__MAC_ADDRf, mac); 435 soc_mem_field32_set(unit, mem, &vx1ent, KEY_TYPEf, 436 TD2_VLXLT_HASH_KEY_TYPE_VLAN_MAC); 437 soc_mem_field32_set(unit, mem, &vx1ent, DATA_TYPEf, 438 TD2_VLXLT_HASH_KEY_TYPE_VLAN_MAC); 439 soc_mem_field32_set(unit, mem, &vx1ent, MAC__OVIDf, action->new_outer_vlan); 440 soc_mem_field32_set(unit, mem, &vx1ent, MAC__IVIDf, action->new_inner_vlan); 441 442 if (soc_feature(unit, soc_feature_vlan_pri_cfi_action)) { 443 soc_mem_field32_set(unit, mem, &vx1ent, MAC__OPRIf, action->priority); 444 soc_mem_field32_set(unit, mem, &vx1ent, MAC__OCFIf, 445 action->new_outer_cfi); 446 soc_mem_field32_set(unit, mem, &vx1ent, MAC__IPRIf, 447 action->new_inner_pkt_prio); 448 soc_mem_field32_set(unit, mem, &vx1ent, MAC__ICFIf, 449 action->new_inner_cfi); 450 } else { 451 if (action->priority >= BCM_PRIO_MIN && 452 action->priority <= BCM_PRIO_MAX) { 453 soc_mem_field32_set(unit, mem, &vx1ent, MAC__PRIf, action->priority); 454 } 455 } 456 soc_mem_field32_set(unit, mem, &vx1ent, MAC__TAG_ACTION_PROFILE_PTRf, 457 profile_idx); 458 459 if (SOC_MEM_FIELD_VALID(unit, mem, MAC__VLAN_ACTION_VALIDf)) { 460 soc_mem_field32_set(unit, mem, &vx1ent, MAC__VLAN_ACTION_VALIDf, 1); 461 } 462 soc_mem_field32_set(unit, mem, &vx1ent, BASE_VALID_0f, 3); 463 soc_mem_field32_set(unit, mem, &vx1ent, BASE_VALID_1f, 7); 464 465 rv = soc_mem_insert_return_old(unit, mem, MEM_BLOCK_ALL, &vx1ent, &vx1ent); 466 467 if (rv == SOC_E_EXISTS) { 468 /* Delete the old vlan action profile entry */ 469 profile_idx = soc_mem_field32_get(unit, mem, &vx1ent, 470 MAC__TAG_ACTION_PROFILE_PTRf); 471 rv = _bcm_trx_vlan_action_profile_entry_delete(unit, profile_idx); 472 } 473 474 return rv; 475 } 476 477 /* 478 * Function: 479 * _bcm_td3_vlan_mac_action_get 480 * Description : 481 * Get association from MAC address to VLAN tag actions. 482 * Parameters : 483 * unit (IN) BCM unit number 484 * mac (IN) MAC address 485 * action (OUT) Action for outer and inner tag 486 * Returns: 487 * BCM_E_XXX 488 */ 489 int 490 _bcm_td3_vlan_mac_action_get(int unit, bcm_mac_t mac, 491 bcm_vlan_action_set_t *action) 492 { 493 vlan_xlate_2_double_entry_t vx1ent; /* Lookup key hw buffer. */ 494 vlan_xlate_2_double_entry_t res_vx1ent; /* Lookup result buffer. */ 495 uint32 profile_idx; /* Vlan action profile index. */ 496 int rv; /* Operation return status. */ 497 int idx = 0; /* Lookup result entry index. */ 498 soc_mem_t mem = VLAN_XLATE_2_DOUBLEm; 499 500 /* Input parameters check. */ 501 if (NULL == action) { 502 return (BCM_E_PARAM); 503 } 504 505 /* Reset lookup key and result destination buffer. */ 506 sal_memset(&vx1ent, 0, sizeof(vx1ent)); 507 sal_memset(&res_vx1ent, 0, sizeof(res_vx1ent)); 508 509 /* Initialize lookup key. */ 510 soc_mem_mac_addr_set(unit, mem, &vx1ent, MAC__MAC_ADDRf, mac); 511 soc_mem_field32_set(unit, mem, &vx1ent, KEY_TYPEf, 512 TD2_VLXLT_HASH_KEY_TYPE_VLAN_MAC); 513 soc_mem_field32_set(unit, mem, &vx1ent, DATA_TYPEf, 514 TD2_VLXLT_HASH_KEY_TYPE_VLAN_MAC); 515 /* Perform VLAN_MAC table search by mac address. */ 516 soc_mem_lock(unit, mem); 517 rv = soc_mem_search(unit, mem, MEM_BLOCK_ALL, &idx, 518 &vx1ent, &res_vx1ent, 0); 519 soc_mem_unlock(unit, mem); 520 BCM_IF_ERROR_RETURN(rv); 521 522 action->new_outer_vlan = 523 soc_mem_field32_get(unit, mem, &res_vx1ent, MAC__OVIDf); 524 action->new_inner_vlan = 525 soc_mem_field32_get(unit, mem, &res_vx1ent, MAC__IVIDf); 526 if (soc_feature(unit, soc_feature_vlan_pri_cfi_action)) { 527 action->priority = 528 soc_mem_field32_get(unit, mem, &res_vx1ent, MAC__OPRIf); 529 action->new_outer_cfi = 530 soc_mem_field32_get(unit, mem, &res_vx1ent, MAC__OCFIf); 531 action->new_inner_pkt_prio = 532 soc_mem_field32_get(unit, mem, &res_vx1ent, MAC__IPRIf); 533 action->new_inner_cfi = 534 soc_mem_field32_get(unit, mem, &res_vx1ent, MAC__ICFIf); 535 } else { 536 action->priority = soc_mem_field32_get(unit, mem, &res_vx1ent, MAC__PRIf); 537 } 538 539 /* Read action profile data. */ 540 profile_idx = soc_mem_field32_get(unit, mem, &res_vx1ent, 541 MAC__TAG_ACTION_PROFILE_PTRf); 542 _bcm_trx_vlan_action_profile_entry_get(unit, action, profile_idx); 543 544 return (BCM_E_NONE); 545 } 546 547 /* 548 * Function: 549 * _bcm_td3_vlan_mac_delete 550 * Purpose: 551 * Delete a vlan mac lookup entry. 552 * Parameters: 553 * unit (IN) BCM unit number 554 * mac (IN) MAC address 555 * Returns: 556 * BCM_E_XXX 557 */ 558 int 559 _bcm_td3_vlan_mac_delete(int unit, bcm_mac_t mac) 560 { 561 int rv; 562 vlan_xlate_2_double_entry_t vx1ent; 563 uint32 profile_idx; 564 soc_mem_t mem = VLAN_XLATE_2_DOUBLEm; 565 566 sal_memset(&vx1ent, 0, sizeof(vx1ent)); 567 soc_mem_mac_addr_set(unit, mem, &vx1ent, MAC__MAC_ADDRf, mac); 568 soc_mem_field32_set(unit, mem, &vx1ent, KEY_TYPEf, 569 TD2_VLXLT_HASH_KEY_TYPE_VLAN_MAC); 570 soc_mem_field32_set(unit, mem, &vx1ent, DATA_TYPEf, 571 TD2_VLXLT_HASH_KEY_TYPE_VLAN_MAC); 572 soc_mem_lock(unit, mem); 573 rv = soc_mem_delete_return_old(unit, mem, MEM_BLOCK_ALL, &vx1ent, &vx1ent); 574 soc_mem_unlock(unit, mem); 575 if (rv == SOC_E_NOT_FOUND) { 576 rv = SOC_E_NONE; 577 } else if ((rv == SOC_E_NONE) && 578 (soc_mem_field32_get(unit, mem, &vx1ent, BASE_VALID_0f) == 3) && 579 (soc_mem_field32_get(unit, mem, &vx1ent, BASE_VALID_1f) == 7)) { 580 profile_idx = soc_mem_field32_get(unit, mem, &vx1ent, 581 MAC__TAG_ACTION_PROFILE_PTRf); 582 /* Delete the old vlan action profile entry */ 583 rv = _bcm_trx_vlan_action_profile_entry_delete(unit, profile_idx); 584 } 585 return rv; 586 } 587 588 /* 589 * Function: 590 * _bcm_td3_vlan_mac_delete_all 591 * Purpose: 592 * Delete all vlan mac lookup entry. 593 * Parameters: 594 * unit (IN) BCM unit number 595 * Returns: 596 * BCM_E_XXX 597 */ 598 int 599 _bcm_td3_vlan_mac_delete_all(int unit) 600 { 601 int i, imin, imax, nent, rv; 602 uint32 old_profile_idx; 603 vlan_xlate_2_double_entry_t *vxtab, *vmnull, *vxtabp; 604 soc_mem_t mem = VLAN_XLATE_2_DOUBLEm; 605 606 imin = soc_mem_index_min(unit, mem); 607 imax = soc_mem_index_max(unit, mem); 608 nent = soc_mem_index_count(unit, mem); 609 610 vxtab = soc_cm_salloc(unit, SOC_MEM_TABLE_BYTES(unit, mem), "vlan_xlate"); 611 612 if (vxtab == NULL) { 613 return BCM_E_MEMORY; 614 } 615 616 vmnull = soc_mem_entry_null(unit, mem); 617 618 soc_mem_lock(unit, mem); 619 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, 620 imin, imax, vxtab); 621 if (rv < 0) { 622 soc_mem_unlock(unit, mem); 623 soc_cm_sfree(unit, vxtab); 624 return rv; 625 } 626 627 for (i = 0; i < nent; i++) { 628 vxtabp = soc_mem_table_idx_to_pointer(unit, mem, 629 vlan_xlate_2_double_entry_t *, vxtab, i); 630 631 if (!((soc_mem_field32_get(unit, mem, vxtabp, BASE_VALID_0f) == 3) && 632 (soc_mem_field32_get(unit, mem, vxtabp, BASE_VALID_1f) == 7)) || 633 (soc_mem_field32_get(unit, mem, vxtabp, KEY_TYPEf) != 634 TD2_VLXLT_HASH_KEY_TYPE_VLAN_MAC)) { 635 continue; 636 } 637 old_profile_idx = soc_mem_field32_get(unit, mem, vxtabp, 638 MAC__TAG_ACTION_PROFILE_PTRf); 639 640 rv = soc_mem_write(unit, mem, MEM_BLOCK_ANY, i, vmnull); 641 642 if (rv >= 0) { 643 /* Delete the old vlan action profile entry */ 644 rv = _bcm_trx_vlan_action_profile_entry_delete(unit, old_profile_idx); 645 } 646 } 647 648 soc_mem_unlock(unit, mem); 649 soc_cm_sfree(unit, vxtab); 650 return rv; 651 } 652 653 /* 654 * Function: 655 * _bcm_td3_vlan_mac_action_traverse 656 * Description : 657 * Traverse over vlan mac actions, which are used for VLAN 658 * tag/s assignment to untagged packets. 659 * Parameters : 660 * unit (IN) BCM unit number 661 * cb (IN) Call back function 662 * user_data (IN) User provided data to pass to a call back 663 * Returns: 664 * BCM_E_XXX 665 */ 666 int 667 _bcm_td3_vlan_mac_action_traverse(int unit, 668 bcm_vlan_mac_action_traverse_cb cb, 669 void *user_data) 670 { 671 int idx, imin, imax, nent, rv; 672 uint32 profile_idx; 673 bcm_mac_t mac; 674 bcm_vlan_action_set_t action; 675 vlan_xlate_2_double_entry_t * vmtab, *vmtabp; 676 soc_mem_t mem = VLAN_XLATE_2_DOUBLEm; 677 678 /* Input parameters check. */ 679 if (NULL == cb) { 680 return (BCM_E_PARAM); 681 } 682 683 imin = soc_mem_index_min(unit, mem); 684 imax = soc_mem_index_max(unit, mem); 685 nent = soc_mem_index_count(unit, mem); 686 vmtab = soc_cm_salloc(unit, SOC_MEM_TABLE_BYTES(unit, mem), "vlan_mac"); 687 688 if (vmtab == NULL) { 689 return BCM_E_MEMORY; 690 } 691 692 soc_mem_lock(unit, mem); 693 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, imin, imax, vmtab); 694 if (BCM_FAILURE(rv)) { 695 soc_mem_unlock(unit, mem); 696 soc_cm_sfree(unit, vmtab); 697 return rv; 698 } 699 700 for (idx = 0; idx < nent; idx++) { 701 sal_memset(mac, 0, sizeof(bcm_mac_t)); 702 sal_memset(&action, 0, sizeof(bcm_vlan_action_set_t)); 703 vmtabp = soc_mem_table_idx_to_pointer(unit, mem, 704 vlan_xlate_2_double_entry_t *, 705 vmtab, idx); 706 707 if (!((soc_mem_field32_get(unit, mem, vmtabp, BASE_VALID_0f) == 3) && 708 (soc_mem_field32_get(unit, mem, vmtabp, BASE_VALID_1f) == 7)) || 709 (soc_mem_field32_get(unit, mem, vmtabp, KEY_TYPEf) != 710 TD2_VLXLT_HASH_KEY_TYPE_VLAN_MAC)) { 711 continue; 712 } 713 714 /* Get entry mac address. */ 715 soc_mem_mac_addr_get(unit, mem, vmtabp, MAC__MAC_ADDRf, mac); 716 717 action.new_outer_vlan = 718 soc_mem_field32_get(unit, mem, vmtabp, MAC__OVIDf); 719 action.new_inner_vlan = 720 soc_mem_field32_get(unit, mem, vmtabp, MAC__IVIDf); 721 if (soc_feature(unit, soc_feature_vlan_pri_cfi_action)) { 722 action.priority = soc_mem_field32_get(unit, mem, vmtabp, MAC__OPRIf); 723 action.new_outer_cfi = 724 soc_mem_field32_get(unit, mem, vmtabp, MAC__OCFIf); 725 action.new_inner_pkt_prio = 726 soc_mem_field32_get(unit, mem, vmtabp, MAC__IPRIf); 727 action.new_inner_cfi = 728 soc_mem_field32_get(unit, mem, vmtabp, MAC__ICFIf); 729 } else { 730 action.priority = 731 soc_mem_field32_get(unit, mem, vmtabp, MAC__PRIf); 732 } 733 734 /* Read action profile data. */ 735 profile_idx = 736 soc_mem_field32_get(unit, mem, vmtabp, MAC__TAG_ACTION_PROFILE_PTRf); 737 _bcm_trx_vlan_action_profile_entry_get(unit, &action, profile_idx); 738 739 /* Call traverse callback with the data. */ 740 rv = cb(unit, mac, &action, user_data); 741 if (BCM_FAILURE(rv)) { 742 soc_mem_unlock(unit, mem); 743 soc_cm_sfree(unit, vmtab); 744 return rv; 745 } 746 } 747 748 soc_mem_unlock(unit, mem); 749 soc_cm_sfree(unit, vmtab); 750 return rv; 751 } 752 753 /* 754 * Function: 755 * bcmi_td3_def_vfi_profile_add 756 * 757 * Purpose: 758 * Programs VFI_PROFILE table based on vpn type 759 * 760 * Parameters: 761 * unit - (IN) BCM device number. 762 * int - (IN) is_eline 763 * profile_index - (OUT) Profile index allocated by soc_mem_profile_add 764 * 765 * Returns: 766 * BCM_E_XXXs 767 */ 768 int 769 _bcm_td3_def_vfi_profile_add(int unit, int is_eline, uint32 *profile_index){ 770 vfi_profile_entry_t vfi_profile_entry; 771 void *entries[1]; 772 int value = 0; 773 774 sal_memset(&vfi_profile_entry, 0, sizeof(vfi_profile_entry_t)); 775 /* from bcm56870_a0_cancun_cmh.yml */ 776 if(is_eline) { 777 value = 8; 778 } 779 else { 780 value = 4; 781 } 782 783 soc_mem_field32_set(unit, VFI_PROFILEm, &vfi_profile_entry, 784 PKT_FLOW_SELECT_CTRL_ID_2f, value); 785 soc_mem_field32_set(unit, VFI_PROFILEm, &vfi_profile_entry, 786 EN_IFILTERf, 1); 787 entries[0] = &vfi_profile_entry; 788 BCM_IF_ERROR_RETURN(_bcm_vfi_profile_entry_add(unit, entries, 1, 789 profile_index)); 790 791 return BCM_E_NONE; 792 } 793 794 /* 795 * Function: 796 * _bcm_td3_sd_tag_action_profile_get 797 * 798 * Purpose: 799 * get vlan profile index based on sd_tag action 800 * 801 * Parameters: 802 * unit - (IN) BCM device number. 803 * int - (IN) sd_tag_action_present 804 * int - (IN) sd_tag_action_not_present 805 * index - (IN, OUT) Profile index 806 * 807 * Returns: 808 * BCM_E_XXXs 809 */ 810 int 811 _bcm_td3_sd_tag_action_profile_get( 812 int unit, 813 int sd_tag_action_present, 814 int sd_tag_action_not_present, 815 uint32 *index) 816 { 817 int rv = BCM_E_NONE; 818 bcm_vlan_action_set_t action; 819 uint32 new_index = 0; 820 821 822 bcm_vlan_action_set_t_init(&action); 823 824 /* sd_tag_action_not_present 825 * 0 = NOOP 1 = ADD_VID_TPID 2 = RSVD_2 3 = RSVD_3 826 */ 827 if (sd_tag_action_not_present == 1) { 828 action.outer_tpid_action = bcmVlanTpidActionModify; 829 action.it_outer = bcmVlanActionAdd; 830 action.it_outer_pkt_prio = bcmVlanActionAdd; 831 action.it_outer_cfi = bcmVlanActionAdd; 832 action.ut_outer = bcmVlanActionAdd; 833 action.ut_outer_pkt_prio = bcmVlanActionAdd; 834 action.ut_outer_cfi = bcmVlanActionAdd; 835 } else { 836 action.outer_tpid_action = bcmVlanTpidActionNone; 837 action.it_outer = bcmVlanActionNone; 838 action.ut_outer = bcmVlanActionNone; 839 } 840 841 /* sd_tag_action_present 842 * 0 = NOOP 843 * 1 = REPLACE_VID_TPID 844 * 2 = REPLACE_VID_ONLY 845 * 3 = DELETE 846 * 4 = REPLACE_VID_PRI_TPID 847 * 5 = REPLACE_VID_PRI_ONLY 848 * 6 = REPLACE_PRI_ONLY 849 * 7 = REPLACE_TPID_ONLY 850 */ 851 if (sd_tag_action_present == 0){ 852 action.outer_tpid_action = bcmVlanTpidActionNone; 853 action.ot_outer = bcmVlanActionNone; 854 action.ot_outer_pkt_prio = bcmVlanActionNone; 855 action.ot_outer_cfi = bcmVlanActionNone; 856 action.dt_outer = bcmVlanActionNone; 857 action.dt_outer_pkt_prio = bcmVlanActionNone; 858 action.dt_outer_cfi = bcmVlanActionNone; 859 } else if (sd_tag_action_present == 1) { 860 action.outer_tpid_action = bcmVlanTpidActionModify; 861 action.ot_outer = bcmVlanActionReplace; 862 action.ot_outer_pkt_prio = bcmVlanActionNone; 863 action.ot_outer_cfi = bcmVlanActionNone; 864 action.dt_outer = bcmVlanActionReplace; 865 action.dt_outer_pkt_prio = bcmVlanActionNone; 866 action.dt_outer_cfi = bcmVlanActionNone; 867 } else if (sd_tag_action_present == 2) { 868 action.outer_tpid_action = bcmVlanTpidActionNone; 869 action.ot_outer = bcmVlanActionReplace; 870 action.ot_outer_pkt_prio = bcmVlanActionNone; 871 action.ot_outer_cfi = bcmVlanActionNone; 872 action.dt_outer = bcmVlanActionReplace; 873 action.dt_outer_pkt_prio = bcmVlanActionNone; 874 action.dt_outer_cfi = bcmVlanActionNone; 875 } else if (sd_tag_action_present == 3) { 876 action.outer_tpid_action = bcmVlanTpidActionModify; 877 action.ot_outer = bcmVlanActionDelete; 878 action.ot_outer_pkt_prio = bcmVlanActionDelete; 879 action.ot_outer_cfi = bcmVlanActionDelete; 880 action.dt_outer = bcmVlanActionDelete; 881 action.dt_outer_pkt_prio = bcmVlanActionDelete; 882 action.dt_outer_cfi = bcmVlanActionDelete; 883 } else if (sd_tag_action_present == 4) { 884 action.outer_tpid_action = bcmVlanTpidActionModify; 885 action.ot_outer = bcmVlanActionReplace; 886 action.ot_outer_pkt_prio = bcmVlanActionReplace; 887 action.ot_outer_cfi = bcmVlanActionReplace; 888 action.dt_outer = bcmVlanActionReplace; 889 action.dt_outer_pkt_prio = bcmVlanActionReplace; 890 action.dt_outer_cfi = bcmVlanActionReplace; 891 } else if (sd_tag_action_present == 5) { 892 action.outer_tpid_action = bcmVlanTpidActionNone; 893 action.ot_outer = bcmVlanActionReplace; 894 action.ot_outer_pkt_prio = bcmVlanActionReplace; 895 action.ot_outer_cfi = bcmVlanActionReplace; 896 action.dt_outer = bcmVlanActionReplace; 897 action.dt_outer_pkt_prio = bcmVlanActionReplace; 898 action.dt_outer_cfi = bcmVlanActionReplace; 899 } else if (sd_tag_action_present == 6) { 900 action.outer_tpid_action = bcmVlanTpidActionNone; 901 action.ot_outer = bcmVlanActionNone; 902 action.ot_outer_pkt_prio = bcmVlanActionReplace; 903 action.ot_outer_cfi = bcmVlanActionReplace; 904 action.dt_outer = bcmVlanActionNone; 905 action.dt_outer_pkt_prio = bcmVlanActionReplace; 906 action.dt_outer_cfi = bcmVlanActionReplace; 907 } else if (sd_tag_action_present == 7) { 908 action.outer_tpid_action = bcmVlanTpidActionModify; 909 action.ot_outer = bcmVlanActionNone; 910 action.ot_outer_pkt_prio = bcmVlanActionNone; 911 action.ot_outer_cfi = bcmVlanActionNone; 912 action.dt_outer = bcmVlanActionNone; 913 action.dt_outer_pkt_prio = bcmVlanActionNone; 914 action.dt_outer_cfi = bcmVlanActionNone; 915 } else { 916 /* default as 0 */ 917 action.outer_tpid_action = bcmVlanTpidActionNone; 918 action.ot_outer = bcmVlanActionNone; 919 action.ot_outer_pkt_prio = bcmVlanActionNone; 920 action.dt_outer = bcmVlanActionNone; 921 action.dt_outer_pkt_prio = bcmVlanActionNone; 922 } 923 924 rv = _bcm_trx_egr_vlan_action_profile_entry_add(unit, &action, &new_index); 925 if (rv != BCM_E_NONE) { 926 return rv; 927 } 928 if (new_index != *index) { 929 if (*index != 0) { 930 rv = _bcm_trx_egr_vlan_action_profile_entry_delete(unit, *index); 931 } 932 *index = new_index; 933 } 934 935 return rv; 936 } 937 938 /* 939 * Function: 940 * _bcm_td3_sd_tag_action_get 941 * 942 * Purpose: 943 * get sd_tag action based on vlan profile index 944 * 945 * Parameters: 946 * unit - (IN) BCM device number. 947 * index - (IN) Profile index 948 * int - (OUT) sd_tag_action_present 949 * int - (OUT) sd_tag_action_not_present 950 * 951 * Returns: 952 * BCM_E_XXXs 953 */ 954 int 955 _bcm_td3_sd_tag_action_get( 956 int unit, 957 uint32 index, 958 int *sd_tag_action_present, 959 int *sd_tag_action_not_present) 960 { 961 bcm_vlan_action_set_t action; 962 963 bcm_vlan_action_set_t_init(&action); 964 965 _bcm_trx_egr_vlan_action_profile_entry_get(unit, &action, index); 966 967 if ((action.it_outer == bcmVlanActionAdd) && 968 (action.ut_outer == bcmVlanActionAdd)) { 969 *sd_tag_action_not_present = 1; 970 } else { 971 *sd_tag_action_not_present = 0; 972 } 973 974 if ((action.outer_tpid_action == bcmVlanTpidActionNone) && 975 (action.ot_outer == bcmVlanActionNone) && 976 (action.ot_outer_pkt_prio == bcmVlanActionNone)) { 977 978 *sd_tag_action_present = 0; 979 } else if ((action.outer_tpid_action == bcmVlanTpidActionModify) && 980 (action.ot_outer == bcmVlanActionReplace) && 981 (action.ot_outer_pkt_prio == bcmVlanActionNone)) { 982 983 *sd_tag_action_present = 1; 984 } else if ((action.outer_tpid_action == bcmVlanTpidActionNone) && 985 (action.ot_outer == bcmVlanActionReplace) && 986 (action.ot_outer_pkt_prio == bcmVlanActionNone)) { 987 988 *sd_tag_action_present = 2; 989 } else if ((action.outer_tpid_action == bcmVlanTpidActionModify) && 990 (action.ot_outer == bcmVlanActionDelete)) { 991 992 *sd_tag_action_present = 3; 993 } else if ((action.outer_tpid_action == bcmVlanTpidActionModify) && 994 (action.ot_outer == bcmVlanActionReplace) && 995 (action.ot_outer_pkt_prio == bcmVlanActionReplace)) { 996 997 *sd_tag_action_present = 4; 998 } else if ((action.outer_tpid_action == bcmVlanTpidActionNone) && 999 (action.ot_outer == bcmVlanActionReplace) && 1000 (action.ot_outer_pkt_prio == bcmVlanActionReplace)) { 1001 1002 *sd_tag_action_present = 5; 1003 } else if ((action.outer_tpid_action == bcmVlanTpidActionNone) && 1004 (action.ot_outer == bcmVlanActionNone) && 1005 (action.ot_outer_pkt_prio == bcmVlanActionReplace)) { 1006 1007 *sd_tag_action_present = 6; 1008 } else if ((action.outer_tpid_action == bcmVlanTpidActionModify) && 1009 (action.ot_outer == bcmVlanActionNone) && 1010 (action.ot_outer_pkt_prio == bcmVlanActionNone)) { 1011 1012 *sd_tag_action_present = 7; 1013 } else { 1014 /* default as 0 */ 1015 *sd_tag_action_present = 0; 1016 } 1017 1018 return BCM_E_NONE; 1019 } 1020 1021 /* 1022 * Function: 1023 * _bcm_td3_def_vlan_profile_get 1024 * 1025 * Purpose: 1026 * get vlan profile index to add vlan for untagged packet 1027 * 1028 * Parameters: 1029 * unit - (IN) BCM device number. 1030 * index - (IN, OUT) Profile index 1031 * 1032 * Returns: 1033 * BCM_E_XXXs 1034 */ 1035 int 1036 _bcm_td3_def_vlan_profile_get( 1037 int unit, 1038 uint32 *index) 1039 { 1040 int rv = BCM_E_NONE; 1041 bcm_vlan_action_set_t action; 1042 uint32 new_index = 0; 1043 1044 1045 bcm_vlan_action_set_t_init(&action); 1046 1047 1048 action.ut_outer = bcmVlanActionAdd; 1049 1050 rv = _bcm_trx_vlan_action_profile_entry_add(unit, &action, &new_index); 1051 if (rv != BCM_E_NONE) { 1052 return rv; 1053 } 1054 if (new_index != *index) { 1055 if ((*index != 0) && (*index != 1)) { 1056 rv = _bcm_trx_vlan_action_profile_entry_delete(unit, *index); 1057 } 1058 *index = new_index; 1059 } 1060 1061 return rv; 1062 } 1063 1064 /* 1065 * Function: 1066 * _bcm_td3_vlan_shared_vlan_enable_get 1067 * 1068 * Purpose: 1069 * get shared vlan enable status 1070 * 1071 * Parameters: 1072 * unit - (IN) BCM device number. 1073 * enable - (OUT) enable status 1074 * 1075 * Returns: 1076 * BCM_E_XXXs 1077 */ 1078 int 1079 _bcm_td3_vlan_shared_vlan_enable_get(int unit, int *enable) 1080 { 1081 bcm_vlan_info_t *vi = &vlan_info[unit]; 1082 *enable = vi->shared_vlan_enable; 1083 1084 return BCM_E_NONE; 1085 } 1086 1087 /* 1088 * Function: 1089 * _bcm_td3_vlan_shared_vlan_enable_set 1090 * 1091 * Purpose: 1092 * set shared vlan enable status 1093 * 1094 * Parameters: 1095 * unit - (IN) BCM device number. 1096 * enable - (IN) enable status 1097 * 1098 * Returns: 1099 * BCM_E_XXXs 1100 */ 1101 int 1102 _bcm_td3_vlan_shared_vlan_enable_set(int unit, int enable) 1103 { 1104 bcm_vlan_info_t *vi = &vlan_info[unit]; 1105 vi->shared_vlan_enable = enable ? 1 : 0; 1106 1107 return BCM_E_NONE; 1108 } 1109 1110 #endif /* BCM_TRIDENT3_SUPPORT */ 1111