flexflow_encap.c (185045B)
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: flexflow_encap.c 8 * Purpose: Flex flow Encap APIs. 9 */ 10 11 #include <shared/bsl.h> 12 #include <soc/defs.h> 13 14 #ifdef INCLUDE_L3 15 16 #include <assert.h> 17 #include <bcm/error.h> 18 #include <soc/error.h> 19 #include <bcm/types.h> 20 #include <soc/drv.h> 21 #include <soc/format.h> 22 #include <bcm_int/esw/trident2plus.h> 23 #include <bcm_int/esw/trident3.h> 24 #include <bcm_int/esw/virtual.h> 25 #include <bcm_int/esw/trx.h> 26 #include <bcm_int/esw/vlan.h> 27 #include <bcm_int/esw/port.h> 28 #include <bcm_int/esw_dispatch.h> 29 #include <bcm_int/esw/stack.h> 30 #include <bcm_int/esw/vpn.h> 31 #include <bcm_int/esw/flow.h> 32 #include <soc/esw/flow_db.h> 33 34 /* encap criteria specifies the key field composition excluding key type. A 35 * same criteria can associate with both fixed key type and flex key type. 36 * encap criteria along with flow_handle and flow_option 37 * determines the key type. In a get/delete operation, user is required to 38 * specify all these parameters. 39 * 40 * for network-facing side: 41 * L3_INTF -- no fixed key type 42 * VFI -- L2GRE_VFI, VXLAN_VFI and flex key types 43 * VFI_DVP -- L2GRE_VFI_DVP,VXLAN_VFI_DVP and flex key types 44 * VFI_DVP_GROUP -- VFI_DVP_GROUP and flex key types 45 * VRF_MAPPING -- VRF_MAPPING and flex key types 46 * 47 * for access-facing side: 48 * L3_INTF -- no fixed key type 49 * VFI_DVP -- VLAN_XLATE_VFI and flex key types 50 * VFI_DVP_GROUP -- VFI_DVP_GROUP and flex key types 51 */ 52 53 #define _BCM_FLOW_DATA_TYPE_COMMON 0 54 #define _BCM_FLOW_PDD_FIELD_MAX 50 55 #define _BCM_FLOW_MODID_SHIFTER 8 56 #define _BCM_FLOW_PORT_MASK 8 57 58 STATIC int _bcm_flow_nexthop_entry_set(int unit, int nh_index, int drop, 59 bcm_flow_port_encap_t *pe_info, int is_network_port); 60 STATIC int _bcm_flow_sd_tag_set(int unit, bcm_flow_encap_config_t *info, 61 uint32 *sd_tag, int *tpid_index); 62 STATIC int _bcm_flow_sd_tag_get(int unit, bcm_flow_encap_config_t *info, 63 uint32 sd_tag, int *tpid_idx); 64 STATIC int _bcm_flow_port_encap_info_convert(bcm_flow_port_encap_t *pe_info, 65 bcm_flow_encap_config_t *info, int port_encap2config); 66 STATIC void _bcm_flow_egr_nh_sd_tag_get(int unit, soc_mem_t hw_mem, 67 uint32 *entry, uint32 *sd_tag); 68 STATIC int _bcm_flow_linked_tbl_sd_tag_get(int unit, soc_mem_t view_id, 69 uint32 *egr_nh, uint32 *sd_tag); 70 STATIC int _bcm_flow_sd_tag_set_to_entry(int unit, 71 bcm_flow_encap_config_t *info, soc_mem_t mem, uint32 *entry, 72 int *tpid_index); 73 STATIC int _bcm_flow_sd_tag_get_from_entry(int unit, 74 bcm_flow_encap_config_t *info, soc_mem_t mem, uint32 *entry, 75 int *tpid_idx); 76 STATIC int _bcm_flow_sd_tag_set_to_format(int unit, 77 bcm_flow_encap_config_t *info, soc_mem_t mem, uint32 *entry, 78 int *tpid_index); 79 STATIC int _bcm_flow_sd_tag_get_from_format(int unit, 80 bcm_flow_encap_config_t *info, soc_mem_t mem, uint32 *entry, 81 int *tpid_idx); 82 83 84 /* 85 * Function: 86 * bcmi_esw_flow_dvp_vlan_xlate_key_set 87 * Description: 88 * Set egress vlan translation key per flow gport. call from 89 * bcm_vlan_control_port_set with control type bcmVlanPortTranslateEgressKey 90 * 91 * Parameters: 92 * unit - (IN) unit number 93 * port_id - (IN) vxlan gport 94 * key_type - (IN) Hardware egress vlan translation key type. 95 * 96 * Return Value: 97 * BCM_E_XXX 98 */ 99 int 100 bcmi_esw_flow_dvp_vlan_xlate_key_set(int unit, bcm_gport_t port_id, 101 int key_type) 102 { 103 int vp, egr_key_type_value = 0, rv = BCM_E_UNAVAIL; 104 soc_mem_t mem = EGR_DVP_ATTRIBUTEm; 105 int network_port = 0; 106 egr_dvp_attribute_entry_t egr_dvp_attribute; 107 _bcm_vp_info_t vp_info; 108 soc_field_t evxlt_field_id = 0; 109 int key_type_value; 110 uint32 data_type; 111 112 vp = BCM_GPORT_FLOW_PORT_ID_GET(port_id); 113 if (vp < 0) { 114 return BCM_E_NOT_FOUND; 115 } 116 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeFlow)) { 117 return BCM_E_NOT_FOUND; 118 } 119 120 /* make sure the dvp is initialized */ 121 if (!_BCM_FLOW_EGR_DVP_USED_GET(unit,vp)) { 122 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 123 "DVP %d not initialized, call bcm_flow_port_encap_set first\n"), vp)); 124 return BCM_E_NOT_FOUND; 125 } 126 BCM_IF_ERROR_RETURN(_bcm_esw_dvp_vtkey_type_value_get(unit, key_type, 127 &key_type_value)); 128 129 /* Check for Network-Port */ 130 BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info)); 131 if (vp_info.flags & _BCM_VP_INFO_NETWORK_PORT) { 132 network_port = TRUE; 133 } else { 134 network_port = FALSE; 135 } 136 137 /* bcmVlanTranslateEgressKeyVpn only for network port*/ 138 if ((!network_port) && (key_type == bcmVlanTranslateEgressKeyVpn)) { 139 return BCM_E_UNAVAIL; 140 } 141 142 sal_memset(&egr_dvp_attribute, 0, 143 sizeof(egr_dvp_attribute_entry_t)); 144 145 soc_mem_lock(unit,mem); 146 rv = soc_mem_read(unit, mem, MEM_BLOCK_ALL, vp, &egr_dvp_attribute); 147 if (BCM_FAILURE(rv)) { 148 soc_mem_unlock(unit,mem); 149 return rv; 150 } 151 152 data_type = soc_mem_field32_get(unit, mem, &egr_dvp_attribute, 153 DATA_TYPEf); 154 if (data_type == _BCM_FLOW_VXLAN_EGRESS_DEST_VP_TYPE) { 155 evxlt_field_id = VXLAN__EVXLT_KEY_SELf; 156 } else if (data_type == _BCM_FLOW_L2GRE_EGRESS_DEST_VP_TYPE) { 157 evxlt_field_id = L2GRE__EVXLT_KEY_SELf; 158 } else if (data_type > _BCM_FLOW_L2GRE_EGRESS_DEST_VP_TYPE) { 159 /* flex type */ 160 /* use vxlt_control_id */ 161 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 162 "DVP %d is for flex flow, TBD\n"), vp)); 163 } else if (data_type == _BCM_FLOW_DATA_TYPE_COMMON) { 164 evxlt_field_id = COMMON__EVXLT_KEY_SELf; 165 } 166 if (evxlt_field_id != 0) { 167 egr_key_type_value = soc_mem_field32_get(unit, mem, &egr_dvp_attribute, 168 evxlt_field_id); 169 170 if (key_type_value != egr_key_type_value) { 171 soc_mem_field32_set(unit, mem, &egr_dvp_attribute, 172 evxlt_field_id, key_type); 173 rv = soc_mem_write(unit, mem, MEM_BLOCK_ANY, 174 vp, &egr_dvp_attribute); 175 } else { 176 /* already exist, same key */ 177 rv = BCM_E_NONE; 178 } 179 } 180 soc_mem_unlock(unit,mem); 181 return rv; 182 } 183 184 /* 185 * Function: 186 * bcmi_esw_flow_dvp_vlan_xlate_key_get 187 * Description: 188 * Get egress vlan translation key per flow gport. call from 189 * bcm_vlan_control_port_get with control type bcmVlanPortTranslateEgressKey 190 * 191 * Parameters: 192 * unit - (IN) unit number 193 * port_id - (IN) vxlan gport 194 * key_type - (OUT) logical egress vlan translation key type. 195 * 196 * Return Value: 197 * BCM_E_XXX 198 */ 199 int 200 bcmi_esw_flow_dvp_vlan_xlate_key_get(int unit, bcm_gport_t port_id, 201 int *key_type) 202 { 203 int vp, egr_key_type_value = 0, rv = BCM_E_UNAVAIL; 204 soc_mem_t mem = EGR_DVP_ATTRIBUTEm; 205 int network_port = 0; 206 egr_dvp_attribute_entry_t egr_dvp_attribute; 207 _bcm_vp_info_t vp_info; 208 soc_field_t evxlt_field_id = 0; 209 uint32 data_type; 210 211 vp = BCM_GPORT_FLOW_PORT_ID_GET(port_id); 212 if (vp < 0) { 213 return BCM_E_NOT_FOUND; 214 } 215 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeFlow)) { 216 return BCM_E_NOT_FOUND; 217 } 218 219 /* make sure the dvp is initialized */ 220 if (!_BCM_FLOW_EGR_DVP_USED_GET(unit,vp)) { 221 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 222 "DVP %d not initialized, call bcm_flow_port_encap_set first\n"), vp)); 223 return BCM_E_NOT_FOUND; 224 } 225 226 /* Check for Network-Port */ 227 BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info)); 228 if (vp_info.flags & _BCM_VP_INFO_NETWORK_PORT) { 229 network_port = TRUE; 230 } else { 231 network_port = FALSE; 232 } 233 234 sal_memset(&egr_dvp_attribute, 0, 235 sizeof(egr_dvp_attribute_entry_t)); 236 237 rv = soc_mem_read(unit, mem, MEM_BLOCK_ALL, vp, &egr_dvp_attribute); 238 if (BCM_FAILURE(rv)) { 239 return rv; 240 } 241 242 data_type = soc_mem_field32_get(unit, mem, &egr_dvp_attribute, 243 DATA_TYPEf); 244 if (data_type == _BCM_FLOW_VXLAN_EGRESS_DEST_VP_TYPE) { 245 evxlt_field_id = VXLAN__EVXLT_KEY_SELf; 246 } else if (data_type == _BCM_FLOW_L2GRE_EGRESS_DEST_VP_TYPE) { 247 evxlt_field_id = L2GRE__EVXLT_KEY_SELf; 248 } else if (data_type > _BCM_FLOW_L2GRE_EGRESS_DEST_VP_TYPE) { 249 /* flex type */ 250 /* use vxlt_control_id */ 251 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 252 "DVP %d is for flex flow, TBD\n"), vp)); 253 } else if (data_type == _BCM_FLOW_DATA_TYPE_COMMON) { 254 evxlt_field_id = COMMON__EVXLT_KEY_SELf; 255 } 256 if (evxlt_field_id != 0) { 257 egr_key_type_value = soc_mem_field32_get(unit, mem, &egr_dvp_attribute, 258 evxlt_field_id); 259 rv = _bcm_esw_dvp_vtkey_type_get(unit, 260 egr_key_type_value, key_type); 261 262 /* bcmVlanTranslateEgressKeyVpn only for network port*/ 263 if ((!network_port) && (*key_type == bcmVlanTranslateEgressKeyVpn)) { 264 return BCM_E_UNAVAIL; 265 } 266 } 267 return rv; 268 } 269 270 STATIC int 271 _bcm_flow_egress_network_dvp_set(int unit, 272 bcm_flow_port_encap_t *info, 273 bcm_flow_logical_field_t *field, 274 int num_of_fields) 275 { 276 277 int rv=BCM_E_UNAVAIL; 278 int local_drop = 0; 279 int network_group=0; 280 soc_mem_t mem_view_id; 281 soc_mem_t mem_id = 0; 282 int dvp; 283 uint32 entry[SOC_MAX_MEM_WORDS]; 284 uint32 dvp_ctrl; 285 soc_field_t dvp_grp_f; 286 soc_field_t network_grp_f; 287 soc_field_t dvp_port_f; 288 soc_field_t dis_vp_p_f; 289 soc_field_t del_vntag_f; 290 soc_field_t class_id_f; 291 soc_field_t mtu_val_f; 292 soc_field_t mtu_en_f; 293 soc_field_t uuc_drop_f; 294 soc_field_t umc_drop_f; 295 soc_field_t bc_drop_f; 296 uint32 data_ids[_BCM_FLOW_LOGICAL_FIELD_MAX]; 297 uint32 cnt; 298 int i; 299 int j; 300 301 dvp = _SHR_GPORT_FLOW_PORT_ID_GET(info->flow_port); 302 mem_id = EGR_DVP_ATTRIBUTEm; 303 304 /* get the physical memory view */ 305 if (_BCM_FLOW_IS_FLEX_VIEW(info)) { 306 rv = soc_flow_db_ffo_to_mem_view_id_get(unit,info->flow_handle, 307 info->flow_option, SOC_FLOW_DB_FUNC_ENCAP_SET_ID, 308 (uint32 *)&mem_view_id); 309 BCM_IF_ERROR_RETURN(rv); 310 LOG_VERBOSE(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 311 "dvp: %d mem_view_id: 0x%x\n"), dvp, mem_view_id)); 312 313 mem_id = mem_view_id; 314 } 315 316 if (info->options & BCM_FLOW_PORT_ENCAP_OPTION_REPLACE) { 317 if (!_BCM_FLOW_EGR_DVP_USED_GET(unit,dvp)) { 318 return BCM_E_NOT_FOUND; 319 } 320 BCM_IF_ERROR_RETURN(soc_mem_read(unit,mem_id, MEM_BLOCK_ANY, dvp, 321 entry)); 322 } else { 323 sal_memset(entry, 0, sizeof(entry)); 324 if (_BCM_FLOW_IS_FLEX_VIEW(info)) { 325 /* flex view, initialize all control fields such as data_type */ 326 soc_flow_db_mem_view_entry_init(unit,mem_view_id,entry); 327 } 328 } 329 330 local_drop = (info->flags & BCM_FLOW_PORT_ENCAP_FLAG_DROP) ? 1 : 0; 331 332 if (info->valid_elements & BCM_FLOW_PORT_ENCAP_NETWORK_GROUP_VALID) { 333 if (soc_feature(unit, soc_feature_multiple_split_horizon_group)){ 334 network_group = info->network_group; 335 rv = _bcm_validate_splithorizon_network_group(unit, 336 TRUE, &network_group); 337 BCM_IF_ERROR_RETURN(rv); 338 } 339 } 340 341 if (!_BCM_FLOW_IS_FLEX_VIEW(info)) { 342 soc_mem_field32_set(unit, mem_id, entry, DATA_TYPEf, 343 info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN? 344 _BCM_FLOW_VXLAN_EGRESS_DEST_VP_TYPE: 345 _BCM_FLOW_L2GRE_EGRESS_DEST_VP_TYPE); 346 347 if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) { 348 dvp_grp_f = VXLAN__VT_DVP_GROUP_IDf; 349 network_grp_f = VXLAN__DVP_NETWORK_GROUPf; 350 dvp_port_f = VXLAN__DVP_IS_NETWORK_PORTf; 351 dis_vp_p_f = VXLAN__DISABLE_VP_PRUNINGf; 352 del_vntag_f = VXLAN__DELETE_VNTAGf; 353 class_id_f = VXLAN__CLASS_IDf; 354 mtu_val_f = VXLAN__MTU_VALUEf; 355 mtu_en_f = VXLAN__MTU_ENABLEf; 356 uuc_drop_f = VXLAN__UUC_DROPf; 357 umc_drop_f = VXLAN__UMC_DROPf; 358 bc_drop_f = VXLAN__BC_DROPf; 359 } else if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) { 360 dvp_grp_f = L2GRE__VT_DVP_GROUP_IDf; 361 network_grp_f = L2GRE__DVP_NETWORK_GROUPf; 362 dvp_port_f = L2GRE__DVP_IS_NETWORK_PORTf; 363 dis_vp_p_f = L2GRE__DISABLE_VP_PRUNINGf; 364 del_vntag_f = L2GRE__DELETE_VNTAGf; 365 class_id_f = L2GRE__CLASS_IDf; 366 mtu_val_f = L2GRE__MTU_VALUEf; 367 mtu_en_f = L2GRE__MTU_ENABLEf; 368 uuc_drop_f = L2GRE__UUC_DROPf; 369 umc_drop_f = L2GRE__UMC_DROPf; 370 bc_drop_f = L2GRE__BC_DROPf; 371 } else { 372 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 373 "flow handle: %d unsupported\n"), info->flow_handle)); 374 return BCM_E_PARAM; 375 } 376 377 if (info->valid_elements & BCM_FLOW_PORT_ENCAP_NETWORK_GROUP_VALID) { 378 if (soc_feature(unit, soc_feature_multiple_split_horizon_group)){ 379 soc_mem_field32_set(unit, mem_id, entry, network_grp_f, 380 network_group); 381 } else { 382 soc_mem_field32_set(unit, mem_id, entry, dvp_port_f, 1); 383 } 384 } 385 soc_mem_field32_set(unit, mem_id, entry, dis_vp_p_f, 0); 386 soc_mem_field32_set(unit, mem_id, entry, del_vntag_f, 1); 387 if (info->valid_elements & BCM_FLOW_PORT_ENCAP_CLASS_ID_VALID) { 388 soc_mem_field32_set(unit, mem_id, entry, class_id_f,info->class_id); 389 } 390 if (info->valid_elements & BCM_FLOW_PORT_ENCAP_MTU_VALID) { 391 soc_mem_field32_set(unit, mem_id, entry, mtu_val_f, info->mtu); 392 soc_mem_field32_set(unit, mem_id, entry, mtu_en_f, info->mtu? 1: 0); 393 } 394 if (info->valid_elements & BCM_FLOW_PORT_ENCAP_DVP_GROUP_VALID) { 395 soc_mem_field32_set(unit, mem_id, entry, dvp_grp_f,info->dvp_group); 396 } 397 soc_mem_field32_set(unit, mem_id, entry, uuc_drop_f, local_drop); 398 soc_mem_field32_set(unit, mem_id, entry, umc_drop_f, local_drop); 399 soc_mem_field32_set(unit, mem_id, entry, bc_drop_f, local_drop); 400 401 } else { 402 403 if (info->valid_elements & BCM_FLOW_PORT_ENCAP_NETWORK_GROUP_VALID) { 404 if (SOC_MEM_FIELD_VALID(unit,mem_id,SWITCHING_CTRLS_ACTION_SETf)) { 405 dvp_ctrl = 0; 406 if (soc_feature(unit, soc_feature_multiple_split_horizon_group)){ 407 soc_format_field32_set(unit, DVP_SWITCHING_CTRLS_ACTION_SETfmt, 408 &dvp_ctrl, DVP_NETWORK_GROUPf,network_group); 409 } 410 soc_format_field32_set(unit, DVP_SWITCHING_CTRLS_ACTION_SETfmt, 411 &dvp_ctrl, DISABLE_VP_PRUNINGf,0); 412 413 soc_format_field32_set(unit, DVP_SWITCHING_CTRLS_ACTION_SETfmt, 414 &dvp_ctrl, UUC_DROPf,local_drop); 415 soc_format_field32_set(unit, DVP_SWITCHING_CTRLS_ACTION_SETfmt, 416 &dvp_ctrl, UMC_DROPf,local_drop); 417 soc_format_field32_set(unit, DVP_SWITCHING_CTRLS_ACTION_SETfmt, 418 &dvp_ctrl, BC_DROPf,local_drop); 419 soc_mem_field32_set(unit, mem_id, entry, 420 SWITCHING_CTRLS_ACTION_SETf, dvp_ctrl); 421 } else { 422 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 423 "SWITCHING_CTRLS_ACTION_SETf not defined in memory view\n"))); 424 return BCM_E_PARAM; 425 } 426 } 427 if (info->valid_elements & BCM_FLOW_PORT_ENCAP_CLASS_ID_VALID) { 428 if (SOC_MEM_FIELD_VALID(unit,mem_id,CLASS_ID_ACTION_SETf)) { 429 soc_mem_field32_set(unit, mem_id, entry, CLASS_ID_ACTION_SETf, 430 info->class_id); 431 } else { 432 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 433 "CLASS_ID_ACTION_SETf not defined in memory view\n"))); 434 return BCM_E_INTERNAL; 435 } 436 } 437 if (info->valid_elements & BCM_FLOW_PORT_ENCAP_MTU_VALID) { 438 if (SOC_MEM_FIELD_VALID(unit,mem_id,MTU_CONTROLS_ACTION_SETf)) { 439 uint32 mtu = 0; 440 441 soc_format_field32_set(unit, MTU_CONTROLS_ACTION_SETfmt, 442 &mtu, MTU_VALUEf,info->mtu); 443 soc_format_field32_set(unit, MTU_CONTROLS_ACTION_SETfmt, 444 &mtu, MTU_ENABLEf,info->mtu? 1 : 0); 445 soc_mem_field32_set(unit, mem_id, entry, 446 MTU_CONTROLS_ACTION_SETf, mtu); 447 } else { 448 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 449 "MTU_CONTROLS_ACTION_SETf not defined in memory view\n"))); 450 return BCM_E_PARAM; 451 } 452 } 453 if (info->valid_elements & BCM_FLOW_PORT_ENCAP_DVP_GROUP_VALID) { 454 if (SOC_MEM_FIELD_VALID(unit,mem_id,VXLT_CLASS_IDf)) { 455 soc_mem_field32_set(unit, mem_id, entry, VXLT_CLASS_IDf, 456 info->dvp_group); 457 } else { 458 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 459 "VXLT_CLASS_IDf not defined in memory view\n"))); 460 return BCM_E_PARAM; 461 } 462 } 463 464 if (info->valid_elements & BCM_FLOW_PORT_ENCAP_FLEX_DATA_VALID) { 465 rv = soc_flow_db_mem_view_field_list_get(unit, 466 mem_id, 467 SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA, 468 _BCM_FLOW_LOGICAL_FIELD_MAX, data_ids, &cnt); 469 BCM_IF_ERROR_RETURN(rv); 470 for (i = 0; i < num_of_fields; i++) { 471 for (j = 0; j < cnt; j++) { 472 if (field[i].id == data_ids[j]) { 473 soc_mem_field32_set(unit,mem_id, entry, 474 field[i].id, field[i].value); 475 break; 476 } 477 } 478 } 479 } 480 } 481 rv = soc_mem_write(unit, mem_id, MEM_BLOCK_ALL, dvp, entry); 482 BCM_IF_ERROR_RETURN(rv); 483 return rv; 484 } 485 486 STATIC int 487 _bcm_flow_egress_dvp_get(int unit, 488 bcm_flow_port_encap_t *info, 489 bcm_flow_logical_field_t *field, 490 int num_of_fields) 491 { 492 493 int rv; 494 int local_drop = 0; 495 soc_mem_t mem_id = 0; 496 int dvp; 497 uint32 entry[SOC_MAX_MEM_WORDS]; 498 uint32 dvp_ctrl; 499 soc_field_t dvp_grp_f; 500 soc_field_t netowk_grp_f; 501 soc_field_t class_id_f; 502 soc_field_t mtu_val_f; 503 soc_field_t uuc_drop_f; 504 uint32 data_type; 505 uint32 data_ids[_BCM_FLOW_LOGICAL_FIELD_MAX]; 506 uint32 cnt; 507 int i; 508 int j; 509 soc_mem_t mem_view_id; 510 511 dvp = _SHR_GPORT_FLOW_PORT_ID_GET(info->flow_port); 512 mem_id = EGR_DVP_ATTRIBUTEm; 513 514 BCM_IF_ERROR_RETURN(soc_mem_read(unit,mem_id, MEM_BLOCK_ANY, dvp, 515 entry)); 516 data_type = soc_mem_field32_get(unit, mem_id, entry, DATA_TYPEf); 517 518 if (data_type == _BCM_FLOW_DATA_TYPE_COMMON) { 519 info->flow_handle = 0; 520 info->mtu = soc_mem_field32_get(unit, mem_id, entry, 521 COMMON__MTU_VALUEf); 522 info->network_group = soc_mem_field32_get(unit, mem_id, entry, 523 COMMON__DVP_NETWORK_GROUPf); 524 return BCM_E_NONE; 525 } else if (data_type == _BCM_FLOW_VXLAN_EGRESS_DEST_VP_TYPE) { 526 info->flow_handle = SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN; 527 } else if (data_type == _BCM_FLOW_L2GRE_EGRESS_DEST_VP_TYPE) { 528 info->flow_handle = SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE; 529 } else { /* flex */ 530 /* find the memory view based on the memory and key type */ 531 rv = soc_flow_db_mem_to_view_id_get (unit, mem_id, 532 SOC_FLOW_DB_KEY_TYPE_INVALID, data_type, 533 0, NULL, (uint32 *)&mem_view_id); 534 SOC_IF_ERROR_RETURN(rv); 535 mem_id = mem_view_id; 536 } 537 538 if (data_type <= _BCM_FLOW_L2GRE_EGRESS_DEST_VP_TYPE) { /* fixed view */ 539 if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) { 540 netowk_grp_f = VXLAN__DVP_NETWORK_GROUPf; 541 dvp_grp_f = VXLAN__VT_DVP_GROUP_IDf; 542 class_id_f = VXLAN__CLASS_IDf; 543 mtu_val_f = VXLAN__MTU_VALUEf; 544 uuc_drop_f = VXLAN__UUC_DROPf; 545 } else { 546 netowk_grp_f = L2GRE__DVP_NETWORK_GROUPf; 547 dvp_grp_f = L2GRE__VT_DVP_GROUP_IDf; 548 class_id_f = L2GRE__CLASS_IDf; 549 mtu_val_f = L2GRE__MTU_VALUEf; 550 uuc_drop_f = L2GRE__UUC_DROPf; 551 } 552 info->network_group = soc_mem_field32_get(unit, mem_id, entry, 553 netowk_grp_f); 554 info->dvp_group = soc_mem_field32_get(unit, mem_id, entry, 555 dvp_grp_f); 556 557 info->class_id = soc_mem_field32_get(unit, mem_id, entry, class_id_f); 558 info->mtu = soc_mem_field32_get(unit, mem_id, entry, mtu_val_f); 559 local_drop = soc_mem_field32_get(unit, mem_id, entry, uuc_drop_f); 560 if (local_drop) { 561 info->flags |= BCM_FLOW_PORT_ENCAP_FLAG_DROP; 562 } 563 564 } else { /* flex view */ 565 if (SOC_MEM_FIELD_VALID(unit,mem_id,SWITCHING_CTRLS_ACTION_SETf)) { 566 dvp_ctrl = soc_mem_field32_get(unit, mem_id, entry, 567 SWITCHING_CTRLS_ACTION_SETf); 568 info->network_group = soc_format_field32_get(unit, 569 DVP_SWITCHING_CTRLS_ACTION_SETfmt, 570 &dvp_ctrl, DVP_NETWORK_GROUPf); 571 local_drop = soc_format_field32_get(unit, 572 DVP_SWITCHING_CTRLS_ACTION_SETfmt, 573 &dvp_ctrl, UUC_DROPf); 574 } 575 if (SOC_MEM_FIELD_VALID(unit,mem_id,CLASS_ID_ACTION_SETf)) { 576 info->class_id = soc_mem_field32_get(unit, mem_id, entry, 577 CLASS_ID_ACTION_SETf); 578 } 579 if (SOC_MEM_FIELD_VALID(unit,mem_id,MTU_CONTROLS_ACTION_SETf)) { 580 uint32 mtu = 0; 581 582 mtu = soc_mem_field32_get(unit, mem_id, entry, 583 MTU_CONTROLS_ACTION_SETf); 584 info->mtu = soc_format_field32_get(unit, MTU_CONTROLS_ACTION_SETfmt, 585 &mtu, MTU_VALUEf); 586 } 587 if (SOC_MEM_FIELD_VALID(unit,mem_id,VXLT_CLASS_IDf)) { 588 info->dvp_group = soc_mem_field32_get(unit, mem_id, entry, 589 VXLT_CLASS_IDf); 590 } 591 592 if (field != NULL && num_of_fields) { 593 rv = soc_flow_db_mem_view_field_list_get(unit, 594 mem_id, 595 SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA, 596 _BCM_FLOW_LOGICAL_FIELD_MAX, data_ids, &cnt); 597 BCM_IF_ERROR_RETURN(rv); 598 for (i = 0; i < num_of_fields; i++) { 599 for (j = 0; j < cnt; j++) { 600 if (field[i].id == data_ids[j]) { 601 field[i].value = soc_mem_field32_get(unit,mem_id, entry, 602 field[i].id); 603 break; 604 } 605 } 606 } 607 } 608 } 609 return BCM_E_NONE; 610 } 611 612 STATIC int 613 _bcm_flow_egress_access_dvp_set(int unit, 614 bcm_flow_port_encap_t *info, 615 bcm_flow_logical_field_t *field, 616 int num_of_fields) 617 { 618 int rv = BCM_E_UNAVAIL; 619 soc_mem_t mem = EGR_DVP_ATTRIBUTEm; 620 uint32 entry[SOC_MAX_MEM_WORDS]; 621 int dvp; 622 soc_mem_t mem_view_id; 623 uint32 data_ids[_BCM_FLOW_LOGICAL_FIELD_MAX]; 624 uint32 cnt; 625 int i; 626 int j; 627 int network_group = 0; 628 629 dvp = _SHR_GPORT_FLOW_PORT_ID_GET(info->flow_port); 630 631 /* get the physical memory view */ 632 if (_BCM_FLOW_IS_FLEX_VIEW(info)) { 633 rv = soc_flow_db_ffo_to_mem_view_id_get(unit,info->flow_handle, 634 info->flow_option, SOC_FLOW_DB_FUNC_ENCAP_SET_ID, 635 (uint32 *)&mem_view_id); 636 BCM_IF_ERROR_RETURN(rv); 637 mem = mem_view_id; 638 } 639 640 if (info->options & BCM_FLOW_PORT_ENCAP_OPTION_REPLACE) { 641 if (!_BCM_FLOW_EGR_DVP_USED_GET(unit,dvp)) { 642 return BCM_E_NOT_FOUND; 643 } 644 BCM_IF_ERROR_RETURN(soc_mem_read(unit,mem, MEM_BLOCK_ANY, dvp, 645 entry)); 646 } else { 647 sal_memset(entry, 0, sizeof(entry)); 648 if (_BCM_FLOW_IS_FLEX_VIEW(info)) { 649 /* flex view, initialize all control fields such as data_type */ 650 soc_flow_db_mem_view_entry_init(unit,mem_view_id,entry); 651 } 652 } 653 654 if (info->valid_elements & BCM_FLOW_PORT_ENCAP_NETWORK_GROUP_VALID) { 655 if (soc_feature(unit, soc_feature_multiple_split_horizon_group)){ 656 network_group = info->network_group; 657 rv = _bcm_validate_splithorizon_network_group(unit, 658 TRUE, &network_group); 659 BCM_IF_ERROR_RETURN(rv); 660 } 661 } 662 663 if (!_BCM_FLOW_IS_FLEX_VIEW(info)) { 664 if (info->valid_elements & BCM_FLOW_PORT_ENCAP_MTU_VALID) { 665 /* L2 MTU - This is different from L3 MTU */ 666 if (info->mtu > 0) { 667 soc_mem_field32_set(unit, mem, entry, COMMON__MTU_VALUEf, 668 info->mtu); 669 soc_mem_field32_set(unit, mem, entry, COMMON__MTU_ENABLEf, 0x1); 670 } else { 671 /* Disable mtu checking if mtu = 0 */ 672 soc_mem_field32_set(unit, mem, entry, COMMON__MTU_ENABLEf, 0x0); 673 } 674 } 675 676 if (info->valid_elements & BCM_FLOW_PORT_ENCAP_NETWORK_GROUP_VALID) { 677 if (soc_feature(unit, soc_feature_multiple_split_horizon_group)){ 678 soc_mem_field32_set(unit, mem, entry, COMMON__DVP_NETWORK_GROUPf, 679 network_group); 680 } 681 } 682 } else { 683 if (info->valid_elements & BCM_FLOW_PORT_ENCAP_MTU_VALID) { 684 if (SOC_MEM_FIELD_VALID(unit,mem,MTU_CONTROLS_ACTION_SETf)) { 685 uint32 mtu = 0; 686 687 soc_format_field32_set(unit, MTU_CONTROLS_ACTION_SETfmt, 688 &mtu, MTU_VALUEf,info->mtu); 689 soc_format_field32_set(unit, MTU_CONTROLS_ACTION_SETfmt, 690 &mtu, MTU_ENABLEf,info->mtu? 1 : 0); 691 soc_mem_field32_set(unit, mem, entry, 692 MTU_CONTROLS_ACTION_SETf, mtu); 693 } 694 } 695 696 if (info->valid_elements & BCM_FLOW_PORT_ENCAP_FLEX_DATA_VALID) { 697 rv = soc_flow_db_mem_view_field_list_get(unit, 698 mem, 699 SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA, 700 _BCM_FLOW_LOGICAL_FIELD_MAX, data_ids, &cnt); 701 BCM_IF_ERROR_RETURN(rv); 702 for (i = 0; i < num_of_fields; i++) { 703 for (j = 0; j < cnt; j++) { 704 if (field[i].id == data_ids[j]) { 705 soc_mem_field32_set(unit,mem, entry, 706 field[i].id, field[i].value); 707 break; 708 } 709 } 710 } 711 } 712 } 713 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, dvp, entry); 714 BCM_IF_ERROR_RETURN(rv); 715 716 return rv; 717 } 718 719 /* 720 * Function: 721 * _bcm_flow_nh_cnt_dec 722 * Purpose: 723 * Decrease vxlan port's nexthop count. 724 * Parameters: 725 * unit - (IN) SOC unit number. 726 * vp - (IN) Virtual port number. 727 * Returns: 728 * BCM_E_XXX 729 */ 730 731 STATIC int 732 _bcm_flow_nh_cnt_dec(int unit, int vp) 733 { 734 int nh_ecmp_index = -1; 735 ing_dvp_table_entry_t dvp; 736 uint32 flags = 0; 737 int ref_count = 0; 738 int ecmp = 0; 739 740 BCM_IF_ERROR_RETURN( 741 READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp)); 742 743 ecmp = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMPf); 744 if (ecmp) { 745 nh_ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMP_PTRf); 746 flags = BCM_L3_MULTIPATH; 747 /* Decrement reference count */ 748 BCM_IF_ERROR_RETURN( 749 bcm_xgs3_get_ref_count_from_nhi(unit, flags, &ref_count, nh_ecmp_index)); 750 } else { 751 nh_ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, 752 NEXT_HOP_INDEXf); 753 if(nh_ecmp_index != 0) { 754 /* Decrement reference count */ 755 BCM_IF_ERROR_RETURN( 756 bcm_xgs3_get_ref_count_from_nhi(unit, flags, &ref_count, nh_ecmp_index)); 757 } 758 } 759 760 return BCM_E_NONE; 761 } 762 763 /* 764 * Function: 765 * _bcm_flow_ecmp_member_egress_get_first 766 * Purpose: 767 * Modify flow ecmp member object's Egress next hop entry 768 * Parameters: 769 * unit - Device Number 770 * ecmp_index - ECMP index 771 * index - poiter to first next hop index 772 * Returns: 773 * BCM_E_XXX 774 */ 775 776 STATIC int 777 _bcm_flow_ecmp_member_egress_get_first(int unit, int ecmp_index, int* index) 778 { 779 int i = 0, ecmp_member_count = 0; 780 int alloc_size; 781 bcm_if_t *ecmp_member_array = NULL; 782 int rv = BCM_E_NONE; 783 784 if (!BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, ecmp_index)) { 785 return BCM_E_PARAM; 786 } 787 alloc_size = sizeof(bcm_if_t)*BCM_XGS3_L3_ECMP_MAX(unit); 788 ecmp_member_array = sal_alloc(alloc_size, "ecmp member array"); 789 if (NULL == ecmp_member_array) { 790 return BCM_E_MEMORY; 791 } 792 sal_memset(ecmp_member_array, 0, alloc_size); 793 794 rv = bcm_xgs3_l3_egress_multipath_get(unit, ecmp_index, BCM_XGS3_L3_ECMP_MAX(unit), 795 ecmp_member_array, &ecmp_member_count); 796 if (BCM_FAILURE(rv)) { 797 goto clean_up; 798 } 799 800 if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, 801 ecmp_member_array[i])) { 802 *index = (ecmp_member_array[i] - BCM_XGS3_EGRESS_IDX_MIN(unit)); 803 } else { 804 rv = BCM_E_PARAM; 805 goto clean_up; 806 } 807 clean_up: 808 if (ecmp_member_array) { 809 sal_free(ecmp_member_array); 810 ecmp_member_array = NULL; 811 } 812 813 return rv; 814 } 815 816 817 /* 818 * Function: 819 * _bcm_flow_port_egr_nh_get 820 * Purpose: 821 * Get FLOW Next Hop entry 822 * Parameters: 823 * Returns: 824 * BCM_E_XXX 825 */ 826 827 STATIC int 828 _bcm_flow_port_egr_nh_get(int unit, bcm_flow_port_encap_t *info) 829 { 830 egr_l3_next_hop_entry_t egr_nh; 831 ing_dvp_table_entry_t dvp; 832 bcm_flow_encap_config_t einfo; 833 int nh_ecmp_index=0; 834 uint32 ecmp=0; 835 int vp_type; 836 int rv = BCM_E_NONE; 837 uint32 action_set = 0; 838 uint8 process_sd_tag = 0; 839 uint8 process_higig_controls = 0; 840 uint8 process_switching_controls = 0; 841 int i; 842 int vp; 843 int data_type; 844 uint32 view_id = 0; 845 uint32 flex_data_array[_BCM_FLOW_PDD_FIELD_MAX]; 846 uint32 flex_data_count; 847 int old_tpid_idx; 848 soc_mem_t mem; 849 int num_vp; 850 uint32 sd_tag; 851 852 vp = _SHR_GPORT_FLOW_PORT_ID_GET(info->flow_port); 853 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 854 if ((vp <= 0) || (vp >= num_vp)) { 855 return BCM_E_PARAM; 856 } 857 mem = EGR_L3_NEXT_HOPm; 858 859 /* Read the HW entries */ 860 BCM_IF_ERROR_RETURN (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp)); 861 vp_type = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, VP_TYPEf); 862 if (vp_type == _BCM_FLOW_VXLAN_INGRESS_DEST_VP_TYPE || 863 vp_type == _BCM_FLOW_L2GRE_INGRESS_DEST_VP_TYPE) { 864 ecmp = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMPf); 865 if (ecmp) { 866 nh_ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, 867 ECMP_PTRf); 868 info->egress_if = nh_ecmp_index + 869 BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit); 870 /*get ecmp's first member nexthop index*/ 871 BCM_IF_ERROR_RETURN(_bcm_flow_ecmp_member_egress_get_first(unit, 872 info->egress_if, &nh_ecmp_index)); 873 } else { 874 nh_ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, 875 NEXT_HOP_INDEXf); 876 /* Extract next hop index from unipath egress object. */ 877 info->egress_if = nh_ecmp_index + BCM_XGS3_EGRESS_IDX_MIN(unit); 878 } 879 880 } else if (soc_ING_DVP_TABLEm_field32_get(unit, &dvp, 881 VP_TYPEf) == _BCM_FLOW_DEST_VP_TYPE_ACCESS) { 882 /* Egress into Access-side, find the tunnel_if */ 883 BCM_IF_ERROR_RETURN( 884 READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp)); 885 nh_ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, 886 NEXT_HOP_INDEXf); 887 /* Extract next hop index from unipath egress object. */ 888 info->egress_if = nh_ecmp_index + BCM_XGS3_EGRESS_IDX_MIN(unit); 889 } else { 890 return BCM_E_NOT_FOUND; 891 } 892 893 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 894 nh_ecmp_index, &egr_nh)); 895 896 data_type = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, DATA_TYPEf); 897 898 if (BCMI_L3_NH_FLEX_VIEW(data_type)) { 899 /* Get view id corresponding to the data type. */ 900 rv = soc_flow_db_mem_to_view_id_get(unit, 901 mem, 902 SOC_FLOW_DB_KEY_TYPE_INVALID, 903 data_type, 904 0, 905 NULL, 906 &view_id); 907 BCM_IF_ERROR_RETURN(rv); 908 909 /* Get PDD field list corresponding to the view id. */ 910 rv = soc_flow_db_mem_view_field_list_get(unit, 911 view_id, 912 SOC_FLOW_DB_FIELD_TYPE_POLICY_DATA, 913 _BCM_FLOW_PDD_FIELD_MAX, 914 flex_data_array, 915 &flex_data_count); 916 917 BCM_IF_ERROR_RETURN(rv); 918 919 for (i=0; i<flex_data_count; i++) { 920 switch (flex_data_array[i]) { 921 case SD_TAG_ACTION_SETf: 922 process_sd_tag = 1; 923 break; 924 case HIGIG_CONTROLS_ACTION_SETf: 925 process_higig_controls = 1; 926 break; 927 case SWITCHING_CTRLS_ACTION_SETf: 928 process_switching_controls = 1; 929 break; 930 default: 931 break; 932 } 933 } 934 } 935 936 if (BCMI_L3_NH_FLEX_VIEW(data_type) || 937 (data_type == _BCM_VXLAN_EGR_NEXT_HOP_SDTAG_VIEW) || 938 (data_type == _BCM_VXLAN_EGR_NEXT_HOP_L2OTAG_VIEW)) { 939 940 bcm_flow_encap_config_t_init(&einfo); 941 /* just to give a flex handle to indicate the flex view */ 942 if (BCMI_L3_NH_FLEX_VIEW(data_type)) { 943 einfo.flow_handle = SOC_FLOW_DB_FLOW_ID_START + 1; 944 if (process_sd_tag) { 945 sd_tag = soc_mem_field32_get(unit, view_id, &egr_nh, 946 SD_TAG_ACTION_SETf); 947 } else { 948 /* check other linked tables */ 949 (void)_bcm_flow_linked_tbl_sd_tag_get(unit, view_id, 950 (uint32 *)&egr_nh, &sd_tag); 951 } 952 } else { 953 if (data_type != _BCM_VXLAN_EGR_NEXT_HOP_L2OTAG_VIEW) { 954 _bcm_flow_egr_nh_sd_tag_get(unit, mem, (uint32 *)&egr_nh, &sd_tag); 955 } 956 } 957 958 if (data_type == _BCM_VXLAN_EGR_NEXT_HOP_L2OTAG_VIEW) { 959 rv = _bcm_flow_sd_tag_get_from_entry(unit, &einfo, mem, 960 (uint32 *)&egr_nh, &old_tpid_idx); 961 } else { 962 rv = _bcm_flow_sd_tag_get(unit, &einfo, sd_tag, &old_tpid_idx); 963 } 964 BCM_IF_ERROR_RETURN(rv); 965 rv = _bcm_flow_port_encap_info_convert(info, &einfo, FALSE); 966 BCM_IF_ERROR_RETURN(rv); 967 } 968 969 if (BCMI_L3_NH_FLEX_VIEW(data_type)) { 970 if (process_switching_controls) { 971 int drop; 972 action_set = 0; 973 974 action_set = soc_mem_field32_get(unit, view_id, &egr_nh, 975 SWITCHING_CTRLS_ACTION_SETf); 976 drop = soc_format_field32_get(unit, SWITCHING_CTRLS_ACTION_SETfmt, 977 &action_set, L2_DROPf); 978 if (drop) { 979 info->flags |= BCM_FLOW_PORT_ENCAP_FLAG_DROP; 980 } 981 if (process_higig_controls) { 982 action_set = soc_mem_field32_get(unit, view_id, &egr_nh, 983 HIGIG_CONTROLS_ACTION_SETf); 984 if (soc_format_field32_get(unit, HIGIG_CONTROLS_ACTION_SETfmt, 985 &action_set, HG_HDR_SELf)) { 986 info->flags |= BCM_FLOW_PORT_ENCAP_FLAG_LOCAL; 987 } 988 } 989 } 990 } else { 991 if (data_type == _BCM_VXLAN_EGR_NEXT_HOP_SDTAG_VIEW) { 992 if (soc_mem_field32_get(unit, mem, &egr_nh, SD_TAG__BC_DROPf) 993 || soc_mem_field32_get(unit, mem, &egr_nh, SD_TAG__UUC_DROPf) 994 || soc_mem_field32_get(unit, mem, &egr_nh, SD_TAG__UMC_DROPf)) { 995 info->flags |= BCM_FLOW_PORT_ENCAP_FLAG_DROP; 996 } 997 } else if (data_type == _BCM_VXLAN_EGR_NEXT_HOP_L3_VIEW) { 998 if (!soc_mem_field32_get(unit, mem, &egr_nh, L3__HG_HDR_SELf)) { 999 info->flags |= BCM_FLOW_PORT_ENCAP_FLAG_LOCAL; 1000 } 1001 } else if (data_type == _BCM_VXLAN_EGR_NEXT_HOP_L2OTAG_VIEW) { 1002 if (soc_mem_field32_get(unit, mem, &egr_nh, L2_OTAG__BC_DROPf) 1003 || soc_mem_field32_get(unit, mem, &egr_nh, L2_OTAG__UUC_DROPf) 1004 || soc_mem_field32_get(unit, mem, &egr_nh, L2_OTAG__UMC_DROPf)) { 1005 info->flags |= BCM_FLOW_PORT_ENCAP_FLAG_DROP; 1006 } 1007 } 1008 } 1009 return rv; 1010 } 1011 1012 /* 1013 * Function: 1014 * _bcm_flow_ingress_dvp_2_set 1015 * Purpose: 1016 * Set Ingress DVP tables 1017 * Parameters: 1018 * IN : Unit 1019 * IN : vp 1020 * IN : flow_port 1021 * Returns: 1022 * BCM_E_XXX 1023 */ 1024 1025 STATIC int 1026 _bcm_flow_ingress_dvp_2_set(int unit, int vp, uint32 mpath_flag, 1027 int vp_nh_ecmp_index, bcm_flow_port_encap_t *info, 1028 int is_network_port) 1029 { 1030 ing_dvp_2_table_entry_t dvp; 1031 int rv = BCM_E_NONE; 1032 int network_group=0; 1033 1034 if (info->options & BCM_FLOW_PORT_ENCAP_OPTION_REPLACE) { 1035 BCM_IF_ERROR_RETURN( 1036 READ_ING_DVP_2_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp)); 1037 } else { 1038 sal_memset(&dvp, 0, sizeof(ing_dvp_2_table_entry_t)); 1039 } 1040 1041 if (info->valid_elements & BCM_FLOW_PORT_ENCAP_EGRESS_IF_VALID) { 1042 if (mpath_flag) { 1043 soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp, 1044 NEXT_HOP_INDEXf, 0x0); 1045 soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp, 1046 ECMPf, 0x1); 1047 soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp, 1048 ECMP_PTRf, vp_nh_ecmp_index); 1049 } else { 1050 soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp, 1051 ECMPf, 0x0); 1052 soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp, 1053 ECMP_PTRf, 0); 1054 soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp, 1055 NEXT_HOP_INDEXf, vp_nh_ecmp_index); 1056 } 1057 } 1058 1059 network_group = info->network_group; 1060 rv = _bcm_validate_splithorizon_network_group(unit, is_network_port, 1061 &network_group); 1062 BCM_IF_ERROR_RETURN(rv); 1063 1064 /* Enable DVP as Network_port */ 1065 if (is_network_port) { 1066 /* Not setting dvp as network port for RIOT as all 1067 routed packet gets dropped if overlay SVP and DVP 1068 both are network ports. 1069 SVP and DVP as network ports is a valid used case 1070 but reg file says that this field 1071 is set when DVP is a TRILL port */ 1072 #ifdef BCM_RIOT_SUPPORT 1073 if ((BCMI_RIOT_IS_ENABLED(unit))) { 1074 if (soc_feature(unit, 1075 soc_feature_multiple_split_horizon_group)) { 1076 soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp, 1077 NETWORK_GROUPf, 0x0); 1078 } else { 1079 soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp, 1080 NETWORK_PORTf, 0x0); 1081 } 1082 } else 1083 #endif 1084 { 1085 if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) { 1086 soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp, NETWORK_GROUPf, 1087 network_group); 1088 } else { 1089 soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp, 1090 NETWORK_PORTf, 0x1); 1091 } 1092 } 1093 if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) { 1094 soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp, 1095 VP_TYPEf, _BCM_FLOW_L2GRE_INGRESS_DEST_VP_TYPE); 1096 } else { 1097 soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp, 1098 VP_TYPEf, _BCM_FLOW_VXLAN_INGRESS_DEST_VP_TYPE); 1099 } 1100 } else { 1101 if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) { 1102 soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp, NETWORK_GROUPf, 1103 network_group); 1104 } else { 1105 soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp, NETWORK_PORTf, 0x0); 1106 } 1107 soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp, 1108 VP_TYPEf, _BCM_FLOW_DEST_VP_TYPE_ACCESS); 1109 } 1110 1111 rv = WRITE_ING_DVP_2_TABLEm(unit, MEM_BLOCK_ALL, vp, &dvp); 1112 return rv; 1113 } 1114 1115 /* 1116 * Function: 1117 * _bcm_flow_ingress_dvp_set 1118 * Purpose: 1119 * Set Ingress DVP tables 1120 * Parameters: 1121 * IN : Unit 1122 * IN : vp 1123 * IN : flow_port 1124 * Returns: 1125 * BCM_E_XXX 1126 */ 1127 1128 STATIC int 1129 _bcm_flow_ingress_dvp_set(int unit, int vp, uint32 mpath_flag, 1130 int vp_nh_ecmp_index, bcm_flow_port_encap_t *info, 1131 int is_network_port) 1132 { 1133 ing_dvp_table_entry_t dvp; 1134 int rv = BCM_E_NONE; 1135 1136 if (info->options & BCM_FLOW_PORT_ENCAP_OPTION_REPLACE) { 1137 BCM_IF_ERROR_RETURN( 1138 READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp)); 1139 } else { 1140 sal_memset(&dvp, 0, sizeof(ing_dvp_table_entry_t)); 1141 } 1142 1143 if (info->valid_elements & BCM_FLOW_PORT_ENCAP_EGRESS_IF_VALID) { 1144 if (mpath_flag) { 1145 soc_ING_DVP_TABLEm_field32_set(unit, &dvp, 1146 NEXT_HOP_INDEXf, 0x0); 1147 soc_ING_DVP_TABLEm_field32_set(unit, &dvp, 1148 ECMPf, 0x1); 1149 soc_ING_DVP_TABLEm_field32_set(unit, &dvp, 1150 ECMP_PTRf, vp_nh_ecmp_index); 1151 } else { 1152 soc_ING_DVP_TABLEm_field32_set(unit, &dvp, 1153 ECMPf, 0x0); 1154 soc_ING_DVP_TABLEm_field32_set(unit, &dvp, 1155 ECMP_PTRf, 0); 1156 soc_ING_DVP_TABLEm_field32_set(unit, &dvp, 1157 NEXT_HOP_INDEXf, vp_nh_ecmp_index); 1158 } 1159 } 1160 1161 if (is_network_port) { 1162 if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) { 1163 soc_ING_DVP_TABLEm_field32_set(unit, &dvp, 1164 VP_TYPEf, _BCM_FLOW_VXLAN_INGRESS_DEST_VP_TYPE); 1165 } else if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) { 1166 soc_ING_DVP_TABLEm_field32_set(unit, &dvp, 1167 VP_TYPEf, _BCM_FLOW_L2GRE_INGRESS_DEST_VP_TYPE); 1168 } else { 1169 soc_ING_DVP_TABLEm_field32_set(unit, &dvp, 1170 VP_TYPEf, _BCM_FLOW_VXLAN_INGRESS_DEST_VP_TYPE); 1171 } 1172 } else { 1173 soc_ING_DVP_TABLEm_field32_set(unit, &dvp, 1174 VP_TYPEf, _BCM_FLOW_DEST_VP_TYPE_ACCESS); 1175 } 1176 1177 rv = WRITE_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, vp, &dvp); 1178 return rv; 1179 } 1180 1181 STATIC int 1182 _bcm_flow_port_encap_info_convert( 1183 bcm_flow_port_encap_t *pe_info, 1184 bcm_flow_encap_config_t *info, 1185 int port_encap2config) 1186 { 1187 uint32 pe_vl[] = {BCM_FLOW_PORT_ENCAP_VLAN_VALID, 1188 BCM_FLOW_PORT_ENCAP_PKT_PRI_VALID, 1189 BCM_FLOW_PORT_ENCAP_PKT_CFI_VALID, 1190 0}; 1191 uint32 pe_flg[] = {BCM_FLOW_PORT_ENCAP_FLAG_SERVICE_VLAN_ADD, 1192 BCM_FLOW_PORT_ENCAP_FLAG_SERVICE_VLAN_TPID_REPLACE, 1193 BCM_FLOW_PORT_ENCAP_FLAG_VLAN_REPLACE, 1194 BCM_FLOW_PORT_ENCAP_FLAG_VLAN_DELETE, 1195 BCM_FLOW_PORT_ENCAP_FLAG_VLAN_PRI_TPID_REPLACE, 1196 BCM_FLOW_PORT_ENCAP_FLAG_VLAN_PRI_REPLACE, 1197 BCM_FLOW_PORT_ENCAP_FLAG_PRI_REPLACE, 1198 BCM_FLOW_PORT_ENCAP_FLAG_TPID_REPLACE, 1199 0}; 1200 uint32 e_vl[] = {BCM_FLOW_ENCAP_VLAN_VALID, 1201 BCM_FLOW_ENCAP_PKT_PRI_VALID, 1202 BCM_FLOW_ENCAP_PKT_CFI_VALID, 1203 0}; 1204 uint32 e_flg[] = {BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_ADD, 1205 BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_TPID_REPLACE, 1206 BCM_FLOW_ENCAP_FLAG_VLAN_REPLACE, 1207 BCM_FLOW_ENCAP_FLAG_VLAN_DELETE, 1208 BCM_FLOW_ENCAP_FLAG_VLAN_PRI_TPID_REPLACE, 1209 BCM_FLOW_ENCAP_FLAG_VLAN_PRI_REPLACE, 1210 BCM_FLOW_ENCAP_FLAG_PRI_REPLACE, 1211 BCM_FLOW_ENCAP_FLAG_TPID_REPLACE, 1212 0}; 1213 int i; 1214 1215 if (port_encap2config) { 1216 i = 0; 1217 while (pe_vl[i]) { 1218 if (pe_info->valid_elements & pe_vl[i]) { 1219 info->valid_elements |= e_vl[i]; 1220 } 1221 i++; 1222 } 1223 i = 0; 1224 while (pe_flg[i]) { 1225 if (pe_info->flags & pe_flg[i]) { 1226 info->flags |= e_flg[i]; 1227 } 1228 i++; 1229 } 1230 info->vlan = pe_info->vlan; 1231 info->pri = pe_info->pri; 1232 info->cfi = pe_info->cfi; 1233 info->tpid = pe_info->tpid; 1234 } else { /* reverse */ 1235 i = 0; 1236 while (e_vl[i]) { 1237 if (info->valid_elements & e_vl[i]) { 1238 pe_info->valid_elements |= pe_vl[i]; 1239 } 1240 i++; 1241 } 1242 i = 0; 1243 while (e_flg[i]) { 1244 if (info->flags & e_flg[i]) { 1245 pe_info->flags |= pe_flg[i]; 1246 } 1247 i++; 1248 } 1249 pe_info->vlan = info->vlan; 1250 pe_info->pri = info->pri; 1251 pe_info->cfi = info->cfi; 1252 pe_info->tpid = info->tpid; 1253 } 1254 return BCM_E_NONE; 1255 } 1256 1257 /* 1258 * Function: 1259 * _bcm_td2_vxlan_ecmp_higig_ppd_select 1260 * Purpose: 1261 * Modify vxlan ecmp member object's higig ppd select 1262 * Parameters: 1263 * unit - Device Number 1264 * ecmp_index - ECMP index 1265 * flags - vxlan vp flags 1266 * Returns: 1267 * BCM_E_XXX 1268 */ 1269 1270 STATIC int 1271 _bcm_flow_ecmp_nexthop_entry_set(int unit, int ecmp_index, 1272 bcm_flow_port_encap_t *pe_info, int is_network_port) 1273 { 1274 int i = 0, ecmp_member_count = 0; 1275 int alloc_size, index; 1276 bcm_if_t *ecmp_member_array = NULL; 1277 int rv = BCM_E_NONE; 1278 1279 if (!BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, ecmp_index)) { 1280 return BCM_E_PARAM; 1281 } 1282 1283 alloc_size = sizeof(bcm_if_t) * BCM_XGS3_L3_ECMP_MAX(unit); 1284 ecmp_member_array = sal_alloc(alloc_size, "ecmp member array"); 1285 if (NULL == ecmp_member_array) { 1286 return BCM_E_MEMORY; 1287 } 1288 sal_memset(ecmp_member_array, 0, alloc_size); 1289 1290 rv = bcm_xgs3_l3_egress_multipath_get(unit, ecmp_index, 1291 BCM_XGS3_L3_ECMP_MAX(unit), 1292 ecmp_member_array, &ecmp_member_count); 1293 if (BCM_FAILURE(rv)) { 1294 goto clean_up; 1295 } 1296 1297 while(i < ecmp_member_count) { 1298 if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, 1299 ecmp_member_array[i])) { 1300 index = (ecmp_member_array[i] - BCM_XGS3_EGRESS_IDX_MIN(unit)); 1301 1302 } else { 1303 rv = BCM_E_PARAM; 1304 goto clean_up; 1305 } 1306 rv = _bcm_flow_nexthop_entry_set(unit, index, 0, 1307 pe_info, is_network_port); 1308 1309 if (BCM_FAILURE(rv)) { 1310 goto clean_up; 1311 } 1312 1313 i++; 1314 } 1315 1316 clean_up: 1317 if (ecmp_member_array) { 1318 sal_free(ecmp_member_array); 1319 ecmp_member_array = NULL; 1320 } 1321 1322 return rv; 1323 } 1324 1325 STATIC void 1326 _bcm_flow_egr_nh_sd_tag_set(int unit, soc_mem_t hw_mem, uint32 *entry, 1327 uint32 sd_tag) 1328 { 1329 int tag_format; 1330 uint32 value; 1331 1332 tag_format = SD_TAG_DATA_FORMAT_DOUBLEfmt; 1333 1334 value = soc_format_field32_get(unit,tag_format,&sd_tag, SD_TAG_VIDf); 1335 soc_mem_field32_set(unit, hw_mem, entry, SD_TAG__SD_TAG_VIDf, value); 1336 1337 value = soc_format_field32_get(unit,tag_format,&sd_tag, SD_TAG_NEW_PRIf); 1338 soc_mem_field32_set(unit, hw_mem, entry, SD_TAG__NEW_PRIf, value); 1339 1340 value = soc_format_field32_get(unit,tag_format,&sd_tag, SD_TAG_NEW_CFIf); 1341 soc_mem_field32_set(unit, hw_mem, entry, SD_TAG__NEW_CFIf, value); 1342 1343 value = soc_format_field32_get(unit,tag_format,&sd_tag, SD_TAG_REMARK_CFIf); 1344 soc_mem_field32_set(unit, hw_mem, entry, SD_TAG__SD_TAG_REMARK_CFIf, value); 1345 1346 value = soc_format_field32_get(unit,tag_format,&sd_tag, 1347 SD_TAG_ACTION_IF_NOT_PRESENTf); 1348 soc_mem_field32_set(unit, hw_mem, entry, 1349 SD_TAG__SD_TAG_ACTION_IF_NOT_PRESENTf, value); 1350 1351 value = soc_format_field32_get(unit,tag_format,&sd_tag, 1352 SD_TAG_ACTION_IF_PRESENTf); 1353 soc_mem_field32_set(unit, hw_mem, entry, 1354 SD_TAG__SD_TAG_ACTION_IF_PRESENTf, value); 1355 1356 value = soc_format_field32_get(unit,tag_format,&sd_tag, SD_TAG_TPID_INDEXf); 1357 soc_mem_field32_set(unit, hw_mem, entry, SD_TAG__SD_TAG_TPID_INDEXf, value); 1358 } 1359 1360 STATIC void 1361 _bcm_flow_egr_nh_sd_tag_get(int unit, soc_mem_t hw_mem, uint32 *entry, 1362 uint32 *sd_tag) 1363 { 1364 int tag_format; 1365 uint32 value; 1366 1367 tag_format = SD_TAG_DATA_FORMAT_DOUBLEfmt; 1368 1369 *sd_tag = 0; 1370 value = soc_mem_field32_get(unit, hw_mem, entry, SD_TAG__SD_TAG_VIDf); 1371 soc_format_field32_set(unit,tag_format,sd_tag, SD_TAG_VIDf, value); 1372 1373 value = soc_mem_field32_get(unit, hw_mem, entry, SD_TAG__NEW_PRIf); 1374 soc_format_field32_set(unit,tag_format,sd_tag, SD_TAG_NEW_PRIf, value); 1375 1376 value = soc_mem_field32_get(unit, hw_mem, entry, SD_TAG__NEW_CFIf); 1377 soc_format_field32_set(unit,tag_format,sd_tag, SD_TAG_NEW_CFIf, value); 1378 1379 value = soc_mem_field32_get(unit, hw_mem, entry,SD_TAG__SD_TAG_REMARK_CFIf); 1380 soc_format_field32_set(unit,tag_format,sd_tag, SD_TAG_REMARK_CFIf, value); 1381 1382 value = soc_mem_field32_get(unit, hw_mem, entry, 1383 SD_TAG__SD_TAG_ACTION_IF_NOT_PRESENTf); 1384 soc_format_field32_set(unit,tag_format,sd_tag, 1385 SD_TAG_ACTION_IF_NOT_PRESENTf, value); 1386 1387 value = soc_mem_field32_get(unit, hw_mem, entry, 1388 SD_TAG__SD_TAG_ACTION_IF_PRESENTf); 1389 soc_format_field32_set(unit,tag_format,sd_tag, 1390 SD_TAG_ACTION_IF_PRESENTf, value); 1391 1392 value = soc_mem_field32_get(unit, hw_mem, entry,SD_TAG__SD_TAG_TPID_INDEXf); 1393 soc_format_field32_set(unit,tag_format,sd_tag, SD_TAG_TPID_INDEXf, value); 1394 } 1395 1396 STATIC int 1397 _bcm_flow_linked_tbl_sd_tag_set(int unit, soc_mem_t view_id, 1398 uint32 *egr_nh, uint32 sd_tag) 1399 { 1400 uint32 nptr_entry[SOC_MAX_MEM_WORDS]; 1401 uint32 action_set; 1402 int next_ptr_type; 1403 int next_ptr; 1404 int data_type; 1405 uint32 nptr_view_id; 1406 soc_mem_t mem; 1407 int rv = SOC_E_NOT_FOUND; 1408 1409 if (!SOC_MEM_FIELD_VALID(unit,view_id,NEXT_PTR_ACTION_SETf)) { 1410 return SOC_E_NOT_FOUND; 1411 } 1412 action_set = soc_mem_field32_get(unit, view_id, egr_nh, 1413 NEXT_PTR_ACTION_SETf); 1414 next_ptr_type = soc_format_field32_get(unit, NEXT_PTR_ACTION_SETfmt, 1415 &action_set, NEXT_PTR_TYPEf); 1416 next_ptr = soc_format_field32_get(unit, NEXT_PTR_ACTION_SETfmt, 1417 &action_set, NEXT_PTRf); 1418 1419 /* for now only handle VC_AND_SWAP table */ 1420 if (next_ptr_type == 3) { /* VC_AND_SWAP */ 1421 mem = EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm; 1422 } else { 1423 mem = 0; 1424 } 1425 1426 if (mem) { 1427 soc_mem_lock(unit,mem); 1428 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, 1429 next_ptr, nptr_entry); 1430 if (SOC_FAILURE(rv)) { 1431 soc_mem_unlock(unit,mem); 1432 return rv; 1433 } 1434 data_type = soc_mem_field32_get(unit, mem, nptr_entry, DATA_TYPEf); 1435 1436 rv = soc_flow_db_mem_to_view_id_get(unit, 1437 mem, 1438 SOC_FLOW_DB_KEY_TYPE_INVALID, 1439 data_type, 1440 0, 1441 NULL, 1442 &nptr_view_id); 1443 if (SOC_FAILURE(rv)) { 1444 soc_mem_unlock(unit,mem); 1445 return rv; 1446 } 1447 if (SOC_MEM_FIELD_VALID(unit,nptr_view_id, SD_TAG_ACTION_SETf)) { 1448 soc_mem_field32_set(unit, nptr_view_id, nptr_entry, 1449 SD_TAG_ACTION_SETf, sd_tag); 1450 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, next_ptr, nptr_entry); 1451 1452 } 1453 soc_mem_unlock(unit,mem); 1454 } 1455 return rv; 1456 } 1457 STATIC int 1458 _bcm_flow_linked_tbl_sd_tag_get(int unit, soc_mem_t view_id, 1459 uint32 *egr_nh, uint32 *sd_tag) 1460 { 1461 uint32 nptr_entry[SOC_MAX_MEM_WORDS]; 1462 uint32 action_set; 1463 int next_ptr_type; 1464 int next_ptr; 1465 int data_type; 1466 uint32 nptr_view_id; 1467 soc_mem_t mem; 1468 1469 *sd_tag = 0; 1470 if (!SOC_MEM_FIELD_VALID(unit,view_id,NEXT_PTR_ACTION_SETf)) { 1471 return SOC_E_NOT_FOUND; 1472 } 1473 action_set = soc_mem_field32_get(unit, view_id, egr_nh, 1474 NEXT_PTR_ACTION_SETf); 1475 next_ptr_type = soc_format_field32_get(unit, NEXT_PTR_ACTION_SETfmt, 1476 &action_set, NEXT_PTR_TYPEf); 1477 next_ptr = soc_format_field32_get(unit, NEXT_PTR_ACTION_SETfmt, 1478 &action_set, NEXT_PTRf); 1479 1480 /* for now only handle VC_AND_SWAP table */ 1481 if (next_ptr_type == 3) { /* VC_AND_SWAP */ 1482 mem = EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm; 1483 } else { 1484 mem = 0; 1485 } 1486 1487 if (mem) { 1488 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ANY, 1489 next_ptr, nptr_entry)); 1490 data_type = soc_mem_field32_get(unit, mem, nptr_entry, DATA_TYPEf); 1491 1492 SOC_IF_ERROR_RETURN(soc_flow_db_mem_to_view_id_get(unit, 1493 mem, 1494 SOC_FLOW_DB_KEY_TYPE_INVALID, 1495 data_type, 1496 0, 1497 NULL, 1498 &nptr_view_id)); 1499 if (SOC_MEM_FIELD_VALID(unit,nptr_view_id, SD_TAG_ACTION_SETf)) { 1500 *sd_tag = soc_mem_field32_get(unit, nptr_view_id, nptr_entry, 1501 SD_TAG_ACTION_SETf); 1502 } 1503 } 1504 return SOC_E_NONE; 1505 } 1506 1507 1508 1509 /* 1510 * Function: 1511 * _bcm_flow_nexthop_entry_set 1512 * Purpose: 1513 * Modify Egress entry - flex views only 1514 * Parameters: 1515 * unit - Device Number 1516 * nh_index - Next Hop Index 1517 * new_entry_type - New Entry type 1518 * Returns: 1519 * BCM_E_XXX 1520 */ 1521 1522 STATIC int 1523 _bcm_flow_nexthop_entry_set(int unit, int nh_index, int drop, 1524 bcm_flow_port_encap_t *pe_info, int is_network_port) 1525 { 1526 uint32 egr_nh[SOC_MAX_MEM_WORDS]; 1527 bcm_flow_encap_config_t einfo; 1528 uint32 sd_tag; 1529 int tpid_index = -1; 1530 int vp; 1531 source_vp_entry_t svp; 1532 int data_type; 1533 1534 int rv = BCM_E_NONE; 1535 1536 int i; 1537 uint32 action_set = 0; 1538 uint8 process_sd_tag = 0; 1539 uint8 process_higig_controls = 0; 1540 uint8 process_switching_controls = 0; 1541 uint8 process_next_ptr = 0; 1542 uint8 is_eline; 1543 1544 uint32 view_id=0; 1545 uint32 flex_data_array[_BCM_FLOW_PDD_FIELD_MAX]; 1546 uint32 flex_data_count; 1547 1548 vp = _SHR_GPORT_FLOW_PORT_ID_GET(pe_info->flow_port); 1549 rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp); 1550 BCM_IF_ERROR_RETURN(rv); 1551 1552 soc_mem_lock(unit,EGR_L3_NEXT_HOPm); 1553 rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ALL, 1554 nh_index, egr_nh); 1555 if (SOC_FAILURE(rv)) { 1556 goto cleanup; 1557 } 1558 1559 data_type = soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh, DATA_TYPEf); 1560 1561 if (BCMI_L3_NH_FLEX_VIEW(data_type)) { 1562 /* Get view id corresponding to the data type. */ 1563 rv = soc_flow_db_mem_to_view_id_get(unit, 1564 EGR_L3_NEXT_HOPm, 1565 SOC_FLOW_DB_KEY_TYPE_INVALID, 1566 data_type, 1567 0, 1568 NULL, 1569 &view_id); 1570 if (SOC_FAILURE(rv)) { 1571 goto cleanup; 1572 } 1573 1574 /* Get PDD field list corresponding to the view id. */ 1575 rv = soc_flow_db_mem_view_field_list_get(unit, 1576 view_id, 1577 SOC_FLOW_DB_FIELD_TYPE_POLICY_DATA, 1578 _BCM_FLOW_PDD_FIELD_MAX, 1579 flex_data_array, 1580 &flex_data_count); 1581 1582 if (SOC_FAILURE(rv)) { 1583 goto cleanup; 1584 } 1585 1586 for (i=0; i<flex_data_count; i++) { 1587 switch (flex_data_array[i]) { 1588 case SD_TAG_ACTION_SETf: 1589 process_sd_tag = 1; 1590 break; 1591 case HIGIG_CONTROLS_ACTION_SETf: 1592 process_higig_controls = 1; 1593 break; 1594 case SWITCHING_CTRLS_ACTION_SETf: 1595 process_switching_controls = 1; 1596 break; 1597 case NEXT_PTR_ACTION_SETf: 1598 process_next_ptr = 1; 1599 break; 1600 default: 1601 break; 1602 } 1603 } 1604 } 1605 1606 if (!is_network_port) { /* access port side */ 1607 1608 if (BCMI_L3_NH_FLEX_VIEW(data_type)) { 1609 if (process_next_ptr) { 1610 action_set = 0; 1611 soc_format_field32_set(unit, NEXT_PTR_ACTION_SETfmt, 1612 &action_set, NEXT_PTR_TYPEf, 1613 BCMI_L3_NH_EGR_NEXT_PTR_TYPE_DVP); 1614 1615 soc_format_field32_set(unit, NEXT_PTR_ACTION_SETfmt, 1616 &action_set, NEXT_PTRf, 1617 vp); 1618 1619 soc_mem_field32_set(unit, view_id, egr_nh, 1620 NEXT_PTR_ACTION_SETf, action_set); 1621 } 1622 } else { 1623 if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) { 1624 /* should always be L2TAG view */ 1625 if (data_type != _BCM_VXLAN_EGR_NEXT_HOP_L2OTAG_VIEW) { 1626 /* first time setup */ 1627 sal_memset(egr_nh, 0, sizeof(egr_nh)); 1628 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh, 1629 DATA_TYPEf, _BCM_VXLAN_EGR_NEXT_HOP_L2OTAG_VIEW); 1630 1631 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh, 1632 L2_OTAG__FLOW_SELECT_CTRL_IDf, 0x8); 1633 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh, 1634 L2_OTAG__NEXT_PTR_TYPEf, 0x1); 1635 data_type = _BCM_VXLAN_EGR_NEXT_HOP_L2OTAG_VIEW; 1636 } 1637 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh, 1638 L2_OTAG__DVPf, vp); 1639 if (pe_info->valid_elements & BCM_FLOW_PORT_ENCAP_CLASS_ID_VALID) { 1640 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh, 1641 L2_OTAG__CLASS_IDf, pe_info->class_id); 1642 } 1643 } else { 1644 /* should always be SDTAG view */ 1645 if (data_type != _BCM_VXLAN_EGR_NEXT_HOP_SDTAG_VIEW) { 1646 /* first time setup */ 1647 sal_memset(egr_nh, 0, sizeof(egr_nh)); 1648 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh, 1649 DATA_TYPEf, _BCM_VXLAN_EGR_NEXT_HOP_SDTAG_VIEW); 1650 } 1651 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh, 1652 SD_TAG__DVPf, vp); 1653 } 1654 } 1655 1656 if (pe_info->valid_elements & BCM_FLOW_PORT_ENCAP_FLAGS_VALID) { 1657 rv = bcmi_esw_flow_vp_is_eline(unit,vp, &is_eline); 1658 if (SOC_FAILURE(rv)) { 1659 goto cleanup; 1660 } 1661 1662 if (!BCMI_L3_NH_FLEX_VIEW(data_type) ) { 1663 if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) { 1664 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh, 1665 L2_OTAG__BC_DROPf, drop ? 1 : 0); 1666 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh, 1667 L2_OTAG__UUC_DROPf, drop ? 1 : 0); 1668 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh, 1669 L2_OTAG__UMC_DROPf, drop ? 1 : 0); 1670 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh, 1671 L2_OTAG__HG_LEARN_OVERRIDEf, is_eline ? 1 : 0); 1672 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh, 1673 L2_OTAG__HG_MODIFY_ENABLEf, 0x0); 1674 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh, 1675 L2_OTAG__HG_HDR_SELf, 1676 pe_info->flags & BCM_FLOW_PORT_ENCAP_FLAG_LOCAL? 0: 1); 1677 } else { 1678 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh, 1679 SD_TAG__BC_DROPf, drop ? 1 : 0); 1680 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh, 1681 SD_TAG__UUC_DROPf, drop ? 1 : 0); 1682 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh, 1683 SD_TAG__UMC_DROPf, drop ? 1 : 0); 1684 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh, 1685 SD_TAG__HG_LEARN_OVERRIDEf, is_eline ? 1 : 0); 1686 /* HG_MODIFY_ENABLE must be 0x0 for Ingress and Egress Chip */ 1687 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh, 1688 SD_TAG__HG_MODIFY_ENABLEf, 0x0); 1689 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh, 1690 SD_TAG__HG_HDR_SELf, 1691 pe_info->flags & BCM_FLOW_PORT_ENCAP_FLAG_LOCAL? 0: 1); 1692 } 1693 } else { 1694 if (process_switching_controls) { 1695 action_set = 0; 1696 1697 action_set = soc_mem_field32_get(unit, view_id, egr_nh, 1698 SWITCHING_CTRLS_ACTION_SETf); 1699 soc_format_field32_set(unit, SWITCHING_CTRLS_ACTION_SETfmt, 1700 &action_set, L2_DROPf, 1701 drop ? 1: 0 ); 1702 soc_mem_field32_set(unit, view_id, egr_nh, 1703 SWITCHING_CTRLS_ACTION_SETf, action_set); 1704 } 1705 1706 if (process_higig_controls) { 1707 action_set = 0; 1708 action_set = soc_mem_field32_get(unit, view_id, egr_nh, 1709 HIGIG_CONTROLS_ACTION_SETf); 1710 soc_format_field32_set(unit, HIGIG_CONTROLS_ACTION_SETfmt, 1711 &action_set, HG_LEARN_OVERRIDEf, 1712 is_eline ? 1 : 0); 1713 soc_mem_field32_set(unit, view_id, egr_nh, 1714 HIGIG_CONTROLS_ACTION_SETf, action_set); 1715 } 1716 } 1717 } 1718 } else { /* network port side. Should only have L3 view */ 1719 if (!BCMI_L3_NH_FLEX_VIEW(data_type)) { 1720 if (data_type == _BCM_VXLAN_EGR_NEXT_HOP_L3_VIEW) { 1721 if (soc_feature(unit, soc_feature_egr_modport_to_nhi)) { 1722 if (pe_info->flags & BCM_FLOW_PORT_ENCAP_FLAG_LOCAL) { 1723 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh, 1724 L3__HG_L2_TUNNEL_ENCAP_ENABLEf, 1); 1725 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh, 1726 L3__HG_HDR_SELf, 0); 1727 } else { 1728 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh, 1729 L3__HG_L2_TUNNEL_ENCAP_ENABLEf, 0); 1730 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh, 1731 L3__HG_HDR_SELf, 1); 1732 } 1733 } else { 1734 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh, 1735 L3__HG_HDR_SELf, 1); 1736 } 1737 } 1738 } else { /* flex view */ 1739 if (process_higig_controls) { 1740 action_set = 0; 1741 action_set = soc_mem_field32_get(unit, view_id, egr_nh, 1742 HIGIG_CONTROLS_ACTION_SETf); 1743 soc_format_field32_set(unit, HIGIG_CONTROLS_ACTION_SETfmt, 1744 &action_set, HG_HDR_SELf, 1745 (pe_info->flags & BCM_FLOW_PORT_ENCAP_FLAG_LOCAL)? 0 : 1); 1746 soc_mem_field32_set(unit, view_id, egr_nh, 1747 HIGIG_CONTROLS_ACTION_SETf, action_set); 1748 } 1749 } 1750 } 1751 1752 if (pe_info->valid_elements & BCM_FLOW_PORT_ENCAP_FLAGS_VALID) { 1753 /* SD_TAG handling */ 1754 bcm_flow_encap_config_t_init(&einfo); 1755 1756 if (pe_info->flags & BCM_FLOW_PORT_ENCAP_FLAG_SERVICE_TAGGED) { 1757 rv = _bcm_flow_port_encap_info_convert(pe_info, &einfo, TRUE); 1758 if (SOC_FAILURE(rv)) { 1759 goto cleanup; 1760 } 1761 if (BCMI_L3_NH_FLEX_VIEW(data_type)) { 1762 /* just to indicate the flex flow */ 1763 einfo.flow_handle = SOC_FLOW_DB_FLOW_ID_START + 1; 1764 } 1765 if (data_type == _BCM_VXLAN_EGR_NEXT_HOP_L2OTAG_VIEW) { 1766 rv = _bcm_flow_sd_tag_set_to_entry(unit, &einfo, 1767 EGR_L3_NEXT_HOPm, egr_nh, &tpid_index); 1768 } else { 1769 rv = _bcm_flow_sd_tag_set(unit, &einfo, &sd_tag, &tpid_index); 1770 } 1771 if (SOC_FAILURE(rv)) { 1772 goto cleanup; 1773 } 1774 if (BCMI_L3_NH_FLEX_VIEW(data_type)) { 1775 if (process_sd_tag) { 1776 soc_mem_field32_set(unit, view_id, egr_nh, 1777 SD_TAG_ACTION_SETf, sd_tag); 1778 } else { 1779 /* check sd-tag should be set in a different table */ 1780 rv = _bcm_flow_linked_tbl_sd_tag_set(unit, view_id, 1781 egr_nh, sd_tag); 1782 if (rv != SOC_E_NONE && rv != SOC_E_NOT_FOUND) { 1783 if (SOC_FAILURE(rv)) { 1784 goto cleanup; 1785 } 1786 } 1787 } 1788 } else { 1789 if (!is_network_port) { /* access port side */ 1790 if (data_type != _BCM_VXLAN_EGR_NEXT_HOP_L2OTAG_VIEW) { 1791 _bcm_flow_egr_nh_sd_tag_set(unit, EGR_L3_NEXT_HOPm, egr_nh, 1792 sd_tag); 1793 } 1794 } 1795 } 1796 } 1797 } 1798 rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm, 1799 MEM_BLOCK_ALL, nh_index, egr_nh); 1800 soc_mem_unlock(unit,EGR_L3_NEXT_HOPm); 1801 return rv; 1802 1803 cleanup: 1804 soc_mem_unlock(unit,EGR_L3_NEXT_HOPm); 1805 if (tpid_index != -1) { 1806 (void) _bcm_fb2_outer_tpid_entry_delete(unit, tpid_index); 1807 } 1808 return rv; 1809 } 1810 1811 /* 1812 * Function: 1813 * _bcm_flow_port_egr_nh_add 1814 * Purpose: 1815 * Add FLOW Next Hop entry 1816 * Parameters: 1817 * Returns: 1818 * BCM_E_XXX 1819 */ 1820 1821 STATIC int 1822 _bcm_flow_port_egr_nh_add(int unit, bcm_flow_port_encap_t *info, 1823 int is_network_port, int *nh_idx, uint32 *mflag) 1824 { 1825 egr_l3_next_hop_entry_t egr_nh; 1826 int rv=BCM_E_NONE; 1827 uint32 mpath_flag=0; 1828 int vp_nh_ecmp_index=-1; 1829 int ref_count = 0; 1830 int vp; 1831 int drop; 1832 int nh_ecmp_index = -1; 1833 ing_dvp_table_entry_t dvp; 1834 1835 vp = _SHR_GPORT_FLOW_PORT_ID_GET(info->flow_port); 1836 drop = (info->flags & BCM_FLOW_PORT_ENCAP_FLAG_DROP) ? 1 : 0; 1837 *nh_idx = 0; 1838 *mflag = 0; 1839 1840 if (info->options & BCM_FLOW_PORT_ENCAP_OPTION_REPLACE) { 1841 SOC_IF_ERROR_RETURN( 1842 READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp)); 1843 1844 nh_ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, 1845 NEXT_HOP_INDEXf); 1846 if (nh_ecmp_index) { 1847 BCM_IF_ERROR_RETURN(_bcm_flow_nh_cnt_dec(unit, vp)); 1848 } 1849 } 1850 1851 /* 1852 * Get egress next-hop index from egress object and 1853 * increment egress object reference count. multicast will be entirely 1854 * handled in bcm_l3_egress_create API context. 1855 */ 1856 rv = bcm_xgs3_get_nh_from_egress_object(unit, info->egress_if, 1857 &mpath_flag, 1, &vp_nh_ecmp_index); 1858 BCM_IF_ERROR_RETURN(rv); 1859 1860 /* Read the existing egress next_hop entry */ 1861 if (mpath_flag == 0) { 1862 if (is_network_port) { 1863 int l3_flag = BCM_XGS3_L3_ENT_FLAG( 1864 BCM_XGS3_L3_TBL_PTR(unit, next_hop), vp_nh_ecmp_index); 1865 if (l3_flag != _BCM_L3_FLOW_ONLY) { 1866 rv = BCM_E_CONFIG; 1867 _BCM_FLOW_CLEANUP(rv) 1868 } 1869 } 1870 rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 1871 vp_nh_ecmp_index, &egr_nh); 1872 _BCM_FLOW_CLEANUP(rv) 1873 } 1874 #if defined(BCM_RIOT_SUPPORT) || defined(BCM_MULTI_LEVEL_ECMP_SUPPORT) 1875 else { 1876 /* 1877 * When Multi-level ECMP is enabled, ECMP group pointed 1878 * to by DVP must be an underlay group. 1879 */ 1880 if (BCMI_L3_ECMP_IS_MULTI_LEVEL(unit)) { 1881 if (vp_nh_ecmp_index < BCMI_L3_ECMP_OVERLAY_ENTRIES(unit)) { 1882 return BCM_E_PARAM; 1883 } 1884 } 1885 } 1886 #endif 1887 1888 *nh_idx = vp_nh_ecmp_index; 1889 *mflag = mpath_flag; 1890 if (is_network_port) { 1891 if (mpath_flag == 0) { 1892 rv = _bcm_flow_nexthop_entry_set(unit, vp_nh_ecmp_index, drop, 1893 info, is_network_port); 1894 _BCM_FLOW_CLEANUP(rv) 1895 } else { 1896 rv = _bcm_flow_ecmp_nexthop_entry_set(unit, info->egress_if, 1897 info, is_network_port); 1898 _BCM_FLOW_CLEANUP(rv) 1899 } 1900 } else { /* Egress into Access - Non Tunnel */ 1901 rv = _bcm_flow_nexthop_entry_set(unit, vp_nh_ecmp_index, drop, 1902 info, is_network_port); 1903 _BCM_FLOW_CLEANUP(rv) 1904 } 1905 1906 #ifdef BCM_RIOT_SUPPORT 1907 if (info->options & BCM_FLOW_PORT_ENCAP_OPTION_REPLACE) { 1908 rv = bcmi_l3_nh_assoc_ol_ul_link_replace(unit, nh_ecmp_index, 1909 vp_nh_ecmp_index); 1910 } 1911 #endif /* BCM_RIOT_SUPPORT */ 1912 return rv; 1913 1914 cleanup: 1915 if (vp_nh_ecmp_index != -1) { 1916 /* Decrement reference count */ 1917 (void) bcm_xgs3_get_ref_count_from_nhi( 1918 unit, mpath_flag, &ref_count, vp_nh_ecmp_index); 1919 } 1920 return rv; 1921 } 1922 1923 /* 1924 * Function: 1925 * _bcm_flow_port_egr_nh_reset 1926 * Purpose: 1927 * Reset VXLAN Egress NextHop 1928 * Parameters: 1929 * IN : Unit 1930 * IN : nh_index 1931 * Returns: 1932 * BCM_E_XXX 1933 */ 1934 1935 STATIC int 1936 _bcm_flow_port_egr_nh_reset(int unit, int nh_index, int vp_type) 1937 { 1938 egr_l3_next_hop_entry_t egr_nh; 1939 int rv=BCM_E_NONE; 1940 int action_present=0, action_not_present=0, old_tpid_idx = -1; 1941 uint32 view_id; 1942 uint32 action_set; 1943 uint32 entry_type; 1944 1945 BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_NEXT_HOPm, 1946 MEM_BLOCK_ANY, nh_index, &egr_nh)); 1947 entry_type = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, DATA_TYPEf); 1948 1949 if (BCMI_L3_NH_FLEX_VIEW(entry_type)) { 1950 /* Get view id corresponding to the entry type. */ 1951 rv = soc_flow_db_mem_to_view_id_get(unit, 1952 EGR_L3_NEXT_HOPm, 1953 SOC_FLOW_DB_KEY_TYPE_INVALID, 1954 entry_type, 1955 0, 1956 NULL, 1957 &view_id); 1958 1959 if (!SOC_MEM_FIELD_VALID(unit, view_id, SD_TAG_ACTION_SETf)) { 1960 return rv; 1961 } 1962 1963 action_set = soc_mem_field32_get(unit, view_id, &egr_nh, 1964 SD_TAG_ACTION_SETf); 1965 1966 if (vp_type == _BCM_FLOW_DEST_VP_TYPE_ACCESS) { 1967 action_present = 1968 soc_format_field32_get(unit, SD_TAG_ACTION_SETfmt, 1969 &action_set, SD_TAG_ACTION_IF_PRESENTf); 1970 action_not_present = 1971 soc_format_field32_get(unit, SD_TAG_ACTION_SETfmt, 1972 &action_set, SD_TAG_ACTION_IF_NOT_PRESENTf); 1973 if ((action_not_present == 0x1) || (action_present == 0x1) || 1974 (action_present == 0x4) || (action_present == 0x7)) { 1975 old_tpid_idx = 1976 soc_format_field32_get(unit, SD_TAG_ACTION_SETfmt, 1977 &action_set, SD_TAG_TPID_INDEXf); 1978 BCM_IF_ERROR_RETURN( 1979 _bcm_fb2_outer_tpid_entry_delete(unit, old_tpid_idx)); 1980 } 1981 soc_mem_field32_set(unit, view_id, &egr_nh, SD_TAG_ACTION_SETf,0); 1982 } else { /* XXXX reset HG_HDR */ 1983 } 1984 } else { /* fixed view */ 1985 if (entry_type == _BCM_VXLAN_EGR_NEXT_HOP_SDTAG_VIEW) { 1986 action_present = 1987 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 1988 SD_TAG__SD_TAG_ACTION_IF_PRESENTf); 1989 action_not_present = 1990 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 1991 SD_TAG__SD_TAG_ACTION_IF_NOT_PRESENTf); 1992 if ((action_not_present == 0x1) || (action_present == 0x1) || 1993 (action_present == 0x4) || (action_present == 0x7)) { 1994 old_tpid_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, 1995 &egr_nh, SD_TAG__SD_TAG_TPID_INDEXf); 1996 BCM_IF_ERROR_RETURN( 1997 _bcm_fb2_outer_tpid_entry_delete(unit, old_tpid_idx)); 1998 } 1999 /* Normalize Next-hop Entry to L3 View */ 2000 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, DATA_TYPEf, 0); 2001 } else if (entry_type == _BCM_VXLAN_EGR_NEXT_HOP_L2OTAG_VIEW) { 2002 uint32 profile_index; 2003 2004 profile_index = soc_EGR_L3_NEXT_HOPm_field32_get(unit, 2005 &egr_nh, L2_OTAG__TAG_ACTION_PROFILE_PTRf); 2006 BCM_IF_ERROR_RETURN(_bcm_td3_sd_tag_action_get(unit, profile_index, 2007 &action_present, &action_not_present)); 2008 if (profile_index != 0) { 2009 BCM_IF_ERROR_RETURN( 2010 _bcm_trx_egr_vlan_action_profile_entry_delete(unit, 2011 profile_index)); 2012 } 2013 if ((action_not_present == 0x1) || (action_present == 0x1) || 2014 (action_present == 0x4) || (action_present == 0x7)) { 2015 old_tpid_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, 2016 &egr_nh, L2_OTAG__TPID_INDEXf); 2017 BCM_IF_ERROR_RETURN( 2018 _bcm_fb2_outer_tpid_entry_delete(unit, old_tpid_idx)); 2019 } 2020 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, DATA_TYPEf, 0); 2021 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 2022 L2_OTAG__FLOW_SELECT_CTRL_IDf, 0x0); 2023 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 2024 L2_OTAG__NEXT_PTR_TYPEf, 0x0); 2025 } else { /* L3 view */ 2026 } 2027 } 2028 2029 BCM_IF_ERROR_RETURN(soc_mem_write(unit, EGR_L3_NEXT_HOPm, 2030 MEM_BLOCK_ANY, nh_index, &egr_nh)); 2031 2032 return rv; 2033 } 2034 2035 /* 2036 * Function: 2037 * _bcm_flow_port_egr_nh_delete 2038 * Purpose: 2039 * Delete FLOW Next Hop entry 2040 * Parameters: 2041 * Returns: 2042 * BCM_E_XXX 2043 */ 2044 2045 STATIC int 2046 _bcm_flow_port_egr_nh_delete(int unit, int vp) 2047 { 2048 int rv=BCM_E_NONE; 2049 int nh_ecmp_index=-1; 2050 ing_dvp_table_entry_t dvp; 2051 uint32 vp_type=0; 2052 uint32 flags=0; 2053 int ref_count=0; 2054 int ecmp =-1; 2055 2056 BCM_IF_ERROR_RETURN(READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp)); 2057 2058 vp_type = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, VP_TYPEf); 2059 ecmp = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMPf); 2060 if (ecmp) { 2061 nh_ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMP_PTRf); 2062 flags = BCM_L3_MULTIPATH; 2063 /* Decrement reference count */ 2064 BCM_IF_ERROR_RETURN(bcm_xgs3_get_ref_count_from_nhi(unit, flags, 2065 &ref_count, nh_ecmp_index)); 2066 if (ref_count == 1) { 2067 if (nh_ecmp_index && 2068 ((vp_type == _BCM_FLOW_VXLAN_INGRESS_DEST_VP_TYPE) || 2069 (vp_type == _BCM_FLOW_L2GRE_INGRESS_DEST_VP_TYPE))) { 2070 /* support ecmp on network port only 2071 * only deal with the field in L3_VIEW changed by this API 2072 * That is the HG_HDR XXXX 2073 */ 2074 } 2075 } 2076 } else { 2077 nh_ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, 2078 NEXT_HOP_INDEXf); 2079 if(nh_ecmp_index != 0) { 2080 /* Decrement reference count */ 2081 BCM_IF_ERROR_RETURN(bcm_xgs3_get_ref_count_from_nhi(unit, flags, 2082 &ref_count, nh_ecmp_index)); 2083 } 2084 if (ref_count == 1) { 2085 if (nh_ecmp_index) { 2086 BCM_IF_ERROR_RETURN(_bcm_flow_port_egr_nh_reset( 2087 unit, nh_ecmp_index, vp_type)); 2088 } 2089 } 2090 } 2091 return rv; 2092 } 2093 2094 /* 2095 * Function: 2096 * _bcm_flow_ingress_dvp_reset 2097 * Purpose: 2098 * Reset Ingress DVP tables 2099 * Parameters: 2100 * IN : Unit 2101 * IN : vp 2102 * Returns: 2103 * BCM_E_XXX 2104 */ 2105 2106 STATIC int 2107 _bcm_flow_ingress_dvp_reset(int unit, int vp) 2108 { 2109 int rv=BCM_E_UNAVAIL; 2110 ing_dvp_table_entry_t dvp; 2111 ing_dvp_2_table_entry_t dvp_2; 2112 2113 2114 sal_memset(&dvp, 0, sizeof(ing_dvp_table_entry_t)); 2115 rv = WRITE_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, vp, &dvp); 2116 BCM_IF_ERROR_RETURN(rv); 2117 sal_memset(&dvp_2, 0, sizeof(ing_dvp_2_table_entry_t)); 2118 rv = WRITE_ING_DVP_2_TABLEm(unit, MEM_BLOCK_ALL, vp, &dvp_2); 2119 2120 return rv; 2121 } 2122 2123 /* 2124 * Function: 2125 * _bcm_flow_egress_dvp_reset 2126 * Purpose: 2127 * Reet Egress DVP tables 2128 * Parameters: 2129 * IN : Unit 2130 * IN : vp 2131 * Returns: 2132 * BCM_E_XXX 2133 */ 2134 2135 STATIC int 2136 _bcm_flow_egress_dvp_reset(int unit, int vp) 2137 { 2138 uint32 dvp[SOC_MAX_MEM_WORDS]; 2139 2140 sal_memset(dvp, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS); 2141 BCM_IF_ERROR_RETURN(soc_mem_write(unit, 2142 EGR_DVP_ATTRIBUTEm, MEM_BLOCK_ALL, vp, dvp)); 2143 2144 return BCM_E_NONE; 2145 } 2146 2147 /* 2148 * Function: 2149 * bcmi_esw_flow_port_encap_set 2150 * Purpose: 2151 * bind the tunnel object and egress object to the given dvp and cofigure 2152 * the dvp's tunnel attributes if it is L2 tunnel. For L3 tunnel, bind the 2153 * egress object with the given tunnel. 2154 * 2155 * Parameters: 2156 * unit - (IN) Device Number 2157 * info - (IN) Flow egress encap descriptor 2158 * num_of_fields - (IN) number of logical fields 2159 * field - (IN) logical field array 2160 * Returns: 2161 * BCM_E_XXX 2162 */ 2163 2164 int bcmi_esw_flow_port_encap_set( 2165 int unit, 2166 bcm_flow_port_encap_t *info, 2167 uint32 num_of_fields, 2168 bcm_flow_logical_field_t *field) 2169 { 2170 int dvp; 2171 int rv; 2172 int network_port = 0; 2173 _bcm_vp_info_t vp_info; 2174 int nh_idx = 0; 2175 uint32 mpath_flag = 0; 2176 int num_vp; 2177 2178 if (info == NULL) { 2179 return BCM_E_PARAM; 2180 } 2181 2182 dvp = _SHR_GPORT_FLOW_PORT_ID_GET(info->flow_port); 2183 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 2184 if ((dvp <= 0) || (dvp >= num_vp)) { 2185 return BCM_E_PARAM; 2186 } 2187 bcmi_esw_flow_lock(unit); 2188 if (info->options & BCM_FLOW_PORT_ENCAP_OPTION_CLEAR) { 2189 if (_BCM_FLOW_EGR_DVP_USED_GET(unit,dvp)) { 2190 _BCM_FLOW_EGR_DVP_USED_CLR(unit,dvp); 2191 rv = _bcm_flow_port_egr_nh_delete(unit,dvp); 2192 if (BCM_SUCCESS(rv)) { 2193 rv = _bcm_flow_egress_dvp_reset(unit, dvp); 2194 if (BCM_SUCCESS(rv)) { 2195 rv = _bcm_flow_ingress_dvp_reset(unit, dvp); 2196 } 2197 } 2198 } else { 2199 rv = BCM_E_NOT_FOUND; 2200 } 2201 bcmi_esw_flow_unlock(unit); 2202 SOC_IF_ERROR_RETURN(rv); 2203 return rv; 2204 } 2205 2206 if (!_bcm_vp_used_get(unit, dvp, _bcmVpTypeFlow)) { 2207 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 2208 "DVP %d is not flow port, create flow port first\n"), dvp)); 2209 bcmi_esw_flow_unlock(unit); 2210 return BCM_E_NOT_FOUND; 2211 } 2212 2213 /* Check for Network-Port */ 2214 rv = _bcm_vp_info_get(unit, dvp, &vp_info); 2215 _BCM_FLOW_CLEANUP(rv); 2216 if (vp_info.flags & _BCM_VP_INFO_NETWORK_PORT) { 2217 network_port = TRUE; 2218 } else { 2219 network_port = FALSE; 2220 } 2221 2222 if (info->valid_elements & BCM_FLOW_PORT_ENCAP_EGRESS_IF_VALID) { 2223 rv = _bcm_flow_port_egr_nh_add(unit, info, network_port, &nh_idx, 2224 &mpath_flag); 2225 _BCM_FLOW_CLEANUP(rv); 2226 } 2227 if (network_port) { 2228 rv = _bcm_flow_egress_network_dvp_set(unit, info, field, 2229 num_of_fields); 2230 _BCM_FLOW_CLEANUP(rv); 2231 2232 /* Program DVP entry - Ingress */ 2233 rv = _bcm_flow_ingress_dvp_set(unit, dvp, mpath_flag, 2234 nh_idx, info, network_port); 2235 _BCM_FLOW_CLEANUP(rv); 2236 2237 rv = _bcm_flow_ingress_dvp_2_set(unit, dvp, mpath_flag, 2238 nh_idx, info, network_port); 2239 _BCM_FLOW_CLEANUP(rv); 2240 2241 } else { 2242 rv = _bcm_flow_egress_access_dvp_set(unit, info, field, num_of_fields); 2243 _BCM_FLOW_CLEANUP(rv); 2244 2245 /* Program DVP entry with ECMP / Next Hop Index */ 2246 rv = _bcm_flow_ingress_dvp_set(unit, dvp, mpath_flag, 2247 nh_idx, info, network_port); 2248 _BCM_FLOW_CLEANUP(rv); 2249 2250 rv = _bcm_flow_ingress_dvp_2_set(unit, dvp, mpath_flag, 2251 nh_idx, info, network_port); 2252 _BCM_FLOW_CLEANUP(rv); 2253 } 2254 2255 if (BCM_SUCCESS(rv)) { 2256 /* indicates the dvp is set up */ 2257 _BCM_FLOW_EGR_DVP_USED_SET(unit,dvp); 2258 } 2259 2260 cleanup: 2261 bcmi_esw_flow_unlock(unit); 2262 return rv; 2263 } 2264 2265 /* 2266 * Function: 2267 * bcmi_esw_flow_port_encap_get 2268 * Purpose: 2269 * Get the user configuration parameters from the given object. For L2 2270 tunnel, it is dvp. For L3 tunnel, it is egress object id. 2271 * 2272 * Parameters: 2273 * unit - (IN) Device Number 2274 * info - (IN/OUT) Flow egress encap descriptor 2275 * num_of_fields - (IN) number of logical fields 2276 * field - (IN/OUT) logical field array 2277 * Returns: 2278 * BCM_E_XXX 2279 */ 2280 2281 2282 int bcmi_esw_flow_port_encap_get( 2283 int unit, 2284 bcm_flow_port_encap_t *info, 2285 uint32 num_of_fields, 2286 bcm_flow_logical_field_t *field) 2287 { 2288 int dvp; 2289 int num_vp; 2290 2291 if (info == NULL) { 2292 return BCM_E_PARAM; 2293 } 2294 2295 dvp = _SHR_GPORT_FLOW_PORT_ID_GET(info->flow_port); 2296 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 2297 if ((dvp <= 0) || (dvp >= num_vp)) { 2298 return BCM_E_PARAM; 2299 } 2300 if (!_bcm_vp_used_get(unit, dvp, _bcmVpTypeFlow)) { 2301 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 2302 "DVP %d is not flow port, create flow port first\n"), dvp)); 2303 return BCM_E_NOT_FOUND; 2304 } 2305 2306 BCM_IF_ERROR_RETURN(_bcm_flow_port_egr_nh_get(unit, info)); 2307 BCM_IF_ERROR_RETURN(_bcm_flow_egress_dvp_get(unit, 2308 info, field, num_of_fields)); 2309 return BCM_E_NONE; 2310 } 2311 2312 /* 2313 * Function: 2314 * _bcm_flow_encap_fixed_view_entry_init 2315 * Purpose: 2316 * initialize the fixed view memory entry 2317 * Parameters: 2318 * unit - (IN) Device Number 2319 * mem - (IN) memory id 2320 * info - (IN) flow encap configuration info 2321 * key_type - (IN) the fixed key type 2322 * entry - (OUT) point to the entry to be initialized 2323 * Returns: 2324 * BCM_E_XXX 2325 */ 2326 STATIC int 2327 _bcm_flow_encap_fixed_view_entry_init(int unit, 2328 soc_mem_t mem, 2329 uint32 key_type, 2330 uint32 *entry) 2331 { 2332 int rv = BCM_E_NONE; 2333 2334 soc_mem_field32_set(unit,mem, entry, KEY_TYPEf, key_type); 2335 if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) { 2336 if ((key_type == _BCM_FLOW_ENCAP_VXLAN_KEY_TYPE_VFI) || 2337 (key_type == _BCM_FLOW_ENCAP_VXLAN_KEY_TYPE_VFI_DVP)) { 2338 soc_mem_field32_set(unit, mem, entry, DATA_TYPEf, 23); 2339 } else if (key_type == _BCM_FLOW_ENCAP_KEY_TYPE_VFI_DVP_GROUP) { 2340 soc_mem_field32_set(unit, mem, entry, DATA_TYPEf, 21); 2341 } else { 2342 soc_mem_field32_set(unit, mem, entry, DATA_TYPEf, key_type); 2343 } 2344 } else { 2345 soc_mem_field32_set(unit, mem, entry, DATA_TYPEf, key_type); 2346 } 2347 if (soc_mem_field_valid(unit, mem, BASE_VALIDf)) { 2348 soc_mem_field32_set(unit, mem, entry, BASE_VALIDf, 1); 2349 } else { 2350 soc_mem_field32_set(unit, mem, entry, BASE_VALID_0f, 3); 2351 soc_mem_field32_set(unit, mem, entry, BASE_VALID_1f, 7); 2352 } 2353 return rv; 2354 } 2355 2356 /* 2357 * Function: 2358 * _bcm_flow_encap_entry_key_set 2359 * Purpose: 2360 * Set flow encap Entry Key 2361 * Parameters: 2362 * unit - (IN) Device Number 2363 * info - (IN) flow_match configuration info 2364 * field - (IN) array of logical fields 2365 * num_of_fields -(IN) the size of the above array 2366 * mem - (IN) memory id 2367 * entry - (IN) point to the match entry 2368 * Returns: 2369 * BCM_E_XXX 2370 */ 2371 2372 STATIC 2373 int _bcm_flow_encap_entry_key_set(int unit, 2374 bcm_flow_encap_config_t *info, 2375 bcm_flow_logical_field_t *field, 2376 int num_of_fields, 2377 soc_mem_t mem_id, 2378 uint32 *entry, 2379 int network_port) 2380 { 2381 int i; 2382 int j; 2383 soc_field_t vfi_f = 0; 2384 soc_field_t vrf_f = 0; 2385 soc_field_t dvp_f = 0; 2386 soc_field_t dvp_grp_f = 0; 2387 soc_field_t oif_grp_f = 0; 2388 int rv; 2389 uint32 dvp = 0; 2390 uint32 vfi = 0; 2391 uint32 vrf = 0; 2392 2393 /* 2394 * BCM_FLOW_ENCAP_CRITERIA_VFI_DVP_GROUP 2395 * if network_port 2396 * VFI_DVP_GROUP__DATA_TYPE = 0 tunnel data 2397 * else access DVP 2398 * VFI_DVP_GROUP__DATA_TYPE = 1 vlan_xlate 2399 * 2400 * BCM_FLOW_ENCAP_CRITERIA_VFI_DVP 2401 * if network_port 2402 * regular match 2403 * else access DVP 2404 * VLAN_XLATE_VFI key_type = 12 2405 */ 2406 2407 /* validate parameters */ 2408 2409 if (info->valid_elements & BCM_FLOW_ENCAP_FLOW_PORT_VALID) { 2410 if (!BCM_GPORT_IS_MODPORT(info->flow_port)) { 2411 dvp = _SHR_GPORT_FLOW_PORT_ID_GET(info->flow_port); 2412 } 2413 } 2414 if (info->valid_elements & BCM_FLOW_ENCAP_VPN_VALID) { 2415 BCM_IF_ERROR_RETURN( 2416 (bcmi_esw_flow_vpn_is_valid(unit, info->vpn))); 2417 _BCM_FLOW_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, info->vpn); 2418 } 2419 2420 if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_DVP) { 2421 if (!dvp) { 2422 return BCM_E_PARAM; 2423 } 2424 /* only apply to flex view */ 2425 if (!_BCM_FLOW_IS_FLEX_VIEW(info)) { 2426 return BCM_E_PARAM; 2427 } 2428 if (SOC_MEM_FIELD_VALID(unit,mem_id,DVPf)) { 2429 soc_mem_field32_set(unit,mem_id, entry, DVPf, dvp); 2430 } else { 2431 LOG_VERBOSE(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 2432 "DVPf not in memory view definition\n"))); 2433 return BCM_E_PARAM; 2434 } 2435 2436 } else if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_L3_INTF) { 2437 2438 if (info->valid_elements & BCM_FLOW_ENCAP_INTF_VALID) { 2439 2440 /* only apply to flex view */ 2441 if (!_BCM_FLOW_IS_FLEX_VIEW(info)) { 2442 return BCM_E_PARAM; 2443 } 2444 if (SOC_MEM_FIELD_VALID(unit,mem_id,L3_OIFf)) { 2445 soc_mem_field32_set(unit,mem_id, entry, L3_OIFf, info->intf_id); 2446 } else { 2447 LOG_VERBOSE(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 2448 "L3_OIFf not in memory view definition\n"))); 2449 return BCM_E_PARAM; 2450 } 2451 } 2452 } else if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VRF_MAPPING) { 2453 /* KEY : VRF,VT_DVP_GROUP_ID,VT_L3_OIF_GROUP_ID 2454 * VT_DVP_GROUP_ID : from EGR_DVP_ATTRIBUTEm 2455 * VT_L3_OIF_GROUP_ID : from EGR_L3_INTFm 2456 */ 2457 _BCM_FLOW_VPN_GET(vrf, _BCM_VPN_TYPE_L3, info->vpn); 2458 if (_BCM_FLOW_IS_FLEX_VIEW(info)) { 2459 vrf_f = VRFf; 2460 dvp_grp_f = VT_DVP_GROUP_IDf; 2461 oif_grp_f = VT_L3OIF_GROUP_IDf; 2462 } else { 2463 vrf_f = VRF_MAPPING__VRFf; 2464 dvp_grp_f = VRF_MAPPING__VT_DVP_GROUP_IDf; 2465 oif_grp_f = VRF_MAPPING__VT_L3OIF_GROUP_IDf; 2466 } 2467 if (info->valid_elements & BCM_FLOW_ENCAP_VPN_VALID) { 2468 if (!SOC_MEM_FIELD_VALID(unit, mem_id, vrf_f) || 2469 (vrf > SOC_VRF_MAX(unit))) { 2470 return BCM_E_PARAM; 2471 } 2472 soc_mem_field32_set(unit,mem_id, entry, vrf_f, vrf); 2473 } 2474 if (info->valid_elements & BCM_FLOW_ENCAP_DVP_GROUP_VALID) { 2475 if (!SOC_MEM_FIELD_VALID(unit, mem_id, dvp_grp_f)) { 2476 return BCM_E_PARAM; 2477 } 2478 soc_mem_field32_set(unit,mem_id, entry, dvp_grp_f, info->dvp_group); 2479 } 2480 if (info->valid_elements & BCM_FLOW_ENCAP_OIF_GROUP_VALID) { 2481 if (!SOC_MEM_FIELD_VALID(unit, mem_id, oif_grp_f)) { 2482 return BCM_E_PARAM; 2483 } 2484 soc_mem_field32_set(unit,mem_id, entry, oif_grp_f, info->oif_group); 2485 } 2486 } else if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI_DVP_GROUP) { 2487 if (_BCM_FLOW_IS_FLEX_VIEW(info)) { 2488 vfi_f = VFIf; 2489 dvp_grp_f = VT_DVP_GROUP_IDf; 2490 } else { 2491 vfi_f = VFI_DVP_GROUP__VFIf; 2492 dvp_grp_f = VFI_DVP_GROUP__VT_DVP_GROUP_IDf; 2493 } 2494 if (info->valid_elements & BCM_FLOW_ENCAP_VPN_VALID) { 2495 if (!SOC_MEM_FIELD_VALID(unit, mem_id, vfi_f)) { 2496 return BCM_E_PARAM; 2497 } 2498 soc_mem_field32_set(unit,mem_id, entry, vfi_f, vfi); 2499 } 2500 if (info->valid_elements & BCM_FLOW_ENCAP_DVP_GROUP_VALID) { 2501 if (!SOC_MEM_FIELD_VALID(unit, mem_id, dvp_grp_f)) { 2502 return BCM_E_PARAM; 2503 } 2504 soc_mem_field32_set(unit,mem_id, entry, dvp_grp_f, info->dvp_group); 2505 } 2506 if (!_BCM_FLOW_IS_FLEX_VIEW(info)) { 2507 if (!SOC_MEM_FIELD_VALID(unit, mem_id, 2508 VFI_DVP_GROUP__DATA_OVERLAY_TYPEf)) { 2509 return BCM_E_PARAM; 2510 } 2511 if (network_port) { 2512 soc_mem_field32_set(unit,mem_id, entry, 2513 VFI_DVP_GROUP__DATA_OVERLAY_TYPEf, 0); 2514 } else { /* access DVP */ 2515 soc_mem_field32_set(unit,mem_id, entry, 2516 VFI_DVP_GROUP__DATA_OVERLAY_TYPEf, 1); 2517 } 2518 } 2519 } else if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI) { 2520 if (_BCM_FLOW_IS_FLEX_VIEW(info)) { 2521 vfi_f = VFIf; 2522 } else { 2523 if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) { 2524 if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) { 2525 vfi_f = VXLAN_VFI_FLEX__VFIf; 2526 } else { 2527 vfi_f = VXLAN_VFI__VFIf; 2528 } 2529 } else if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) { 2530 vfi_f = L2GRE_VFI__VFIf; 2531 } else { 2532 return BCM_E_PARAM; 2533 } 2534 } 2535 if (info->valid_elements & BCM_FLOW_ENCAP_VPN_VALID) { 2536 if (!SOC_MEM_FIELD_VALID(unit, mem_id, vfi_f)) { 2537 return BCM_E_PARAM; 2538 } 2539 soc_mem_field32_set(unit,mem_id, entry, vfi_f, vfi); 2540 } 2541 } else if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI_DVP) { 2542 2543 if (_BCM_FLOW_IS_FLEX_VIEW(info)) { 2544 vfi_f = VFIf; 2545 dvp_f = DVPf; 2546 } else { 2547 if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) { 2548 if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) { 2549 vfi_f = VXLAN_VFI_FLEX__VFIf; 2550 dvp_f = VXLAN_VFI_FLEX__DVPf; 2551 } else { 2552 vfi_f = VXLAN_VFI__VFIf; 2553 dvp_f = VXLAN_VFI__DVPf; 2554 } 2555 } else if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) { 2556 vfi_f = L2GRE_VFI__VFIf; 2557 dvp_f = L2GRE_VFI__DVPf; 2558 } else { 2559 vfi_f = VLAN_XLATE_VFI__VFIf; 2560 dvp_f = VLAN_XLATE_VFI__DVPf; 2561 } 2562 } 2563 if (info->valid_elements & BCM_FLOW_ENCAP_VPN_VALID) { 2564 if (!SOC_MEM_FIELD_VALID(unit,mem_id,vfi_f)) { 2565 return BCM_E_PARAM; 2566 } 2567 soc_mem_field32_set(unit, mem_id, entry, vfi_f, vfi); 2568 } 2569 if (info->valid_elements & BCM_FLOW_ENCAP_FLOW_PORT_VALID) { 2570 if (!dvp) { 2571 return BCM_E_PARAM; 2572 } 2573 if (!SOC_MEM_FIELD_VALID(unit,mem_id,dvp_f)) { 2574 return BCM_E_PARAM; 2575 } 2576 soc_mem_field32_set(unit, mem_id, entry, dvp_f, dvp); 2577 } 2578 } else if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_FLEX) { 2579 uint32 key_ids[_BCM_FLOW_LOGICAL_FIELD_MAX]; 2580 uint32 cnt; 2581 2582 rv = soc_flow_db_mem_view_field_list_get(unit, 2583 mem_id, 2584 SOC_FLOW_DB_FIELD_TYPE_LOGICAL_KEY, 2585 _BCM_FLOW_LOGICAL_FIELD_MAX, key_ids, &cnt); 2586 BCM_IF_ERROR_RETURN(rv); 2587 for (i = 0; i < num_of_fields; i++) { 2588 for (j = 0; j < cnt; j++) { 2589 if (field[i].id == key_ids[j]) { 2590 soc_mem_field32_set(unit,mem_id, entry, 2591 field[i].id, field[i].value); 2592 break; 2593 } 2594 } 2595 } 2596 if (info->valid_elements & BCM_FLOW_ENCAP_FLOW_PORT_VALID) { 2597 if (BCM_GPORT_IS_MODPORT(info->flow_port)) { 2598 if (!SOC_MEM_FIELD_VALID(unit, mem_id, DGPPf)) { 2599 return BCM_E_PARAM; 2600 } 2601 soc_mem_field32_set(unit,mem_id, entry, DGPPf, 2602 (_SHR_GPORT_MODPORT_MODID_GET(info->flow_port) << 2603 _BCM_FLOW_MODID_SHIFTER) | 2604 _SHR_GPORT_MODPORT_PORT_GET(info->flow_port)); 2605 } else { 2606 if (!dvp) { 2607 return BCM_E_PARAM; 2608 } 2609 if (!SOC_MEM_FIELD_VALID(unit, mem_id, DVPf)) { 2610 return BCM_E_PARAM; 2611 } 2612 soc_mem_field32_set(unit,mem_id, entry, DVPf, dvp); 2613 } 2614 } 2615 if (info->valid_elements & BCM_FLOW_ENCAP_VPN_VALID) { 2616 if (!SOC_MEM_FIELD_VALID(unit, mem_id, VFIf)) { 2617 return BCM_E_PARAM; 2618 } 2619 soc_mem_field32_set(unit,mem_id, entry, VFIf, vfi); 2620 } 2621 if (info->valid_elements & BCM_FLOW_ENCAP_INTF_VALID) { 2622 if (!SOC_MEM_FIELD_VALID(unit, mem_id, L3_OIFf)) { 2623 return BCM_E_PARAM; 2624 } 2625 soc_mem_field32_set(unit,mem_id, entry, L3_OIFf, info->intf_id); 2626 } 2627 if (info->valid_elements & BCM_FLOW_ENCAP_DVP_GROUP_VALID) { 2628 if (!SOC_MEM_FIELD_VALID(unit, mem_id, VT_DVP_GROUP_IDf)) { 2629 return BCM_E_PARAM; 2630 } 2631 soc_mem_field32_set(unit,mem_id, entry, VT_DVP_GROUP_IDf, 2632 info->dvp_group); 2633 } 2634 if (info->valid_elements & BCM_FLOW_ENCAP_OIF_GROUP_VALID) { 2635 if (!SOC_MEM_FIELD_VALID(unit, mem_id, VT_L3OIF_GROUP_IDf)) { 2636 return BCM_E_PARAM; 2637 } 2638 soc_mem_field32_set(unit,mem_id, entry, VT_L3OIF_GROUP_IDf, 2639 info->oif_group); 2640 } 2641 if (info->valid_elements & BCM_FLOW_ENCAP_SRC_FLOW_PORT_VALID) { 2642 uint32 svp = 0; 2643 if (BCM_GPORT_IS_FLOW_PORT(info->src_flow_port)) { 2644 svp = _SHR_GPORT_FLOW_PORT_ID_GET(info->src_flow_port); 2645 } else { 2646 return BCM_E_PARAM; 2647 } 2648 if (!SOC_MEM_FIELD_VALID(unit, mem_id, SVPf)) { 2649 return BCM_E_PARAM; 2650 } 2651 soc_mem_field32_set(unit,mem_id, entry, SVPf, svp); 2652 } 2653 if (info->valid_elements & BCM_FLOW_ENCAP_CLASS_ID_VALID) { 2654 if (SOC_MEM_FIELD_VALID(unit, mem_id, CLASS_IDf)) { 2655 soc_mem_field32_set(unit, mem_id, entry, CLASS_IDf, info->class_id); 2656 } else if (SOC_MEM_FIELD_VALID(unit, mem_id, CLASS_ID_ACTION_SETf)) { 2657 soc_mem_field32_set(unit, mem_id, entry, CLASS_ID_ACTION_SETf, info->class_id); 2658 } else { 2659 return BCM_E_PARAM; 2660 } 2661 } 2662 } else if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_SVP_DVP) { 2663 if (soc_feature(unit, soc_feature_vxlan_evpn)) { 2664 if (!dvp) { 2665 return BCM_E_PARAM; 2666 } 2667 if (!SOC_MEM_FIELD_VALID(unit, mem_id, DVPf)) { 2668 return BCM_E_PARAM; 2669 } 2670 soc_mem_field32_set(unit,mem_id, entry, DVPf, dvp); 2671 2672 if (info->valid_elements & BCM_FLOW_ENCAP_SRC_FLOW_PORT_VALID) { 2673 uint32 svp = 0; 2674 2675 if (BCM_GPORT_IS_FLOW_PORT(info->src_flow_port)) { 2676 svp = _SHR_GPORT_FLOW_PORT_ID_GET(info->src_flow_port); 2677 } else { 2678 return BCM_E_PARAM; 2679 } 2680 2681 if (!SOC_MEM_FIELD_VALID(unit, mem_id, SVPf)) { 2682 return BCM_E_PARAM; 2683 } 2684 soc_mem_field32_set(unit,mem_id, entry, SVPf, svp); 2685 } 2686 } else { 2687 return BCM_E_UNAVAIL; 2688 } 2689 } 2690 return BCM_E_NONE; 2691 } 2692 2693 2694 /* 2695 * Function: 2696 * _bcm_flow_encap_key_set 2697 * Purpose: 2698 * Set the key for a flow encap entry 2699 * Parameters: 2700 * unit - (IN) Device Number 2701 * info - (IN) flow_match configuration info 2702 * field - (IN) array of logical fields 2703 * num_of_fields -(IN) the size of the above array 2704 * entry - (IN) point to the match entry 2705 * mem - (OUT) memory id 2706 * mem_view - (OUT) memory view id 2707 * Returns: 2708 * BCM_E_XXX 2709 */ 2710 2711 STATIC 2712 int _bcm_flow_encap_key_set( 2713 int unit, 2714 bcm_flow_encap_config_t *info, 2715 bcm_flow_logical_field_t *field, 2716 uint32 num_of_fields, 2717 uint32 *entry, 2718 soc_mem_t *mem, 2719 soc_mem_t *mem_view, 2720 int *network_port) 2721 { 2722 int rv; 2723 soc_mem_t mem_view_id = 0; 2724 uint32 key_type = 0; 2725 soc_mem_t mem_id = 0; 2726 soc_flow_db_mem_view_info_t vinfo; 2727 2728 *network_port = FALSE; 2729 /* validate parameters */ 2730 2731 /* flow port based encap */ 2732 if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_DVP || 2733 info->criteria == BCM_FLOW_ENCAP_CRITERIA_L3_INTF) { 2734 /* no fixed view supported */ 2735 if (!_BCM_FLOW_IS_FLEX_VIEW(info)) { 2736 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 2737 "encap criteria not supported in legacy flow\n"))); 2738 return BCM_E_PARAM; 2739 } 2740 } else if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VRF_MAPPING) { 2741 mem_id = EGR_VLAN_XLATE_1_DOUBLEm; 2742 key_type = _BCM_FLOW_ENCAP_KEY_TYPE_VRF_MAPPING; 2743 *network_port = TRUE; 2744 } else if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI) { 2745 mem_id = EGR_VLAN_XLATE_1_DOUBLEm; /* fixed view */ 2746 if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) { 2747 if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) { 2748 mem_id = EGR_VLAN_XLATE_1_SINGLEm; 2749 } 2750 key_type = _BCM_FLOW_ENCAP_VXLAN_KEY_TYPE_VFI; 2751 *network_port = TRUE; 2752 } else if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) { 2753 key_type = _BCM_FLOW_ENCAP_L2GRE_KEY_TYPE_VFI; 2754 *network_port = TRUE; 2755 } 2756 } else if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI_DVP) { 2757 mem_id = EGR_VLAN_XLATE_1_DOUBLEm; /* fixed view */ 2758 if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) { 2759 key_type = _BCM_FLOW_ENCAP_VXLAN_KEY_TYPE_VFI_DVP; 2760 *network_port = TRUE; 2761 if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) { 2762 mem_id = EGR_VLAN_XLATE_1_SINGLEm; 2763 } 2764 } else if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) { 2765 key_type = _BCM_FLOW_ENCAP_L2GRE_KEY_TYPE_VFI_DVP; 2766 *network_port = TRUE; 2767 } else if (!(info->flow_handle)) { /* access DVP */ 2768 key_type = _BCM_FLOW_ENCAP_KEY_TYPE_VLAN_XLATE_VFI; 2769 } 2770 } else if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI_DVP_GROUP) { 2771 key_type = _BCM_FLOW_ENCAP_KEY_TYPE_VFI_DVP_GROUP; 2772 if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN || 2773 info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) { 2774 *network_port = TRUE; 2775 } else if (!(info->flow_handle)) { /* access DVP */ 2776 key_type = _BCM_FLOW_ENCAP_KEY_TYPE_VLAN_XLATE_VFI; 2777 } 2778 2779 mem_id = EGR_VLAN_XLATE_1_DOUBLEm; /* fixed view */ 2780 } 2781 *mem = mem_id; 2782 2783 if (!_BCM_FLOW_IS_FLEX_VIEW(info)) { 2784 if (!(*mem)) { 2785 return BCM_E_PARAM; 2786 } 2787 rv = _bcm_flow_encap_fixed_view_entry_init(unit, mem_id, 2788 key_type, entry); 2789 BCM_IF_ERROR_RETURN(rv); 2790 } else { 2791 /* get the physical memory view */ 2792 rv = soc_flow_db_ffo_to_mem_view_id_get(unit,info->flow_handle, 2793 info->flow_option, 2794 SOC_FLOW_DB_FUNC_ENCAP_ID, (uint32 *)&mem_view_id); 2795 BCM_IF_ERROR_RETURN(rv); 2796 rv = soc_flow_db_mem_view_info_get(unit, mem_view_id, &vinfo); 2797 BCM_IF_ERROR_RETURN(rv); 2798 if (mem_view != NULL) { 2799 *mem_view = mem_view_id; 2800 } 2801 *mem = vinfo.mem; 2802 2803 /* flex view, initialize all control fields such as data_type */ 2804 soc_flow_db_mem_view_entry_init(unit,mem_view_id,entry); 2805 mem_id = mem_view_id; 2806 *network_port = TRUE; 2807 } 2808 2809 rv = _bcm_flow_encap_entry_key_set(unit,info,field,num_of_fields, 2810 mem_id, entry,*network_port); 2811 return rv; 2812 } 2813 2814 STATIC int 2815 _bcm_flow_encap_vlan_set(int unit, bcm_flow_encap_config_t *info, 2816 soc_mem_t mem, 2817 uint32 *entry, 2818 uint32 *otag, 2819 uint32 *xlate_data) 2820 { 2821 int xlate_format; 2822 bcm_vlan_action_set_t action; 2823 uint32 profile_idx; 2824 xlate_format = EGR_VLAN_XLATE_XLATE_DATA_DOUBLEfmt; 2825 2826 /* access facing port. Derive vlan tag from VFI/DVP. If VFI is valid 2827 * in EGR_L3_INTF, then the packet is treated as un-tagged 2828 */ 2829 if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI_DVP_GROUP || 2830 info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI_DVP) { 2831 if (info->valid_elements & BCM_FLOW_ENCAP_VLAN_VALID) { 2832 if (_BCM_FLOW_IS_FLEX_VIEW(info)) { 2833 soc_format_field32_set(unit,OTAG_ACTION_SETfmt,&otag, 2834 VIDf,info->vlan); 2835 } else { 2836 if (soc_mem_field_valid(unit, mem, VXLAN_VFI_FLEX__OVIDf)) { 2837 soc_mem_field32_set(unit, mem, entry, VXLAN_VFI_FLEX__OVIDf, info->vlan); 2838 } else { 2839 soc_format_field32_set(unit,xlate_format, 2840 xlate_data, NEW_OVIDf,info->vlan); 2841 } 2842 } 2843 } 2844 if (info->valid_elements & BCM_FLOW_ENCAP_PKT_PRI_VALID) { 2845 if (_BCM_FLOW_IS_FLEX_VIEW(info)) { 2846 soc_format_field32_set(unit,OTAG_ACTION_SETfmt,&otag, 2847 PCPf,info->pri); 2848 } else { 2849 if (soc_mem_field_valid(unit, mem, VXLAN_VFI_FLEX__OPRIf)) { 2850 soc_mem_field32_set(unit, mem, entry, VXLAN_VFI_FLEX__OPRIf, info->pri); 2851 } else { 2852 soc_format_field32_set(unit,xlate_format, 2853 xlate_data, NEW_OPRIf,info->pri); 2854 } 2855 } 2856 } 2857 if (info->valid_elements & BCM_FLOW_ENCAP_PKT_CFI_VALID) { 2858 if (_BCM_FLOW_IS_FLEX_VIEW(info)) { 2859 soc_format_field32_set(unit,OTAG_ACTION_SETfmt,&otag, 2860 DEf,info->cfi); 2861 } else { 2862 if (soc_mem_field_valid(unit, mem, VXLAN_VFI_FLEX__OCFIf)) { 2863 soc_mem_field32_set(unit, mem, entry, VXLAN_VFI_FLEX__OCFIf,info->cfi); 2864 } else { 2865 soc_format_field32_set(unit,xlate_format, 2866 xlate_data, NEW_OCFIf,info->cfi); 2867 } 2868 } 2869 } 2870 if (info->valid_elements & (BCM_FLOW_ENCAP_VLAN_VALID | 2871 BCM_FLOW_ENCAP_PKT_PRI_VALID | 2872 BCM_FLOW_ENCAP_PKT_CFI_VALID) ) { 2873 2874 /* action profile */ 2875 bcm_vlan_action_set_t_init(&action); 2876 action.ut_outer = bcmVlanActionAdd; 2877 action.ut_outer_pkt_prio = bcmVlanActionAdd; 2878 action.ut_outer_cfi = bcmVlanActionAdd; 2879 2880 BCM_IF_ERROR_RETURN(_bcm_trx_egr_vlan_action_profile_entry_add( 2881 unit, &action, &profile_idx)); 2882 if (_BCM_FLOW_IS_FLEX_VIEW(info)) { 2883 soc_mem_field32_set(unit,mem, entry, 2884 TAG_ACTION_PROFILE_ACTION_SETf,profile_idx); 2885 } else { 2886 if (soc_mem_field_valid(unit, mem, VXLAN_VFI_FLEX__TAG_ACTION_PROFILE_PTRf)) { 2887 soc_mem_field32_set(unit, mem, entry, 2888 VXLAN_VFI_FLEX__TAG_ACTION_PROFILE_PTRf, profile_idx); 2889 } else { 2890 soc_format_field32_set(unit,xlate_format, 2891 xlate_data, TAG_ACTION_PROFILE_PTRf,profile_idx); 2892 } 2893 } 2894 } 2895 } 2896 return BCM_E_NONE; 2897 } 2898 2899 STATIC int 2900 _bcm_flow_encap_vlan_get(int unit, bcm_flow_encap_config_t *info, 2901 soc_mem_t hw_mem, 2902 uint32 *entry, 2903 uint32 *otag, 2904 uint32 *xlate_data) 2905 { 2906 int xlate_format; 2907 xlate_format = EGR_VLAN_XLATE_XLATE_DATA_DOUBLEfmt; 2908 2909 /* access facing port. Derive vlan tag from VFI/DVP. If VFI is valid 2910 * in EGR_L3_INTF, then the packet is treated as un-tagged 2911 */ 2912 if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI_DVP_GROUP || 2913 info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI_DVP) { 2914 if (_BCM_FLOW_IS_FLEX_VIEW(info)) { 2915 info->vlan = soc_format_field32_get(unit,OTAG_ACTION_SETfmt,&otag, 2916 VIDf); 2917 info->pri = soc_format_field32_get(unit,OTAG_ACTION_SETfmt,&otag, 2918 PCPf); 2919 info->cfi = soc_format_field32_get(unit,OTAG_ACTION_SETfmt,&otag, 2920 DEf); 2921 } else { 2922 if (soc_mem_field_valid(unit, hw_mem, OVIDf)) { 2923 info->vlan = soc_mem_field32_get(unit,hw_mem, entry, OVIDf); 2924 } else { 2925 info->vlan = soc_format_field32_get(unit,xlate_format, 2926 xlate_data, NEW_OVIDf); 2927 } 2928 if (soc_mem_field_valid(unit, hw_mem, OPRIf)) { 2929 info->pri = soc_mem_field32_get(unit,hw_mem, entry, OPRIf); 2930 } else { 2931 info->pri = soc_format_field32_get(unit,xlate_format, 2932 xlate_data, NEW_OPRIf); 2933 } 2934 if (soc_mem_field_valid(unit, hw_mem, OCFIf)) { 2935 info->cfi = soc_mem_field32_get(unit,hw_mem, entry, OCFIf); 2936 } else { 2937 info->cfi = soc_format_field32_get(unit,xlate_format, 2938 xlate_data, NEW_OCFIf); 2939 } 2940 } 2941 } 2942 return BCM_E_NONE; 2943 } 2944 2945 STATIC int 2946 _bcm_flow_sd_tag_set(int unit, bcm_flow_encap_config_t *info, 2947 uint32 *sd_tag, 2948 int *tpid_index) 2949 { 2950 int action_present; 2951 int action_not_present; 2952 int sd_tag_remark_cfi_set = 0; 2953 int tag_format; 2954 int old_tpid_inx; 2955 2956 if (_BCM_FLOW_IS_FLEX_VIEW(info) || 2957 (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI_DVP_GROUP)) { 2958 tag_format = SD_TAG_ACTION_SETfmt; 2959 } else { 2960 tag_format = SD_TAG_DATA_FORMAT_DOUBLEfmt; 2961 } 2962 2963 action_present = 0; 2964 action_not_present = 0; 2965 2966 /* only these two fixed views use specific field names 2967 * Others use sd_tag format 2968 */ 2969 if (info->valid_elements & BCM_FLOW_ENCAP_VLAN_VALID) { 2970 if (info->vlan >= BCM_VLAN_INVALID) { 2971 return BCM_E_PARAM; 2972 } 2973 soc_format_field32_set(unit,tag_format,sd_tag, 2974 SD_TAG_VIDf,info->vlan); 2975 } 2976 if (info->valid_elements & BCM_FLOW_ENCAP_PKT_PRI_VALID) { 2977 if (info->pri > BCM_PRIO_MAX) { 2978 return BCM_E_PARAM; 2979 } 2980 soc_format_field32_set(unit,tag_format,sd_tag, 2981 SD_TAG_NEW_PRIf,info->pri); 2982 } 2983 if (info->valid_elements & BCM_FLOW_ENCAP_PKT_CFI_VALID) { 2984 if (info->cfi > 1) { 2985 return BCM_E_PARAM; 2986 } 2987 soc_format_field32_set(unit,tag_format,sd_tag, 2988 SD_TAG_NEW_CFIf,info->cfi); 2989 } 2990 2991 if (info->flags & BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_ADD) { 2992 sd_tag_remark_cfi_set = TRUE; 2993 action_not_present = 0x1; /* ADD */ 2994 } 2995 2996 if (info->flags & BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_TPID_REPLACE) { 2997 action_present = 0x1; /* REPLACE_VID_TPID */ 2998 2999 } else if (info->flags & BCM_FLOW_ENCAP_FLAG_VLAN_REPLACE) { 3000 action_present = 0x2; /* REPLACE_VID_ONLY */ 3001 3002 } else if (info->flags & BCM_FLOW_ENCAP_FLAG_VLAN_DELETE) { 3003 action_present = 0x3; /* DELETE */ 3004 3005 } else if (info->flags & BCM_FLOW_ENCAP_FLAG_VLAN_PRI_TPID_REPLACE) { 3006 sd_tag_remark_cfi_set = TRUE; 3007 action_present = 0x4; /* REPLACE_VID_PRI_TPID */ 3008 3009 } else if (info->flags & BCM_FLOW_ENCAP_FLAG_VLAN_PRI_REPLACE){ 3010 sd_tag_remark_cfi_set = TRUE; 3011 action_present = 0x5; /* REPLACE_VID_PRI */ 3012 3013 } else if (info->flags & BCM_FLOW_ENCAP_FLAG_PRI_REPLACE ) { 3014 sd_tag_remark_cfi_set = TRUE; 3015 action_present = 0x6; /* REPLACE_PRI_ONLY */ 3016 3017 } else if (info->flags & BCM_FLOW_ENCAP_FLAG_TPID_REPLACE) { 3018 action_present = 0x7; /* REPLACE_TPID_ONLY */ 3019 } 3020 if (sd_tag_remark_cfi_set) { 3021 soc_format_field32_set(unit,tag_format,sd_tag, 3022 SD_TAG_REMARK_CFIf,info->cfi); 3023 } 3024 if (action_not_present) { 3025 soc_format_field32_set(unit,tag_format,sd_tag, 3026 SD_TAG_ACTION_IF_NOT_PRESENTf,action_not_present); 3027 } 3028 if (action_present) { 3029 soc_format_field32_set(unit,tag_format,sd_tag, 3030 SD_TAG_ACTION_IF_PRESENTf,action_present); 3031 } 3032 3033 if ((info->flags & BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_ADD) || 3034 (info->flags & BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_TPID_REPLACE) || 3035 (info->flags & BCM_FLOW_ENCAP_FLAG_TPID_REPLACE) || 3036 (info->flags & BCM_FLOW_ENCAP_FLAG_VLAN_PRI_TPID_REPLACE)) { 3037 if (info->options & BCM_FLOW_ENCAP_OPTION_REPLACE) { 3038 old_tpid_inx = soc_format_field32_get(unit,tag_format,sd_tag, 3039 SD_TAG_TPID_INDEXf); 3040 BCM_IF_ERROR_RETURN(_bcm_fb2_outer_tpid_entry_delete(unit, 3041 old_tpid_inx)); 3042 } 3043 3044 /* TPID value is used */ 3045 BCM_IF_ERROR_RETURN(_bcm_fb2_outer_tpid_entry_add(unit, info->tpid, 3046 tpid_index)); 3047 soc_format_field32_set(unit,tag_format,sd_tag, 3048 SD_TAG_TPID_INDEXf,*tpid_index); 3049 } 3050 return BCM_E_NONE; 3051 } 3052 3053 STATIC int 3054 _bcm_flow_sd_tag_get(int unit, bcm_flow_encap_config_t *info, uint32 sd_tag, 3055 int *tpid_idx) 3056 { 3057 int action_present; 3058 int action_not_present; 3059 int tag_format; 3060 int tpid_index; 3061 int rv; 3062 3063 if (_BCM_FLOW_IS_FLEX_VIEW(info) || 3064 (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI_DVP_GROUP)) { 3065 tag_format = SD_TAG_ACTION_SETfmt; 3066 } else { 3067 tag_format = SD_TAG_DATA_FORMAT_DOUBLEfmt; 3068 } 3069 action_present = 0; 3070 action_not_present = 0; 3071 3072 info->vlan = soc_format_field32_get(unit,tag_format,&sd_tag, 3073 SD_TAG_VIDf); 3074 3075 info->pri = soc_format_field32_get(unit,tag_format,&sd_tag, 3076 SD_TAG_NEW_PRIf); 3077 info->cfi = soc_format_field32_get(unit,tag_format,&sd_tag, 3078 SD_TAG_NEW_CFIf); 3079 action_not_present = soc_format_field32_get(unit,tag_format,&sd_tag, 3080 SD_TAG_ACTION_IF_NOT_PRESENTf); 3081 action_present = soc_format_field32_get(unit,tag_format,&sd_tag, 3082 SD_TAG_ACTION_IF_PRESENTf); 3083 3084 if (action_not_present || action_present) { 3085 info->flags |= BCM_FLOW_ENCAP_FLAG_SERVICE_TAGGED; 3086 } 3087 if (action_not_present) { 3088 info->flags |= BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_ADD; 3089 } 3090 3091 if (action_present == 0x1) { 3092 info->flags |= BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_TPID_REPLACE; 3093 3094 } else if (action_present == 0x2) { 3095 info->flags |= BCM_FLOW_ENCAP_FLAG_VLAN_REPLACE; 3096 3097 } else if (action_present == 0x3) { 3098 info->flags |= BCM_FLOW_ENCAP_FLAG_VLAN_DELETE; 3099 3100 } else if (action_present == 4) { 3101 info->flags |= BCM_FLOW_ENCAP_FLAG_VLAN_PRI_TPID_REPLACE; 3102 3103 } else if (action_present == 0x5) { 3104 info->flags |= BCM_FLOW_ENCAP_FLAG_VLAN_PRI_REPLACE; 3105 3106 } else if (action_present == 0x6) { 3107 info->flags |= BCM_FLOW_ENCAP_FLAG_PRI_REPLACE; 3108 3109 } else if (action_present == 0x7) { 3110 info->flags |= BCM_FLOW_ENCAP_FLAG_TPID_REPLACE; 3111 } 3112 3113 if ((info->flags & BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_ADD) || 3114 (info->flags & BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_TPID_REPLACE) || 3115 (info->flags & BCM_FLOW_ENCAP_FLAG_TPID_REPLACE) || 3116 (info->flags & BCM_FLOW_ENCAP_FLAG_VLAN_PRI_TPID_REPLACE)) { 3117 3118 tpid_index = soc_format_field32_get(unit,tag_format,&sd_tag, 3119 SD_TAG_TPID_INDEXf); 3120 rv = _bcm_fb2_outer_tpid_entry_get(unit,&info->tpid,tpid_index); 3121 if (BCM_FAILURE(rv)) { 3122 info->flags |= _BCM_FLOW_ENCAP_FLAG_TPID_INDEX; 3123 info->tpid = tpid_index; 3124 } 3125 if (tpid_idx != NULL) { 3126 *tpid_idx = tpid_index; 3127 } 3128 } 3129 return BCM_E_NONE; 3130 } 3131 3132 STATIC int 3133 _bcm_flow_sd_tag_set_to_entry( 3134 int unit, 3135 bcm_flow_encap_config_t *info, 3136 soc_mem_t mem, 3137 uint32 *entry, 3138 int *tpid_index) 3139 { 3140 int action_present = 0; 3141 int action_not_present = 0; 3142 int sd_tag_remark_cfi_set = 0; 3143 int old_tpid_inx = 0; 3144 uint32 profile_index = 0; 3145 soc_field_t vlan_f = INVALIDf; 3146 soc_field_t pri_f = INVALIDf; 3147 soc_field_t cfi_f = INVALIDf; 3148 soc_field_t pri_cfi_sel_f = INVALIDf; 3149 soc_field_t tag_act_f = INVALIDf; 3150 soc_field_t tpid_f = INVALIDf; 3151 3152 if (_BCM_FLOW_IS_FLEX_VIEW(info)) { 3153 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 3154 "Fixed view only\n"))); 3155 return BCM_E_PARAM; 3156 } 3157 3158 if (mem == EGR_VLAN_XLATE_1_SINGLEm) { 3159 /* View VXLAN_VFI_FLEX */ 3160 vlan_f = VXLAN_VFI_FLEX__OVIDf; 3161 pri_f = VXLAN_VFI_FLEX__OPRIf; 3162 cfi_f = VXLAN_VFI_FLEX__OCFIf; 3163 pri_cfi_sel_f = VXLAN_VFI_FLEX__OPRI_OCFI_SELf; 3164 tag_act_f = VXLAN_VFI_FLEX__TAG_ACTION_PROFILE_PTRf; 3165 tpid_f = VXLAN_VFI_FLEX__OUTER_TPID_INDEXf; 3166 } else if (mem == EGR_L3_NEXT_HOPm) { 3167 /* View L2_OTAG */ 3168 vlan_f = L2_OTAG__VIDf; 3169 pri_f = L2_OTAG__PCPf; 3170 cfi_f = L2_OTAG__DEf; 3171 pri_cfi_sel_f = L2_OTAG__PCP_DE_SELf; 3172 tag_act_f = L2_OTAG__TAG_ACTION_PROFILE_PTRf; 3173 tpid_f = L2_OTAG__TPID_INDEXf; 3174 } else { 3175 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 3176 "Unsupported mem or view: %s\n"), SOC_MEM_UFNAME(unit, mem))); 3177 return BCM_E_PARAM; 3178 } 3179 3180 if (info->valid_elements & BCM_FLOW_ENCAP_VLAN_VALID) { 3181 if (info->vlan >= BCM_VLAN_INVALID) { 3182 return BCM_E_PARAM; 3183 } 3184 soc_mem_field32_set(unit, mem, entry, vlan_f, info->vlan); 3185 } 3186 if (info->valid_elements & BCM_FLOW_ENCAP_PKT_PRI_VALID) { 3187 if (info->pri > BCM_PRIO_MAX) { 3188 return BCM_E_PARAM; 3189 } 3190 soc_mem_field32_set(unit, mem, entry, pri_f, info->pri); 3191 } 3192 if (info->valid_elements & BCM_FLOW_ENCAP_PKT_CFI_VALID) { 3193 if (info->cfi > 1) { 3194 return BCM_E_PARAM; 3195 } 3196 soc_mem_field32_set(unit, mem, entry, cfi_f, info->cfi); 3197 } 3198 3199 if (info->flags & BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_ADD) { 3200 sd_tag_remark_cfi_set = TRUE; 3201 action_not_present = 0x1; /* ADD */ 3202 } 3203 3204 if (info->flags & BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_TPID_REPLACE) { 3205 action_present = 0x1; /* REPLACE_VID_TPID */ 3206 3207 } else if (info->flags & BCM_FLOW_ENCAP_FLAG_VLAN_REPLACE) { 3208 action_present = 0x2; /* REPLACE_VID_ONLY */ 3209 3210 } else if (info->flags & BCM_FLOW_ENCAP_FLAG_VLAN_DELETE) { 3211 action_present = 0x3; /* DELETE */ 3212 3213 } else if (info->flags & BCM_FLOW_ENCAP_FLAG_VLAN_PRI_TPID_REPLACE) { 3214 sd_tag_remark_cfi_set = TRUE; 3215 action_present = 0x4; /* REPLACE_VID_PRI_TPID */ 3216 3217 } else if (info->flags & BCM_FLOW_ENCAP_FLAG_VLAN_PRI_REPLACE){ 3218 sd_tag_remark_cfi_set = TRUE; 3219 action_present = 0x5; /* REPLACE_VID_PRI */ 3220 3221 } else if (info->flags & BCM_FLOW_ENCAP_FLAG_PRI_REPLACE ) { 3222 sd_tag_remark_cfi_set = TRUE; 3223 action_present = 0x6; /* REPLACE_PRI_ONLY */ 3224 3225 } else if (info->flags & BCM_FLOW_ENCAP_FLAG_TPID_REPLACE) { 3226 action_present = 0x7; /* REPLACE_TPID_ONLY */ 3227 } 3228 3229 soc_mem_field32_set(unit, mem, entry, pri_cfi_sel_f, sd_tag_remark_cfi_set); 3230 profile_index = soc_mem_field32_get(unit, mem, entry, tag_act_f); 3231 _bcm_td3_sd_tag_action_profile_get(unit, action_present, 3232 action_not_present, &profile_index); 3233 soc_mem_field32_set(unit, mem, entry, tag_act_f, profile_index); 3234 3235 if ((info->flags & BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_ADD) || 3236 (info->flags & BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_TPID_REPLACE) || 3237 (info->flags & BCM_FLOW_ENCAP_FLAG_TPID_REPLACE) || 3238 (info->flags & BCM_FLOW_ENCAP_FLAG_VLAN_PRI_TPID_REPLACE)) { 3239 if (info->options & BCM_FLOW_ENCAP_OPTION_REPLACE) { 3240 old_tpid_inx = soc_mem_field32_get(unit, mem, entry, tpid_f); 3241 BCM_IF_ERROR_RETURN(_bcm_fb2_outer_tpid_entry_delete(unit, 3242 old_tpid_inx)); 3243 } 3244 3245 /* TPID value is used */ 3246 BCM_IF_ERROR_RETURN(_bcm_fb2_outer_tpid_entry_add(unit, info->tpid, 3247 tpid_index)); 3248 soc_mem_field32_set(unit, mem, entry, tpid_f, *tpid_index); 3249 } 3250 return BCM_E_NONE; 3251 } 3252 3253 3254 STATIC int 3255 _bcm_flow_sd_tag_get_from_entry( 3256 int unit, 3257 bcm_flow_encap_config_t *info, 3258 soc_mem_t mem, 3259 uint32 *entry, 3260 int *tpid_idx) 3261 { 3262 int action_present = 0; 3263 int action_not_present = 0; 3264 int tpid_index = 0; 3265 uint32 profile_index = 0; 3266 int rv = BCM_E_NONE; 3267 soc_field_t vlan_f = INVALIDf; 3268 soc_field_t pri_f = INVALIDf; 3269 soc_field_t cfi_f = INVALIDf; 3270 soc_field_t tag_act_f = INVALIDf; 3271 soc_field_t tpid_f = INVALIDf; 3272 3273 if (_BCM_FLOW_IS_FLEX_VIEW(info)) { 3274 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 3275 "Fixed view only\n"))); 3276 return BCM_E_PARAM; 3277 } 3278 3279 if (mem == EGR_VLAN_XLATE_1_SINGLEm) { 3280 /* View VXLAN_VFI_FLEX */ 3281 vlan_f = VXLAN_VFI_FLEX__OVIDf; 3282 pri_f = VXLAN_VFI_FLEX__OPRIf; 3283 cfi_f = VXLAN_VFI_FLEX__OCFIf; 3284 tag_act_f = VXLAN_VFI_FLEX__TAG_ACTION_PROFILE_PTRf; 3285 tpid_f = VXLAN_VFI_FLEX__OUTER_TPID_INDEXf; 3286 } else if (mem == EGR_L3_NEXT_HOPm) { 3287 /* View L2_OTAG */ 3288 vlan_f = L2_OTAG__VIDf; 3289 pri_f = L2_OTAG__PCPf; 3290 cfi_f = L2_OTAG__DEf; 3291 tag_act_f = L2_OTAG__TAG_ACTION_PROFILE_PTRf; 3292 tpid_f = L2_OTAG__TPID_INDEXf; 3293 } else { 3294 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 3295 "Unsupported mem or view: %s\n"), SOC_MEM_UFNAME(unit, mem))); 3296 return BCM_E_PARAM; 3297 } 3298 3299 info->vlan = soc_mem_field32_get(unit, mem, entry, vlan_f); 3300 info->pri = soc_mem_field32_get(unit, mem, entry, pri_f); 3301 info->cfi = soc_mem_field32_get(unit, mem, entry, cfi_f); 3302 3303 profile_index = soc_mem_field32_get(unit, mem, entry, tag_act_f); 3304 (void)_bcm_td3_sd_tag_action_get(unit, profile_index, &action_present, 3305 &action_not_present); 3306 3307 if (action_not_present || action_present) { 3308 info->flags |= BCM_FLOW_ENCAP_FLAG_SERVICE_TAGGED; 3309 } 3310 if (action_not_present) { 3311 info->flags |= BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_ADD; 3312 } 3313 3314 if (action_present == 0x1) { 3315 info->flags |= BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_TPID_REPLACE; 3316 3317 } else if (action_present == 0x2) { 3318 info->flags |= BCM_FLOW_ENCAP_FLAG_VLAN_REPLACE; 3319 3320 } else if (action_present == 0x3) { 3321 info->flags |= BCM_FLOW_ENCAP_FLAG_VLAN_DELETE; 3322 3323 } else if (action_present == 4) { 3324 info->flags |= BCM_FLOW_ENCAP_FLAG_VLAN_PRI_TPID_REPLACE; 3325 3326 } else if (action_present == 0x5) { 3327 info->flags |= BCM_FLOW_ENCAP_FLAG_VLAN_PRI_REPLACE; 3328 3329 } else if (action_present == 0x6) { 3330 info->flags |= BCM_FLOW_ENCAP_FLAG_PRI_REPLACE; 3331 3332 } else if (action_present == 0x7) { 3333 info->flags |= BCM_FLOW_ENCAP_FLAG_TPID_REPLACE; 3334 } 3335 3336 if ((info->flags & BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_ADD) || 3337 (info->flags & BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_TPID_REPLACE) || 3338 (info->flags & BCM_FLOW_ENCAP_FLAG_TPID_REPLACE) || 3339 (info->flags & BCM_FLOW_ENCAP_FLAG_VLAN_PRI_TPID_REPLACE)) { 3340 tpid_index = soc_mem_field32_get(unit, mem, entry, tpid_f); 3341 3342 rv = _bcm_fb2_outer_tpid_entry_get(unit, &info->tpid, tpid_index); 3343 if (BCM_FAILURE(rv)) { 3344 info->flags |= _BCM_FLOW_ENCAP_FLAG_TPID_INDEX; 3345 info->tpid = tpid_index; 3346 } 3347 if (tpid_idx != NULL) { 3348 *tpid_idx = tpid_index; 3349 } 3350 } 3351 return BCM_E_NONE; 3352 } 3353 3354 STATIC int 3355 _bcm_flow_sd_tag_set_to_format( 3356 int unit, 3357 bcm_flow_encap_config_t *info, 3358 soc_mem_t mem, 3359 uint32 *entry, 3360 int *tpid_index) 3361 { 3362 int action_present = 0; 3363 int action_not_present = 0; 3364 int sd_tag_remark_cfi_set = 0; 3365 int old_tpid_inx = 0; 3366 uint32 profile_index = 0; 3367 soc_format_t tag_profile_fmt = TAG_ACTION_PROFILE_ACTION_SETfmt; 3368 soc_format_t tag_act_fmt = OTAG_ACTION_SETfmt; 3369 soc_field_t tag_profile_fmt_f = TAG_ACTION_PROFILE_ACTION_SETf; 3370 soc_field_t tag_act_fmt_f = OTAG_ACTION_SETf; 3371 uint32 tag_profile_set = 0; 3372 uint32 tag_act_set = 0; 3373 soc_field_t vlan_f = VIDf; 3374 soc_field_t pri_f = PCPf; 3375 soc_field_t cfi_f = DEf; 3376 soc_field_t pri_cfi_sel_f = PCP_DE_SELf; 3377 soc_field_t tag_act_f = TAG_ACTION_PROFILE_PTRf; 3378 soc_field_t tpid_f = TPID_INDEXf; 3379 3380 if (!_BCM_FLOW_IS_FLEX_VIEW(info)) { 3381 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 3382 "Flex view only\n"))); 3383 return BCM_E_PARAM; 3384 } 3385 3386 if (info->valid_elements & BCM_FLOW_ENCAP_VLAN_VALID) { 3387 if (info->vlan >= BCM_VLAN_INVALID) { 3388 return BCM_E_PARAM; 3389 } 3390 soc_format_field32_set(unit, tag_act_fmt, &tag_act_set, vlan_f, info->vlan); 3391 } 3392 if (info->valid_elements & BCM_FLOW_ENCAP_PKT_PRI_VALID) { 3393 if (info->pri > BCM_PRIO_MAX) { 3394 return BCM_E_PARAM; 3395 } 3396 soc_format_field32_set(unit, tag_act_fmt, &tag_act_set, pri_f, info->pri); 3397 } 3398 if (info->valid_elements & BCM_FLOW_ENCAP_PKT_CFI_VALID) { 3399 if (info->cfi > 1) { 3400 return BCM_E_PARAM; 3401 } 3402 soc_format_field32_set(unit, tag_act_fmt, &tag_act_set, cfi_f, info->cfi); 3403 } 3404 3405 if (info->flags & BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_ADD) { 3406 sd_tag_remark_cfi_set = TRUE; 3407 action_not_present = 0x1; /* ADD */ 3408 } 3409 3410 if (info->flags & BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_TPID_REPLACE) { 3411 action_present = 0x1; /* REPLACE_VID_TPID */ 3412 3413 } else if (info->flags & BCM_FLOW_ENCAP_FLAG_VLAN_REPLACE) { 3414 action_present = 0x2; /* REPLACE_VID_ONLY */ 3415 3416 } else if (info->flags & BCM_FLOW_ENCAP_FLAG_VLAN_DELETE) { 3417 action_present = 0x3; /* DELETE */ 3418 3419 } else if (info->flags & BCM_FLOW_ENCAP_FLAG_VLAN_PRI_TPID_REPLACE) { 3420 sd_tag_remark_cfi_set = TRUE; 3421 action_present = 0x4; /* REPLACE_VID_PRI_TPID */ 3422 3423 } else if (info->flags & BCM_FLOW_ENCAP_FLAG_VLAN_PRI_REPLACE){ 3424 sd_tag_remark_cfi_set = TRUE; 3425 action_present = 0x5; /* REPLACE_VID_PRI */ 3426 3427 } else if (info->flags & BCM_FLOW_ENCAP_FLAG_PRI_REPLACE ) { 3428 sd_tag_remark_cfi_set = TRUE; 3429 action_present = 0x6; /* REPLACE_PRI_ONLY */ 3430 3431 } else if (info->flags & BCM_FLOW_ENCAP_FLAG_TPID_REPLACE) { 3432 action_present = 0x7; /* REPLACE_TPID_ONLY */ 3433 } 3434 3435 soc_format_field32_set(unit, tag_act_fmt, &tag_act_set, pri_cfi_sel_f, sd_tag_remark_cfi_set); 3436 soc_mem_field32_set(unit, mem, entry, tag_act_fmt_f, tag_act_set); 3437 3438 tag_profile_set = soc_mem_field32_get(unit, mem, entry, tag_profile_fmt_f); 3439 3440 profile_index = soc_format_field32_get(unit, tag_profile_fmt, &tag_profile_set, tag_act_f); 3441 _bcm_td3_sd_tag_action_profile_get(unit, action_present, 3442 action_not_present, &profile_index); 3443 soc_format_field32_set(unit, tag_profile_fmt, &tag_profile_set, tag_act_f, profile_index); 3444 soc_mem_field32_set(unit, mem, entry, tag_profile_fmt_f, tag_profile_set); 3445 3446 if ((info->flags & BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_ADD) || 3447 (info->flags & BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_TPID_REPLACE) || 3448 (info->flags & BCM_FLOW_ENCAP_FLAG_TPID_REPLACE) || 3449 (info->flags & BCM_FLOW_ENCAP_FLAG_VLAN_PRI_TPID_REPLACE)) { 3450 if (info->options & BCM_FLOW_ENCAP_OPTION_REPLACE) { 3451 tag_act_set = soc_mem_field32_get(unit, mem, entry, tag_act_fmt_f); 3452 old_tpid_inx = soc_format_field32_get(unit, tag_act_fmt, &tag_act_set, tpid_f); 3453 BCM_IF_ERROR_RETURN(_bcm_fb2_outer_tpid_entry_delete(unit, 3454 old_tpid_inx)); 3455 } 3456 3457 /* TPID value is used */ 3458 BCM_IF_ERROR_RETURN(_bcm_fb2_outer_tpid_entry_add(unit, info->tpid, 3459 tpid_index)); 3460 3461 soc_format_field32_set(unit, tag_act_fmt, &tag_act_set, tpid_f, *tpid_index); 3462 soc_mem_field32_set(unit, mem, entry, tag_act_fmt_f, tag_act_set); 3463 } 3464 return BCM_E_NONE; 3465 } 3466 3467 3468 STATIC int 3469 _bcm_flow_sd_tag_get_from_format( 3470 int unit, 3471 bcm_flow_encap_config_t *info, 3472 soc_mem_t mem, 3473 uint32 *entry, 3474 int *tpid_idx) 3475 { 3476 int action_present = 0; 3477 int action_not_present = 0; 3478 int tpid_index = 0; 3479 uint32 profile_index = 0; 3480 int rv = BCM_E_NONE; 3481 soc_format_t tag_profile_fmt = TAG_ACTION_PROFILE_ACTION_SETfmt; 3482 soc_format_t tag_act_fmt = OTAG_ACTION_SETfmt; 3483 soc_field_t tag_profile_fmt_f = TAG_ACTION_PROFILE_ACTION_SETf; 3484 soc_field_t tag_act_fmt_f = OTAG_ACTION_SETf; 3485 uint32 tag_profile_set = 0; 3486 uint32 tag_act_set = 0; 3487 soc_field_t vlan_f = VIDf; 3488 soc_field_t pri_f = PCPf; 3489 soc_field_t cfi_f = DEf; 3490 soc_field_t tag_act_f = TAG_ACTION_PROFILE_PTRf; 3491 soc_field_t tpid_f = TPID_INDEXf; 3492 3493 3494 if (!_BCM_FLOW_IS_FLEX_VIEW(info)) { 3495 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 3496 "Flex view only\n"))); 3497 return BCM_E_PARAM; 3498 } 3499 3500 tag_act_set = soc_mem_field32_get(unit, mem, entry, tag_act_fmt_f); 3501 3502 info->vlan = soc_format_field32_get(unit, tag_act_fmt, &tag_act_set, vlan_f); 3503 info->pri = soc_format_field32_get(unit, tag_act_fmt, &tag_act_set, pri_f); 3504 info->cfi = soc_format_field32_get(unit, tag_act_fmt, &tag_act_set, cfi_f); 3505 3506 tag_profile_set = soc_mem_field32_get(unit, mem, entry, tag_profile_fmt_f); 3507 3508 profile_index = soc_format_field32_get(unit, tag_profile_fmt, &tag_profile_set, tag_act_f); 3509 (void)_bcm_td3_sd_tag_action_get(unit, profile_index, &action_present, 3510 &action_not_present); 3511 3512 if (action_not_present || action_present) { 3513 info->flags |= BCM_FLOW_ENCAP_FLAG_SERVICE_TAGGED; 3514 } 3515 if (action_not_present) { 3516 info->flags |= BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_ADD; 3517 } 3518 3519 if (action_present == 0x1) { 3520 info->flags |= BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_TPID_REPLACE; 3521 3522 } else if (action_present == 0x2) { 3523 info->flags |= BCM_FLOW_ENCAP_FLAG_VLAN_REPLACE; 3524 3525 } else if (action_present == 0x3) { 3526 info->flags |= BCM_FLOW_ENCAP_FLAG_VLAN_DELETE; 3527 3528 } else if (action_present == 4) { 3529 info->flags |= BCM_FLOW_ENCAP_FLAG_VLAN_PRI_TPID_REPLACE; 3530 3531 } else if (action_present == 0x5) { 3532 info->flags |= BCM_FLOW_ENCAP_FLAG_VLAN_PRI_REPLACE; 3533 3534 } else if (action_present == 0x6) { 3535 info->flags |= BCM_FLOW_ENCAP_FLAG_PRI_REPLACE; 3536 3537 } else if (action_present == 0x7) { 3538 info->flags |= BCM_FLOW_ENCAP_FLAG_TPID_REPLACE; 3539 } 3540 3541 if ((info->flags & BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_ADD) || 3542 (info->flags & BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_TPID_REPLACE) || 3543 (info->flags & BCM_FLOW_ENCAP_FLAG_TPID_REPLACE) || 3544 (info->flags & BCM_FLOW_ENCAP_FLAG_VLAN_PRI_TPID_REPLACE)) { 3545 tpid_index = soc_format_field32_get(unit, tag_act_fmt, &tag_act_set, tpid_f); 3546 3547 rv = _bcm_fb2_outer_tpid_entry_get(unit, &info->tpid, tpid_index); 3548 if (BCM_FAILURE(rv)) { 3549 info->flags |= _BCM_FLOW_ENCAP_FLAG_TPID_INDEX; 3550 info->tpid = tpid_index; 3551 } 3552 if (tpid_idx != NULL) { 3553 *tpid_idx = tpid_index; 3554 } 3555 } 3556 return BCM_E_NONE; 3557 } 3558 3559 /* 3560 * Function: 3561 * _bcm_flow_encap_profile_delete 3562 * Purpose: 3563 * Delete a profile in flow encap entry based on the given info 3564 * Parameters: 3565 * unit - (IN) Device Number 3566 * info - (IN) Flow encap config descriptor 3567 * mem - (IN) mempru ID 3568 * mem_view - (IN) memory view ID 3569 * key_data - (IN) entry key 3570 * Returns: 3571 * BCM_E_XXX 3572 */ 3573 3574 STATIC int 3575 _bcm_flow_encap_profile_delete( 3576 int unit, 3577 bcm_flow_encap_config_t *info, 3578 soc_mem_t mem, 3579 soc_mem_t mem_view, 3580 void *key_data) 3581 { 3582 soc_format_t tag_profile_fmt = TAG_ACTION_PROFILE_ACTION_SETfmt; 3583 soc_field_t tag_profile_fmt_f = TAG_ACTION_PROFILE_ACTION_SETf; 3584 soc_field_t tag_act_f = TAG_ACTION_PROFILE_PTRf; 3585 uint32 tag_profile_set = 0; 3586 uint32 profile_index = 0; 3587 uint32 return_entry[SOC_MAX_MEM_WORDS]; 3588 int index = 0; 3589 int rv = BCM_E_NONE; 3590 3591 rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &index, 3592 key_data, return_entry, 0); 3593 if (rv != BCM_E_NONE) { 3594 return BCM_E_NONE; 3595 } 3596 if (soc_flow_db_mem_view_is_valid(unit, mem_view)){ 3597 if (soc_mem_field_valid(unit, mem_view, tag_profile_fmt_f)){ 3598 tag_profile_set = soc_mem_field32_get(unit, mem_view, return_entry, 3599 tag_profile_fmt_f); 3600 profile_index = soc_format_field32_get(unit, tag_profile_fmt, 3601 &tag_profile_set, tag_act_f); 3602 } 3603 } else if ((info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) && 3604 (soc_mem_field_valid(unit, mem, tag_act_f))) { 3605 profile_index = soc_mem_field32_get(unit, mem, return_entry, 3606 tag_act_f); 3607 } 3608 3609 if (profile_index != 0) { 3610 rv = _bcm_trx_egr_vlan_action_profile_entry_delete(unit, 3611 profile_index); 3612 } 3613 return rv; 3614 } 3615 3616 3617 /* 3618 * Function: 3619 * _bcm_flow_encap_entry_set 3620 * Purpose: 3621 * Set flow Match Entry 3622 * Parameters: 3623 * unit - (IN) Device Number 3624 * info - (IN) flow_match configuration info 3625 * field - (IN) array of logical fields 3626 * num_of_fields -(IN) the size of the above array 3627 * mem - (IN) memory id 3628 * entry - (IN) point to the match entry 3629 * Returns: 3630 * BCM_E_XXX 3631 */ 3632 3633 STATIC int 3634 _bcm_flow_encap_entry_set(int unit, 3635 bcm_flow_encap_config_t *info, 3636 bcm_flow_logical_field_t *field, 3637 int num_of_fields, 3638 soc_mem_t mem, 3639 uint32 *entry, 3640 int network_port) 3641 { 3642 int rv = BCM_E_NONE; 3643 int index = -1; 3644 uint32 return_entry[SOC_MAX_MEM_WORDS]; 3645 int i; 3646 int j; 3647 soc_field_t vnid_f; 3648 uint32 sd_tag; 3649 int tpid_index; 3650 uint32 tunnel_data[3]; 3651 uint32 otag; 3652 uint32 xlate_data[3]; 3653 int tunnel_format; 3654 int type = 0; 3655 int new_entry_add = FALSE; 3656 tunnel_format = EGR_VLAN_XLATE_TUNNEL_DATA_DOUBLEfmt; 3657 3658 /* data fields: flex view uses PDD */ 3659 sal_memset(tunnel_data, 0, sizeof(tunnel_data)); 3660 3661 rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &index, entry, 3662 return_entry, 0); 3663 if (BCM_E_NONE == rv) { 3664 /* found memory entry */ 3665 if (info->options & BCM_FLOW_ENCAP_OPTION_REPLACE) { 3666 sal_memcpy(entry,return_entry,SOC_MAX_MEM_WORDS * 4); 3667 } else { 3668 return BCM_E_EXISTS; 3669 } 3670 } else if (BCM_E_NOT_FOUND == rv) { 3671 if (info->options & BCM_FLOW_ENCAP_OPTION_REPLACE) { 3672 return BCM_E_NOT_FOUND; 3673 } else { 3674 new_entry_add = TRUE; 3675 } 3676 } else { 3677 return rv; 3678 } 3679 3680 if (network_port) { 3681 sd_tag = 0; 3682 if (info->options & BCM_FLOW_ENCAP_OPTION_REPLACE) { 3683 if (_BCM_FLOW_SD_TAG_FORMAT(info)) { 3684 if (!_BCM_FLOW_IS_FLEX_VIEW(info)) { 3685 if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VRF_MAPPING) { 3686 soc_mem_field_get(unit, mem, entry, 3687 VRF_MAPPING__TUNNEL_DATAf, tunnel_data); 3688 sd_tag = soc_format_field32_get(unit,tunnel_format, 3689 tunnel_data, SD_TAG_DATAf); 3690 } else { 3691 if (soc_mem_field_valid(unit, mem, VFI_DVP_GROUP__TUNNEL_DATAf)) { 3692 soc_mem_field_get(unit, mem, entry, 3693 VFI_DVP_GROUP__TUNNEL_DATAf, tunnel_data); 3694 sd_tag = soc_format_field32_get(unit,tunnel_format, 3695 tunnel_data, SD_TAG_DATAf); 3696 } 3697 } 3698 } else { 3699 if (SOC_MEM_FIELD_VALID(unit,mem,SD_TAG_ACTION_SETf)) { 3700 sd_tag = soc_mem_field32_get(unit, mem, entry, 3701 SD_TAG_ACTION_SETf); 3702 } 3703 } 3704 } else { 3705 if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI) { 3706 if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) { 3707 if (soc_mem_field_valid(unit, mem, VXLAN_VFI__SD_TAG_DATAf)) { 3708 sd_tag = soc_mem_field32_get(unit, mem, entry, 3709 VXLAN_VFI__SD_TAG_DATAf); 3710 } 3711 } else if (info->flow_handle == 3712 SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) { 3713 sd_tag = soc_mem_field32_get(unit, mem, entry, 3714 L2GRE_VFI__SD_TAG_DATAf); 3715 } 3716 } 3717 } 3718 } 3719 if ((info->valid_elements & BCM_FLOW_ENCAP_FLAGS_VALID) && 3720 (info->flags & BCM_FLOW_ENCAP_FLAG_SERVICE_TAGGED)) { 3721 if ((info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) && 3722 soc_feature(unit, soc_feature_vxlan_decoupled_mode)) { 3723 rv = _bcm_flow_sd_tag_set_to_entry(unit, info, mem, entry, 3724 &tpid_index); 3725 } else if (soc_mem_field_valid(unit, mem, OTAG_ACTION_SETf) && 3726 soc_mem_field_valid(unit, mem, TAG_ACTION_PROFILE_ACTION_SETf)) { 3727 rv = _bcm_flow_sd_tag_set_to_format(unit, info, mem, entry, 3728 &tpid_index); 3729 } else { 3730 rv = _bcm_flow_sd_tag_set(unit, info, &sd_tag, 3731 &tpid_index); 3732 } 3733 BCM_IF_ERROR_RETURN(rv); 3734 } 3735 3736 if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI_DVP_GROUP && 3737 (!(_BCM_FLOW_IS_FLEX_VIEW(info)))) { 3738 soc_mem_field32_set(unit, mem, entry, 3739 VFI_DVP_GROUP__DATA_OVERLAY_TYPEf, 0); /* tunnel data */ 3740 } 3741 if (info->valid_elements & BCM_FLOW_ENCAP_VNID_VALID) { 3742 if (_BCM_FLOW_IS_FLEX_VIEW(info)) { 3743 vnid_f = DIRECT_ASSIGNMENT_22_ACTION_SETf; /* VNID */ 3744 } else { 3745 if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) { 3746 if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) { 3747 vnid_f = VXLAN_VFI_FLEX__VNIDf; 3748 } else { 3749 vnid_f = VXLAN_VFI__VN_IDf; 3750 } 3751 type = 2; 3752 } else if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) { 3753 vnid_f = L2GRE_VFI__VPNIDf; 3754 type = 1; 3755 } else { 3756 return BCM_E_PARAM; 3757 } 3758 } 3759 if (_BCM_FLOW_TUNNEL_DATA_FORMAT(info) && 3760 (!_BCM_FLOW_IS_FLEX_VIEW(info))) { 3761 soc_format_field32_set(unit,tunnel_format,tunnel_data, 3762 TUNNEL_HEADER_DATA_TYPEf,type); 3763 if (type == 1) { 3764 soc_format_field32_set(unit,tunnel_format,tunnel_data, 3765 VPNIDf,info->vnid); 3766 } else if (type == 2) { 3767 if ((info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) 3768 && soc_feature(unit, soc_feature_vxlan_decoupled_mode)) { 3769 if (soc_mem_field_valid(unit, mem, vnid_f)) { 3770 soc_mem_field32_set(unit, mem, entry, vnid_f, info->vnid); 3771 } 3772 } else { 3773 soc_format_field32_set(unit,tunnel_format,tunnel_data, 3774 VN_IDf,info->vnid); 3775 } 3776 } 3777 soc_mem_field_set(unit, mem, entry, 3778 VFI_DVP_GROUP__TUNNEL_DATAf, tunnel_data); 3779 } else { 3780 if (!SOC_MEM_FIELD_VALID(unit, mem, vnid_f)) { 3781 return BCM_E_PARAM; 3782 } 3783 soc_mem_field32_set(unit, mem, entry, vnid_f, info->vnid); 3784 } 3785 } 3786 if ((info->valid_elements & BCM_FLOW_ENCAP_FLAGS_VALID) && 3787 (info->flags & BCM_FLOW_ENCAP_FLAG_SERVICE_TAGGED)) { 3788 if (_BCM_FLOW_SD_TAG_FORMAT(info)) { 3789 if (!_BCM_FLOW_IS_FLEX_VIEW(info)) { 3790 soc_format_field32_set(unit,tunnel_format,tunnel_data, 3791 SD_TAG_DATAf,sd_tag); 3792 if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VRF_MAPPING) { 3793 soc_mem_field_set(unit, mem, entry, 3794 VRF_MAPPING__TUNNEL_DATAf, tunnel_data); 3795 } else { 3796 if (soc_mem_field_valid(unit, mem, VFI_DVP_GROUP__TUNNEL_DATAf)) { 3797 soc_mem_field_set(unit, mem, entry, 3798 VFI_DVP_GROUP__TUNNEL_DATAf, tunnel_data); 3799 } 3800 } 3801 } else { 3802 if (!(soc_mem_field_valid(unit, mem, OTAG_ACTION_SETf) && 3803 soc_mem_field_valid(unit, mem, TAG_ACTION_PROFILE_ACTION_SETf))) { 3804 if (!SOC_MEM_FIELD_VALID(unit, mem, SD_TAG_ACTION_SETf)) { 3805 return BCM_E_PARAM; 3806 } 3807 soc_mem_field32_set(unit, mem, entry, 3808 SD_TAG_ACTION_SETf, sd_tag); 3809 } 3810 } 3811 } else { 3812 if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI) { 3813 if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) { 3814 /* VXLAN_VFI__SD_TAG_DATAf defined in regsfile */ 3815 } else if (info->flow_handle == 3816 SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) { 3817 soc_mem_field32_set(unit, mem, entry, 3818 L2GRE_VFI__SD_TAG_DATAf,sd_tag); 3819 } 3820 } 3821 } 3822 } 3823 } else { /* if (network_port) */ 3824 if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI_DVP_GROUP || 3825 info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI_DVP) { 3826 3827 sal_memset(xlate_data, 0, sizeof(xlate_data)); 3828 rv = _bcm_flow_encap_vlan_set(unit, info, mem, entry, 3829 &otag,xlate_data); 3830 BCM_IF_ERROR_RETURN(rv); 3831 if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI_DVP_GROUP && 3832 (!(_BCM_FLOW_IS_FLEX_VIEW(info)))) { 3833 if (soc_mem_field_valid(unit, mem, VFI_DVP_GROUP__DATA_OVERLAY_TYPEf)) { 3834 soc_mem_field32_set(unit, mem, entry, 3835 VFI_DVP_GROUP__DATA_OVERLAY_TYPEf, 1); /* vlan xlate data */ 3836 } 3837 } 3838 if (!_BCM_FLOW_IS_FLEX_VIEW(info)) { 3839 if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI_DVP_GROUP) { 3840 if (soc_mem_field_valid(unit, mem, VFI_DVP_GROUP__XLATE_DATAf)) { 3841 soc_mem_field_set(unit, mem, entry, 3842 VFI_DVP_GROUP__XLATE_DATAf, xlate_data); 3843 } 3844 } else { /* VLAN_XLATE_VFI */ 3845 soc_mem_field_set(unit, mem, entry, 3846 VLAN_XLATE_VFI__XLATE_DATAf, xlate_data); 3847 } 3848 } else { 3849 if (!SOC_MEM_FIELD_VALID(unit, mem, OTAG_ACTION_SETf)) { 3850 return BCM_E_PARAM; 3851 } 3852 soc_mem_field32_set(unit, mem, entry, OTAG_ACTION_SETf, otag); 3853 } 3854 } 3855 } 3856 3857 if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_SVP_DVP) { 3858 if (soc_feature(unit, soc_feature_vxlan_evpn)) { 3859 if (info->valid_elements & BCM_FLOW_ENCAP_CLASS_ID_VALID) { 3860 if (!SOC_MEM_FIELD_VALID(unit, mem, CLASS_ID_ACTION_SETf)) { 3861 return BCM_E_PARAM; 3862 } 3863 soc_mem_field32_set(unit,mem, entry, CLASS_ID_ACTION_SETf, info->class_id); 3864 } 3865 } 3866 } 3867 3868 if (info->valid_elements & BCM_FLOW_ENCAP_FLEX_DATA_VALID) { 3869 uint32 data_ids[_BCM_FLOW_LOGICAL_FIELD_MAX]; 3870 uint32 cnt; 3871 rv = soc_flow_db_mem_view_field_list_get(unit, 3872 mem, 3873 SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA, 3874 _BCM_FLOW_LOGICAL_FIELD_MAX, data_ids, &cnt); 3875 BCM_IF_ERROR_RETURN(rv); 3876 for (i = 0; i < num_of_fields; i++) { 3877 for (j = 0; j < cnt; j++) { 3878 if (field[i].id == data_ids[j]) { 3879 soc_mem_field32_set(unit,mem, entry, 3880 field[i].id, field[i].value); 3881 break; 3882 } 3883 } 3884 } 3885 } 3886 3887 if (new_entry_add) { 3888 rv = soc_mem_insert(unit, mem, MEM_BLOCK_ALL, entry); 3889 } else { /* replace action */ 3890 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, entry); 3891 } 3892 3893 BCM_IF_ERROR_RETURN(rv); 3894 return rv; 3895 } 3896 3897 /* 3898 * Function: 3899 * _bcm_flow_encap_entry_data_get 3900 * Purpose: 3901 * Convert the hardware entry data to the flow encap user data 3902 * Parameters: 3903 * unit - (IN) Device Number 3904 * info - (IN) flow_encap configuration info 3905 * field - (IN) array of logical fields 3906 * num_of_fields -(IN) the size of the above array 3907 * mem - (IN) memory id 3908 * entry - (IN) point to the encap entry 3909 * Returns: 3910 * BCM_E_XXX 3911 */ 3912 3913 STATIC int 3914 _bcm_flow_encap_entry_data_get(int unit, 3915 bcm_flow_encap_config_t *info, 3916 bcm_flow_logical_field_t *field, 3917 int num_of_fields, 3918 soc_mem_t mem, 3919 uint32 *entry, 3920 int network_port) 3921 { 3922 int rv = BCM_E_NONE; 3923 int i; 3924 int j; 3925 soc_field_t vnid_f; 3926 uint32 tunnel_data[3]; 3927 uint32 otag; 3928 uint32 xlate_data[3]; 3929 int tunnel_format; 3930 int type; 3931 uint32 sd_tag = 0; 3932 3933 tunnel_format = EGR_VLAN_XLATE_TUNNEL_DATA_DOUBLEfmt; 3934 3935 /* data fields: flex view uses PDD */ 3936 sal_memset(tunnel_data, 0, sizeof(tunnel_data)); 3937 3938 if (network_port) { 3939 if (_BCM_FLOW_SD_TAG_FORMAT(info)) { 3940 if (!_BCM_FLOW_IS_FLEX_VIEW(info)) { 3941 if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VRF_MAPPING) { 3942 soc_mem_field_get(unit, mem, entry, 3943 VRF_MAPPING__TUNNEL_DATAf, tunnel_data); 3944 } else { 3945 soc_mem_field_get(unit, mem, entry, 3946 VFI_DVP_GROUP__TUNNEL_DATAf, tunnel_data); 3947 } 3948 sd_tag = soc_format_field32_get(unit,tunnel_format, 3949 tunnel_data, SD_TAG_DATAf); 3950 } else { 3951 if (SOC_MEM_FIELD_VALID(unit,mem,SD_TAG_ACTION_SETf)) { 3952 sd_tag = soc_mem_field32_get(unit, mem, entry, 3953 SD_TAG_ACTION_SETf); 3954 } 3955 } 3956 } else { 3957 if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI) { 3958 if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) { 3959 if (!soc_feature(unit, soc_feature_vxlan_decoupled_mode)) { 3960 sd_tag = soc_mem_field32_get(unit, mem, entry, 3961 VXLAN_VFI__SD_TAG_DATAf); 3962 } 3963 } else if (info->flow_handle == 3964 SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) { 3965 sd_tag = soc_mem_field32_get(unit, mem, entry, 3966 L2GRE_VFI__SD_TAG_DATAf); 3967 } 3968 } 3969 } 3970 if (soc_feature(unit, soc_feature_vxlan_decoupled_mode) && 3971 (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) && 3972 (mem == EGR_VLAN_XLATE_1_SINGLEm)) { 3973 rv = _bcm_flow_sd_tag_get_from_entry(unit, info, mem, entry, NULL); 3974 } else if (soc_mem_field_valid(unit, mem, OTAG_ACTION_SETf) && 3975 soc_mem_field_valid(unit, mem, TAG_ACTION_PROFILE_ACTION_SETf)) { 3976 rv = _bcm_flow_sd_tag_get_from_format(unit, info, mem, entry, NULL); 3977 } else { 3978 rv = _bcm_flow_sd_tag_get(unit, info, sd_tag, NULL); 3979 } 3980 BCM_IF_ERROR_RETURN(rv); 3981 3982 if (_BCM_FLOW_IS_FLEX_VIEW(info)) { 3983 vnid_f = DIRECT_ASSIGNMENT_22_ACTION_SETf; /* VNID */ 3984 } else { 3985 if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) { 3986 if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) { 3987 vnid_f = VXLAN_VFI_FLEX__VNIDf; 3988 } else { 3989 vnid_f = VXLAN_VFI__VN_IDf; 3990 } 3991 } else if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) { 3992 vnid_f = L2GRE_VFI__VPNIDf; 3993 } else { 3994 return BCM_E_PARAM; 3995 } 3996 } 3997 if (_BCM_FLOW_TUNNEL_DATA_FORMAT(info) && 3998 (!_BCM_FLOW_IS_FLEX_VIEW(info))) { 3999 type = soc_format_field32_get(unit,tunnel_format,tunnel_data, 4000 TUNNEL_HEADER_DATA_TYPEf); 4001 if (type == 1) { 4002 info->vnid = soc_format_field32_get(unit,tunnel_format, 4003 tunnel_data, VPNIDf); 4004 } else if (type == 2) { 4005 info->vnid = soc_format_field32_get(unit,tunnel_format, 4006 tunnel_data, VN_IDf); 4007 } 4008 4009 } else { 4010 if (SOC_MEM_FIELD_VALID(unit,mem,vnid_f)) { 4011 info->vnid = soc_mem_field32_get(unit, mem, entry, vnid_f); 4012 } 4013 } 4014 4015 } else { /* if (network_port) */ 4016 if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI_DVP_GROUP || 4017 info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI_DVP) { 4018 4019 if (!_BCM_FLOW_IS_FLEX_VIEW(info)) { 4020 if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI_DVP_GROUP) { 4021 if (soc_mem_field_valid(unit, mem, VFI_DVP_GROUP__XLATE_DATAf)) { 4022 soc_mem_field_get(unit, mem, entry, 4023 VFI_DVP_GROUP__XLATE_DATAf, xlate_data); 4024 } 4025 } else { /* VLAN_XLATE_VFI */ 4026 soc_mem_field_get(unit, mem, entry, 4027 VLAN_XLATE_VFI__XLATE_DATAf, xlate_data); 4028 } 4029 } else { 4030 otag = soc_mem_field32_get(unit, mem, entry, OTAG_ACTION_SETf); 4031 } 4032 rv = _bcm_flow_encap_vlan_get(unit, info, mem, entry, 4033 &otag,xlate_data); 4034 BCM_IF_ERROR_RETURN(rv); 4035 } 4036 } 4037 4038 if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_SVP_DVP) { 4039 if (soc_feature(unit, soc_feature_vxlan_evpn)) { 4040 if (info->valid_elements & BCM_FLOW_ENCAP_SRC_FLOW_PORT_VALID) { 4041 if (!SOC_MEM_FIELD_VALID(unit, mem, CLASS_ID_ACTION_SETf)) { 4042 return BCM_E_PARAM; 4043 } 4044 info->class_id = soc_mem_field32_get(unit,mem, entry, CLASS_ID_ACTION_SETf); 4045 } 4046 } 4047 } 4048 4049 if (_BCM_FLOW_IS_FLEX_VIEW(info) && (field != NULL)) { 4050 uint32 data_ids[_BCM_FLOW_LOGICAL_FIELD_MAX]; 4051 uint32 cnt; 4052 rv = soc_flow_db_mem_view_field_list_get(unit, 4053 mem, 4054 SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA, 4055 _BCM_FLOW_LOGICAL_FIELD_MAX, data_ids, &cnt); 4056 BCM_IF_ERROR_RETURN(rv); 4057 for (i = 0; i < num_of_fields; i++) { 4058 for (j = 0; j < cnt; j++) { 4059 if (field[i].id == data_ids[j]) { 4060 field[i].value = soc_mem_field32_get(unit,mem, entry, 4061 field[i].id); 4062 break; 4063 } 4064 } 4065 } 4066 } 4067 4068 return rv; 4069 } 4070 4071 /* 4072 * Function: 4073 * bcmi_esw_flow_encap_add 4074 * Purpose: 4075 * Add a flow encap entry 4076 * Parameters: 4077 * unit - (IN) Device Number 4078 * info - (IN) Flow encap config descriptor 4079 * num_of_fields - (IN) number of logical fields 4080 * field - (IN) logical field array 4081 * Returns: 4082 * BCM_E_XXX 4083 */ 4084 4085 int bcmi_esw_flow_encap_add( 4086 int unit, 4087 bcm_flow_encap_config_t *info, 4088 uint32 num_of_fields, 4089 bcm_flow_logical_field_t *field) 4090 { 4091 soc_mem_t mem; 4092 soc_mem_t mem_view; 4093 uint32 entry[SOC_MAX_MEM_WORDS]; 4094 int rv; 4095 int network_port; 4096 _bcm_vp_info_t vp_info; 4097 int dvp; 4098 _bcm_flow_bookkeeping_t *flow_info; 4099 4100 if (info == NULL) { 4101 return BCM_E_PARAM; 4102 } 4103 4104 if (info->valid_elements & BCM_FLOW_ENCAP_CLASS_ID_VALID) { 4105 if ((info->class_id == 0) || (info->class_id > 0xfff)) { 4106 return BCM_E_PARAM; 4107 } 4108 } 4109 4110 flow_info = FLOW_INFO(unit); 4111 4112 sal_memset(entry, 0, sizeof(entry)); 4113 BCM_IF_ERROR_RETURN(_bcm_flow_encap_key_set(unit,info,field, 4114 num_of_fields,entry,&mem,&mem_view,&network_port)); 4115 4116 /* validate the dvp */ 4117 if ((info->valid_elements & BCM_FLOW_ENCAP_FLOW_PORT_VALID) && 4118 (!BCM_GPORT_IS_MODPORT(info->flow_port))) { 4119 dvp = _SHR_GPORT_FLOW_PORT_ID_GET(info->flow_port); 4120 if (!_bcm_vp_used_get(unit, dvp, _bcmVpTypeFlow)) { 4121 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 4122 "DVP %d is not the flow port\n"), dvp)); 4123 return BCM_E_NOT_FOUND; 4124 } 4125 BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, dvp, &vp_info)); 4126 if (vp_info.flags & _BCM_VP_INFO_NETWORK_PORT) { 4127 if (!network_port) { 4128 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 4129 "DVP %d is a network port, incorrect encap criteria\n"), 4130 dvp)); 4131 return BCM_E_PARAM; 4132 } 4133 } 4134 } 4135 4136 soc_mem_lock(unit,mem); 4137 /* set the match object and attributes and write to memory */ 4138 rv = _bcm_flow_encap_entry_set(unit,info,field, 4139 num_of_fields, 4140 _BCM_FLOW_IS_FLEX_VIEW(info)? mem_view: mem, 4141 entry,network_port); 4142 soc_mem_unlock(unit,mem); 4143 4144 if (BCM_SUCCESS(rv)) { 4145 if (!(info->options & BCM_FLOW_ENCAP_OPTION_REPLACE)) { 4146 bcmi_esw_flow_lock(unit); 4147 if ((mem == EGR_VLAN_XLATE_1_DOUBLEm) || (mem == EGR_VLAN_XLATE_1_SINGLEm)) { 4148 flow_info->mem_use_cnt[_BCM_FLOW_EVXLT1_INX]++; 4149 } else if ((mem == EGR_VLAN_XLATE_2_DOUBLEm) || (mem == EGR_VLAN_XLATE_2_SINGLEm)) { 4150 flow_info->mem_use_cnt[_BCM_FLOW_EVXLT2_INX]++; 4151 } 4152 bcmi_esw_flow_unlock(unit); 4153 } 4154 } 4155 4156 return rv; 4157 } 4158 4159 /* 4160 * Function: 4161 * _bcm_flow_encap_entry_get 4162 * Purpose: 4163 * Get the flow Encap Entry based on the given key 4164 * Parameters: 4165 * unit - (IN) Device Number 4166 * info - (IN/OUT) flow_encap configuration info 4167 * field - (IN/OUT) array of logical fields 4168 * num_of_fields -(IN) the size of the above array 4169 * mem - (IN) memory id 4170 * entry - (IN) point to the encap entry 4171 * Returns: 4172 * BCM_E_XXX 4173 */ 4174 4175 STATIC int 4176 _bcm_flow_encap_entry_get(int unit, 4177 bcm_flow_encap_config_t *info, 4178 bcm_flow_logical_field_t *field, 4179 int num_of_fields, 4180 soc_mem_t mem, 4181 uint32 *entry, 4182 int network_port) 4183 { 4184 int index = -1; 4185 uint32 return_entry[SOC_MAX_MEM_WORDS]; 4186 int rv = BCM_E_NONE; 4187 4188 SOC_IF_ERROR_RETURN(soc_mem_search(unit, mem, MEM_BLOCK_ANY, &index, 4189 entry, return_entry, 0)); 4190 rv = _bcm_flow_encap_entry_data_get(unit,info,field,num_of_fields, 4191 mem,return_entry,network_port); 4192 BCM_IF_ERROR_RETURN(rv); 4193 return rv; 4194 } 4195 4196 STATIC int 4197 _bcm_flow_encap_entry_valid(int unit, soc_mem_t mem, uint32 *entry, int *valid) 4198 { 4199 uint32 base_valid_0 = 0; 4200 uint32 base_valid_1 = 0; 4201 uint32 base_valid = 0; 4202 4203 if (INVALIDm == mem) { 4204 return BCM_E_MEMORY; 4205 } 4206 4207 if ((NULL == entry) || (NULL == valid)) { 4208 return BCM_E_PARAM; 4209 } 4210 if (soc_mem_field_valid(unit, mem, BASE_VALID_0f)) { 4211 base_valid_0 = soc_mem_field32_get(unit, mem, entry, BASE_VALID_0f); 4212 } 4213 if (soc_mem_field_valid(unit, mem, BASE_VALID_1f)) { 4214 base_valid_1 = soc_mem_field32_get(unit, mem, entry, BASE_VALID_1f); 4215 } 4216 if (soc_mem_field_valid(unit, mem, BASE_VALIDf)) { 4217 base_valid = soc_mem_field32_get(unit, mem, entry, BASE_VALIDf); 4218 } 4219 4220 if ((base_valid != 0x1) && ((base_valid_0 == 0) || (base_valid_1 == 0)) ) { 4221 *valid = FALSE; 4222 } else { 4223 *valid = TRUE; 4224 } 4225 return BCM_E_NONE; 4226 } 4227 4228 int 4229 _bcm_flow_key_is_valid(int unit, soc_mem_t mem_view_id, 4230 uint32 *key, int num_keys) 4231 { 4232 int rv; 4233 uint32 key_ids[_BCM_FLOW_LOGICAL_FIELD_MAX]; 4234 uint32 cnt = 0; 4235 int i,j; 4236 int key_match; 4237 int num_key_fields; 4238 4239 rv = soc_flow_db_mem_view_field_list_get(unit, 4240 mem_view_id, 4241 SOC_FLOW_DB_FIELD_TYPE_KEY, 4242 _BCM_FLOW_LOGICAL_FIELD_MAX, key_ids, &cnt); 4243 if (BCM_FAILURE(rv)) { 4244 return FALSE; 4245 } 4246 4247 /* don't count the overlapped hash key fields */ 4248 num_key_fields = cnt; 4249 for (i = 0; i < cnt; i++) { 4250 if ((key_ids[i] == KEY_0f) || (key_ids[i] == KEY_1f)) { 4251 num_key_fields--; 4252 } 4253 } 4254 4255 if (num_keys != num_key_fields) { 4256 return FALSE; 4257 } 4258 4259 key_match = 0; 4260 for (i = 0; i < num_keys; i++) { 4261 for (j = 0; j < cnt; j++) { 4262 if (key[i] == key_ids[j]) { 4263 key_match++; 4264 break; 4265 } 4266 } 4267 } 4268 if (key_match != num_key_fields) { 4269 return FALSE; 4270 } 4271 return TRUE; 4272 } 4273 4274 /* 4275 * Function : 4276 * _bcm_flow_encap_entry_parse 4277 * Description : 4278 * Convert the memory entry field data to the flow match configuration 4279 * parameters. 4280 * Parameters : 4281 * unit - (IN) Device Number 4282 * mem - (IN) memory id. 4283 * entry - (IN) HW entry. 4284 * info - (OUT) Flow match config descriptor 4285 * num_of_fields - (OUT) number of logical fields 4286 * field - (OUT) logical field array 4287 */ 4288 int 4289 _bcm_flow_encap_entry_parse(int unit, soc_mem_t mem, uint32 *entry, 4290 bcm_flow_encap_config_t *info, 4291 uint32 *num_of_fields, 4292 bcm_flow_logical_field_t *field) 4293 { 4294 int data_type; 4295 int key_type; 4296 soc_field_t vfi_f = 0; 4297 soc_field_t vrf_f = 0; 4298 soc_field_t dvp_f = 0; 4299 soc_field_t dvp_grp_f = 0; 4300 soc_field_t oif_grp_f = 0; 4301 uint32 dgpp; 4302 4303 uint32 field_id[_BCM_FLOW_LOGICAL_FIELD_MAX]; 4304 uint32 cnt; 4305 uint32 data_cnt; 4306 int i; 4307 int rv; 4308 soc_mem_t mem_view_id; 4309 uint32 tunnel_data[3]; 4310 int tunnel_format; 4311 int type; 4312 uint32 dvp = 0; 4313 uint32 vfi = 0; 4314 uint32 vrf = 0; 4315 int network_port; 4316 uint32 svp = 0; 4317 4318 tunnel_format = EGR_VLAN_XLATE_TUNNEL_DATA_DOUBLEfmt; 4319 key_type = 0; 4320 data_type = 0; 4321 network_port = FALSE; 4322 4323 if (SOC_MEM_FIELD_VALID(unit,mem,KEY_TYPEf)) { 4324 key_type = soc_mem_field32_get(unit, mem, entry, KEY_TYPEf); 4325 } 4326 if (SOC_MEM_FIELD_VALID(unit,mem,DATA_TYPEf)) { 4327 data_type = soc_mem_field32_get(unit, mem, entry, DATA_TYPEf); 4328 } 4329 4330 /* find the memory view based on the memory and key type */ 4331 rv = soc_flow_db_mem_to_view_id_get (unit, mem, key_type, data_type, 4332 0, NULL, (uint32 *)&mem_view_id); 4333 4334 if (rv != SOC_E_NONE && rv != SOC_E_NOT_FOUND) { 4335 return rv; 4336 } 4337 4338 if (rv == SOC_E_NOT_FOUND) { /* fixed view */ 4339 rv = SOC_E_NONE; 4340 switch (key_type) { 4341 case _BCM_FLOW_ENCAP_L2GRE_KEY_TYPE_VFI: 4342 info->criteria = BCM_FLOW_ENCAP_CRITERIA_VFI; 4343 info->valid_elements |= BCM_FLOW_ENCAP_VPN_VALID; 4344 info->flow_handle = SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE; 4345 network_port = TRUE; 4346 break; 4347 4348 case _BCM_FLOW_ENCAP_L2GRE_KEY_TYPE_VFI_DVP: 4349 info->criteria = BCM_FLOW_ENCAP_CRITERIA_VFI_DVP; 4350 info->valid_elements |= BCM_FLOW_ENCAP_VPN_VALID | 4351 BCM_FLOW_ENCAP_FLOW_PORT_VALID; 4352 info->flow_handle = SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE; 4353 network_port = TRUE; 4354 break; 4355 4356 case _BCM_FLOW_ENCAP_VXLAN_KEY_TYPE_VFI: 4357 info->criteria = BCM_FLOW_ENCAP_CRITERIA_VFI; 4358 info->valid_elements |= BCM_FLOW_ENCAP_VPN_VALID; 4359 info->flow_handle = SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN; 4360 network_port = TRUE; 4361 break; 4362 4363 case _BCM_FLOW_ENCAP_VXLAN_KEY_TYPE_VFI_DVP: 4364 info->criteria = BCM_FLOW_ENCAP_CRITERIA_VFI_DVP; 4365 info->valid_elements |= BCM_FLOW_ENCAP_VPN_VALID | 4366 BCM_FLOW_ENCAP_FLOW_PORT_VALID; 4367 info->flow_handle = SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN; 4368 network_port = TRUE; 4369 break; 4370 case _BCM_FLOW_ENCAP_KEY_TYPE_VFI_DVP_GROUP: 4371 info->criteria = BCM_FLOW_ENCAP_CRITERIA_VFI_DVP_GROUP; 4372 info->valid_elements |= BCM_FLOW_ENCAP_VPN_VALID | 4373 BCM_FLOW_ENCAP_DVP_GROUP_VALID; 4374 if (soc_mem_field32_get(unit, mem, entry, 4375 VFI_DVP_GROUP__DATA_OVERLAY_TYPEf)) { 4376 /* xlate data */ 4377 4378 } else { /* tunnal data */ 4379 soc_mem_field_get(unit, mem, entry, 4380 VFI_DVP_GROUP__TUNNEL_DATAf, tunnel_data); 4381 type = soc_format_field32_get(unit,tunnel_format, 4382 tunnel_data, TUNNEL_HEADER_DATA_TYPEf); 4383 if (type == 1) { 4384 info->flow_handle = SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE; 4385 network_port = TRUE; 4386 info->vnid = soc_format_field32_get(unit,tunnel_format, 4387 tunnel_data, VPNIDf); 4388 } else if (type == 2) { 4389 info->flow_handle = SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN; 4390 network_port = TRUE; 4391 info->vnid = soc_format_field32_get(unit,tunnel_format, 4392 tunnel_data, VN_IDf); 4393 } 4394 } 4395 break; 4396 4397 case _BCM_FLOW_ENCAP_KEY_TYPE_VRF_MAPPING: 4398 info->criteria = BCM_FLOW_ENCAP_CRITERIA_VRF_MAPPING; 4399 info->valid_elements |= BCM_FLOW_ENCAP_VPN_VALID; 4400 network_port = TRUE; 4401 soc_mem_field_get(unit, mem, entry, 4402 VRF_MAPPING__TUNNEL_DATAf, tunnel_data); 4403 type = soc_format_field32_get(unit,tunnel_format,tunnel_data, 4404 TUNNEL_HEADER_DATA_TYPEf); 4405 if (type == 1) { 4406 info->flow_handle = SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE; 4407 info->vnid = soc_format_field32_get(unit,tunnel_format, 4408 tunnel_data, VPNIDf); 4409 } else if (type == 2) { 4410 info->flow_handle = SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN; 4411 info->vnid = soc_format_field32_get(unit,tunnel_format, 4412 tunnel_data, VN_IDf); 4413 } 4414 break; 4415 4416 case _BCM_FLOW_ENCAP_KEY_TYPE_VLAN_XLATE_VFI: 4417 info->criteria = BCM_FLOW_ENCAP_CRITERIA_VFI_DVP; 4418 info->valid_elements |= BCM_FLOW_ENCAP_VPN_VALID | 4419 BCM_FLOW_ENCAP_FLOW_PORT_VALID; 4420 break; 4421 4422 default: 4423 /* not used by the flow_match functions */ 4424 return BCM_E_NOT_FOUND; 4425 break; 4426 } 4427 } else { /* flex view found */ 4428 soc_flow_db_mem_view_info_t vinfo; 4429 uint32 vfi_dvp_ids[2]; 4430 uint32 vfi_grp_ids[2]; 4431 uint32 vfi_id[1]; 4432 uint32 dvp_id[1]; 4433 uint32 oif_id[1]; 4434 uint32 vrf_id[1]; 4435 uint32 svp_dvp_ids[2]; 4436 4437 /* find the memory view info */ 4438 rv = soc_flow_db_mem_view_info_get(unit, mem_view_id, &vinfo); 4439 SOC_IF_ERROR_RETURN(rv); 4440 4441 mem = mem_view_id; 4442 vfi_dvp_ids[0] = VFIf; 4443 vfi_dvp_ids[1] = DVPf; 4444 4445 vfi_grp_ids[0] = VFIf; 4446 vfi_grp_ids[1] = VT_DVP_GROUP_IDf; 4447 4448 svp_dvp_ids[0] = SVPf; 4449 svp_dvp_ids[1] = DVPf; 4450 4451 vfi_id[0] = VFIf; 4452 dvp_id[0] = DVPf; 4453 oif_id[0] = L3_OIFf; 4454 vrf_id[0] = VRFf; 4455 if (_bcm_flow_key_is_valid(unit, mem_view_id, vfi_dvp_ids, 2)) { 4456 info->criteria = BCM_FLOW_ENCAP_CRITERIA_VFI_DVP; 4457 info->valid_elements |= BCM_FLOW_ENCAP_VPN_VALID | 4458 BCM_FLOW_ENCAP_FLOW_PORT_VALID; 4459 } else if (_bcm_flow_key_is_valid(unit, mem_view_id, vfi_grp_ids, 2)) { 4460 info->criteria = BCM_FLOW_ENCAP_CRITERIA_VFI_DVP_GROUP; 4461 info->valid_elements |= BCM_FLOW_ENCAP_VPN_VALID | 4462 BCM_FLOW_ENCAP_DVP_GROUP_VALID; 4463 } else if (_bcm_flow_key_is_valid(unit, mem_view_id, vfi_id, 1)) { 4464 info->criteria = BCM_FLOW_ENCAP_CRITERIA_VFI; 4465 info->valid_elements |= BCM_FLOW_ENCAP_VPN_VALID; 4466 } else if (_bcm_flow_key_is_valid(unit, mem_view_id, dvp_id, 1)) { 4467 info->criteria = BCM_FLOW_ENCAP_CRITERIA_DVP; 4468 info->valid_elements |= BCM_FLOW_ENCAP_FLOW_PORT_VALID; 4469 } else if (_bcm_flow_key_is_valid(unit, mem_view_id, oif_id, 1)) { 4470 info->criteria = BCM_FLOW_ENCAP_CRITERIA_L3_INTF; 4471 info->valid_elements |= BCM_FLOW_ENCAP_INTF_VALID; 4472 } else if (_bcm_flow_key_is_valid(unit, mem_view_id, vrf_id, 1)) { 4473 info->criteria = BCM_FLOW_ENCAP_CRITERIA_VRF_MAPPING; 4474 info->valid_elements |= BCM_FLOW_ENCAP_VPN_VALID; 4475 } else if (_bcm_flow_key_is_valid(unit, mem_view_id, svp_dvp_ids, 2)) { 4476 info->criteria = BCM_FLOW_ENCAP_CRITERIA_SVP_DVP; 4477 info->valid_elements |= BCM_FLOW_ENCAP_FLOW_PORT_VALID | 4478 BCM_FLOW_ENCAP_SRC_FLOW_PORT_VALID; 4479 } else { 4480 info->criteria = BCM_FLOW_ENCAP_CRITERIA_FLEX; 4481 info->valid_elements |= BCM_FLOW_ENCAP_FLEX_KEY_VALID; 4482 } 4483 rv = _bcm_flow_mem_view_to_flow_info_get(unit, mem_view_id, 4484 SOC_FLOW_DB_FUNC_ENCAP_ID, 4485 &info->flow_handle, &info->flow_option, 1); 4486 SOC_IF_ERROR_RETURN(rv); 4487 4488 network_port = TRUE; 4489 } 4490 4491 if (_BCM_FLOW_IS_FLEX_VIEW(info)) { 4492 vfi_f = VFIf; 4493 dvp_f = DVPf; 4494 dvp_grp_f = VT_DVP_GROUP_IDf; 4495 vrf_f = VRFf; 4496 oif_grp_f = VT_L3OIF_GROUP_IDf; 4497 } else { 4498 dvp_grp_f = VFI_DVP_GROUP__VT_DVP_GROUP_IDf; 4499 oif_grp_f = VRF_MAPPING__VT_L3OIF_GROUP_IDf; 4500 if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) { 4501 if (soc_feature(unit, soc_feature_vxlan_decoupled_mode) && 4502 (mem == EGR_VLAN_XLATE_1_SINGLEm)) { 4503 vfi_f = VXLAN_VFI_FLEX__VFIf; 4504 dvp_f = VXLAN_VFI_FLEX__DVPf; 4505 } else { 4506 vfi_f = VXLAN_VFI__VFIf; 4507 dvp_f = VXLAN_VFI__DVPf; 4508 } 4509 } else if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) { 4510 vfi_f = L2GRE_VFI__VFIf; 4511 dvp_f = L2GRE_VFI__DVPf; 4512 } else { 4513 /* access side: VLAN_XLATE_VFI */ 4514 vfi_f = VLAN_XLATE_VFI__VFIf; 4515 dvp_f = VLAN_XLATE_VFI__DVPf; 4516 } 4517 } 4518 4519 /* retrieve the key fields */ 4520 if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI) { 4521 vfi = soc_mem_field32_get(unit,mem, entry, vfi_f); 4522 _BCM_FLOW_VPN_SET(info->vpn,_BCM_VPN_TYPE_VFI,vfi); 4523 4524 } else if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI_DVP) { 4525 vfi = soc_mem_field32_get(unit, mem, entry, vfi_f); 4526 _BCM_FLOW_VPN_SET(info->vpn,_BCM_VPN_TYPE_VFI,vfi); 4527 dvp = soc_mem_field32_get(unit, mem, entry, dvp_f); 4528 _SHR_GPORT_FLOW_PORT_ID_SET(info->flow_port,dvp); 4529 4530 } else if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VFI_DVP_GROUP) { 4531 if (!_BCM_FLOW_IS_FLEX_VIEW(info)) { 4532 vfi_f = VFI_DVP_GROUP__VFIf; 4533 } 4534 vfi = soc_mem_field32_get(unit,mem, entry, vfi_f); 4535 _BCM_FLOW_VPN_SET(info->vpn,_BCM_VPN_TYPE_VFI,vfi); 4536 info->dvp_group = soc_mem_field32_get(unit,mem, entry, 4537 dvp_grp_f); 4538 } else if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_VRF_MAPPING) { 4539 /* KEY : VRF,VT_DVP_GROUP_ID,VT_L3_OIF_GROUP_ID 4540 * VT_DVP_GROUP_ID : from EGR_DVP_ATTRIBUTEm 4541 * VT_L3_OIF_GROUP_ID : from EGR_L3_INTFm 4542 */ 4543 if (!_BCM_FLOW_IS_FLEX_VIEW(info)) { 4544 vrf_f = VRF_MAPPING__VRFf; 4545 dvp_grp_f = VRF_MAPPING__VT_DVP_GROUP_IDf; 4546 oif_grp_f = VRF_MAPPING__VT_L3OIF_GROUP_IDf; 4547 } 4548 vrf = soc_mem_field32_get(unit,mem, entry, vrf_f); 4549 _BCM_FLOW_VPN_SET(info->vpn,_BCM_VPN_TYPE_L3,vrf); 4550 info->dvp_group = soc_mem_field32_get(unit,mem, entry,dvp_grp_f); 4551 info->oif_group = soc_mem_field32_get(unit,mem, entry,oif_grp_f); 4552 } else if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_L3_INTF) { 4553 /* only apply to flex view */ 4554 if (!_BCM_FLOW_IS_FLEX_VIEW(info)) { 4555 return BCM_E_PARAM; 4556 } 4557 info->intf_id = soc_mem_field32_get(unit,mem, entry, L3_OIFf); 4558 4559 } else if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_DVP) { 4560 /* only apply to flex view */ 4561 if (!_BCM_FLOW_IS_FLEX_VIEW(info)) { 4562 return BCM_E_PARAM; 4563 } 4564 dvp = soc_mem_field32_get(unit,mem, entry, dvp_f); 4565 _SHR_GPORT_FLOW_PORT_ID_SET(info->flow_port,dvp); 4566 4567 } else if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_SVP_DVP) { 4568 /* only apply to flex view */ 4569 if (!_BCM_FLOW_IS_FLEX_VIEW(info)) { 4570 return BCM_E_PARAM; 4571 } 4572 dvp = soc_mem_field32_get(unit,mem, entry, dvp_f); 4573 _SHR_GPORT_FLOW_PORT_ID_SET(info->flow_port, dvp); 4574 svp = soc_mem_field32_get(unit,mem, entry, SVPf); 4575 _SHR_GPORT_FLOW_PORT_ID_SET(info->src_flow_port, svp); 4576 4577 } else if (info->criteria == BCM_FLOW_ENCAP_CRITERIA_FLEX) { 4578 rv = soc_flow_db_mem_view_field_list_get(unit, 4579 mem, 4580 SOC_FLOW_DB_FIELD_TYPE_LOGICAL_KEY, 4581 _BCM_FLOW_LOGICAL_FIELD_MAX, field_id, &cnt); 4582 SOC_IF_ERROR_RETURN(rv); 4583 if (cnt >= _BCM_FLOW_LOGICAL_FIELD_MAX) { 4584 return BCM_E_PARAM; 4585 } 4586 for (i = 0; i < cnt; i++) { 4587 field[i].id = field_id[i]; 4588 field[i].value = soc_mem_field32_get(unit,mem, entry, 4589 field[i].id); 4590 } 4591 if (SOC_MEM_FIELD_VALID(unit,mem,vfi_f)) { 4592 vfi = soc_mem_field32_get(unit,mem, entry, vfi_f); 4593 _BCM_FLOW_VPN_SET(info->vpn,_BCM_VPN_TYPE_VFI,vfi); 4594 } 4595 if (SOC_MEM_FIELD_VALID(unit,mem,dvp_f)) { 4596 dvp = soc_mem_field32_get(unit,mem, entry, dvp_f); 4597 _SHR_GPORT_FLOW_PORT_ID_SET(info->flow_port,dvp); 4598 } else { 4599 if (SOC_MEM_FIELD_VALID(unit,mem,DGPPf)) { 4600 dgpp = soc_mem_field32_get(unit,mem, entry, DGPPf); 4601 _SHR_GPORT_MODPORT_SET(info->flow_port, 4602 dgpp >> _BCM_FLOW_MODID_SHIFTER, 4603 dgpp & _BCM_FLOW_PORT_MASK); 4604 } 4605 } 4606 if (SOC_MEM_FIELD_VALID(unit,mem,dvp_grp_f)) { 4607 info->dvp_group = soc_mem_field32_get(unit,mem, entry, 4608 dvp_grp_f); 4609 } 4610 if (SOC_MEM_FIELD_VALID(unit,mem,oif_grp_f)) { 4611 info->oif_group = soc_mem_field32_get(unit,mem, entry, 4612 oif_grp_f); 4613 } 4614 if (SOC_MEM_FIELD_VALID(unit,mem,vrf_f)) { 4615 vrf = soc_mem_field32_get(unit,mem, entry, vrf_f); 4616 _BCM_FLOW_VPN_SET(info->vpn,_BCM_VPN_TYPE_L3,vrf); 4617 } 4618 if (SOC_MEM_FIELD_VALID(unit,mem,L3_OIFf)) { 4619 info->intf_id = soc_mem_field32_get(unit,mem, entry, L3_OIFf); 4620 } 4621 if (SOC_MEM_FIELD_VALID(unit, mem, CLASS_IDf)) { 4622 info->class_id = soc_mem_field32_get(unit, mem, entry, CLASS_IDf); 4623 } 4624 if (SOC_MEM_FIELD_VALID(unit, mem, SVPf)) { 4625 svp = soc_mem_field32_get(unit, mem, entry, SVPf); 4626 _SHR_GPORT_FLOW_PORT_ID_SET(info->src_flow_port, svp); 4627 } 4628 } 4629 4630 if (info->criteria != BCM_FLOW_ENCAP_CRITERIA_FLEX) { 4631 cnt = 0; 4632 } 4633 4634 data_cnt = 0; 4635 if (_BCM_FLOW_IS_FLEX_VIEW(info)) { 4636 /* retrieve the data fields, cnt: number of key fields */ 4637 rv = soc_flow_db_mem_view_field_list_get(unit, 4638 mem, 4639 SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA, 4640 _BCM_FLOW_LOGICAL_FIELD_MAX - cnt, field_id, &data_cnt); 4641 BCM_IF_ERROR_RETURN(rv); 4642 if (data_cnt >= _BCM_FLOW_LOGICAL_FIELD_MAX - cnt) { 4643 return BCM_E_PARAM; 4644 } 4645 for (i = 0; i < data_cnt; i++) { 4646 field[i+cnt].id = field_id[i]; 4647 } 4648 } 4649 rv = _bcm_flow_encap_entry_data_get(unit, info, field+cnt, 4650 data_cnt, mem, entry,network_port); 4651 BCM_IF_ERROR_RETURN(rv); 4652 *num_of_fields = cnt + data_cnt; 4653 if (data_cnt) { 4654 info->valid_elements |= BCM_FLOW_ENCAP_FLEX_DATA_VALID; 4655 } 4656 return BCM_E_NONE; 4657 } 4658 4659 /* 4660 * Function: 4661 * _bcm_flow_match_traverse_mem 4662 * Purpose: 4663 * Read the given memory table and call the user callback function on 4664 * each entry. 4665 * Parameters: 4666 * unit - (IN) Device Number 4667 * mem - (IN) the memory id 4668 * cb - (IN) user callback function 4669 * user_data - (IN) user context data 4670 * Returns: 4671 * BCM_E_XXX 4672 */ 4673 4674 STATIC int 4675 _bcm_flow_encap_traverse_mem(int unit, soc_mem_t mem, 4676 bcm_flow_encap_traverse_cb cb, 4677 void *user_data) 4678 { 4679 /* Indexes to iterate over memories, chunks and entries */ 4680 int chnk_idx, ent_idx, chnk_idx_max, mem_idx_max; 4681 int buf_size, chunksize, chnk_end; 4682 /* Buffer to store chunk of table we currently work on */ 4683 uint32 *vt_tbl_chnk; 4684 uint32 *entry; 4685 int valid, rv = BCM_E_NONE; 4686 bcm_flow_encap_config_t info; 4687 uint32 num_of_fields = _BCM_FLOW_LOGICAL_FIELD_MAX; 4688 bcm_flow_logical_field_t field[_BCM_FLOW_LOGICAL_FIELD_MAX]; 4689 4690 if (INVALIDm == mem) { 4691 return BCM_E_MEMORY; 4692 } 4693 if (!soc_mem_index_count(unit, mem)) { 4694 return BCM_E_NONE; 4695 } 4696 4697 chunksize = soc_property_get(unit, spn_VLANDELETE_CHUNKS, 4698 VLAN_MEM_CHUNKS_DEFAULT); 4699 4700 buf_size = 4 * SOC_MAX_MEM_FIELD_WORDS * chunksize; 4701 vt_tbl_chnk = soc_cm_salloc(unit, buf_size, "flow encap traverse"); 4702 if (NULL == vt_tbl_chnk) { 4703 return BCM_E_MEMORY; 4704 } 4705 4706 mem_idx_max = soc_mem_index_max(unit, mem); 4707 for (chnk_idx = soc_mem_index_min(unit, mem); 4708 chnk_idx <= mem_idx_max; 4709 chnk_idx += chunksize) { 4710 sal_memset((void *)vt_tbl_chnk, 0, buf_size); 4711 4712 chnk_idx_max = 4713 ((chnk_idx + chunksize) <= mem_idx_max) ? 4714 chnk_idx + chunksize - 1: mem_idx_max; 4715 4716 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, 4717 chnk_idx, chnk_idx_max, vt_tbl_chnk); 4718 if (SOC_FAILURE(rv)) { 4719 break; 4720 } 4721 chnk_end = (chnk_idx_max - chnk_idx); 4722 for (ent_idx = 0 ; ent_idx <= chnk_end; ent_idx ++) { 4723 entry = 4724 soc_mem_table_idx_to_pointer(unit, mem, uint32 *, 4725 vt_tbl_chnk, ent_idx); 4726 rv = _bcm_flow_encap_entry_valid(unit, mem, entry, &valid); 4727 if (BCM_FAILURE(rv)) { 4728 break; 4729 } 4730 if (!valid) { 4731 continue; 4732 } 4733 bcm_flow_encap_config_t_init(&info); 4734 rv = _bcm_flow_encap_entry_parse(unit, mem, entry, &info, 4735 &num_of_fields,field); 4736 if (rv == BCM_E_NOT_FOUND) { /* for entries not exposed to user */ 4737 continue; 4738 } else if (BCM_FAILURE(rv)) { 4739 break; 4740 } 4741 rv = cb(unit, &info, num_of_fields,field,user_data); 4742 if (BCM_FAILURE(rv)) { 4743 break; 4744 } 4745 } 4746 } 4747 soc_cm_sfree(unit, vt_tbl_chnk); 4748 return rv; 4749 } 4750 4751 /* 4752 * Function: 4753 * bcmi_esw_flow_encap_delete 4754 * Purpose: 4755 * Delete a flow encap entry based on the given key 4756 * Parameters: 4757 * unit - (IN) Device Number 4758 * info - (IN) Flow encap config descriptor 4759 * num_of_fields - (IN) number of logical fields 4760 * field - (IN) logical field array 4761 * Returns: 4762 * BCM_E_XXX 4763 */ 4764 4765 int bcmi_esw_flow_encap_delete( 4766 int unit, 4767 bcm_flow_encap_config_t *info, 4768 uint32 num_of_fields, 4769 bcm_flow_logical_field_t *field) 4770 { 4771 soc_mem_t mem; 4772 uint32 entry[SOC_MAX_MEM_WORDS]; 4773 int network_port; 4774 _bcm_flow_bookkeeping_t *flow_info; 4775 soc_mem_t mem_view; 4776 4777 if (info == NULL) { 4778 return BCM_E_PARAM; 4779 } 4780 4781 flow_info = FLOW_INFO(unit); 4782 4783 sal_memset(entry, 0, sizeof(entry)); 4784 BCM_IF_ERROR_RETURN(_bcm_flow_encap_key_set(unit,info,field, 4785 num_of_fields,entry,&mem, &mem_view, &network_port)); 4786 BCM_IF_ERROR_RETURN(_bcm_flow_encap_profile_delete(unit, info, mem, mem_view, entry)); 4787 BCM_IF_ERROR_RETURN(soc_mem_delete(unit, mem, MEM_BLOCK_ANY, entry)); 4788 4789 bcmi_esw_flow_lock(unit); 4790 if ((mem == EGR_VLAN_XLATE_1_DOUBLEm) || (mem == EGR_VLAN_XLATE_1_SINGLEm)) { 4791 if (flow_info->mem_use_cnt[_BCM_FLOW_EVXLT1_INX]) { 4792 flow_info->mem_use_cnt[_BCM_FLOW_EVXLT1_INX]--; 4793 } 4794 } else if ((mem == EGR_VLAN_XLATE_2_DOUBLEm) || (mem == EGR_VLAN_XLATE_2_SINGLEm)) { 4795 if (flow_info->mem_use_cnt[_BCM_FLOW_EVXLT2_INX]) { 4796 flow_info->mem_use_cnt[_BCM_FLOW_EVXLT2_INX]--; 4797 } 4798 } 4799 bcmi_esw_flow_unlock(unit); 4800 4801 return BCM_E_NONE; 4802 } 4803 4804 /* 4805 * Function: 4806 * bcmi_esw_flow_encap_get 4807 * Purpose: 4808 * Delete a flow encap entry based on the given key 4809 * Parameters: 4810 * unit - (IN) Device Number 4811 * info - (IN) Flow encap config descriptor 4812 * num_of_fields - (IN) number of logical fields 4813 * field - (IN) logical field array 4814 * Returns: 4815 * BCM_E_XXX 4816 */ 4817 4818 int bcmi_esw_flow_encap_get( 4819 int unit, 4820 bcm_flow_encap_config_t *info, 4821 uint32 num_of_fields, 4822 bcm_flow_logical_field_t *field) 4823 { 4824 soc_mem_t mem; 4825 soc_mem_t mem_view; 4826 uint32 entry[SOC_MAX_MEM_WORDS]; 4827 int network_port; 4828 4829 if (info == NULL) { 4830 return BCM_E_PARAM; 4831 } 4832 4833 sal_memset(entry, 0, sizeof(entry)); 4834 BCM_IF_ERROR_RETURN(_bcm_flow_encap_key_set(unit,info,field, 4835 num_of_fields,entry,&mem,&mem_view,&network_port)); 4836 4837 BCM_IF_ERROR_RETURN(_bcm_flow_encap_entry_get(unit,info,field, 4838 num_of_fields, 4839 _BCM_FLOW_IS_FLEX_VIEW(info)? mem_view: mem, 4840 entry,network_port)); 4841 return BCM_E_NONE; 4842 } 4843 4844 /* 4845 * Function: 4846 * bcmi_esw_flow_encap_traverse 4847 * Purpose: 4848 * Traverse flow encap entries. Call the user callback function on each 4849 * entry. 4850 * Parameters: 4851 * unit - (IN) Device Number 4852 * info - (IN) Flow encap config descriptor 4853 * num_of_fields - (IN) number of logical fields 4854 * field - (IN) logical field array 4855 * cb - (IN) user callback function 4856 * user_data - (IN) user context data 4857 * Returns: 4858 * BCM_E_XXX 4859 */ 4860 4861 int bcmi_esw_flow_encap_traverse( 4862 int unit, 4863 bcm_flow_encap_traverse_cb cb, 4864 void *user_data) 4865 { 4866 soc_mem_t mem; 4867 int rv; 4868 _bcm_flow_bookkeeping_t *flow_info; 4869 4870 if (cb == NULL) { 4871 return BCM_E_PARAM; 4872 } 4873 4874 flow_info = FLOW_INFO(unit); 4875 4876 /* traverse the first vlan_xlate */ 4877 if (flow_info->mem_use_cnt[_BCM_FLOW_EVXLT1_INX]) { 4878 mem = EGR_VLAN_XLATE_1_DOUBLEm; 4879 rv = _bcm_flow_encap_traverse_mem(unit, mem, cb, user_data); 4880 BCM_IF_ERROR_RETURN(rv); 4881 } 4882 4883 if (flow_info->mem_use_cnt[_BCM_FLOW_EVXLT1_INX]) { 4884 if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) { 4885 mem = EGR_VLAN_XLATE_1_SINGLEm; 4886 rv = _bcm_flow_encap_traverse_mem(unit, mem, cb, user_data); 4887 BCM_IF_ERROR_RETURN(rv); 4888 } 4889 } 4890 4891 /* traverse the second vlan_xlate */ 4892 if (flow_info->mem_use_cnt[_BCM_FLOW_EVXLT2_INX]) { 4893 mem = EGR_VLAN_XLATE_2_DOUBLEm; 4894 rv = _bcm_flow_encap_traverse_mem(unit, mem, cb, user_data); 4895 BCM_IF_ERROR_RETURN(rv); 4896 } 4897 return BCM_E_NONE; 4898 } 4899 4900 /* 4901 * Function: 4902 * bcmi_esw_flow_mshg_prune_egress_set 4903 * Parameters: 4904 * unit (IN)device number 4905 * src_group_id (IN) source split horizon group ID 4906 * dst_group_id (IN) destination split horizon group ID 4907 * prune_enable (IN) enable or disable pruning 4908 * Purpose 4909 * This API is used to enable/disable egress pruning for Ipv6 VxLAN flow 4910 * Returns: 4911 * BCM_E_XXX 4912 */ 4913 int 4914 bcmi_esw_flow_mshg_prune_egress_set( 4915 int unit, 4916 bcm_switch_network_group_t src_group_id, 4917 bcm_switch_network_group_t dst_group_id, 4918 int prune_enable) 4919 { 4920 bcm_flow_handle_t flow_handle = 0; 4921 bcm_flow_option_id_t flow_option = 0; 4922 soc_mem_t mem_view_id = 0; 4923 soc_mem_t mem_id = 0; 4924 int index = 0; 4925 uint32 entry[SOC_MAX_MEM_WORDS]; 4926 uint32 return_entry[SOC_MAX_MEM_WORDS]; 4927 soc_flow_db_mem_view_info_t mem_view_info; 4928 uint32 src_group_id_f = 0; 4929 uint32 dst_group_id_f = 0; 4930 int entry_exist = 0; 4931 int rv = BCM_E_NONE; 4932 4933 BCM_IF_ERROR_RETURN(soc_flow_db_flow_handle_get(unit ,"VXLAN", &flow_handle)); 4934 BCM_IF_ERROR_RETURN(soc_flow_db_flow_option_id_get(unit, flow_handle, 4935 "LOOKUP_SPLIT_HORIZON_GROUPS_ASSIGN_PASS_ACTION", &flow_option)); 4936 BCM_IF_ERROR_RETURN(soc_flow_db_ffo_to_mem_view_id_get(unit, flow_handle, 4937 flow_option, 4938 SOC_FLOW_DB_FUNC_ENCAP_ID, (uint32 *)&mem_view_id)); 4939 BCM_IF_ERROR_RETURN(soc_flow_db_mem_view_logical_field_id_get(unit, 4940 flow_handle, "SVP_NETWORK_GROUP", &src_group_id_f)); 4941 BCM_IF_ERROR_RETURN(soc_flow_db_mem_view_logical_field_id_get(unit, 4942 flow_handle, "DVP_NETWORK_GROUP", &dst_group_id_f)); 4943 4944 sal_memset(entry, 0, sizeof(entry)); 4945 soc_flow_db_mem_view_entry_init(unit, mem_view_id, entry); 4946 soc_mem_field32_set(unit, mem_view_id, entry, src_group_id_f, src_group_id); 4947 soc_mem_field32_set(unit, mem_view_id, entry, dst_group_id_f, dst_group_id); 4948 sal_memset(&mem_view_info, 0, sizeof(mem_view_info)); 4949 BCM_IF_ERROR_RETURN(soc_flow_db_mem_view_info_get(unit, mem_view_id, 4950 &mem_view_info)); 4951 mem_id = mem_view_info.mem; 4952 rv = soc_mem_search(unit, mem_id, MEM_BLOCK_ANY, &index, entry, 4953 return_entry, 0); 4954 if (BCM_E_NONE == rv) { 4955 entry_exist = 1; 4956 } else if (BCM_E_NOT_FOUND == rv) { 4957 entry_exist = 0; 4958 } else { 4959 return rv; 4960 } 4961 4962 if (prune_enable) { 4963 sal_memset(entry, 0, sizeof(entry)); 4964 } 4965 if (entry_exist) { 4966 rv = soc_mem_write(unit, mem_id, MEM_BLOCK_ALL, index, entry); 4967 } else { 4968 rv = soc_mem_insert(unit, mem_id, MEM_BLOCK_ALL, entry); 4969 } 4970 4971 return rv; 4972 } 4973 4974 /* 4975 * Function: 4976 * bcmi_esw_flow_mshg_prune_egress_init 4977 * Parameters: 4978 * unit (IN)device number 4979 * Purpose 4980 * Egress pruning for Ipv6 VxLAN flow initialization. 4981 * Returns: 4982 * BCM_E_XXX 4983 */ 4984 int 4985 bcmi_esw_flow_mshg_prune_egress_init(int unit) 4986 { 4987 bcm_switch_network_group_t src_group_id; 4988 bcm_switch_network_group_t dst_group_id; 4989 int rv = BCM_E_NONE; 4990 4991 if (soc_reg_field_valid(unit, VXLAN_IPV6_CONTROLr, MSHG_ENABLEf)) { 4992 soc_reg_field32_modify(unit, VXLAN_IPV6_CONTROLr, 0, MSHG_ENABLEf, 0x1); 4993 } 4994 4995 for (dst_group_id = 0; dst_group_id < 8; dst_group_id++) { 4996 for (src_group_id = 0; src_group_id < 8; src_group_id++) { 4997 if ((dst_group_id != src_group_id) || 4998 ((src_group_id == 0) && (dst_group_id == 0))) { 4999 rv = bcmi_esw_flow_mshg_prune_egress_set(unit, src_group_id, 5000 dst_group_id, 0x0); 5001 if (rv != BCM_E_NONE) { 5002 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 5003 "Ipv6 VxLAN flow: %s\n"), bcm_errmsg(rv))); 5004 return rv; 5005 } 5006 } 5007 } 5008 } 5009 5010 return rv; 5011 } 5012 5013 5014 #endif /* INCLUDE_L3 */ 5015