flexflow_port.c (91445B)
1 /* 2 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 3 * 4 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 5 */ 6 7 8 #include <sal/core/libc.h> 9 #if defined(INCLUDE_L3) 10 11 #include <bcm/flow.h> 12 #include <bcm_int/esw/flow.h> 13 #include <bcm/error.h> 14 #include <soc/drv.h> 15 #include <soc/format.h> 16 #include <bcm_int/esw/vpn.h> 17 #include <bcm_int/esw/virtual.h> 18 #include <bcm_int/esw/trx.h> 19 #include <bcm_int/common/multicast.h> 20 #include <bcm_int/esw/trident2.h> 21 #include <bcm_int/esw/trident3.h> 22 #include <bcm_int/esw/vxlan.h> 23 #include <bcm_int/esw/trident2plus.h> 24 #include <bcm_int/esw/tomahawk.h> 25 #include <bcm_int/esw/xgs5.h> 26 #include <bcm_int/api_xlate_port.h> 27 #include <soc/esw/flow_db.h> 28 #include <soc/esw/cancun.h> 29 30 #define VIRTUAL_INFO(_unit_) (&_bcm_virtual_bk_info[_unit_]) 31 #define PORT_DEFAULT_ALL (BCM_FLOW_PORT_DEFAULT | BCM_FLOW_PORT_DEFAULT_L2GRE | \ 32 BCM_FLOW_PORT_DEFAULT_GPE | BCM_FLOW_PORT_DEFAULT_GENEVE) 33 34 STATIC int 35 _bcm_td3_flow_default_port_get(int unit, int vp, bcm_flow_port_t *flow_port); 36 STATIC int 37 _bcmi_esw_flow_port_get(int unit, bcm_vpn_t vpn, int vp, bcm_flow_port_t *flow_port); 38 39 /* Function: 40 * bcmi_esw_flow_vp_is_eline 41 * Purpose: 42 * Find if given FLOW VP is ELINE 43 * Parameters: 44 * unit - Device Number 45 * vp - FLOW VP 46 * isEline - Flag 47 * Returns: 48 * BCM_E_XXXX 49 * Assumes: 50 * l2vpn is valid 51 */ 52 53 int 54 bcmi_esw_flow_vp_is_eline( int unit, int vp, uint8 *isEline) 55 { 56 source_vp_entry_t svp; 57 vfi_entry_t vfi_entry; 58 int rv = BCM_E_PARAM; 59 int vfi_index; 60 61 if (vp == -1) { 62 return BCM_E_PARAM; 63 } 64 65 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeFlow)) { 66 return BCM_E_NOT_FOUND; 67 } 68 69 rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp); 70 if (rv < 0) { 71 return rv; 72 } 73 74 vfi_index = soc_SOURCE_VPm_field32_get(unit, &svp, VFIf); 75 BCM_IF_ERROR_RETURN 76 (READ_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry)); 77 78 /* Set the returned VPN id */ 79 if (soc_VFIm_field32_get(unit, &vfi_entry, PT2PT_ENf)) { 80 *isEline = 0x1; 81 } else { 82 *isEline = 0x0; 83 } 84 return BCM_E_NONE; 85 } 86 87 /* 88 * Function: 89 * _bcm_td3_flow_nexthop_glp_get 90 * Purpose: 91 * Get the modid, port, trunk values for a FLOW nexthop 92 * Returns: 93 * BCM_E_XXX 94 */ 95 STATIC int 96 _bcm_td3_flow_nexthop_glp_get(int unit, int nh_idx, 97 bcm_module_t *modid, bcm_port_t *port, bcm_trunk_t *trunk_id) 98 99 { 100 ing_l3_next_hop_entry_t ing_nh; 101 uint32 dt, dv; 102 103 BCM_IF_ERROR_RETURN (soc_mem_read(unit, 104 ING_L3_NEXT_HOPm, MEM_BLOCK_ANY, nh_idx, &ing_nh)); 105 106 dv = soc_mem_field32_dest_get(unit, 107 ING_L3_NEXT_HOPm, &ing_nh, DESTINATIONf, &dt); 108 if (dt == SOC_MEM_FIF_DEST_LAG) { 109 *trunk_id = dv & SOC_MEM_FIF_DGPP_TGID_MASK; 110 } else if (dt == SOC_MEM_FIF_DEST_DGPP) { 111 *port = (dv & SOC_MEM_FIF_DGPP_PORT_MASK); 112 *modid = (dv & SOC_MEM_FIF_DGPP_MOD_ID_MASK) >> 113 SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS; 114 } else if (dt == SOC_MEM_FIF_DEST_DVP) { 115 return BCM_E_NOT_FOUND; 116 } else { 117 return BCM_E_INTERNAL; 118 } 119 120 return BCM_E_NONE; 121 } 122 123 /* 124 * Function: 125 * _bcm_td3_flow_port_resolve 126 * Purpose: 127 * Get the modid, port, trunk values for a FLOW port 128 * Returns: 129 * BCM_E_XXX 130 */ 131 int 132 _bcm_td3_flow_port_resolve(int unit, bcm_gport_t flow_port_id, 133 bcm_if_t encap_id, bcm_module_t *modid, bcm_port_t *port, 134 bcm_trunk_t *trunk_id, int *id) 135 136 { 137 int rv = BCM_E_NONE; 138 egr_l3_next_hop_entry_t egr_nh; 139 ing_dvp_table_entry_t dvp; 140 int ecmp=0, nh_index=-1, nh_ecmp_index=-1, vp=-1; 141 uint32 hw_buf[SOC_MAX_MEM_FIELD_WORDS]; /* Buffer to read hw entry. */ 142 int idx, max_ent_count, base_idx; 143 144 rv = bcmi_esw_flow_check_init(unit); 145 if (rv < 0) { 146 return rv; 147 } 148 149 if (!BCM_GPORT_IS_FLOW_PORT(flow_port_id)) { 150 return (BCM_E_BADID); 151 } 152 153 vp = BCM_GPORT_FLOW_PORT_ID_GET(flow_port_id); 154 if (vp == -1) { 155 return BCM_E_PARAM; 156 } 157 158 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeFlow)) { 159 return BCM_E_NOT_FOUND; 160 } 161 BCM_IF_ERROR_RETURN (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp)); 162 ecmp = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMPf); 163 if (!ecmp) { 164 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, 165 NEXT_HOP_INDEXf); 166 BCM_IF_ERROR_RETURN(_bcm_td3_flow_nexthop_glp_get(unit, 167 nh_index, modid, port, trunk_id)); 168 } else { 169 /* Select the desired nhop from ECMP group - pointed by encap_id */ 170 nh_ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMP_PTRf); 171 BCM_IF_ERROR_RETURN( 172 soc_mem_read(unit, L3_ECMP_COUNTm, MEM_BLOCK_ANY, 173 nh_ecmp_index, hw_buf)); 174 175 if (soc_feature(unit, soc_feature_l3_ecmp_1k_groups)) { 176 max_ent_count = soc_mem_field32_get(unit, L3_ECMP_COUNTm, 177 hw_buf, COUNTf); 178 base_idx = soc_mem_field32_get(unit, L3_ECMP_COUNTm, 179 hw_buf, BASE_PTRf); 180 } else { 181 max_ent_count = soc_mem_field32_get(unit, L3_ECMP_COUNTm, 182 hw_buf, COUNT_0f); 183 base_idx = soc_mem_field32_get(unit, L3_ECMP_COUNTm, 184 hw_buf, BASE_PTR_0f); 185 } 186 max_ent_count++; /* Count is zero based. */ 187 188 if(encap_id == -1) { 189 BCM_IF_ERROR_RETURN( 190 soc_mem_read(unit, L3_ECMPm, MEM_BLOCK_ANY, 191 base_idx, hw_buf)); 192 nh_index = soc_mem_field32_get(unit, L3_ECMPm, 193 hw_buf, NEXT_HOP_INDEXf); 194 195 BCM_IF_ERROR_RETURN(_bcm_td3_flow_nexthop_glp_get(unit, 196 nh_index, modid, port, trunk_id)); 197 } else { 198 for (idx = 0; idx < max_ent_count; idx++) { 199 BCM_IF_ERROR_RETURN( 200 soc_mem_read(unit, L3_ECMPm, MEM_BLOCK_ANY, 201 (base_idx+idx), hw_buf)); 202 nh_index = soc_mem_field32_get(unit, L3_ECMPm, 203 hw_buf, NEXT_HOP_INDEXf); 204 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, 205 MEM_BLOCK_ANY, nh_index, &egr_nh)); 206 if (encap_id == soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, 207 &egr_nh, INTF_NUMf)) { 208 BCM_IF_ERROR_RETURN(_bcm_td3_flow_nexthop_glp_get(unit, 209 nh_index, modid, port, trunk_id)); 210 break; 211 } 212 } 213 } 214 } 215 *id = vp; 216 return rv; 217 } 218 219 /* 220 * Function: 221 * _bcm_td3_flow_port_cnt_update 222 * Purpose: 223 * Update port's VP count. 224 * Parameters: 225 * unit - (IN) SOC unit number. 226 * gport - (IN) GPORT ID. 227 * vp - (IN) Virtual port number. 228 * incr - (IN) If TRUE, increment VP count, else decrease VP count. 229 * Returns: 230 * BCM_X_XXX 231 */ 232 233 STATIC int 234 _bcm_td3_flow_port_cnt_update(int unit, bcm_gport_t gport, 235 int vp, int incr_decr_flag) 236 { 237 int mod_out=-1, port_out=-1, tgid_out=-1, vp_out=-1; 238 bcm_port_t local_member_array[SOC_MAX_NUM_PORTS]; 239 int local_member_count=0; 240 int idx=-1; 241 int mod_local=-1; 242 _bcm_port_info_t *port_info; 243 uint32 port_flags; 244 245 BCM_IF_ERROR_RETURN( 246 _bcm_td3_flow_port_resolve(unit, gport, -1, &mod_out, 247 &port_out, &tgid_out, &vp_out)); 248 249 if (vp_out == -1) { 250 return BCM_E_PARAM; 251 } 252 253 /* Update the physical port's SW state. If associated with a trunk, 254 * update each local physical port's SW state. 255 */ 256 257 if (BCM_TRUNK_INVALID != tgid_out) { 258 259 BCM_IF_ERROR_RETURN(_bcm_esw_trunk_local_members_get(unit, tgid_out, 260 SOC_MAX_NUM_PORTS, local_member_array, &local_member_count)); 261 262 for (idx = 0; idx < local_member_count; idx++) { 263 _bcm_port_info_access(unit, local_member_array[idx], &port_info); 264 if (incr_decr_flag) { 265 port_info->vp_count++; 266 } else { 267 port_info->vp_count--; 268 } 269 BCM_IF_ERROR_RETURN( 270 bcm_esw_port_vlan_member_get( 271 unit, local_member_array[idx], &port_flags)); 272 BCM_IF_ERROR_RETURN( 273 bcm_esw_port_vlan_member_set( 274 unit, local_member_array[idx], port_flags)); 275 } 276 } else { 277 #if defined(BCM_HGPROXY_COE_SUPPORT) 278 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 279 (_bcm_xgs5_subport_coe_mod_port_local(unit, mod_out, port_out))) { 280 BCM_IF_ERROR_RETURN( 281 _bcmi_coe_subport_mod_port_physical_port_get( 282 unit, mod_out, port_out, &port_out)); 283 mod_local = 1; 284 } else 285 #endif 286 { 287 BCM_IF_ERROR_RETURN( 288 _bcm_esw_modid_is_local(unit, mod_out, &mod_local)); 289 if (mod_local && soc_feature(unit, soc_feature_sysport_remap)) { 290 BCM_XLATE_SYSPORT_S2P(unit, &port_out); 291 } 292 } 293 if (mod_local) { 294 if (soc_feature(unit, soc_feature_sysport_remap)) { 295 BCM_XLATE_SYSPORT_S2P(unit, &port_out); 296 } 297 _bcm_port_info_access(unit, port_out, &port_info); 298 if (incr_decr_flag) { 299 port_info->vp_count++; 300 } else { 301 port_info->vp_count--; 302 } 303 BCM_IF_ERROR_RETURN( 304 bcm_esw_port_vlan_member_get( 305 unit, port_out, &port_flags)); 306 BCM_IF_ERROR_RETURN( 307 bcm_esw_port_vlan_member_set( 308 unit, port_out, port_flags)); 309 } 310 } 311 312 return BCM_E_NONE; 313 } 314 315 /* 316 * Function: 317 * _bcm_td3_flow_eline_vp_map_set 318 * Purpose: 319 * Set FLOW ELINE ports from VPN 320 * Parameters: 321 * unit - (IN) Device Number 322 * vpn - (IN) VPN instance ID 323 * Returns: 324 * BCM_E_XXX 325 */ 326 STATIC int 327 _bcm_td3_flow_eline_vp_map_set(int unit, int vfi_index, int vp1, int vp2) 328 { 329 vfi_entry_t vfi_entry; 330 int rv=BCM_E_NONE; 331 int num_vp=0; 332 333 if (!_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeFlow)) { 334 return BCM_E_NOT_FOUND; 335 } 336 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 337 338 BCM_IF_ERROR_RETURN 339 (READ_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry)); 340 341 if (soc_VFIm_field32_get(unit, &vfi_entry, PT2PT_ENf)) { 342 if ((vp1 > 0) && (vp1 < num_vp)) { 343 soc_VFIm_field32_set(unit, &vfi_entry, VP_0f, vp1); 344 } else { 345 return BCM_E_PARAM; 346 } 347 if ((vp2 > 0) && (vp2 < num_vp)) { 348 soc_VFIm_field32_set(unit, &vfi_entry, VP_1f, vp2); 349 } else { 350 return BCM_E_PARAM; 351 } 352 } else { 353 /* ELAN */ 354 return BCM_E_PARAM; 355 } 356 357 rv = WRITE_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry); 358 return rv; 359 } 360 /* 361 * Function: 362 * _bcm_td3_flow_eline_vp_map_get 363 * Purpose: 364 * Get FLOW ELINE ports from VPN 365 * Parameters: 366 * unit - (IN) Device Number 367 * vpn - (IN) VPN instance ID 368 * Returns: 369 * BCM_E_XXX 370 */ 371 372 STATIC int 373 _bcm_td3_flow_eline_vp_map_get(int unit, int vfi_index, int *vp1, int *vp2) 374 { 375 vfi_entry_t vfi_entry; 376 377 if (!_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeFlow)) { 378 return BCM_E_NOT_FOUND; 379 } 380 381 BCM_IF_ERROR_RETURN 382 (READ_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry)); 383 384 if (soc_VFIm_field32_get(unit, &vfi_entry, PT2PT_ENf)) { 385 *vp1 = soc_VFIm_field32_get(unit, &vfi_entry, VP_0f); 386 *vp2 = soc_VFIm_field32_get(unit, &vfi_entry, VP_1f); 387 return BCM_E_NONE; 388 } else { 389 return BCM_E_PARAM; 390 } 391 } 392 393 /* 394 * Function: 395 * _bcm_td3_flow_eline_vp_map_clear 396 * Purpose: 397 * Clear FLOW ELINE ports from VPN 398 * Parameters: 399 * unit - (IN) Device Number 400 * vpn - (IN) VPN instance ID 401 * Returns: 402 * BCM_E_XXX 403 */ 404 405 STATIC int 406 _bcm_td3_flow_eline_vp_map_clear(int unit, int vfi_index, int vp1, int vp2) 407 { 408 vfi_entry_t vfi_entry; 409 int rv=BCM_E_NONE; 410 int num_vp=0; 411 412 if (!_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeFlow)) { 413 return BCM_E_NOT_FOUND; 414 } 415 416 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 417 418 BCM_IF_ERROR_RETURN 419 (READ_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry)); 420 421 if (soc_VFIm_field32_get(unit, &vfi_entry, PT2PT_ENf)) { 422 if ((vp1 > 0) && (vp1 < num_vp)) { 423 soc_VFIm_field32_set(unit, &vfi_entry, VP_0f, 0); 424 } 425 if ((vp2 > 0) && (vp2 < num_vp)) { 426 soc_VFIm_field32_set(unit, &vfi_entry, VP_1f, 0); 427 } 428 } else { 429 /* ELAN */ 430 return BCM_E_PARAM; 431 } 432 rv = WRITE_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry); 433 return rv; 434 } 435 436 /* 437 * Function: 438 * _bcm_td3_flow_next_hop_set 439 * Purpose: 440 * Set FLOW NextHop Entry. 441 * Parameters: 442 * IN : Unit 443 * IN : nh_index 444 * Returns: 445 * BCM_E_XXX 446 */ 447 448 int 449 _bcm_td3_flow_next_hop_set(int unit, int nh_index, uint32 flags, int vp, int drop) 450 { 451 int rv = BCM_E_NONE; 452 ing_l3_next_hop_entry_t ing_nh; 453 bcm_port_t port = -1; 454 bcm_module_t modid = -1, local_modid = -1; 455 bcm_trunk_t tgid = -1; 456 int num_ports=0, idx=-1; 457 int old_nh_index=-1; 458 int replace=0; 459 int gport = 0; 460 _bcm_vp_info_t vp_info; 461 soc_mem_t hw_mem = ING_L3_NEXT_HOPm; 462 bcm_trunk_member_t *tmp_member_gports_array = NULL; 463 464 BCM_IF_ERROR_RETURN(soc_mem_read(unit, 465 hw_mem, MEM_BLOCK_ANY, nh_index, &ing_nh)); 466 soc_mem_field32_set(unit, hw_mem, &ing_nh, 467 ENTRY_TYPEf, _BCM_VXLAN_INGRESS_NEXT_HOP_ENTRY_TYPE); 468 if (SOC_MEM_FIELD_VALID(unit, hw_mem, MTU_SIZEf)) { 469 soc_mem_field32_set(unit, hw_mem, &ing_nh, MTU_SIZEf, 0x3fff); 470 } 471 BCM_IF_ERROR_RETURN( 472 soc_mem_write(unit, hw_mem, MEM_BLOCK_ALL, nh_index, &ing_nh)); 473 474 if (flags & BCM_L3_IPMC) { 475 egr_l3_next_hop_entry_t egr_nh; 476 int entry_type = 0; 477 int hw_mem = EGR_L3_NEXT_HOPm; 478 479 (void)_bcm_vp_info_get(unit, vp, &vp_info); 480 481 SOC_IF_ERROR_RETURN(soc_mem_read(unit, hw_mem, MEM_BLOCK_ALL, 482 nh_index, &egr_nh)); 483 entry_type = soc_mem_field32_get(unit, hw_mem, &egr_nh, DATA_TYPEf); 484 485 if (vp_info.flags & _BCM_VP_INFO_NETWORK_PORT) { /* network VP */ 486 487 /* most should be setup already */ 488 if (entry_type == _BCM_VXLAN_EGR_NEXT_HOP_L3MC_VIEW) { 489 soc_mem_field32_set(unit, hw_mem, &egr_nh, L3MC__HG_HDR_SELf, 490 1); 491 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 492 L3MC__L3_DROPf, drop ? 1 : 0); 493 SOC_IF_ERROR_RETURN(soc_mem_write(unit, hw_mem, 494 MEM_BLOCK_ALL, nh_index, &egr_nh)); 495 } else { 496 /* no change for all other views */ 497 } 498 } else { /* access VP */ 499 /* fixed view should use sd_tag view for access VP */ 500 if (!BCMI_L3_NH_FLEX_VIEW(entry_type)) { 501 if (entry_type != _BCM_VXLAN_EGR_NEXT_HOP_SDTAG_VIEW) { 502 /* first time setup */ 503 sal_memset(&egr_nh, 0, sizeof(egr_nh)); 504 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 505 DATA_TYPEf, _BCM_VXLAN_EGR_NEXT_HOP_SDTAG_VIEW); 506 } 507 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 508 SD_TAG__DVPf, vp); 509 SOC_IF_ERROR_RETURN(soc_mem_write(unit, hw_mem, 510 MEM_BLOCK_ALL, nh_index, &egr_nh)); 511 } else { 512 /* proper process for flex views should be done already */ 513 } 514 } 515 } else { /* Only for FLOW Unicast Nexthops */ 516 replace = flags & BCM_L3_REPLACE; 517 518 BCM_IF_ERROR_RETURN(_bcm_td3_flow_nexthop_glp_get(unit, 519 nh_index, &modid, &port, &tgid)); 520 521 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &local_modid)); 522 if (tgid != -1) { 523 BCM_IF_ERROR_RETURN(_bcm_trunk_id_validate(unit, tgid)); 524 rv = bcm_esw_trunk_get(unit, tgid, NULL, 0, NULL, &num_ports); 525 if (BCM_FAILURE(rv)) { 526 return BCM_E_PORT; 527 } 528 if (num_ports == 0) { 529 return BCM_E_NONE; 530 } 531 if(soc_feature(unit, soc_feature_egr_modport_to_nhi)) { 532 tmp_member_gports_array = sal_alloc( 533 sizeof(bcm_trunk_member_t) * num_ports, "tmp_member_gports_arry"); 534 if (tmp_member_gports_array == NULL) { 535 return BCM_E_MEMORY; 536 } 537 sal_memset(tmp_member_gports_array, 0, 538 sizeof(bcm_trunk_member_t) * num_ports); 539 rv = bcm_esw_trunk_get(unit, tgid, NULL, 540 num_ports, tmp_member_gports_array, &num_ports); 541 if (BCM_FAILURE(rv)) { 542 goto clean_up; 543 } 544 } 545 } else { 546 if (modid != local_modid) { 547 if (!soc_feature(unit, soc_feature_egr_modport_to_nhi)) { 548 /* Ignore EGR_PORT_TO_NHI_MAPPINGs */ 549 return BCM_E_NONE; 550 } 551 } 552 553 if(soc_feature(unit, soc_feature_egr_modport_to_nhi)) { 554 /* Alloc one trunk member size memory */ 555 tmp_member_gports_array = sal_alloc( 556 sizeof(bcm_trunk_member_t), "tmp_member_gports_arry"); 557 if (tmp_member_gports_array == NULL) { 558 return BCM_E_MEMORY; 559 } 560 sal_memset(tmp_member_gports_array, 0, 561 sizeof(bcm_trunk_member_t)); 562 BCM_GPORT_MODPORT_SET(gport, modid, port); 563 tmp_member_gports_array[num_ports++].gport = gport; 564 } 565 } 566 567 for (idx = 0; idx < num_ports; idx++) { 568 if(soc_feature(unit, soc_feature_egr_modport_to_nhi)) { 569 gport = tmp_member_gports_array[idx].gport; 570 } 571 572 rv = _bcm_trx_gport_to_nhi_get(unit, gport, &old_nh_index); 573 if (BCM_FAILURE(rv)) { 574 goto clean_up; 575 } 576 if (old_nh_index && !replace) { 577 if (old_nh_index != nh_index) { 578 /* Limitation: For TD/TR3/TD2, 579 VxLAN egress port can be configured with one NHI */ 580 rv = BCM_E_RESOURCE; 581 goto clean_up; 582 } 583 } else { 584 rv = _bcm_trx_gport_to_nhi_set(unit, gport, nh_index); 585 if (BCM_FAILURE(rv)) { 586 goto clean_up; 587 } 588 } 589 } 590 } 591 592 clean_up: 593 if (NULL != tmp_member_gports_array) { 594 sal_free(tmp_member_gports_array); 595 } 596 return rv; 597 } 598 599 /* 600 * Function: 601 * bcm_td3_flow_nexthop_reset 602 * Purpose: 603 * Reset VXLAN NextHop entry 604 * Parameters: 605 * IN : Unit 606 * IN : nh_index 607 * Returns: 608 * BCM_E_XXX 609 */ 610 611 STATIC int 612 _bcm_td3_flow_nexthop_reset(int unit, int nh_index) 613 { 614 int rv=BCM_E_NONE; 615 ing_l3_next_hop_entry_t ing_nh; 616 egr_l3_next_hop_entry_t egr_nh; 617 bcm_port_t port=0; 618 bcm_trunk_t tgid= BCM_TRUNK_INVALID; 619 int num_ports=0, idx=-1; 620 soc_mem_t hw_mem; 621 bcm_module_t modid=0, local_modid=0; 622 uint8 multicast_entry=0; 623 int old_nh_index=-1; 624 int gport = 0; 625 uint32 entry_type=0; 626 uint32 view_id; 627 uint32 action_set; 628 uint32 l3_intf; 629 int nh_index_out; 630 bcm_trunk_member_t *tmp_member_gports_array = NULL; 631 632 hw_mem = EGR_L3_NEXT_HOPm; 633 634 BCM_IF_ERROR_RETURN(soc_mem_read(unit, hw_mem, 635 MEM_BLOCK_ANY, nh_index, &egr_nh)); 636 637 if (SOC_MEM_FIELD_VALID(unit, hw_mem, DATA_TYPEf)) { 638 entry_type = soc_mem_field32_get(unit, hw_mem, &egr_nh, DATA_TYPEf); 639 } 640 641 if (BCMI_L3_NH_FLEX_VIEW(entry_type)) { 642 /* Get view id corresponding to the entry type. */ 643 rv = soc_flow_db_mem_to_view_id_get(unit, 644 EGR_L3_NEXT_HOPm, 645 SOC_FLOW_DB_KEY_TYPE_INVALID, 646 entry_type, 647 0, 648 NULL, 649 &view_id); 650 BCM_IF_ERROR_RETURN(rv); 651 652 if (SOC_MEM_FIELD_VALID(unit, view_id, INTF_ACTION_SETf)) { 653 action_set = soc_mem_field32_get(unit, view_id, &egr_nh, 654 INTF_ACTION_SETf); 655 656 l3_intf = soc_format_field32_get(unit, INTF_ACTION_SETfmt, 657 &action_set, INTF_PTRf); /* INTF_NUMf */ 658 659 /* determine if this is an IPMC entry from the l3 interface */ 660 _bcm_th_ipmc_l3_intf_next_hop_get(unit, l3_intf, 661 &nh_index_out); 662 if (nh_index_out == -2) { 663 multicast_entry = 1; 664 } 665 } 666 } 667 else if (_BCM_VXLAN_EGR_NEXT_HOP_L3MC_VIEW == entry_type) { 668 if (soc_feature(unit, soc_feature_egr_l3_next_hop_next_ptr)) { 669 if (0x1 == soc_mem_field32_get(unit, hw_mem, &egr_nh, 670 L3MC__NEXT_PTR_TYPEf)) { 671 multicast_entry = 1; /* Multicast NextHop */ 672 } 673 } 674 } 675 676 hw_mem = ING_L3_NEXT_HOPm; 677 BCM_IF_ERROR_RETURN(soc_mem_read(unit, hw_mem, 678 MEM_BLOCK_ANY, nh_index, &ing_nh)); 679 soc_mem_field32_set(unit, hw_mem, &ing_nh, 680 DROPf, 0x0); 681 soc_mem_field32_set(unit, hw_mem, &ing_nh, 682 ENTRY_TYPEf, 0x0); 683 BCM_IF_ERROR_RETURN(soc_mem_write(unit, hw_mem, 684 MEM_BLOCK_ALL, nh_index, &ing_nh)); 685 rv = _bcm_td3_flow_nexthop_glp_get(unit, 686 nh_index, &modid, &port, &tgid); 687 if (BCM_FAILURE(rv)) { 688 if (rv == BCM_E_NOT_FOUND) { 689 /* not a GLP, could be a DVP in riot case. No further process */ 690 return BCM_E_NONE; 691 } else { 692 return rv; 693 } 694 } 695 696 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get (unit, &local_modid)); 697 if (tgid != BCM_TRUNK_INVALID) { 698 rv = _bcm_trunk_id_validate(unit, tgid); 699 if (BCM_FAILURE(rv)) { 700 return BCM_E_PORT; 701 } 702 rv = bcm_esw_trunk_get(unit, tgid, NULL, 0, NULL, &num_ports); 703 if (BCM_FAILURE(rv)) { 704 return BCM_E_PORT; 705 } 706 if (num_ports == 0) { 707 return BCM_E_NONE; 708 } 709 710 if(soc_feature(unit, soc_feature_egr_modport_to_nhi)) { 711 tmp_member_gports_array = sal_alloc( 712 sizeof(bcm_trunk_member_t) * num_ports, "tmp_member_gports_arry"); 713 if (tmp_member_gports_array == NULL) { 714 return BCM_E_MEMORY; 715 } 716 sal_memset(tmp_member_gports_array, 0, 717 sizeof(bcm_trunk_member_t) * num_ports); 718 rv = bcm_esw_trunk_get(unit, tgid, NULL, 719 num_ports, tmp_member_gports_array, &num_ports); 720 if (BCM_FAILURE(rv)) { 721 goto clean_up; 722 } 723 } 724 } else { 725 if (modid != local_modid) { 726 if (!soc_feature(unit, soc_feature_egr_modport_to_nhi)) { 727 /* Ignore EGR_PORT_TO_NHI_MAPPINGs */ 728 return BCM_E_NONE; 729 } 730 } 731 if(soc_feature(unit, soc_feature_egr_modport_to_nhi)) { 732 /* Alloc one trunk member size memory */ 733 tmp_member_gports_array = sal_alloc( 734 sizeof(bcm_trunk_member_t), "tmp_member_gports_arry"); 735 if (tmp_member_gports_array == NULL) { 736 return BCM_E_MEMORY; 737 } 738 sal_memset(tmp_member_gports_array, 0, 739 sizeof(bcm_trunk_member_t)); 740 BCM_GPORT_MODPORT_SET(gport, modid, port); 741 tmp_member_gports_array[num_ports++].gport = gport; 742 } 743 } 744 745 if (!multicast_entry) { 746 for (idx = 0; idx < num_ports; idx++) { 747 if(soc_feature(unit, soc_feature_egr_modport_to_nhi)) { 748 gport = tmp_member_gports_array[idx].gport; 749 } 750 751 rv = _bcm_trx_gport_to_nhi_get(unit, gport, &old_nh_index); 752 if (BCM_FAILURE(rv)) { 753 goto clean_up; 754 } 755 if (old_nh_index == nh_index) { 756 rv = _bcm_trx_gport_to_nhi_set(unit, gport, 0); 757 if (BCM_FAILURE(rv)) { 758 goto clean_up; 759 } 760 } 761 } 762 } 763 764 clean_up: 765 if (NULL != tmp_member_gports_array) { 766 sal_free(tmp_member_gports_array); 767 } 768 return rv; 769 } 770 /* 771 * Function: 772 * _bcm_td3_flow_egress_reset 773 * Purpose: 774 * Reset Flow Egress NextHop 775 * Parameters: 776 * IN : Unit 777 * IN : nh_index 778 * Returns: 779 * BCM_E_XXX 780 */ 781 782 int 783 _bcm_td3_flow_egress_reset(int unit, int nh_index) 784 { 785 ing_l3_next_hop_entry_t ing_nh; 786 soc_mem_t hw_mem; 787 int rv=BCM_E_NONE; 788 789 hw_mem = ING_L3_NEXT_HOPm; 790 BCM_IF_ERROR_RETURN(soc_mem_read(unit, hw_mem, 791 MEM_BLOCK_ANY, nh_index, &ing_nh)); 792 soc_mem_field32_set(unit, hw_mem, &ing_nh, 793 ENTRY_TYPEf, 0x0); 794 if (SOC_MEM_FIELD_VALID(unit, ING_L3_NEXT_HOPm, MTU_SIZEf)) { 795 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 796 &ing_nh, MTU_SIZEf, 0x0); 797 } 798 BCM_IF_ERROR_RETURN(soc_mem_write(unit, hw_mem, 799 MEM_BLOCK_ALL, nh_index, &ing_nh)); 800 801 rv = _bcm_td3_flow_nexthop_reset(unit, nh_index); 802 return rv; 803 } 804 /* 805 * Function: 806 * _bcm_td3_flow_egress_get 807 * Purpose: 808 * Get FLOW Egress NextHop 809 * Parameters: 810 * IN : Unit 811 * IN : nh_index 812 * Returns: 813 * BCM_E_XXX 814 */ 815 816 int 817 _bcm_td3_flow_egress_get(int unit, bcm_l3_egress_t *egr, int nh_index) 818 { 819 int int_l3_flag; 820 int_l3_flag = BCM_XGS3_L3_ENT_FLAG(BCM_XGS3_L3_TBL_PTR(unit, next_hop), 821 nh_index); 822 if (int_l3_flag == _BCM_L3_FLOW_ONLY) { 823 egr->flags2 |= BCM_L3_FLOW_ONLY; 824 } 825 826 return BCM_E_NONE; 827 } 828 829 /* 830 * Function: 831 * _bcm_td3_flow_eline_vp_configure 832 * Purpose: 833 * Configure FLOW ELINE virtual port 834 * Parameters: 835 * unit - (IN) Device Number 836 * vpn - (IN) VPN instance ID 837 * Returns: 838 * BCM_E_XXX 839 */ 840 841 STATIC int 842 _bcm_td3_flow_eline_vp_configure (int unit, int vfi_index, int active_vp, 843 source_vp_entry_t *svp, int tpid_enable, bcm_flow_port_t *flow_port) 844 { 845 int rv = BCM_E_NONE; 846 int network_group=0; 847 848 /* Set SOURCE_VP */ 849 soc_SOURCE_VPm_field32_set(unit, svp, CLASS_IDf, 850 flow_port->if_class); 851 852 /* Default Split Horizon Group Id 853 * 0 - For Access Port;1 - For Network Port*/ 854 network_group = flow_port->network_group_id; 855 rv = _bcm_validate_splithorizon_network_group(unit, 856 flow_port->flags & BCM_FLOW_PORT_NETWORK, &network_group); 857 BCM_IF_ERROR_RETURN(rv); 858 if (flow_port->flags & BCM_FLOW_PORT_NETWORK) { 859 if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) { 860 soc_SOURCE_VPm_field32_set(unit, svp, NETWORK_GROUPf, 861 network_group); 862 } else { 863 soc_SOURCE_VPm_field32_set(unit, svp, NETWORK_PORTf, 1); 864 } 865 } else { 866 if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) { 867 soc_SOURCE_VPm_field32_set(unit, svp, NETWORK_GROUPf, 868 network_group); 869 } else { 870 soc_SOURCE_VPm_field32_set(unit, svp, NETWORK_PORTf, 0); 871 } 872 } 873 874 if (flow_port->flags & BCM_FLOW_PORT_SERVICE_TAGGED) { 875 soc_SOURCE_VPm_field32_set(unit, svp, SD_TAG_MODEf, 1); 876 soc_SOURCE_VPm_field32_set(unit, svp, TPID_ENABLEf, tpid_enable); 877 } else { 878 soc_SOURCE_VPm_field32_set(unit, svp, SD_TAG_MODEf, 0); 879 } 880 881 soc_SOURCE_VPm_field32_set(unit, svp, DISABLE_VLAN_CHECKSf, 1); 882 soc_SOURCE_VPm_field32_set(unit, svp, 883 ENTRY_TYPEf, _BCM_VXLAN_SOURCE_VP_TYPE_VFI); /* VFI Type */ 884 soc_SOURCE_VPm_field32_set(unit, svp, VFIf, vfi_index); 885 886 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, active_vp, svp); 887 if ((vfi_index != _BCM_FLOW_VFI_INVALID) && 888 (flow_port->flags & BCM_FLOW_PORT_NETWORK)) { 889 if ( BCM_E_NONE != soc_cancun_app_dest_entry_set (unit, SOURCE_VPm, 890 active_vp, ENTRY_TYPEf, CANCUN_APP__SOURCE_VP__No_Control_Word, 891 _BCM_VXLAN_SOURCE_VP_TYPE_VFI)) { 892 LOG_ERROR(BSL_LS_BCM_FLOW, 893 (BSL_META_U(unit,"SOURCE_VP cancun app cfg error\n"))); 894 } 895 } 896 897 return rv; 898 } 899 900 901 902 /* 903 * Function: 904 * _bcm_td3_flow_access_niv_pe_set 905 * Purpose: 906 * Set VXLAN Access virtual port which is of NIV/PE type 907 * Parameters: 908 * unit - (IN) Device Number 909 * vp - (IN) Access Virtual Port 910 * vfi - (IN) Virtial forwarding instance 911 * Returns: 912 * BCM_E_XXX 913 */ 914 915 STATIC int 916 _bcm_td3_flow_access_niv_pe_set (int unit, int vp, int vfi) 917 { 918 source_vp_entry_t svp; 919 int rv = BCM_E_PARAM; 920 921 rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp); 922 if (rv < 0) { 923 return rv; 924 } 925 926 if (vfi == _BCM_FLOW_VFI_INVALID) { 927 soc_SOURCE_VPm_field32_set(unit, &svp, 928 ENTRY_TYPEf, _BCM_VXLAN_SOURCE_VP_TYPE_INVALID); 929 } else { 930 /* Initialize VP parameters */ 931 soc_SOURCE_VPm_field32_set(unit, &svp, 932 ENTRY_TYPEf, _BCM_VXLAN_SOURCE_VP_TYPE_VFI); 933 } 934 soc_SOURCE_VPm_field32_set(unit, &svp, VFIf, vfi); 935 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp); 936 return rv; 937 } 938 939 /* 940 * Function: 941 * _bcm_td3_flow_access_niv_pe_reset 942 * Purpose: 943 * Reset FLOW Access virtual port which is of NIV/PE type 944 * Parameters: 945 * unit - (IN) Device Number 946 * vp - (IN) Access Virtual Port 947 * Returns: 948 * BCM_E_XXX 949 */ 950 951 STATIC int 952 _bcm_td3_flow_access_niv_pe_reset (int unit, int vp) 953 { 954 source_vp_entry_t svp; 955 956 BCM_IF_ERROR_RETURN(READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp)); 957 958 /* Initialize VP parameters */ 959 soc_SOURCE_VPm_field32_set(unit, &svp, 960 ENTRY_TYPEf, _BCM_VXLAN_SOURCE_VP_TYPE_VLAN); 961 soc_SOURCE_VPm_field32_set(unit, &svp, VFIf, 0); 962 BCM_IF_ERROR_RETURN(WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp)); 963 964 return BCM_E_NONE; 965 } 966 967 968 /* 969 * Function: 970 * bcm_td3_flow_default_port_add 971 * Purpose: 972 * Add FLOW port to a VPN 973 * Parameters: 974 * unit - (IN) Device Number 975 * vpn - (IN) VPN instance ID 976 * flow_port - (IN/OUT) flow_port information (OUT : flow_port_id) 977 * Returns: 978 * BCM_E_XXX 979 */ 980 981 STATIC int 982 _bcm_td3_flow_default_port_add(int unit, bcm_flow_port_t *flow_port, 983 int *vp_number) 984 { 985 source_vp_entry_t svp; 986 int rv = BCM_E_PARAM, vp=0, num_vp=0; 987 int network_group=0; 988 int cml_default_enable=0, cml_default_new=0, cml_default_move=0; 989 _bcm_vp_info_t vp_info; 990 991 _bcm_vp_info_init(&vp_info); 992 vp_info.vp_type = _bcmVpTypeFlow; 993 if(flow_port->flags & BCM_FLOW_PORT_NETWORK) { 994 vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT; 995 } 996 997 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 998 999 /* ======== Allocate/Get Virtual_Port =============== */ 1000 if (flow_port->flags & BCM_FLOW_PORT_REPLACE) { 1001 vp = BCM_GPORT_FLOW_PORT_ID_GET(flow_port->flow_port_id); 1002 if (vp == -1) { 1003 return BCM_E_PARAM; 1004 } 1005 1006 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeFlow)) { 1007 return BCM_E_NOT_FOUND; 1008 } 1009 rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp); 1010 if (rv < 0) { 1011 return rv; 1012 } 1013 1014 /* Decrement old-port's VP count */ 1015 rv = _bcm_td3_flow_port_cnt_update(unit, flow_port->flow_port_id, vp, FALSE); 1016 if (rv < 0) { 1017 return rv; 1018 } 1019 1020 } else if (flow_port->flags & BCM_FLOW_PORT_WITH_ID ) { 1021 if (!BCM_GPORT_IS_FLOW_PORT(flow_port->flow_port_id)) { 1022 return (BCM_E_BADID); 1023 } 1024 1025 vp = BCM_GPORT_FLOW_PORT_ID_GET(flow_port->flow_port_id); 1026 if (vp == -1) { 1027 return BCM_E_PARAM; 1028 } 1029 /* Vp index zero is reserved in function _bcm_virtual_init because of 1030 * HW restriction. 1031 */ 1032 if (vp >= num_vp || vp < 1) { 1033 return BCM_E_BADID; 1034 } 1035 if (_bcm_vp_used_get(unit, vp, _bcmVpTypeFlow)) { 1036 return BCM_E_EXISTS; 1037 } 1038 1039 BCM_IF_ERROR_RETURN(_bcm_vp_used_set(unit, vp, vp_info)); 1040 sal_memset(&svp, 0, sizeof(source_vp_entry_t)); 1041 } else { 1042 rv = _bcm_vp_alloc(unit, 0, (num_vp - 1), 1, SOURCE_VPm, vp_info, &vp); 1043 if (rv < 0) { 1044 return rv; 1045 } 1046 sal_memset(&svp, 0, sizeof(source_vp_entry_t)); 1047 BCM_IF_ERROR_RETURN(_bcm_vp_used_set(unit, vp, vp_info)); 1048 } 1049 1050 /* ======== Configure SVP/DVP Properties ========== */ 1051 soc_SOURCE_VPm_field32_set(unit, &svp, CLASS_IDf, 1052 flow_port->if_class); 1053 if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) { 1054 network_group = flow_port->network_group_id; 1055 rv = _bcm_validate_splithorizon_network_group(unit, 1056 flow_port->flags & BCM_FLOW_PORT_NETWORK, &network_group); 1057 BCM_IF_ERROR_RETURN(rv); 1058 soc_SOURCE_VPm_field32_set(unit, &svp, NETWORK_GROUPf, 1059 network_group); 1060 } else { 1061 soc_SOURCE_VPm_field32_set(unit, &svp, NETWORK_PORTf, 1); 1062 } 1063 1064 soc_SOURCE_VPm_field32_set(unit, &svp, 1065 ENTRY_TYPEf, _BCM_VXLAN_SOURCE_VP_TYPE_VFI); 1066 1067 /* Keep CML in the replace operation. It may be set by bcm_td2_vxlan_port_learn_set before */ 1068 if (!(flow_port->flags & BCM_FLOW_PORT_REPLACE)) { 1069 rv = _bcm_vp_default_cml_mode_get (unit, 1070 &cml_default_enable, &cml_default_new, 1071 &cml_default_move); 1072 if (rv < 0) { 1073 return rv; 1074 } 1075 1076 if (cml_default_enable) { 1077 /* Set the CML to default values */ 1078 soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_NEWf, cml_default_new); 1079 soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_MOVEf, cml_default_move); 1080 } else { 1081 /* Set the CML to PVP_CML_SWITCH by default (hw learn and forward) */ 1082 soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_NEWf, 0x8); 1083 soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_MOVEf, 0x8); 1084 } 1085 } 1086 if (soc_mem_field_valid(unit, SOURCE_VPm, DISABLE_VLAN_CHECKSf)) { 1087 if (!soc_feature(unit, soc_feature_vlan_vfi_membership)) { 1088 soc_SOURCE_VPm_field32_set(unit, &svp, DISABLE_VLAN_CHECKSf, 1); 1089 } 1090 } 1091 1092 /* Configure VXLAN_DEFAULT_NETWORK_SVPr.SVP */ 1093 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp); 1094 BCM_IF_ERROR_RETURN(rv); 1095 1096 if ( BCM_E_NONE != soc_cancun_app_dest_entry_set (unit, SOURCE_VPm, 1097 vp, ENTRY_TYPEf, CANCUN_APP__SOURCE_VP__No_Control_Word, 1098 _BCM_VXLAN_SOURCE_VP_TYPE_VFI)) { 1099 LOG_ERROR(BSL_LS_BCM_FLOW, 1100 (BSL_META_U(unit,"SOURCE_VP cancun app cfg error\n"))); 1101 } 1102 1103 BCM_GPORT_FLOW_PORT_ID_SET(flow_port->flow_port_id, vp); 1104 1105 /* Increment new-port's VP count */ 1106 rv = _bcm_td3_flow_port_cnt_update(unit, flow_port->flow_port_id, vp, TRUE); 1107 BCM_IF_ERROR_RETURN(rv); 1108 *vp_number = vp; 1109 return rv; 1110 } 1111 1112 /* 1113 * Function: 1114 * _bcm_td3_flow_default_port_delete 1115 * Purpose: 1116 * Delete FLOW Default port from a VPN 1117 * Parameters: 1118 * unit - (IN) Device Number 1119 * vpn - (IN) VPN instance ID 1120 * flow_port_id - (IN) vxlan port information 1121 * Returns: 1122 * BCM_E_XXX 1123 */ 1124 1125 int 1126 _bcm_td3_flow_default_port_delete(int unit, bcm_vpn_t vpn, int vp) 1127 { 1128 source_vp_entry_t svp; 1129 int rv = BCM_E_UNAVAIL; 1130 int vfi_index= -1; 1131 bcm_gport_t flow_port_id; 1132 1133 if ( vpn != BCM_FLOW_VPN_INVALID) { 1134 _BCM_FLOW_VPN_GET(vfi_index, _BCM_FLOW_VPN_TYPE_ELAN, vpn); 1135 if (!_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeFlow)) { 1136 return BCM_E_NOT_FOUND; 1137 } 1138 } 1139 1140 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeFlow)) { 1141 return BCM_E_NOT_FOUND; 1142 } 1143 1144 /* Set FLOW port ID */ 1145 BCM_GPORT_FLOW_PORT_ID_SET(flow_port_id, vp); 1146 1147 /* Clear the SVP and DVP table entries */ 1148 sal_memset(&svp, 0, sizeof(source_vp_entry_t)); 1149 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp); 1150 if (rv < 0) { 1151 return rv; 1152 } 1153 1154 /* Decrement port's VP count */ 1155 rv = _bcm_td3_flow_port_cnt_update(unit, flow_port_id, vp, FALSE); 1156 if (rv < 0) { 1157 return rv; 1158 } 1159 1160 /* Free the VP */ 1161 (void) _bcm_vp_free(unit, _bcmVpTypeFlow, 1, vp); 1162 1163 return rv; 1164 1165 } 1166 1167 /* 1168 * Function: 1169 * _bcm_td3_flow_eline_port_add 1170 * Purpose: 1171 * Add FLOW ELINE port to a VPN 1172 * Parameters: 1173 * unit - (IN) Device Number 1174 * vpn - (IN) VPN instance ID 1175 * flow_port - (IN/OUT) FLOW port information (OUT : flow_port_id) 1176 * Returns: 1177 * BCM_E_XXX 1178 */ 1179 1180 STATIC int 1181 _bcm_td3_flow_eline_port_add(int unit, bcm_vpn_t vpn, bcm_flow_port_t *flow_port) 1182 { 1183 int active_vp = 0; /* default VP */ 1184 source_vp_entry_t svp1, svp2; 1185 uint8 vp_valid_flag = 0; 1186 int tpid_enable = 0, tpid_index=-1; 1187 int rv = BCM_E_PARAM; 1188 int num_vp=0; 1189 int vp1=-1, vp2=-1, vfi_index= -1; 1190 _bcm_vp_info_t vp_info; 1191 1192 _bcm_vp_info_init(&vp_info); 1193 vp_info.vp_type = _bcmVpTypeFlow; 1194 1195 if ( vpn != BCM_FLOW_VPN_INVALID) { 1196 _BCM_FLOW_VPN_GET(vfi_index, _BCM_FLOW_VPN_TYPE_ELINE, vpn); 1197 if (!_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeFlow)) { 1198 return BCM_E_NOT_FOUND; 1199 } 1200 } else { 1201 vfi_index = _BCM_FLOW_VFI_INVALID; 1202 } 1203 1204 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 1205 if ( vpn != BCM_FLOW_VPN_INVALID) { 1206 1207 /* ---- Read in current table values for VP1 and VP2 ----- */ 1208 (void) _bcm_td3_flow_eline_vp_map_get (unit, vfi_index, &vp1, &vp2); 1209 1210 if (_bcm_vp_used_get(unit, vp1, _bcmVpTypeFlow)) { 1211 BCM_IF_ERROR_RETURN ( 1212 READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp1, &svp1)); 1213 if (soc_SOURCE_VPm_field32_get(unit, &svp1, ENTRY_TYPEf) == 0x1) { 1214 vp_valid_flag |= 0x1; /* -- VP1 Valid ----- */ 1215 } 1216 } 1217 1218 if (_bcm_vp_used_get(unit, vp2, _bcmVpTypeFlow)) { 1219 BCM_IF_ERROR_RETURN ( 1220 READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp2, &svp2)); 1221 if (soc_SOURCE_VPm_field32_get(unit, &svp2, ENTRY_TYPEf) == 0x1) { 1222 vp_valid_flag |= 0x2; /* -- VP2 Valid ----- */ 1223 } 1224 } 1225 1226 if (flow_port->flags & BCM_FLOW_PORT_REPLACE) { 1227 active_vp = BCM_GPORT_FLOW_PORT_ID_GET(flow_port->flow_port_id); 1228 if (active_vp == -1) { 1229 return BCM_E_PARAM; 1230 } 1231 if (!_bcm_vp_used_get(unit, active_vp, _bcmVpTypeFlow)) { 1232 return BCM_E_NOT_FOUND; 1233 } 1234 /* Decrement old-port's VP count */ 1235 rv = _bcm_td3_flow_port_cnt_update(unit, flow_port->flow_port_id, 1236 active_vp, FALSE); 1237 if (rv < 0) { 1238 return rv; 1239 } 1240 } 1241 } 1242 1243 switch (vp_valid_flag) { 1244 1245 case 0x0: /* No VP is valid */ 1246 if (flow_port->flags & BCM_FLOW_PORT_REPLACE) { 1247 return BCM_E_NOT_FOUND; 1248 } 1249 1250 if (flow_port->flags & BCM_FLOW_PORT_WITH_ID) { 1251 vp1 = BCM_GPORT_FLOW_PORT_ID_GET(flow_port->flow_port_id); 1252 if (vp1 == -1) { 1253 return BCM_E_PARAM; 1254 } 1255 1256 if (_bcm_vp_used_get(unit, vp1, _bcmVpTypeFlow)) { 1257 return BCM_E_EXISTS; 1258 } 1259 if (vp1 >= num_vp) { 1260 return (BCM_E_BADID); 1261 } 1262 vp_info.flags &= ~(_BCM_VP_INFO_NETWORK_PORT); 1263 BCM_IF_ERROR_RETURN(_bcm_vp_used_set(unit, vp1, vp_info)); 1264 1265 } else { 1266 1267 /* No entries are used, allocate a new VP index for VP1 */ 1268 1269 vp_info.flags &= ~(_BCM_VP_INFO_NETWORK_PORT); 1270 rv = _bcm_vp_alloc(unit, 0, (num_vp - 1), 1, SOURCE_VPm, vp_info, &vp1); 1271 if (rv < 0) { 1272 return rv; 1273 } 1274 /* Allocate a new VP index for VP2 */ 1275 vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT; 1276 rv = _bcm_vp_alloc(unit, 0, (num_vp - 1), 1, SOURCE_VPm, vp_info, &vp2); 1277 if (rv < 0) { 1278 (void) _bcm_vp_free(unit, _bcmVpTypeFlow, 1, vp1); 1279 return rv; 1280 } 1281 } 1282 1283 active_vp = vp1; 1284 vp_valid_flag = 1; 1285 sal_memset(&svp1, 0, sizeof(source_vp_entry_t)); 1286 sal_memset(&svp2, 0, sizeof(source_vp_entry_t)); 1287 (void) _bcm_td3_flow_eline_vp_map_set(unit, vfi_index, vp1, vp2); 1288 break; 1289 1290 1291 case 0x1: /* Only VP1 is valid */ 1292 if (flow_port->flags & BCM_FLOW_PORT_REPLACE) { 1293 if (active_vp != vp1) { 1294 return BCM_E_NOT_FOUND; 1295 } 1296 } else if (flow_port->flags & BCM_FLOW_PORT_WITH_ID) { 1297 vp2 = BCM_GPORT_FLOW_PORT_ID_GET(flow_port->flow_port_id); 1298 if (vp2 == -1) { 1299 return BCM_E_PARAM; 1300 } 1301 1302 if (_bcm_vp_used_get(unit, vp2, _bcmVpTypeFlow)) { 1303 return BCM_E_EXISTS; 1304 } 1305 if (vp2 >= num_vp) { 1306 return (BCM_E_BADID); 1307 } 1308 vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT; 1309 BCM_IF_ERROR_RETURN(_bcm_vp_used_set(unit, vp2, vp_info)); 1310 1311 active_vp = vp2; 1312 } else { 1313 active_vp = vp2; 1314 vp_valid_flag = 3; 1315 sal_memset(&svp2, 0, sizeof(source_vp_entry_t)); 1316 } 1317 1318 (void) _bcm_td3_flow_eline_vp_map_set(unit, vfi_index, vp1, vp2); 1319 break; 1320 1321 1322 1323 case 0x2: /* Only VP2 is valid */ 1324 if (flow_port->flags & BCM_FLOW_PORT_REPLACE) { 1325 if (active_vp != vp2) { 1326 return BCM_E_NOT_FOUND; 1327 } 1328 } else if (flow_port->flags & BCM_FLOW_PORT_WITH_ID) { 1329 vp1 = BCM_GPORT_FLOW_PORT_ID_GET(flow_port->flow_port_id); 1330 if (vp1 == -1) { 1331 return BCM_E_PARAM; 1332 } 1333 1334 if (_bcm_vp_used_get(unit, vp1, _bcmVpTypeFlow)) { 1335 return BCM_E_EXISTS; 1336 } 1337 if (vp1 >= num_vp) { 1338 return (BCM_E_BADID); 1339 } 1340 vp_info.flags &= ~(_BCM_VP_INFO_NETWORK_PORT); 1341 BCM_IF_ERROR_RETURN(_bcm_vp_used_set(unit, vp1, vp_info)); 1342 active_vp = vp1; 1343 1344 } else { 1345 active_vp = vp1; 1346 vp_valid_flag = 3; 1347 sal_memset(&svp1, 0, sizeof(source_vp_entry_t)); 1348 } 1349 1350 (void) _bcm_td3_flow_eline_vp_map_set(unit, vfi_index, vp1, vp2); 1351 break; 1352 1353 1354 1355 case 0x3: /* VP1 and VP2 are valid */ 1356 if (!(flow_port->flags & BCM_FLOW_PORT_REPLACE)) { 1357 return BCM_E_FULL; 1358 } 1359 break; 1360 } 1361 1362 if (active_vp == -1) { 1363 return BCM_E_CONFIG; 1364 } 1365 1366 /* Set FLOW port ID */ 1367 if (!(flow_port->flags & BCM_FLOW_PORT_REPLACE)) { 1368 BCM_GPORT_FLOW_PORT_ID_SET(flow_port->flow_port_id, active_vp); 1369 } 1370 1371 /* ======== Configure Service-Tag Properties =========== */ 1372 if (flow_port->flags & BCM_FLOW_PORT_SERVICE_TAGGED) { 1373 rv = _bcm_fb2_outer_tpid_lkup(unit, flow_port->egress_service_tpid, 1374 &tpid_index); 1375 if (rv < 0) { 1376 goto flow_cleanup; 1377 } 1378 tpid_enable = (1 << tpid_index); 1379 } 1380 1381 /* ======== Configure SVP Property ========== */ 1382 if (active_vp == vp1) { 1383 rv = _bcm_td3_flow_eline_vp_configure (unit, vfi_index, active_vp, &svp1, 1384 tpid_enable, flow_port); 1385 } else if (active_vp == vp2) { 1386 rv = _bcm_td3_flow_eline_vp_configure (unit, vfi_index, active_vp, &svp2, 1387 tpid_enable, flow_port); 1388 } 1389 if (rv < 0) { 1390 goto flow_cleanup; 1391 } 1392 1393 /* match API 1394 rv = _bcm_td2_vxlan_match_add(unit, vxlan_port, active_vp, vpn); 1395 if (rv < 0) { 1396 goto vxlan_cleanup; 1397 } 1398 */ 1399 1400 /* Increment new-port's VP count */ 1401 rv = _bcm_td3_flow_port_cnt_update(unit, flow_port->flow_port_id, active_vp, TRUE); 1402 if (rv < 0) { 1403 goto flow_cleanup; 1404 } 1405 1406 /* Set FLOW port ID */ 1407 if (!(flow_port->flags & BCM_FLOW_PORT_REPLACE)) { 1408 BCM_GPORT_FLOW_PORT_ID_SET(flow_port->flow_port_id, active_vp); 1409 } 1410 1411 flow_cleanup: 1412 if (rv < 0) { 1413 if (tpid_enable) { 1414 (void) _bcm_fb2_outer_tpid_entry_delete(unit, tpid_index); 1415 } 1416 /* Free the VP's */ 1417 if (vp_valid_flag) { 1418 if (vp1 != -1) { 1419 (void) _bcm_vp_free(unit, _bcmVpTypeFlow, 1, vp1); 1420 } 1421 if (vp2 != -1) { 1422 (void) _bcm_vp_free(unit, _bcmVpTypeFlow, 1, vp2); 1423 } 1424 } 1425 } 1426 return rv; 1427 } 1428 1429 /* 1430 * Function: 1431 * _bcm_td3_flow_elan_port_add 1432 * Purpose: 1433 * Add FLOW ELAN port to a VPN 1434 * Parameters: 1435 * unit - (IN) Device Number 1436 * vpn - (IN) VPN instance ID 1437 * flow_port - (IN/OUT) flow port information (OUT : flow_port_id) 1438 * Returns: 1439 * BCM_E_XXX 1440 */ 1441 1442 STATIC int 1443 _bcm_td3_flow_elan_port_add(int unit, bcm_vpn_t vpn, bcm_flow_port_t *flow_port) 1444 { 1445 int vp, num_vp, vfi=0; 1446 source_vp_entry_t svp; 1447 source_vp_2_entry_t svp2; 1448 uint32 tpid_enable = 0; 1449 int tpid_index=-1; 1450 int rv = BCM_E_PARAM; 1451 int cml_default_enable=0, cml_default_new=0, cml_default_move=0; 1452 _bcm_vp_info_t vp_info; 1453 int network_group=0; 1454 uint32 svp1[SOC_MAX_MEM_WORDS]; 1455 1456 if (vpn != BCM_FLOW_VPN_INVALID) { 1457 _BCM_FLOW_VPN_GET(vfi, _BCM_FLOW_VPN_TYPE_ELAN, vpn); 1458 if (!_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeFlow)) { 1459 return BCM_E_NOT_FOUND; 1460 } 1461 } else { 1462 vfi = _BCM_FLOW_VFI_INVALID; 1463 } 1464 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 1465 1466 _bcm_vp_info_init(&vp_info); 1467 vp_info.vp_type = _bcmVpTypeFlow; 1468 if (flow_port->flags & BCM_FLOW_PORT_NETWORK) { 1469 vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT; 1470 } 1471 1472 /* ======== Allocate/Get Virtual_Port =============== */ 1473 if (flow_port->flags & BCM_FLOW_PORT_REPLACE) { 1474 if (BCM_GPORT_IS_NIV_PORT(flow_port->flow_port_id) || 1475 BCM_GPORT_IS_EXTENDER_PORT(flow_port->flow_port_id)) { 1476 if (BCM_GPORT_IS_NIV_PORT(flow_port->flow_port_id)) { 1477 vp = BCM_GPORT_NIV_PORT_ID_GET((flow_port->flow_port_id)); 1478 } else if (BCM_GPORT_IS_EXTENDER_PORT(flow_port->flow_port_id)) { 1479 vp = BCM_GPORT_EXTENDER_PORT_ID_GET((flow_port->flow_port_id)); 1480 } 1481 rv = _bcm_td3_flow_access_niv_pe_set (unit, vp, vfi); 1482 if (BCM_SUCCESS(rv)) { 1483 /* Set FLOW port ID */ 1484 BCM_GPORT_FLOW_PORT_ID_SET(flow_port->flow_port_id, vp); 1485 rv = _bcm_vp_used_set(unit, vp, vp_info); 1486 } 1487 return rv; 1488 } else if (BCM_GPORT_IS_TRUNK(flow_port->flow_port_id)) { 1489 bcm_trunk_member_t trunk_member; 1490 int port_count = 0; 1491 bcm_trunk_t tid = 0; 1492 int tid_is_vp_lag = FALSE; 1493 tid = BCM_GPORT_TRUNK_GET(flow_port->flow_port_id); 1494 BCM_IF_ERROR_RETURN( 1495 _bcm_esw_trunk_id_is_vp_lag(unit, tid, &tid_is_vp_lag)); 1496 if (tid_is_vp_lag) { 1497 BCM_IF_ERROR_RETURN( 1498 bcm_td2_vp_lag_get(unit, tid, NULL, 1, 1499 &trunk_member, &port_count)); 1500 if (BCM_GPORT_IS_NIV_PORT(trunk_member.gport) || 1501 BCM_GPORT_IS_EXTENDER_PORT(trunk_member.gport)) { 1502 BCM_IF_ERROR_RETURN( 1503 _bcm_esw_trunk_tid_to_vp_lag_vp(unit, tid, &vp)); 1504 rv = _bcm_td3_flow_access_niv_pe_set(unit, vp, vfi); 1505 if (BCM_SUCCESS(rv)) { 1506 rv = _bcm_vp_used_set(unit, vp, vp_info); 1507 } 1508 return rv; 1509 } 1510 } 1511 } 1512 1513 vp = BCM_GPORT_FLOW_PORT_ID_GET(flow_port->flow_port_id); 1514 if (vp == -1) { 1515 return BCM_E_PARAM; 1516 } 1517 1518 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeFlow)) { 1519 return BCM_E_NOT_FOUND; 1520 } 1521 1522 BCM_IF_ERROR_RETURN(READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp)); 1523 1524 BCM_IF_ERROR_RETURN(READ_SVP_ATTRS_1m(unit, MEM_BLOCK_ANY, vp, &svp1)); 1525 1526 BCM_IF_ERROR_RETURN(READ_SOURCE_VP_2m(unit, MEM_BLOCK_ANY, vp, &svp2)); 1527 1528 /* Decrement old-port's VP count */ 1529 BCM_IF_ERROR_RETURN(_bcm_td3_flow_port_cnt_update( 1530 unit, flow_port->flow_port_id, vp, FALSE)); 1531 } else if (flow_port->flags & BCM_FLOW_PORT_WITH_ID ) { 1532 if (!BCM_GPORT_IS_FLOW_PORT(flow_port->flow_port_id)) { 1533 return (BCM_E_BADID); 1534 } 1535 1536 vp = BCM_GPORT_FLOW_PORT_ID_GET(flow_port->flow_port_id); 1537 if (vp == -1) { 1538 return BCM_E_PARAM; 1539 } 1540 /* Vp index zero is reserved in function _bcm_virtual_init because of 1541 * HW restriction. 1542 */ 1543 if (vp >= num_vp || vp < 1) { 1544 return BCM_E_BADID; 1545 } 1546 if (_bcm_vp_used_get(unit, vp, _bcmVpTypeAny)) { 1547 return BCM_E_EXISTS; 1548 } 1549 BCM_IF_ERROR_RETURN(_bcm_vp_used_set(unit, vp, vp_info)); 1550 1551 sal_memset(&svp, 0, sizeof(source_vp_entry_t)); 1552 1553 sal_memset(svp1, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS); 1554 1555 sal_memset(&svp2, 0, sizeof(source_vp_2_entry_t)); 1556 } else { 1557 /* allocate a new VP index */ 1558 BCM_IF_ERROR_RETURN(_bcm_vp_alloc 1559 (unit, 0, (num_vp - 1), 1, SOURCE_VPm, vp_info, &vp)); 1560 BCM_GPORT_FLOW_PORT_ID_SET(flow_port->flow_port_id, vp); 1561 1562 sal_memset(&svp, 0, sizeof(source_vp_entry_t)); 1563 1564 sal_memset(svp1, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS); 1565 1566 sal_memset(&svp2, 0, sizeof(source_vp_2_entry_t)); 1567 } 1568 1569 /* ======== Configure Service-Tag Properties =========== */ 1570 if (flow_port->flags & BCM_FLOW_PORT_SERVICE_TAGGED) { 1571 rv = _bcm_fb2_outer_tpid_lkup(unit, 1572 flow_port->egress_service_tpid, &tpid_index); 1573 _BCM_FLOW_CLEANUP(rv) 1574 1575 tpid_enable = (1 << tpid_index); 1576 soc_SOURCE_VPm_field32_set(unit, &svp, SD_TAG_MODEf, 1); 1577 soc_SVP_ATTRS_1m_field_set(unit, &svp1, TPID_ENABLEf, &tpid_enable); 1578 } else { 1579 soc_SOURCE_VPm_field32_set(unit, &svp, SD_TAG_MODEf, 0); 1580 } 1581 1582 /* ======== Configure SVP/DVP Properties ========== */ 1583 soc_SOURCE_VPm_field32_set(unit, &svp, CLASS_IDf, flow_port->if_class); 1584 soc_SOURCE_VPm_field32_set(unit, &svp, ENTRY_TYPEf, _BCM_VXLAN_SOURCE_VP_TYPE_VFI); 1585 1586 /* Default Split Horizon Group Id 1587 * 0 - For Access Port;1 - For Network Port*/ 1588 network_group = flow_port->network_group_id; 1589 rv = _bcm_validate_splithorizon_network_group(unit, 1590 flow_port->flags & BCM_FLOW_PORT_NETWORK, &network_group); 1591 BCM_IF_ERROR_RETURN(rv); 1592 if (flow_port->flags & BCM_FLOW_PORT_NETWORK) { 1593 if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) { 1594 soc_SOURCE_VPm_field32_set(unit, &svp, NETWORK_GROUPf, 1595 network_group); 1596 } else { 1597 soc_SOURCE_VPm_field32_set(unit, &svp, NETWORK_PORTf, 1); 1598 } 1599 } else { 1600 if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) { 1601 soc_SOURCE_VPm_field32_set(unit, &svp, NETWORK_GROUPf, 1602 network_group); 1603 } else { 1604 soc_SOURCE_VPm_field32_set(unit, &svp, NETWORK_PORTf, 0); 1605 } 1606 } 1607 soc_SOURCE_VPm_field32_set(unit, &svp, VFIf, vfi); 1608 /* Keep CML in the replace operation. It may be set by bcm_td2_vxlan_port_learn_set before */ 1609 if (!(flow_port->flags & BCM_FLOW_PORT_REPLACE)) { 1610 rv = _bcm_vp_default_cml_mode_get (unit, &cml_default_enable, 1611 &cml_default_new, &cml_default_move); 1612 _BCM_FLOW_CLEANUP(rv) 1613 1614 if (cml_default_enable) { 1615 /* Set the CML to default values */ 1616 soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_NEWf, cml_default_new); 1617 soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_MOVEf, cml_default_move); 1618 } else { 1619 /* Set the CML to PVP_CML_SWITCH by default (hw learn and forward) */ 1620 soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_NEWf, 0x8); 1621 soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_MOVEf, 0x8); 1622 } 1623 } 1624 if (soc_mem_field_valid(unit, SOURCE_VPm, DISABLE_VLAN_CHECKSf)) { 1625 if (!soc_feature(unit, soc_feature_vlan_vfi_membership)) { 1626 soc_SOURCE_VPm_field32_set(unit, &svp, DISABLE_VLAN_CHECKSf, 1); 1627 } 1628 } 1629 1630 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp); 1631 1632 _BCM_FLOW_CLEANUP(WRITE_SVP_ATTRS_1m(unit, MEM_BLOCK_ALL, vp, &svp1)); 1633 1634 _BCM_FLOW_CLEANUP(WRITE_SOURCE_VP_2m(unit, MEM_BLOCK_ALL, vp, &svp2)); 1635 1636 if ((vfi != _BCM_FLOW_VFI_INVALID) && 1637 (flow_port->flags & BCM_FLOW_PORT_NETWORK)) { 1638 if ( BCM_E_NONE != soc_cancun_app_dest_entry_set (unit, SOURCE_VPm, 1639 vp, ENTRY_TYPEf, CANCUN_APP__SOURCE_VP__No_Control_Word, 1640 _BCM_VXLAN_SOURCE_VP_TYPE_VFI)) { 1641 LOG_ERROR(BSL_LS_BCM_FLOW, 1642 (BSL_META_U(unit,"SOURCE_VP cancun app cfg error\n"))); 1643 } 1644 } 1645 1646 _BCM_FLOW_CLEANUP(rv) 1647 1648 /* Configure VP match criteria */ 1649 /*rv = _bcm_td2_vxlan_match_add(unit, vxlan_port, vp, vpn);*/ /* for match API */ 1650 _BCM_FLOW_CLEANUP(rv) 1651 1652 /* Increment new-port's VP count */ 1653 rv = _bcm_td3_flow_port_cnt_update(unit, flow_port->flow_port_id, vp, TRUE); 1654 _BCM_FLOW_CLEANUP(rv) 1655 1656 return BCM_E_NONE; 1657 1658 cleanup: 1659 if (tpid_enable) { 1660 (void) _bcm_fb2_outer_tpid_entry_delete(unit, tpid_index); 1661 } 1662 if (!(flow_port->flags & BCM_FLOW_PORT_REPLACE)) { 1663 (void) _bcm_vp_free(unit, _bcmVpTypeFlow, 1, vp); 1664 } 1665 return rv; 1666 } 1667 1668 /* 1669 * Function: 1670 * _bcm_td3_flow_eline_port_delete 1671 * Purpose: 1672 * Delete FLOW ELINE port from a VPN 1673 * Parameters: 1674 * unit - (IN) Device Number 1675 * vpn - (IN) VPN instance ID 1676 * flow_port_id - (IN) flow port information 1677 * Returns: 1678 * BCM_E_XXX 1679 */ 1680 1681 int 1682 _bcm_td3_flow_eline_port_delete(int unit, bcm_vpn_t vpn, int active_vp) 1683 { 1684 source_vp_entry_t svp; 1685 source_vp_2_entry_t svp_2_entry; 1686 int network_port_flag=0; 1687 int vp1=0, vp2=0, vfi_index= -1; 1688 int rv = BCM_E_UNAVAIL; 1689 bcm_gport_t flow_port_id; 1690 _bcm_vp_info_t vp_info; 1691 1692 if ( vpn != BCM_FLOW_VPN_INVALID) { 1693 _BCM_FLOW_VPN_GET(vfi_index, _BCM_VXLAN_VPN_TYPE_ELINE, vpn); 1694 if (!_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeFlow)) { 1695 return BCM_E_NOT_FOUND; 1696 } 1697 } else { 1698 vfi_index = _BCM_FLOW_VFI_INVALID; 1699 } 1700 1701 if (!_bcm_vp_used_get(unit, active_vp, _bcmVpTypeFlow)) { 1702 return BCM_E_NOT_FOUND; 1703 } 1704 1705 /* Set FLOW port ID */ 1706 BCM_GPORT_FLOW_PORT_ID_SET(flow_port_id, active_vp); 1707 1708 /* ---- Read in current table values for VP1 and VP2 ----- */ 1709 (void) _bcm_td3_flow_eline_vp_map_get (unit, vfi_index, &vp1, &vp2); 1710 1711 /* flow_match API will handle this 1712 bcm_flow_port_t_init(&flow_port); 1713 flow_port.flow_port_id = flow_port_id; 1714 BCM_IF_ERROR_RETURN(bcmi_esw_flow_port_get(unit, vpn, &flow_port)); 1715 rv = _bcm_td2_vxlan_match_delete(unit, active_vp, vxlan_port); 1716 if ( rv < 0 ) { 1717 if (rv != BCM_E_NOT_FOUND) { 1718 return rv; 1719 } else { 1720 rv = BCM_E_NONE; 1721 } 1722 } 1723 */ 1724 1725 /* If the other port is valid, point it to itself */ 1726 if (active_vp == vp1) { 1727 rv = _bcm_td3_flow_eline_vp_map_clear (unit, vfi_index, active_vp, 0); 1728 } else if (active_vp == vp2) { 1729 rv = _bcm_td3_flow_eline_vp_map_clear (unit, vfi_index, 0, active_vp); 1730 } 1731 1732 if (rv >= 0) { 1733 1734 /* Check for Network-Port */ 1735 BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, active_vp, &vp_info)); 1736 if (vp_info.flags & _BCM_VP_INFO_NETWORK_PORT) { 1737 network_port_flag = TRUE; 1738 } 1739 1740 if (!network_port_flag) { 1741 sal_memset(&svp_2_entry, 0, sizeof(source_vp_2_entry_t)); 1742 BCM_IF_ERROR_RETURN 1743 (WRITE_SOURCE_VP_2m(unit, MEM_BLOCK_ALL, active_vp, &svp_2_entry)); 1744 } 1745 1746 /* Invalidate the VP being deleted */ 1747 sal_memset(&svp, 0, sizeof(source_vp_entry_t)); 1748 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, active_vp, &svp); 1749 } 1750 1751 if (rv < 0) { 1752 return rv; 1753 } 1754 1755 /* Decrement port's VP count */ 1756 rv = _bcm_td3_flow_port_cnt_update(unit, flow_port_id, active_vp, FALSE); 1757 if (rv < 0) { 1758 return rv; 1759 } 1760 1761 /* Free the VP */ 1762 (void) _bcm_vp_free(unit, _bcmVpTypeVxlan, 1, active_vp); 1763 return rv; 1764 1765 } 1766 1767 /* 1768 * Function: 1769 * _bcm_td3_flow_elan_port_delete 1770 * Purpose: 1771 * Delete FLOW ELAN port from a VPN 1772 * Parameters: 1773 * unit - (IN) Device Number 1774 * vpn - (IN) VPN instance ID 1775 * flow_port_id - (IN) flow port information 1776 * Returns: 1777 * BCM_E_XXX 1778 */ 1779 1780 int 1781 _bcm_td3_flow_elan_port_delete(int unit, bcm_vpn_t vpn, int vp) 1782 { 1783 source_vp_entry_t svp; 1784 source_vp_2_entry_t svp_2_entry; 1785 int network_port_flag=0; 1786 int vfi_index= -1; 1787 bcm_gport_t flow_port_id; 1788 bcm_flow_port_t flow_port; 1789 _bcm_vp_info_t vp_info; 1790 1791 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeFlow)) { 1792 return BCM_E_NOT_FOUND; 1793 } 1794 1795 /* Check for Network-Port */ 1796 BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info)); 1797 if (vp_info.flags & _BCM_VP_INFO_NETWORK_PORT) { 1798 network_port_flag = TRUE; 1799 } 1800 1801 /* Set FLOW port ID */ 1802 BCM_GPORT_FLOW_PORT_ID_SET(flow_port_id, vp); 1803 bcm_flow_port_t_init(&flow_port); 1804 flow_port.flow_port_id = flow_port_id; 1805 BCM_IF_ERROR_RETURN(bcmi_esw_flow_port_get(unit, vpn, &flow_port)); 1806 1807 /* handled by flow_match API 1808 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 1809 if ((!network_port_flag) && (vp_info.flags & _BCM_VP_INFO_SHARED_PORT)) { 1810 if (VXLAN_INFO(unit)->match_key[vp].match_count > 0) { 1811 BCM_IF_ERROR_RETURN(bcm_td2p_share_vp_delete(unit, vpn, vp)); 1812 } 1813 if (vpn != BCM_FLOW_VPN_INVALID) { 1814 return BCM_E_NONE; 1815 } 1816 } else 1817 #endif 1818 { 1819 rv = _bcm_td2_vxlan_match_delete(unit, vp, vxlan_port); 1820 if (rv < 0 && rv != BCM_E_NOT_FOUND) { 1821 return rv; 1822 } 1823 } 1824 (void)bcm_td2_vxlan_match_clear(unit, vp); 1825 */ 1826 1827 if ( vpn != BCM_FLOW_VPN_INVALID) { 1828 if (!network_port_flag) { /* Check VPN only for Access VP */ 1829 _BCM_FLOW_VPN_GET(vfi_index, _BCM_FLOW_VPN_TYPE_ELAN, vpn); 1830 if (!_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeFlow)) { 1831 return BCM_E_NOT_FOUND; 1832 } 1833 if (_bcm_vp_used_get(unit, vp, _bcmVpTypeNiv) || 1834 _bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) { 1835 (void) _bcm_vp_free(unit, _bcmVpTypeVxlan, 1, vp); 1836 return _bcm_td3_flow_access_niv_pe_reset (unit, vp); 1837 } 1838 } 1839 } 1840 1841 /* Decrement port's VP count */ 1842 BCM_IF_ERROR_RETURN(_bcm_td3_flow_port_cnt_update(unit, flow_port_id, vp, FALSE)); 1843 1844 /* Clear the SVP table entries */ 1845 sal_memset(&svp, 0, sizeof(source_vp_entry_t)); 1846 BCM_IF_ERROR_RETURN(WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp)); 1847 1848 if (!network_port_flag) { 1849 sal_memset(&svp_2_entry, 0, sizeof(source_vp_2_entry_t)); 1850 BCM_IF_ERROR_RETURN 1851 (WRITE_SOURCE_VP_2m(unit, MEM_BLOCK_ALL, vp, &svp_2_entry)); 1852 } 1853 1854 /* Free the VP */ 1855 BCM_IF_ERROR_RETURN(_bcm_vp_free(unit, _bcmVpTypeFlow, 1, vp)); 1856 1857 return BCM_E_NONE; 1858 } 1859 1860 /* 1861 * Function: 1862 * bcmi_esw_flow_port_get 1863 * Purpose: 1864 * Get an FLOW port from a VPN 1865 * Parameters: 1866 * unit - (IN) Device Number 1867 * vpn - (IN) VPN instance ID 1868 * flow - (IN/OUT) FLOW port information 1869 */ 1870 int 1871 bcmi_esw_flow_port_get(int unit, bcm_vpn_t vpn, bcm_flow_port_t *flow_port) 1872 { 1873 int vp=0; 1874 int rv = BCM_E_NONE; 1875 uint32 reg_val = 0; 1876 int dft_vxlan_vp = -1; 1877 int dft_l2gre_vp = -1; 1878 int dft_gpe_vp = -1; 1879 int dft_geneve_vp = -1; 1880 1881 if (BCM_GPORT_IS_TRUNK(flow_port->flow_port_id)) { 1882 bcm_trunk_member_t trunk_member; 1883 int port_count = 0; 1884 bcm_trunk_t tid = 0; 1885 int tid_is_vp_lag = FALSE; 1886 if (vpn != BCM_FLOW_VPN_INVALID) { 1887 BCM_IF_ERROR_RETURN(bcmi_esw_flow_vpn_is_valid(unit, vpn)); 1888 } 1889 tid = BCM_GPORT_TRUNK_GET(flow_port->flow_port_id); 1890 BCM_IF_ERROR_RETURN( 1891 _bcm_esw_trunk_id_is_vp_lag(unit, tid, &tid_is_vp_lag)); 1892 if (tid_is_vp_lag) { 1893 BCM_IF_ERROR_RETURN( 1894 bcm_td2_vp_lag_get(unit, tid, NULL, 1, 1895 &trunk_member, &port_count)); 1896 if (BCM_GPORT_IS_NIV_PORT(trunk_member.gport) || 1897 BCM_GPORT_IS_EXTENDER_PORT(trunk_member.gport)) { 1898 BCM_IF_ERROR_RETURN( 1899 _bcm_esw_trunk_tid_to_vp_lag_vp(unit, tid, &vp)); 1900 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeFlow)) { 1901 return BCM_E_NOT_FOUND; 1902 } 1903 return BCM_E_NONE; 1904 } 1905 } 1906 } 1907 1908 if (SOC_REG_IS_VALID(unit, VXLAN_DEFAULT_NETWORK_SVPr)) { 1909 BCM_IF_ERROR_RETURN(READ_VXLAN_DEFAULT_NETWORK_SVPr(unit, ®_val)); 1910 dft_vxlan_vp = soc_reg_field_get(unit, 1911 VXLAN_DEFAULT_NETWORK_SVPr, reg_val, SVPf); 1912 } 1913 1914 if (SOC_REG_IS_VALID(unit, L2GRE_DEFAULT_NETWORK_SVPr)) { 1915 BCM_IF_ERROR_RETURN(READ_L2GRE_DEFAULT_NETWORK_SVPr(unit, ®_val)); 1916 dft_l2gre_vp = soc_reg_field_get(unit, 1917 L2GRE_DEFAULT_NETWORK_SVPr, reg_val, SVPf); 1918 } 1919 1920 if (SOC_REG_IS_VALID(unit, GPE_DEFAULT_NETWORK_SVPr)) { 1921 BCM_IF_ERROR_RETURN(READ_GPE_DEFAULT_NETWORK_SVPr(unit, ®_val)); 1922 dft_gpe_vp = soc_reg_field_get(unit, 1923 GPE_DEFAULT_NETWORK_SVPr, reg_val, SVPf); 1924 } 1925 1926 if (SOC_REG_IS_VALID(unit, GENEVE_DEFAULT_NETWORK_SVPr)) { 1927 BCM_IF_ERROR_RETURN(READ_GENEVE_DEFAULT_NETWORK_SVPr(unit, ®_val)); 1928 dft_geneve_vp = soc_reg_field_get(unit, 1929 GENEVE_DEFAULT_NETWORK_SVPr, reg_val, SVPf); 1930 } 1931 1932 vp = BCM_GPORT_FLOW_PORT_ID_GET(flow_port->flow_port_id); 1933 if (vp == -1) { 1934 return BCM_E_PARAM; 1935 } 1936 1937 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeFlow)) { 1938 return BCM_E_NOT_FOUND; 1939 } 1940 1941 if (vpn != BCM_FLOW_VPN_INVALID) { 1942 BCM_IF_ERROR_RETURN(bcmi_esw_flow_vpn_is_valid(unit, vpn)); 1943 } 1944 1945 if (vp == dft_vxlan_vp || vp == dft_l2gre_vp || vp == dft_gpe_vp || 1946 vp == dft_geneve_vp) { 1947 rv = _bcm_td3_flow_default_port_get(unit, vp, flow_port); 1948 if (vp == dft_vxlan_vp) { 1949 flow_port->flags |= BCM_FLOW_PORT_DEFAULT; 1950 } 1951 if (vp == dft_l2gre_vp) { 1952 flow_port->flags |= BCM_FLOW_PORT_DEFAULT_L2GRE; 1953 } 1954 if (vp == dft_gpe_vp) { 1955 flow_port->flags |= BCM_FLOW_PORT_DEFAULT_GPE; 1956 } 1957 if (vp == dft_geneve_vp) { 1958 flow_port->flags |= BCM_FLOW_PORT_DEFAULT_GENEVE; 1959 } 1960 } else { 1961 rv = _bcmi_esw_flow_port_get(unit, vpn, vp, flow_port); 1962 } 1963 1964 return rv; 1965 } 1966 1967 /* 1968 * Function: 1969 * _bcm_flow_share_vp_get 1970 * Purpose: 1971 * Get shared VPs info per VPN 1972 * Parameters: 1973 * unit - (IN) Device Number 1974 * vpn - (IN) VPN that shared vp belong to 1975 * vp_bitmap - (OUT) shared vp bitmap 1976 * Returns: 1977 * BCM_E_XXX 1978 */ 1979 STATIC int 1980 _bcm_flow_share_vp_get(int unit, bcm_vpn_t vpn, SHR_BITDCL *vp_bitmap) 1981 { 1982 vlan_xlate_entry_t *vent; 1983 soc_mem_t mem; 1984 int index_min = 0; 1985 int index_max = 0; 1986 uint8 *xlate_buf = NULL; 1987 int buf_size = 0; 1988 int i = 0; 1989 int rv = BCM_E_NONE; 1990 int vfi = -1; 1991 int vp = -1; 1992 1993 if (vpn != BCM_FLOW_VPN_INVALID) { 1994 BCM_IF_ERROR_RETURN(bcmi_esw_flow_vpn_is_valid(unit, vpn)); 1995 _BCM_FLOW_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, vpn); 1996 } 1997 1998 if (SOC_MEM_IS_VALID(unit, VLAN_XLATE_1_DOUBLEm)) { 1999 mem = VLAN_XLATE_1_DOUBLEm; 2000 } else { 2001 mem = VLAN_XLATEm; 2002 } 2003 index_min = soc_mem_index_min(unit, mem); 2004 index_max = soc_mem_index_max(unit, mem); 2005 2006 buf_size = SOC_MEM_TABLE_BYTES(unit, mem); 2007 xlate_buf = soc_cm_salloc(unit, buf_size, "VLAN_XLATE buffer"); 2008 if (NULL == xlate_buf) { 2009 return BCM_E_MEMORY; 2010 } 2011 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, index_min, index_max, 2012 xlate_buf); 2013 if (rv < 0) { 2014 soc_cm_sfree(unit, xlate_buf); 2015 return rv; 2016 } 2017 2018 for (i = index_min; i <= index_max; i++) { 2019 vent = soc_mem_table_idx_to_pointer(unit, mem, void *, xlate_buf, i); 2020 if (SOC_MEM_IS_VALID(unit, VLAN_XLATE_1_DOUBLEm)) { 2021 if (soc_mem_field32_get(unit, mem, vent, BASE_VALID_0f) != 3) { 2022 continue; 2023 } 2024 if (soc_mem_field32_get(unit, mem, vent, BASE_VALID_1f) != 7) { 2025 continue; 2026 } 2027 } 2028 2029 if (soc_mem_field32_get(unit, mem, vent, XLATE__MPLS_ACTIONf) != 0x1) { 2030 continue; 2031 } 2032 2033 if (vfi != -1 && soc_mem_field32_get(unit, mem, vent, XLATE__VFIf) != 2034 vfi) { 2035 continue; 2036 } 2037 2038 vp = soc_mem_field32_get(unit, mem, vent, XLATE__SOURCE_VPf); 2039 SHR_BITSET(vp_bitmap, vp); 2040 } 2041 2042 (void)soc_cm_sfree(unit, xlate_buf); 2043 2044 return BCM_E_NONE; 2045 } 2046 2047 /* 2048 * Function: 2049 * bcmi_esw_flow_port_get_all 2050 * Purpose: 2051 * Get all FLOW ports from a VPN 2052 * Parameters: 2053 * unit - (IN) Device Number 2054 * vpn - (IN) VPN instance ID 2055 * port_max - (IN) Maximum number of interfaces in array 2056 * port_array - (OUT) Array of FLOW ports 2057 * port_count - (OUT) Number of interfaces returned in array 2058 */ 2059 int 2060 bcmi_esw_flow_port_get_all(int unit, bcm_vpn_t vpn, int port_max, 2061 bcm_flow_port_t *port_array, int *port_count) 2062 { 2063 int vp, rv = BCM_E_NONE; 2064 int vfi_index=-1; 2065 int vp1 = 0, vp2 = 0; 2066 uint8 isEline = 0; 2067 SHR_BITDCL *share_vp_bitmap = NULL; 2068 2069 if (vpn != BCM_FLOW_VPN_INVALID) { 2070 _BCM_FLOW_VPN_GET(vfi_index, _BCM_VPN_TYPE_VFI, vpn); 2071 BCM_IF_ERROR_RETURN(bcmi_esw_flow_vpn_is_eline(unit, vpn, &isEline)); 2072 } else { 2073 vfi_index = _BCM_FLOW_VFI_INVALID; 2074 } 2075 2076 *port_count = 0; 2077 2078 if (isEline == 0x1 ) { 2079 /* ---- Read in current table values for VP1 and VP2 ----- */ 2080 (void) _bcm_td3_flow_eline_vp_map_get (unit, vfi_index, &vp1, &vp2); 2081 vp = vp1; 2082 if (_bcm_vp_used_get(unit, vp, _bcmVpTypeFlow)) { 2083 if (0 == port_max) { 2084 (*port_count)++; 2085 2086 } else if (*port_count < port_max) { 2087 rv = _bcmi_esw_flow_port_get(unit, vpn, vp, 2088 &port_array[*port_count]); 2089 if (rv < 0) { 2090 return rv; 2091 } 2092 (*port_count)++; 2093 } 2094 } 2095 2096 vp = vp2; 2097 if (_bcm_vp_used_get(unit, vp, _bcmVpTypeFlow)) { 2098 if (0 == port_max) { 2099 (*port_count)++; 2100 2101 } else if (*port_count < port_max) { 2102 rv = _bcmi_esw_flow_port_get(unit, vpn, vp, 2103 &port_array[*port_count]); 2104 if (rv < 0) { 2105 return rv; 2106 } 2107 (*port_count)++; 2108 } 2109 } 2110 } else if (isEline == 0x0 ) { 2111 uint32 entry_type = 0; 2112 source_vp_entry_t svp; 2113 int num_vp = soc_mem_index_count(unit, SOURCE_VPm); 2114 2115 share_vp_bitmap = sal_alloc(SHR_BITALLOCSIZE(num_vp), "sharr_vp_bitmap"); 2116 if (share_vp_bitmap == NULL) { 2117 return BCM_E_MEMORY; 2118 } 2119 sal_memset(share_vp_bitmap, 0, SHR_BITALLOCSIZE(num_vp)); 2120 2121 if (soc_feature(unit, soc_feature_vp_sharing)) { 2122 rv = _bcm_flow_share_vp_get(unit, vpn, share_vp_bitmap); 2123 _BCM_FLOW_CLEANUP(rv) 2124 } 2125 2126 SHR_BIT_ITER(VIRTUAL_INFO(unit)->flow_vp_bitmap, num_vp, vp) { 2127 2128 rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp); 2129 _BCM_FLOW_CLEANUP(rv) 2130 entry_type = soc_SOURCE_VPm_field32_get(unit, &svp, ENTRY_TYPEf); 2131 2132 if ((vfi_index == soc_SOURCE_VPm_field32_get(unit, &svp, VFIf) && 2133 entry_type == _BCM_VXLAN_SOURCE_VP_TYPE_VFI) || 2134 SHR_BITGET(share_vp_bitmap, vp)) { 2135 2136 /* Check if number of ports is requested */ 2137 if (0 == port_max) { 2138 (*port_count)++; 2139 continue; 2140 } else if (*port_count == port_max) { 2141 break; 2142 } 2143 2144 rv = _bcmi_esw_flow_port_get(unit, 2145 vpn, vp, &port_array[*port_count]); 2146 _BCM_FLOW_CLEANUP(rv) 2147 2148 (*port_count)++; 2149 } 2150 } 2151 sal_free(share_vp_bitmap); 2152 } 2153 2154 return BCM_E_NONE; 2155 cleanup: 2156 sal_free(share_vp_bitmap); 2157 return rv; 2158 } 2159 2160 /* 2161 * Function: 2162 * _bcm_td3_flow_default_port_get 2163 * Purpose: 2164 * Get FLOW Default port information 2165 * Parameters: 2166 * unit - (IN) Device Number 2167 * vp - (IN) Source Virtual Port 2168 * flow_port - (IN/OUT) flow port information 2169 * Returns: 2170 * BCM_E_XXX 2171 */ 2172 int 2173 _bcm_td3_flow_default_port_get(int unit, int vp, bcm_flow_port_t *flow_port) 2174 { 2175 int rv = BCM_E_NONE; 2176 source_vp_entry_t svp; 2177 _bcm_vp_info_t vp_info; 2178 2179 bcm_flow_port_t_init(flow_port); 2180 BCM_GPORT_FLOW_PORT_ID_SET(flow_port->flow_port_id, vp); 2181 2182 BCM_IF_ERROR_RETURN(READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp)); 2183 flow_port->if_class = soc_SOURCE_VPm_field32_get(unit, &svp, CLASS_IDf); 2184 2185 BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info)); 2186 if (vp_info.flags & _BCM_VP_INFO_NETWORK_PORT) { 2187 flow_port->flags |= BCM_FLOW_PORT_NETWORK; 2188 } 2189 2190 return rv; 2191 } 2192 2193 /* 2194 * Function: 2195 * _bcmi_esw_flow_port_get 2196 * Purpose: 2197 * Get FLOW port information from a VPN 2198 * Parameters: 2199 * unit - (IN) Device Number 2200 * vpn - (IN) VPN instance ID 2201 * flow_port_id - (IN) vxlan port information 2202 * Returns: 2203 * BCM_E_XXX 2204 */ 2205 2206 int 2207 _bcmi_esw_flow_port_get(int unit, bcm_vpn_t vpn, int vp, bcm_flow_port_t *flow_port) 2208 { 2209 int i, rv = BCM_E_NONE; 2210 uint32 tpid_enable = 0; 2211 source_vp_entry_t svp; 2212 int split_horizon_port_flag=0; 2213 _bcm_vp_info_t vp_info; 2214 2215 /* Initialize the structure */ 2216 bcm_flow_port_t_init(flow_port); 2217 BCM_GPORT_FLOW_PORT_ID_SET(flow_port->flow_port_id, vp); 2218 BCM_IF_ERROR_RETURN (READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp)); 2219 2220 /* Check for Network-Port */ 2221 BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info)); 2222 if (vp_info.flags & _BCM_VP_INFO_NETWORK_PORT) { 2223 split_horizon_port_flag = TRUE; 2224 } 2225 2226 if ( vpn != BCM_FLOW_VPN_INVALID) { 2227 if (!split_horizon_port_flag) { /* Check VPN only for Access VP */ 2228 if (_bcm_vp_used_get(unit, vp, _bcmVpTypeNiv) || 2229 _bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) { 2230 return BCM_E_NONE; 2231 } 2232 } 2233 } 2234 2235 if (split_horizon_port_flag) { 2236 flow_port->flags |= BCM_FLOW_PORT_NETWORK; 2237 } 2238 2239 /* Get the match parameters */ 2240 /* Done by match API 2241 rv = _bcm_td2_vxlan_match_get(unit, vxlan_port, vp); 2242 BCM_IF_ERROR_RETURN(rv); 2243 */ 2244 2245 /* Get the BCM_VXLAN_PORT_ENABLE_VLAN_CHECKS flag */ 2246 /* Done by match API 2247 if (!soc_feature(unit, soc_feature_vlan_vfi_membership)) { 2248 BCM_IF_ERROR_RETURN( 2249 _bcm_td2_vxlan_port_vlan_get(unit, vp, vxlan_port)); 2250 } 2251 */ 2252 2253 /* Get Tunnel index */ 2254 /* to be done by flow encap set API 2255 rv = _bcm_td2_vxlan_egress_dvp_get(unit, vp, vxlan_port); 2256 BCM_IF_ERROR_RETURN(rv); 2257 */ 2258 2259 /* Fill in SVP parameters */ 2260 flow_port->if_class = soc_SOURCE_VPm_field32_get(unit, &svp, CLASS_IDf); 2261 flow_port->network_group_id = soc_SOURCE_VPm_field32_get(unit, &svp, 2262 NETWORK_GROUPf); 2263 2264 if (soc_SOURCE_VPm_field32_get(unit, &svp, SD_TAG_MODEf)) { 2265 uint32 svp1[SOC_MAX_MEM_WORDS]; 2266 2267 BCM_IF_ERROR_RETURN(READ_SVP_ATTRS_1m(unit, MEM_BLOCK_ANY, vp, svp1)); 2268 soc_SVP_ATTRS_1m_field_get(unit, &svp1, TPID_ENABLEf, &tpid_enable); 2269 2270 if (tpid_enable) { 2271 flow_port->flags |= BCM_FLOW_PORT_SERVICE_TAGGED; 2272 for (i = 0; i < 4; i++) { 2273 if (tpid_enable & (1 << i)) { 2274 _bcm_fb2_outer_tpid_entry_get(unit, &flow_port->egress_service_tpid, i); 2275 } 2276 } 2277 } 2278 } 2279 2280 return rv; 2281 } 2282 2283 /* 2284 * Function: 2285 * bcmi_esw_flow_port_create 2286 * Purpose: 2287 * Create Flex Flow port and add to a default VPN 2288 * Parameters: 2289 * unit - (IN) Device Number 2290 * vpn - (IN) VPN instance ID 2291 * flow_port - (IN/OUT) flow_port information (OUT : flow_port_id) 2292 * Returns: 2293 * BCM_E_XXX 2294 */ 2295 2296 int 2297 bcmi_esw_flow_port_create(int unit, bcm_vpn_t vpn, bcm_flow_port_t *flow_port) 2298 { 2299 int mode=0, rv = BCM_E_PARAM; 2300 uint8 isEline = 0; 2301 int vp = -1; 2302 int dft_vxlan_port = FALSE; 2303 int dft_l2gre_port = FALSE; 2304 int dft_gpe_port = FALSE; 2305 int dft_geneve_port = FALSE; 2306 2307 BCM_IF_ERROR_RETURN(bcm_xgs3_l3_egress_mode_get(unit, &mode)); 2308 if (!mode) { 2309 LOG_INFO(BSL_LS_BCM_L3, 2310 (BSL_META_U(unit, 2311 "L3 egress mode must be set first\n"))); 2312 return BCM_E_DISABLED; 2313 } 2314 2315 if (flow_port->if_class > 0xfff) { 2316 return BCM_E_PARAM; 2317 } 2318 2319 /* mtu programmed in EGR_DVP_ATTRIBUTEm, will be done by bcm_flow_port_set 2320 if (flow_port->mtu > 0x3fff) { 2321 return BCM_E_PARAM; 2322 } 2323 */ 2324 2325 if (vpn != BCM_FLOW_VPN_INVALID) { 2326 BCM_IF_ERROR_RETURN(bcmi_esw_flow_vpn_is_eline(unit, vpn, &isEline)); 2327 } 2328 2329 if (flow_port->flags & PORT_DEFAULT_ALL) { 2330 rv = _bcm_td3_flow_default_port_add(unit, flow_port, &vp); 2331 BCM_IF_ERROR_RETURN(rv); 2332 2333 if (flow_port->flags & BCM_FLOW_PORT_DEFAULT) { 2334 if (!SOC_REG_IS_VALID(unit, VXLAN_DEFAULT_NETWORK_SVPr)) { 2335 rv = BCM_E_UNAVAIL; 2336 goto err_exit; 2337 } 2338 dft_vxlan_port = TRUE; 2339 2340 rv = soc_reg_field32_modify(unit, VXLAN_DEFAULT_NETWORK_SVPr, 2341 REG_PORT_ANY, SVPf, vp); 2342 if (BCM_FAILURE(rv)) { 2343 goto err_exit; 2344 } 2345 2346 if (SOC_REG_IS_VALID(unit, DEFAULT_SVP_ENABLEr)) { 2347 rv = soc_reg_field32_modify 2348 (unit, DEFAULT_SVP_ENABLEr, REG_PORT_ANY, 2349 VXLAN_DEFAULT_SVP_ENABLEf, 1); 2350 if (BCM_FAILURE(rv)) { 2351 if (rv != BCM_E_NOT_FOUND) { 2352 goto err_exit; 2353 } else { 2354 rv = BCM_E_NONE; 2355 } 2356 } 2357 } 2358 } 2359 if (flow_port->flags & BCM_FLOW_PORT_DEFAULT_L2GRE) { 2360 if (!SOC_REG_IS_VALID(unit, L2GRE_DEFAULT_NETWORK_SVPr)) { 2361 rv = BCM_E_UNAVAIL; 2362 goto err_exit; 2363 } 2364 rv = soc_reg_field32_modify(unit, L2GRE_DEFAULT_NETWORK_SVPr, 2365 REG_PORT_ANY, SVPf, vp); 2366 if (BCM_FAILURE(rv)) { 2367 goto err_exit; 2368 } 2369 2370 dft_l2gre_port = TRUE; 2371 if (SOC_REG_IS_VALID(unit, DEFAULT_SVP_ENABLEr)) { 2372 rv = soc_reg_field32_modify 2373 (unit, DEFAULT_SVP_ENABLEr, REG_PORT_ANY, 2374 L2GRE_DEFAULT_SVP_ENABLEf, 1); 2375 if (BCM_FAILURE(rv)) { 2376 if (rv != BCM_E_NOT_FOUND) { 2377 goto err_exit; 2378 } else { 2379 rv = BCM_E_NONE; 2380 } 2381 } 2382 } 2383 } 2384 2385 if (flow_port->flags & BCM_FLOW_PORT_DEFAULT_GPE) { 2386 if (!SOC_REG_IS_VALID(unit, GPE_DEFAULT_NETWORK_SVPr)) { 2387 rv = BCM_E_UNAVAIL; 2388 goto err_exit; 2389 } 2390 rv = soc_reg_field32_modify(unit, GPE_DEFAULT_NETWORK_SVPr, 2391 REG_PORT_ANY, SVPf, vp); 2392 if (BCM_FAILURE(rv)) { 2393 goto err_exit; 2394 } 2395 dft_gpe_port = TRUE; 2396 } 2397 2398 if (flow_port->flags & BCM_FLOW_PORT_DEFAULT_GENEVE) { 2399 if (!SOC_REG_IS_VALID(unit, GENEVE_DEFAULT_NETWORK_SVPr)) { 2400 rv = BCM_E_UNAVAIL; 2401 goto err_exit; 2402 } 2403 rv = soc_reg_field32_modify(unit, GENEVE_DEFAULT_NETWORK_SVPr, 2404 REG_PORT_ANY, SVPf, vp); 2405 if (BCM_FAILURE(rv)) { 2406 goto err_exit; 2407 } 2408 dft_geneve_port = TRUE; 2409 } 2410 return rv; 2411 } 2412 2413 if (isEline) { 2414 rv = _bcm_td3_flow_eline_port_add(unit, vpn, flow_port); 2415 } else { 2416 rv = _bcm_td3_flow_elan_port_add(unit, vpn, flow_port); 2417 } 2418 2419 return rv; 2420 2421 err_exit: 2422 if (vp >= 0) { 2423 if (dft_vxlan_port == TRUE) { 2424 BCM_IF_ERROR_RETURN(soc_reg_field32_modify(unit, 2425 VXLAN_DEFAULT_NETWORK_SVPr, REG_PORT_ANY, SVPf, 0)); 2426 } 2427 if (dft_l2gre_port == TRUE) { 2428 BCM_IF_ERROR_RETURN(soc_reg_field32_modify(unit, 2429 L2GRE_DEFAULT_NETWORK_SVPr, REG_PORT_ANY, SVPf, 0)); 2430 } 2431 if (dft_gpe_port == TRUE) { 2432 BCM_IF_ERROR_RETURN(soc_reg_field32_modify(unit, 2433 GPE_DEFAULT_NETWORK_SVPr, REG_PORT_ANY, SVPf, 0)); 2434 } 2435 if (dft_geneve_port == TRUE) { 2436 BCM_IF_ERROR_RETURN(soc_reg_field32_modify(unit, 2437 GENEVE_DEFAULT_NETWORK_SVPr, REG_PORT_ANY, SVPf, 0)); 2438 } 2439 BCM_IF_ERROR_RETURN(_bcm_td3_flow_default_port_delete(unit, 2440 BCM_FLOW_VPN_INVALID, vp)); 2441 } 2442 return rv; 2443 } 2444 2445 /* 2446 * Function: 2447 * bcmi_esw_flow_port_destroy 2448 * Purpose: 2449 * Delete FLOW port from a VPN 2450 * Parameters: 2451 * unit - (IN) Device Number 2452 * vpn - (IN) VPN instance ID 2453 * flow_port_id - (IN) flow port information 2454 * Returns: 2455 * BCM_E_XXX 2456 */ 2457 2458 int 2459 bcmi_esw_flow_port_destroy(int unit, bcm_vpn_t vpn, bcm_gport_t flow_port_id) 2460 { 2461 int vp=0; 2462 int rv = BCM_E_UNAVAIL; 2463 uint8 isEline=0; 2464 uint32 reg_val=0; 2465 int default_vp_delete = FALSE; 2466 2467 if (BCM_GPORT_IS_TRUNK(flow_port_id)) { 2468 bcm_trunk_member_t trunk_member; 2469 int port_count = 0; 2470 bcm_trunk_t tid = 0; 2471 int tid_is_vp_lag = FALSE; 2472 if (vpn != BCM_FLOW_VPN_INVALID) { 2473 BCM_IF_ERROR_RETURN(bcmi_esw_flow_vpn_is_valid(unit, vpn)); 2474 } 2475 tid = BCM_GPORT_TRUNK_GET(flow_port_id); 2476 BCM_IF_ERROR_RETURN( 2477 _bcm_esw_trunk_id_is_vp_lag(unit, tid, &tid_is_vp_lag)); 2478 if (tid_is_vp_lag) { 2479 BCM_IF_ERROR_RETURN( 2480 bcm_td2_vp_lag_get(unit, tid, NULL, 1, 2481 &trunk_member, &port_count)); 2482 if (BCM_GPORT_IS_NIV_PORT(trunk_member.gport) || 2483 BCM_GPORT_IS_EXTENDER_PORT(trunk_member.gport)) { 2484 BCM_IF_ERROR_RETURN( 2485 _bcm_esw_trunk_tid_to_vp_lag_vp(unit, tid, &vp)); 2486 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeFlow)) { 2487 return BCM_E_NOT_FOUND; 2488 } 2489 BCM_IF_ERROR_RETURN(_bcm_vp_free(unit, _bcmVpTypeFlow, 1, vp)); 2490 return _bcm_td3_flow_access_niv_pe_reset(unit, vp); 2491 } 2492 } 2493 } 2494 2495 /* Check for Valid Vpn */ 2496 if (vpn != BCM_FLOW_VPN_INVALID) { 2497 BCM_IF_ERROR_RETURN(bcmi_esw_flow_vpn_is_valid(unit, vpn)); 2498 } 2499 2500 vp = BCM_GPORT_FLOW_PORT_ID_GET(flow_port_id); 2501 if (vp == -1) { 2502 return BCM_E_PARAM; 2503 } 2504 2505 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeFlow)) { 2506 return BCM_E_NOT_FOUND; 2507 } 2508 2509 2510 2511 /* Check for VXLAN default port */ 2512 if (SOC_REG_IS_VALID(unit, VXLAN_DEFAULT_NETWORK_SVPr)) { 2513 BCM_IF_ERROR_RETURN(READ_VXLAN_DEFAULT_NETWORK_SVPr(unit, ®_val)); 2514 if (vp == soc_reg_field_get(unit, 2515 VXLAN_DEFAULT_NETWORK_SVPr, reg_val, SVPf)) { 2516 rv = soc_reg_field32_modify(unit, VXLAN_DEFAULT_NETWORK_SVPr, 2517 REG_PORT_ANY, SVPf, 0); 2518 BCM_IF_ERROR_RETURN(rv); 2519 2520 rv = _bcm_td3_flow_default_port_delete(unit, vpn, vp); 2521 BCM_IF_ERROR_RETURN(rv); 2522 if (SOC_REG_IS_VALID(unit, DEFAULT_SVP_ENABLEr)) { 2523 rv = soc_reg_field32_modify 2524 (unit, DEFAULT_SVP_ENABLEr, REG_PORT_ANY, VXLAN_DEFAULT_SVP_ENABLEf, 0); 2525 if (BCM_FAILURE(rv)) { 2526 if (rv != BCM_E_NOT_FOUND) { 2527 return rv; 2528 } else { 2529 rv = BCM_E_NONE; 2530 } 2531 } 2532 } 2533 default_vp_delete = TRUE; 2534 } 2535 } 2536 2537 /* Check for L2GRE default port */ 2538 if (SOC_REG_IS_VALID(unit, L2GRE_DEFAULT_NETWORK_SVPr)) { 2539 BCM_IF_ERROR_RETURN(READ_L2GRE_DEFAULT_NETWORK_SVPr(unit, ®_val)); 2540 if (vp == soc_reg_field_get(unit, 2541 L2GRE_DEFAULT_NETWORK_SVPr, reg_val, SVPf)) { 2542 rv = soc_reg_field32_modify(unit, L2GRE_DEFAULT_NETWORK_SVPr, 2543 REG_PORT_ANY, SVPf, 0); 2544 BCM_IF_ERROR_RETURN(rv); 2545 if (default_vp_delete == FALSE) { 2546 rv = _bcm_td3_flow_default_port_delete(unit, vpn, vp); 2547 BCM_IF_ERROR_RETURN(rv); 2548 } 2549 if (SOC_REG_IS_VALID(unit, DEFAULT_SVP_ENABLEr)) { 2550 rv = soc_reg_field32_modify(unit, DEFAULT_SVP_ENABLEr, 2551 REG_PORT_ANY, L2GRE_DEFAULT_SVP_ENABLEf, 0); 2552 if (BCM_FAILURE(rv)) { 2553 if (rv != BCM_E_NOT_FOUND) { 2554 return rv; 2555 } else { 2556 rv = BCM_E_NONE; 2557 } 2558 } 2559 } 2560 default_vp_delete = TRUE; 2561 } 2562 } 2563 2564 /* Check for GPE default port */ 2565 if (SOC_REG_IS_VALID(unit, GPE_DEFAULT_NETWORK_SVPr)) { 2566 BCM_IF_ERROR_RETURN(READ_GPE_DEFAULT_NETWORK_SVPr(unit, ®_val)); 2567 if (vp == soc_reg_field_get(unit, 2568 GPE_DEFAULT_NETWORK_SVPr, reg_val, SVPf)) { 2569 rv = soc_reg_field32_modify(unit, GPE_DEFAULT_NETWORK_SVPr, 2570 REG_PORT_ANY, SVPf, 0); 2571 BCM_IF_ERROR_RETURN(rv); 2572 if (default_vp_delete == FALSE) { 2573 rv = _bcm_td3_flow_default_port_delete(unit, vpn, vp); 2574 BCM_IF_ERROR_RETURN(rv); 2575 } 2576 default_vp_delete = TRUE; 2577 } 2578 } 2579 2580 /* Check for GENEVE default port */ 2581 if (SOC_REG_IS_VALID(unit, GENEVE_DEFAULT_NETWORK_SVPr)) { 2582 BCM_IF_ERROR_RETURN(READ_GENEVE_DEFAULT_NETWORK_SVPr(unit, ®_val)); 2583 if (vp == soc_reg_field_get(unit, 2584 GENEVE_DEFAULT_NETWORK_SVPr, reg_val, SVPf)) { 2585 rv = soc_reg_field32_modify(unit, GENEVE_DEFAULT_NETWORK_SVPr, 2586 REG_PORT_ANY, SVPf, 0); 2587 BCM_IF_ERROR_RETURN(rv); 2588 if (default_vp_delete == FALSE) { 2589 rv = _bcm_td3_flow_default_port_delete(unit, vpn, vp); 2590 BCM_IF_ERROR_RETURN(rv); 2591 } 2592 default_vp_delete = TRUE; 2593 } 2594 } 2595 2596 if (default_vp_delete == TRUE) { 2597 return BCM_E_NONE; 2598 } 2599 2600 BCM_IF_ERROR_RETURN(bcmi_esw_flow_vp_is_eline(unit, vp, &isEline)); 2601 2602 if (isEline == 0x1 ) { 2603 rv = _bcm_td3_flow_eline_port_delete(unit, vpn, vp); 2604 } else if (isEline == 0x0 ) { 2605 rv = _bcm_td3_flow_elan_port_delete(unit, vpn, vp); 2606 } 2607 return rv; 2608 } 2609 2610 /* 2611 * Function: 2612 * bcmi_esw_flow_port_delete_all 2613 * Purpose: 2614 * Delete all FLOW ports from a VPN 2615 * Parameters: 2616 * unit - (IN) Device Number 2617 * vpn - (IN) VPN instance ID 2618 * Returns: 2619 * BCM_E_XXX 2620 */ 2621 int 2622 bcmi_esw_flow_port_delete_all(int unit, bcm_vpn_t vpn) 2623 { 2624 int rv = BCM_E_NONE; 2625 int vfi_index=0; 2626 int vp1 = 0, vp2 = 0; 2627 uint8 isEline = 0; 2628 bcm_gport_t flow_port_id; 2629 uint32 vp=0; 2630 2631 if (vpn != BCM_FLOW_VPN_INVALID) { 2632 _BCM_FLOW_VPN_GET(vfi_index, _BCM_VPN_TYPE_VFI, vpn); 2633 BCM_IF_ERROR_RETURN(bcmi_esw_flow_vpn_is_eline(unit, vpn, &isEline)); 2634 } else { 2635 vfi_index = _BCM_FLOW_VFI_INVALID; 2636 } 2637 2638 if (isEline == 0x1 ) { 2639 /* ---- Read in current table values for VP1 and VP2 ----- */ 2640 (void) _bcm_td3_flow_eline_vp_map_get (unit, vfi_index, &vp1, &vp2); 2641 if (vp1 != 0) { 2642 rv = _bcm_td3_flow_eline_port_delete(unit, vpn, vp1); 2643 BCM_IF_ERROR_RETURN(rv); 2644 } 2645 if (vp2 != 0) { 2646 rv = _bcm_td3_flow_eline_port_delete(unit, vpn, vp2); 2647 BCM_IF_ERROR_RETURN(rv); 2648 } 2649 } else if (isEline == 0x0 ) { 2650 uint32 num_vp = 0, entry_type = 0; 2651 source_vp_entry_t svp; 2652 uint32 reg_val=0; 2653 2654 if (SOC_REG_IS_VALID(unit, VXLAN_DEFAULT_NETWORK_SVPr)) { 2655 BCM_IF_ERROR_RETURN(READ_VXLAN_DEFAULT_NETWORK_SVPr(unit, ®_val)); 2656 vp = soc_reg_field_get(unit, VXLAN_DEFAULT_NETWORK_SVPr, reg_val, SVPf); 2657 if (_bcm_vp_used_get(unit, vp, _bcmVpTypeVxlan)) { 2658 BCM_IF_ERROR_RETURN(_bcm_td3_flow_default_port_delete(unit, vpn, vp)); 2659 if (SOC_REG_IS_VALID(unit, DEFAULT_SVP_ENABLEr)) { 2660 rv = soc_reg_field32_modify 2661 (unit, DEFAULT_SVP_ENABLEr, REG_PORT_ANY, VXLAN_DEFAULT_SVP_ENABLEf, 0); 2662 if (BCM_FAILURE(rv)) { 2663 if (rv != BCM_E_NOT_FOUND) { 2664 return rv; 2665 } else { 2666 rv = BCM_E_NONE; 2667 } 2668 } 2669 } 2670 } 2671 } 2672 2673 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 2674 SHR_BIT_ITER(VIRTUAL_INFO(unit)->flow_vp_bitmap, num_vp, vp) { 2675 2676 BCM_IF_ERROR_RETURN(READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp)); 2677 entry_type = soc_SOURCE_VPm_field32_get(unit, &svp, ENTRY_TYPEf); 2678 if ((vfi_index == soc_SOURCE_VPm_field32_get(unit, &svp, VFIf) && 2679 entry_type == _BCM_VXLAN_SOURCE_VP_TYPE_VFI) 2680 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 2681 || SHR_BITGET(VIRTUAL_INFO(unit)->vp_shared_vp_bitmap, vp) 2682 #endif 2683 ) { 2684 if (_bcm_vp_used_get(unit, vp, _bcmVpTypeVpLag)) { 2685 bcm_trunk_t tid = 0; 2686 bcm_trunk_member_t trunk_member; 2687 int port_count = 0; 2688 BCM_IF_ERROR_RETURN( 2689 _bcm_esw_trunk_vp_lag_vp_to_tid(unit, vp, &tid)); 2690 BCM_IF_ERROR_RETURN( 2691 bcm_td2_vp_lag_get(unit, tid, NULL, 1, 2692 &trunk_member, &port_count)); 2693 if (BCM_GPORT_IS_NIV_PORT(trunk_member.gport) || 2694 BCM_GPORT_IS_EXTENDER_PORT(trunk_member.gport)) { 2695 BCM_IF_ERROR_RETURN( 2696 _bcm_vp_free(unit, _bcmVpTypeFlow, 1, vp)); 2697 BCM_IF_ERROR_RETURN( 2698 _bcm_td3_flow_access_niv_pe_reset(unit, vp)); 2699 continue; 2700 } 2701 } 2702 /* Set FLOW port ID */ 2703 BCM_GPORT_FLOW_PORT_ID_SET(flow_port_id, vp); 2704 BCM_IF_ERROR_RETURN(bcmi_esw_flow_port_destroy(unit, vpn, flow_port_id)); 2705 } 2706 } 2707 } 2708 return rv; 2709 } 2710 #endif