l2.c (75504B)
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: l2.c 8 * Purpose: Trident3 L2 functions implementation 9 */ 10 11 #include <shared/bsl.h> 12 13 #include <soc/defs.h> 14 15 #include <assert.h> 16 17 #include <sal/core/libc.h> 18 #if defined(BCM_TRIDENT3_SUPPORT) 19 20 #include <soc/mem.h> 21 #include <soc/cm.h> 22 #include <soc/drv.h> 23 #include <soc/register.h> 24 #include <soc/memory.h> 25 #include <soc/hash.h> 26 #include <soc/l2x.h> 27 #include <soc/triumph.h> 28 #include <soc/trident2.h> 29 #include <soc/trident3.h> 30 #include <soc/format.h> 31 #include <soc/esw/flow_db.h> 32 33 #include <bcm/l2.h> 34 #include <bcm/error.h> 35 36 #include <bcm_int/esw/mbcm.h> 37 #include <bcm_int/esw/l2.h> 38 #include <bcm_int/esw/firebolt.h> 39 #include <bcm_int/esw/trx.h> 40 #include <bcm_int/esw/triumph.h> 41 #include <bcm_int/esw/mpls.h> 42 #include <bcm_int/esw/mim.h> 43 #include <bcm_int/esw/stack.h> 44 #include <bcm_int/esw/trunk.h> 45 #include <bcm_int/common/multicast.h> 46 #include <bcm_int/esw/multicast.h> 47 #include <bcm_int/esw/virtual.h> 48 #include <bcm_int/esw_dispatch.h> 49 #include <bcm_int/esw/trident.h> 50 #include <bcm_int/esw/switch.h> 51 #include <bcm_int/esw/triumph3.h> 52 #include <bcm_int/esw/trident2.h> 53 #include <bcm_int/esw/trident3.h> 54 #include <bcm_int/esw/flow.h> 55 56 extern int 57 _bcm_td3_evxlt_entry_valid( int unit, soc_mem_t mem, uint32 *entry, int *valid); 58 59 #define DEST_TYPE_INVALID 0 60 #define DEST_TYPE0_DVP 1 61 #define DEST_TYPE0_DGPP 2 62 #define DEST_TYPE1_L2MC 2 63 #define DEST_TYPE1_IPMC 3 64 #define DEST_TYPE2_LAG 1 65 #define DEST_TYPE3_MY_STATION 3 66 67 /* just need to clear SRC or DES hit bit. Customers may call API bcm_esw_l2_replace 68 * with parameter *match_addr which value is NULL */ 69 #define _CLEAR_ALL_ENTRIES_SRC_OR_DES_HIT_BIT(flag) \ 70 (!(flag & (BCM_L2_REPLACE_MATCH_VLAN |\ 71 BCM_L2_REPLACE_MATCH_MAC |\ 72 BCM_L2_REPLACE_MATCH_DEST)) &&\ 73 (flag & (BCM_L2_REPLACE_DES_HIT_CLEAR |\ 74 BCM_L2_REPLACE_SRC_HIT_CLEAR))) 75 76 #define EXTRACT_MAC_DA_27_0(da) ((da)[0] & 0x0fffffff) 77 #define EXTRACT_MAC_DA_47_28(da) \ 78 ((((da)[1]<<4) | (((da)[0]>>28) & 0xf)) & 0xfffff) 79 80 #define COMBINE_MAC_DA_32_0(da) ((da)[0] | (((da)[1] & 0xf)<<28)) 81 #define COMBINE_MAC_DA_47_32(da) ((da)[1]>>4) 82 83 #define _BCM_TD3_EXLATE_CHANGE_L2_FIELDS_KEY_TYPE 0x11 84 #define _BCM_TD3_EXLATE_CHANGE_L2_FIELDS_DATA_TYPE 0x16 85 86 /* 87 * Function: 88 * _bcm_td3_flex_l2_to_l2x 89 * Purpose: 90 * Convert an L2 API data structure to a Trident3 L2 flex-view entry 91 * Parameters: 92 * unit Unit number 93 * l2x_entry (OUT) Trident3 L2X entry 94 * l2addr L2 API data structure 95 * key_only Only construct key portion 96 */ 97 int 98 _bcm_td3_flex_l2_to_l2x(int unit, l2x_entry_t *l2x_entry, bcm_l2_addr_t *l2addr, int key_only) 99 { 100 int vfi; 101 int tid_is_vp_lag; 102 bcm_cos_t cos_dst = l2addr->cos_dst; 103 int group = l2addr->group; 104 int my_station_config = 0; 105 int i; 106 int rv = BCM_E_NONE; 107 uint32 view_id; 108 uint32 field_array[128]; 109 uint32 field_count; 110 uint32 opaque_array[16]; 111 uint32 opaque_count; 112 bcm_flow_logical_field_t* user_fields; 113 int j; 114 115 uint32 action_set = 0; 116 uint8 process_table_management = 0; 117 uint8 process_fixed = 0; 118 uint8 process_fwd_attributes = 0; 119 uint8 process_qos = 0; 120 uint8 process_class_id = 0; 121 uint8 process_destination = 0; 122 uint8 process_vlan=0; 123 uint8 process_vfi=0; 124 uint8 process_mac=0; 125 126 /* Get view id corresponding to the specified flow. */ 127 rv = soc_flow_db_ffo_to_mem_view_id_get(unit, 128 l2addr->flow_handle, 129 l2addr->flow_option_handle, 130 SOC_FLOW_DB_FUNC_L2_SWITCH_ID, 131 &view_id); 132 BCM_IF_ERROR_RETURN(rv); 133 134 /* Initialize control field list for this view id. */ 135 rv = soc_flow_db_mem_view_entry_init(unit, view_id, (uint32*) l2x_entry); 136 137 /* Get logical KEY field list for this view id. */ 138 rv = soc_flow_db_mem_view_field_list_get(unit, 139 view_id, 140 SOC_FLOW_DB_FIELD_TYPE_LOGICAL_KEY, 141 16, 142 opaque_array, 143 &opaque_count); 144 BCM_IF_ERROR_RETURN(rv); 145 146 user_fields = l2addr->logical_fields; 147 148 for (i=0; i<opaque_count; i++) { 149 for (j = 0; j < l2addr->num_of_fields; j++) { 150 if (user_fields[j].id == opaque_array[i]) { 151 soc_mem_field32_set(unit, view_id, l2x_entry, user_fields[j].id, 152 user_fields[j].value); 153 break; 154 } 155 } 156 } 157 158 159 /* Get KEY field list corresponding to the view id. */ 160 rv = soc_flow_db_mem_view_field_list_get(unit, 161 view_id, 162 SOC_FLOW_DB_FIELD_TYPE_KEY, 163 128, 164 field_array, 165 &field_count); 166 BCM_IF_ERROR_RETURN(rv); 167 168 for (i=0; i<field_count; i++) { 169 switch (field_array[i]) { 170 case VFIf: 171 process_vfi = 1; 172 break; 173 case MAC_DAf: 174 process_mac = 1; 175 break; 176 case VLAN_IDf: 177 process_vlan = 1; 178 break; 179 default: 180 break; 181 } 182 } 183 184 if (_BCM_VPN_VFI_IS_SET(l2addr->vid)) { 185 if (!process_vfi) { 186 return BCM_E_PARAM; 187 } 188 _BCM_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, l2addr->vid); 189 soc_mem_field32_set(unit, view_id, l2x_entry, VFIf, vfi); 190 } else { 191 if (!_BCM_MPLS_VPN_IS_VPWS(l2addr->vid)) { 192 if (process_vlan) { 193 VLAN_CHK_ID(unit, l2addr->vid); 194 soc_mem_field32_set(unit, view_id, l2x_entry, VLAN_IDf, l2addr->vid); 195 } 196 } 197 } 198 199 if (process_mac) { 200 soc_mem_mac_addr_set(unit, view_id, l2x_entry, MAC_DAf, l2addr->mac); 201 } 202 203 if (key_only) { 204 return BCM_E_NONE; 205 } 206 207 /* Get logical PDD field list for this view id. */ 208 rv = soc_flow_db_mem_view_field_list_get(unit, 209 view_id, 210 SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA, 211 16, 212 opaque_array, 213 &opaque_count); 214 BCM_IF_ERROR_RETURN(rv); 215 216 user_fields = l2addr->logical_fields; 217 218 for (i=0; i<opaque_count; i++) { 219 if (user_fields[i].id == opaque_array[i]) { 220 soc_mem_field32_set(unit, view_id, &l2x_entry, user_fields[i].id, 221 user_fields[i].value); 222 } 223 } 224 225 /* Get PDD field list corresponding to the view id. */ 226 rv = soc_flow_db_mem_view_field_list_get(unit, 227 view_id, 228 SOC_FLOW_DB_FIELD_TYPE_POLICY_DATA, 229 128, 230 field_array, 231 &field_count); 232 BCM_IF_ERROR_RETURN(rv); 233 234 for (i=0; i<field_count; i++) { 235 switch (field_array[i]) { 236 case DESTINATION_ACTION_SETf: 237 process_destination = 1; 238 break; 239 case CLASS_ID_ACTION_SETf: 240 process_class_id = 1; 241 break; 242 case QOS_ACTION_SETf: 243 process_qos = 1; 244 break; 245 case FWD_ATTRIBUTES_ACTION_SETf: 246 process_fwd_attributes = 1; 247 break; 248 case FIXED_ACTION_SETf: 249 process_fixed = 1; 250 break; 251 case TABLE_MANAGEMENT_ACTION_SETf: 252 process_table_management = 1; 253 break; 254 default: 255 return BCM_E_INTERNAL; 256 } 257 } 258 259 if (!process_destination) { 260 return BCM_E_INTERNAL; 261 } 262 263 if (BCM_MAC_IS_MCAST(l2addr->mac)) { 264 if (l2addr->l2mc_group < 0) { 265 return BCM_E_PARAM; 266 } 267 268 action_set = 0; 269 270 if (_BCM_MULTICAST_IS_FLOW(l2addr->l2mc_group)) { 271 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 272 &action_set, DEST_TYPE1f, DEST_TYPE1_IPMC); 273 } 274 else { 275 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 276 &action_set, DEST_TYPE1f, DEST_TYPE1_L2MC); 277 } 278 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 279 &action_set, L2MC_GROUPf, 280 _BCM_MULTICAST_ID_GET(l2addr->l2mc_group)); 281 282 soc_mem_field32_set(unit, view_id, l2x_entry, 283 DESTINATION_ACTION_SETf, action_set); 284 } else { 285 bcm_port_t port = -1; 286 bcm_trunk_t tgid = BCM_TRUNK_INVALID; 287 bcm_module_t modid = -1; 288 int gport_id = -1; 289 290 if (BCM_GPORT_IS_SET(l2addr->port)) { 291 _bcm_l2_gport_params_t g_params; 292 293 if (BCM_GPORT_IS_BLACK_HOLE(l2addr->port)) { 294 if (!process_fwd_attributes) { 295 return BCM_E_PARAM; 296 } 297 action_set = 0; 298 soc_format_field32_set(unit, FWD_ATTRIBUTES_ACTION_SETfmt, 299 &action_set, SRC_DISCARDf, 1); 300 soc_mem_field32_set(unit, view_id, l2x_entry, 301 FWD_ATTRIBUTES_ACTION_SETf, action_set); 302 } else { 303 /*soc_L2Xm_field32_set(unit, l2x_entry, SRC_DISCARDf, 0);*/ 304 BCM_IF_ERROR_RETURN( 305 _bcm_esw_l2_gport_parse(unit, l2addr, &g_params)); 306 307 switch (g_params.type) { 308 case _SHR_GPORT_TYPE_TRUNK: 309 tgid = g_params.param0; 310 break; 311 case _SHR_GPORT_TYPE_MODPORT: 312 port = g_params.param0; 313 modid = g_params.param1; 314 break; 315 case _SHR_GPORT_TYPE_LOCAL_CPU: 316 port = g_params.param0; 317 BCM_IF_ERROR_RETURN( 318 bcm_esw_stk_my_modid_get(unit, &modid)); 319 break; 320 case _SHR_GPORT_TYPE_SUBPORT_GROUP: 321 gport_id = g_params.param0; 322 break; 323 case _SHR_GPORT_TYPE_SUBPORT_PORT: 324 gport_id = g_params.param0; 325 break; 326 case _SHR_GPORT_TYPE_MPLS_PORT: 327 gport_id = g_params.param0; 328 break; 329 case _SHR_GPORT_TYPE_MIM_PORT: 330 case _SHR_GPORT_TYPE_WLAN_PORT: 331 case _SHR_GPORT_TYPE_VLAN_PORT: 332 case _SHR_GPORT_TYPE_NIV_PORT: 333 case _SHR_GPORT_TYPE_EXTENDER_PORT: 334 gport_id = g_params.param0; 335 break; 336 case _SHR_GPORT_TYPE_TRILL_PORT: 337 case _SHR_GPORT_TYPE_L2GRE_PORT: 338 case _SHR_GPORT_TYPE_VXLAN_PORT: 339 case _SHR_GPORT_TYPE_FLOW_PORT: 340 341 gport_id = g_params.param0; 342 break; 343 default: 344 return BCM_E_PORT; 345 } 346 } 347 } else if (l2addr->flags & BCM_L2_TRUNK_MEMBER) { 348 tgid = l2addr->tgid; 349 350 } else { 351 if ((NUM_MODID(unit) > 1) && (l2addr->port > SOC_MODPORT_MAX(unit))) { 352 bcm_module_t my_modid; 353 int isLocal; 354 BCM_IF_ERROR_RETURN (bcm_esw_stk_my_modid_get(unit, &my_modid)); 355 if (BCM_MODID_INVALID != my_modid) { 356 BCM_IF_ERROR_RETURN 357 (_bcm_esw_modid_is_local(unit, l2addr->modid, &isLocal)); 358 if (isLocal) { 359 l2addr->port %= (SOC_MODPORT_MAX(unit) + 1); 360 } 361 } 362 } 363 BCM_IF_ERROR_RETURN( 364 _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET, 365 l2addr->modid, l2addr->port, 366 &modid, &port)); 367 /* Check parameters */ 368 if (!SOC_MODID_ADDRESSABLE(unit, modid)) { 369 return BCM_E_BADID; 370 } 371 if (!SOC_PORT_ADDRESSABLE(unit, port)) { 372 return BCM_E_PORT; 373 } 374 } 375 376 action_set = 0; 377 /* Setting l2x_entry fields according to parameters */ 378 if ( BCM_TRUNK_INVALID != tgid) { 379 BCM_IF_ERROR_RETURN(_bcm_esw_trunk_id_is_vp_lag(unit, tgid, 380 &tid_is_vp_lag)); 381 if (tid_is_vp_lag) { 382 if (soc_feature(unit, soc_feature_vp_lag)) { 383 int vp_lag_vp; 384 /* Get the VP value representing VP LAG */ 385 BCM_IF_ERROR_RETURN(_bcm_esw_trunk_tid_to_vp_lag_vp(unit, 386 tgid, &vp_lag_vp)); 387 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 388 &action_set, DEST_TYPE0f, DEST_TYPE0_DVP); 389 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 390 &action_set, DVPf, vp_lag_vp); 391 } else { 392 return BCM_E_PORT; 393 } 394 } else { 395 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 396 &action_set, DEST_TYPE2f, DEST_TYPE2_LAG); 397 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 398 &action_set, LAGf, tgid); 399 } 400 } else if (-1 != port) { 401 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 402 &action_set, DEST_TYPE0f, DEST_TYPE0_DGPP); 403 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 404 &action_set, DGPPf, 405 modid << SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS | port); 406 } else if (-1 != gport_id) { 407 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 408 &action_set, DEST_TYPE0f, DEST_TYPE0_DVP); 409 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 410 &action_set, DVPf, gport_id); 411 } 412 soc_mem_field32_set(unit, view_id, l2x_entry, 413 DESTINATION_ACTION_SETf, action_set); 414 } 415 416 /* not support in flex views */ 417 #if 0 418 if (SOC_MEM_FIELD_VALID(unit, L2Xm, L3f)) { 419 if (l2addr->flags & BCM_L2_L3LOOKUP) { 420 soc_L2Xm_field32_set(unit, l2x_entry, L3f, 1); 421 } 422 } 423 #endif 424 425 if (SOC_L2X_GROUP_ENABLE_GET(unit)) { 426 if (soc_feature(unit, soc_feature_overlaid_address_class) && 427 !BCM_L2_PRE_SET(l2addr->flags)) { 428 if ((l2addr->group > SOC_OVERLAID_ADDR_CLASS_MAX(unit)) || 429 (l2addr->group < 0)) { 430 return BCM_E_PARAM; 431 } 432 cos_dst = (l2addr->group & 0x3C0) >> 6; 433 group = l2addr->group & 0x3F; 434 } 435 } 436 437 if (SOC_CONTROL(unit)->l2x_group_enable && process_class_id) { 438 soc_mem_field32_set(unit, view_id, l2x_entry, 439 CLASS_ID_ACTION_SETf, group); 440 } 441 442 action_set = 0; 443 soc_format_field32_set(unit, FORWARDING_1_QOS_ACTION_SETfmt, 444 &action_set, PRIf, cos_dst); 445 if (l2addr->flags & BCM_L2_SETPRI) { 446 if (!process_qos) { 447 return BCM_E_PARAM; 448 } 449 soc_format_field32_set(unit, FORWARDING_1_QOS_ACTION_SETfmt, 450 &action_set, RPEf, 1); 451 } 452 if (l2addr->flags & BCM_L2_COS_SRC_PRI) { 453 if (!process_qos) { 454 return BCM_E_PARAM; 455 } 456 soc_format_field32_set(unit, FORWARDING_1_QOS_ACTION_SETfmt, 457 &action_set, SCPf, 1); 458 } 459 460 if (process_qos) { 461 soc_mem_field32_set(unit, view_id, l2x_entry, 462 QOS_ACTION_SETf, action_set); 463 } 464 465 action_set = 0; 466 if (l2addr->flags & BCM_L2_COPY_TO_CPU) { 467 if (!process_fwd_attributes) { 468 return BCM_E_PARAM; 469 } 470 soc_format_field32_set(unit, FWD_ATTRIBUTES_ACTION_SETfmt, 471 &action_set, CPUf, 1); 472 } 473 474 if (l2addr->flags & BCM_L2_DISCARD_DST) { 475 if (!process_fwd_attributes) { 476 return BCM_E_PARAM; 477 } 478 soc_format_field32_set(unit, FWD_ATTRIBUTES_ACTION_SETfmt, 479 &action_set, DST_DISCARDf, 1); 480 } 481 482 if (l2addr->flags & BCM_L2_DISCARD_SRC) { 483 if (!process_fwd_attributes) { 484 return BCM_E_PARAM; 485 } 486 soc_format_field32_set(unit, FWD_ATTRIBUTES_ACTION_SETfmt, 487 &action_set, SRC_DISCARDf, 1); 488 } 489 490 if (process_fwd_attributes) { 491 soc_mem_field32_set(unit, view_id, l2x_entry, 492 FWD_ATTRIBUTES_ACTION_SETf, action_set); 493 } 494 495 if (l2addr->flags & BCM_L2_PENDING) { 496 if (!process_table_management) { 497 return BCM_E_PARAM; 498 } 499 action_set = 0; 500 soc_format_field32_set(unit, TABLE_MANAGEMENT_ACTION_SETfmt, 501 &action_set, PENDINGf, 1); 502 soc_mem_field32_set(unit, view_id, l2x_entry, 503 TABLE_MANAGEMENT_ACTION_SETf, action_set); 504 } 505 506 if (l2addr->flags & BCM_L2_STATIC) { 507 if (!process_fixed) { 508 return BCM_E_PARAM; 509 } 510 /* STATIC_BITf */ 511 soc_mem_field32_set(unit, view_id, l2x_entry, 512 FIXED_ACTION_SETf, 1); 513 } 514 515 if ((l2addr->flags & BCM_L2_DES_HIT) || 516 (l2addr->flags & BCM_L2_HIT)) { 517 soc_mem_field32_set(unit, view_id, l2x_entry, HITDAf, 1); 518 } 519 520 if ((l2addr->flags & BCM_L2_SRC_HIT) || 521 (l2addr->flags & BCM_L2_HIT)) { 522 soc_mem_field32_set(unit, view_id, l2x_entry, HITSAf, 1); 523 } 524 525 if (SOC_MEM_FIELD_VALID(unit, view_id, LOCAL_SAf)) { 526 if (l2addr->flags & BCM_L2_NATIVE) { 527 soc_mem_field32_set(unit, view_id, l2x_entry, LOCAL_SAf, 1); 528 } 529 } 530 531 my_station_config = soc_property_get(unit, spn_L2_ENTRY_USED_AS_MY_STATION, 0); 532 if (soc_feature(unit, soc_feature_l2_entry_used_as_my_station) 533 && my_station_config) { 534 if (soc_feature(unit, soc_feature_mysta_profile)) { 535 uint32 mysta_profile_id; 536 bcm_l2_station_t station; 537 my_station_profile_1_entry_t entry; 538 sal_memset(&station, 0, sizeof(bcm_l2_station_t)); 539 sal_memset(&entry, 0, sizeof(entry)); 540 station.flags = l2addr->station_flags; 541 if (l2addr->station_flags != 0) { 542 _bcm_l2_mysta_station_to_entry(unit, &station, MY_STATION_PROFILE_1m, &entry); 543 BCM_IF_ERROR_RETURN( 544 _bcm_l2_mysta_profile_entry_add(unit, &entry, 0, 545 &mysta_profile_id)); 546 action_set = 0; 547 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 548 &action_set, DEST_TYPE3f, 549 DEST_TYPE3_MY_STATION); 550 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 551 &action_set, MY_STATION_PROFILE_IDXf, 552 mysta_profile_id); 553 soc_mem_field32_set(unit, view_id, l2x_entry, 554 DESTINATION_ACTION_SETf, action_set); 555 } 556 } 557 } else { 558 if (l2addr->station_flags & BCM_L2_STATION_IPV4 559 || l2addr->station_flags & BCM_L2_STATION_IPV6 560 || l2addr->station_flags & BCM_L2_STATION_ARP_RARP 561 || l2addr->station_flags & BCM_L2_STATION_OAM 562 || l2addr->station_flags & BCM_L2_STATION_FCOE 563 || l2addr->station_flags & BCM_L2_STATION_IPV4_MCAST 564 || l2addr->station_flags & BCM_L2_STATION_IPV6_MCAST) { 565 return BCM_E_UNAVAIL; 566 } 567 } 568 569 return BCM_E_NONE; 570 } 571 572 /* 573 * Function: 574 * _bcm_td3_flex_l2_from_l2x 575 * Purpose: 576 * Convert a Trident3 Flex L2X entry to an L2 API data structure 577 * Parameters: 578 * unit Unit number 579 * l2addr (OUT) L2 API data structure 580 * l2x_entry Trident3 L2X entry 581 */ 582 int 583 _bcm_td3_flex_l2_from_l2x(int unit, bcm_l2_addr_t *l2addr, l2x_entry_t *l2x_entry, int *mb_index) 584 { 585 int l2mc_index, vfi, rval; 586 int my_station_config = 0; 587 int i; 588 int rv = BCM_E_NONE; 589 uint32 action_set = 0; 590 591 uint8 process_table_management = 0; 592 uint8 process_fixed = 0; 593 uint8 process_fwd_attributes = 0; 594 uint8 process_qos = 0; 595 uint8 process_class_id = 0; 596 uint8 process_destination = 0; 597 uint8 process_mac_block = 0; 598 uint8 process_vlan = 0; 599 uint8 process_vfi = 0; 600 uint8 process_mac = 0; 601 602 uint32 key_type; 603 uint32 view_id=0; 604 uint32 flex_data_array[128]; 605 uint32 flex_data_count; 606 uint32 flex_key_array[64]; 607 uint32 flex_key_count; 608 uint32 opaque_array[16]; 609 uint32 opaque_count; 610 bcm_flow_logical_field_t* user_fields; 611 612 key_type = soc_mem_field32_get(unit, L2Xm, l2x_entry, KEY_TYPEf); 613 614 /* Get view id corresponding to key type */ 615 rv = soc_flow_db_mem_to_view_id_get(unit, 616 L2_ENTRY_SINGLEm, 617 key_type, 618 SOC_FLOW_DB_DATA_TYPE_INVALID, 619 0, 620 NULL, 621 &view_id); 622 623 BCM_IF_ERROR_RETURN(rv); 624 625 /* Get logical KEY field list corresponding to the view id. */ 626 rv = soc_flow_db_mem_view_field_list_get(unit, 627 view_id, 628 SOC_FLOW_DB_FIELD_TYPE_LOGICAL_KEY, 629 16, 630 opaque_array, 631 &opaque_count); 632 BCM_IF_ERROR_RETURN(rv); 633 634 user_fields = l2addr->logical_fields; 635 636 for (i=0; i<opaque_count; i++) { 637 user_fields[i].id = opaque_array[i]; 638 user_fields[i].value = soc_mem_field32_get(unit, view_id, l2x_entry, 639 opaque_array[i]); 640 } 641 642 user_fields = &l2addr->logical_fields[opaque_count]; 643 644 /* Get logical Data field list corresponding to the view id. */ 645 rv = soc_flow_db_mem_view_field_list_get(unit, 646 view_id, 647 SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA, 648 16, 649 opaque_array, 650 &opaque_count); 651 BCM_IF_ERROR_RETURN(rv); 652 653 for (i=0; i<opaque_count; i++) { 654 user_fields[i].id = opaque_array[i]; 655 user_fields[i].value = soc_mem_field32_get(unit, view_id, l2x_entry, 656 opaque_array[i]); 657 } 658 659 /* Get KEY field list corresponding to the view id. */ 660 rv = soc_flow_db_mem_view_field_list_get(unit, 661 view_id, 662 SOC_FLOW_DB_FIELD_TYPE_KEY, 663 64, 664 flex_key_array, 665 &flex_key_count); 666 BCM_IF_ERROR_RETURN(rv); 667 668 for (i=0; i<flex_key_count; i++) { 669 switch (flex_key_array[i]) { 670 case VFIf: 671 process_vfi = 1; 672 break; 673 case MAC_DAf: 674 process_mac = 1; 675 break; 676 case VLAN_IDf: 677 process_vlan = 1; 678 break; 679 default: 680 break; 681 } 682 } 683 684 /* Get PDD field list corresponding to the view id. */ 685 rv = soc_flow_db_mem_view_field_list_get(unit, 686 view_id, 687 SOC_FLOW_DB_FIELD_TYPE_POLICY_DATA, 688 128, 689 flex_data_array, 690 &flex_data_count); 691 BCM_IF_ERROR_RETURN(rv); 692 693 for (i=0; i<flex_data_count; i++) { 694 switch (flex_data_array[i]) { 695 case DESTINATION_ACTION_SETf: 696 process_destination = 1; 697 break; 698 case CLASS_ID_ACTION_SETf: 699 process_class_id = 1; 700 break; 701 case QOS_ACTION_SETf: 702 process_qos = 1; 703 break; 704 case FWD_ATTRIBUTES_ACTION_SETf: 705 process_fwd_attributes = 1; 706 break; 707 case FIXED_ACTION_SETf: 708 process_fixed = 1; 709 break; 710 case TABLE_MANAGEMENT_ACTION_SETf: 711 process_table_management = 1; 712 break; 713 case MAC_BLOCK_ACTION_SETf: 714 process_mac_block = 1; 715 break; 716 default: 717 break; 718 } 719 } 720 721 if (!process_destination) { 722 return BCM_E_INTERNAL; 723 } 724 if (process_mac) { 725 soc_mem_mac_addr_get(unit, view_id, l2x_entry, MAC_DAf, l2addr->mac); 726 } 727 728 if (process_vfi) { 729 vfi = soc_mem_field32_get(unit, view_id, l2x_entry, VFIf); 730 COMPILER_REFERENCE(vfi); 731 /* VPLS or MIM VPN */ 732 #if defined(INCLUDE_L3) 733 if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMpls)) { 734 _BCM_MPLS_VPN_SET(l2addr->vid, _BCM_MPLS_VPN_TYPE_VPLS, vfi); 735 } else if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMim)) { 736 _BCM_MIM_VPN_SET(l2addr->vid, _BCM_MIM_VPN_TYPE_MIM, vfi); 737 } else if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeL2Gre)) { 738 if (soc_feature(unit, soc_feature_l2gre)) { 739 BCM_IF_ERROR_RETURN 740 (_bcm_tr3_l2gre_vpn_get(unit, vfi, &l2addr->vid)); 741 } 742 } else if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeVxlan)) { 743 if (soc_feature(unit, soc_feature_vxlan)) { 744 BCM_IF_ERROR_RETURN( 745 _bcm_td2_vxlan_vpn_get(unit, vfi, &l2addr->vid)); 746 } 747 } else if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeFlow)) { 748 if (soc_feature(unit, soc_feature_flex_flow)) { 749 BCM_IF_ERROR_RETURN( 750 bcmi_esw_flow_vpnid_get(unit, vfi, &l2addr->vid)); 751 } 752 } 753 #endif /* INCLUDE_L3 */ 754 } else if (process_vlan) { 755 l2addr->vid = soc_mem_field32_get(unit, view_id, l2x_entry, VLAN_IDf); 756 } 757 758 if (process_mac && BCM_MAC_IS_MCAST(l2addr->mac)) { 759 uint32 dest_type1 = DEST_TYPE_INVALID; 760 l2addr->flags |= BCM_L2_MCAST; 761 action_set = soc_mem_field32_get(unit, view_id, l2x_entry, 762 DESTINATION_ACTION_SETf); 763 l2mc_index = soc_format_field32_get(unit, DESTINATION_FORMATfmt, 764 &action_set, L2MC_GROUPf); 765 dest_type1 = soc_format_field32_get(unit, DESTINATION_FORMATfmt, 766 &action_set, DEST_TYPE1f); 767 if (dest_type1 != DEST_TYPE1_L2MC) { 768 l2mc_index = 0; 769 } 770 l2addr->l2mc_group = l2mc_index; 771 /* Translate l2mc index */ 772 BCM_IF_ERROR_RETURN( 773 bcm_esw_switch_control_get(unit, bcmSwitchL2McIdxRetType, &rval)); 774 if (rval) { 775 _BCM_MULTICAST_GROUP_SET(l2addr->l2mc_group, _BCM_MULTICAST_TYPE_L2, 776 l2addr->l2mc_group); 777 } 778 } else { 779 _bcm_gport_dest_t dest; 780 int dest_type_is_trunk = 0; 781 int isGport = 0; 782 #if defined(INCLUDE_L3) 783 int dest_type_is_dvp = 0; 784 uint32 dest_type0 = DEST_TYPE_INVALID; 785 uint32 dest_type2 = DEST_TYPE_INVALID; 786 #endif 787 uint32 dest_value = 0; 788 789 _bcm_gport_dest_t_init(&dest); 790 #if defined(INCLUDE_L3) 791 action_set = soc_mem_field32_get(unit, view_id, l2x_entry, 792 DESTINATION_ACTION_SETf); 793 dest_type0 = soc_format_field32_get(unit, DESTINATION_FORMATfmt, 794 &action_set, DEST_TYPE0f); 795 dest_type2 = soc_format_field32_get(unit, DESTINATION_FORMATfmt, 796 &action_set, DEST_TYPE2f); 797 if (dest_type0 == DEST_TYPE0_DVP) { 798 dest_type_is_dvp = 1; 799 } else if (dest_type2 == DEST_TYPE2_LAG) { 800 dest_type_is_trunk = 1; 801 } 802 803 if (dest_type_is_dvp) { 804 int vp; 805 vp = soc_format_field32_get(unit, DESTINATION_FORMATfmt, 806 &action_set, DVPf); 807 808 /* MPLS/MiM virtual port unicast */ 809 if (_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) { 810 dest.mpls_id = vp; 811 dest.gport_type = _SHR_GPORT_TYPE_MPLS_PORT; 812 isGport=1; 813 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeMim)) { 814 dest.mim_id = vp; 815 dest.gport_type = _SHR_GPORT_TYPE_MIM_PORT; 816 isGport=1; 817 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeVxlan)) { 818 dest.vxlan_id = vp; 819 dest.gport_type = _SHR_GPORT_TYPE_VXLAN_PORT; 820 isGport=1; 821 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeFlow)) { 822 dest.flow_id = vp; 823 dest.gport_type = _SHR_GPORT_TYPE_FLOW_PORT; 824 isGport=1; 825 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeL2Gre)) { 826 dest.l2gre_id = vp; 827 dest.gport_type = _SHR_GPORT_TYPE_L2GRE_PORT; 828 isGport=1; 829 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeSubport)) { 830 /* Subport/WLAN unicast */ 831 dest.subport_id = vp; 832 dest.gport_type = _SHR_GPORT_TYPE_SUBPORT_GROUP; 833 isGport=1; 834 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeWlan)) { 835 dest.wlan_id = vp; 836 dest.gport_type = _SHR_GPORT_TYPE_WLAN_PORT; 837 isGport=1; 838 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan)) { 839 dest.vlan_vp_id = vp; 840 dest.gport_type = _SHR_GPORT_TYPE_VLAN_PORT; 841 isGport=1; 842 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeNiv)) { 843 dest.niv_id = vp; 844 dest.gport_type = _SHR_GPORT_TYPE_NIV_PORT; 845 isGport=1; 846 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeTrill)) { 847 dest.trill_id = vp; 848 dest.gport_type = _SHR_GPORT_TYPE_TRILL_PORT; 849 isGport=1; 850 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) { 851 dest.extender_id = vp; 852 dest.gport_type = _SHR_GPORT_TYPE_EXTENDER_PORT; 853 isGport=1; 854 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeVpLag)) { 855 l2addr->flags |= BCM_L2_TRUNK_MEMBER; 856 BCM_IF_ERROR_RETURN(_bcm_esw_trunk_vp_lag_vp_to_tid(unit, 857 vp, &l2addr->tgid)); 858 dest.tgid = l2addr->tgid; 859 dest.gport_type = _SHR_GPORT_TYPE_TRUNK; 860 BCM_IF_ERROR_RETURN(bcm_esw_switch_control_get(unit, 861 bcmSwitchUseGport, &isGport)); 862 } else { 863 /* L2 entries with Stale Gport */ 864 dest.gport_type = BCM_GPORT_INVALID; 865 isGport=0; 866 } 867 } else 868 #endif /* INCLUDE_L3 */ 869 if (dest_type_is_trunk) { 870 /* Trunk group */ 871 l2addr->flags |= BCM_L2_TRUNK_MEMBER; 872 dest_value = soc_format_field32_get(unit, DESTINATION_FORMATfmt, 873 &action_set, DVPf); 874 l2addr->tgid = dest_value & SOC_MEM_FIF_DGPP_TGID_MASK; 875 876 dest.tgid = l2addr->tgid; 877 dest.gport_type = _SHR_GPORT_TYPE_TRUNK; 878 BCM_IF_ERROR_RETURN( 879 bcm_esw_switch_control_get(unit, bcmSwitchUseGport, &isGport)); 880 } else { 881 bcm_module_t mod_in, mod_out; 882 bcm_port_t port_in, port_out; 883 884 dest_value = soc_format_field32_get(unit, DESTINATION_FORMATfmt, 885 &action_set, DGPPf); 886 port_in = dest_value & SOC_MEM_FIF_DGPP_PORT_MASK; 887 mod_in = (dest_value & SOC_MEM_FIF_DGPP_MOD_ID_MASK) >> 888 SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS; 889 890 BCM_IF_ERROR_RETURN 891 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 892 mod_in, port_in, &mod_out, &port_out)); 893 l2addr->modid = mod_out; 894 l2addr->port = port_out; 895 dest.port = l2addr->port; 896 dest.modid = l2addr->modid; 897 dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 898 BCM_IF_ERROR_RETURN( 899 bcm_esw_switch_control_get(unit, bcmSwitchUseGport, &isGport)); 900 } 901 902 if (isGport) { 903 BCM_IF_ERROR_RETURN( 904 _bcm_esw_gport_construct(unit, &dest, &(l2addr->port))); 905 } 906 } 907 908 if (SOC_CONTROL(unit)->l2x_group_enable && process_class_id) { 909 l2addr->group = soc_mem_field32_get(unit, view_id, l2x_entry, 910 CLASS_ID_ACTION_SETf); 911 } else if (process_mac_block) { 912 action_set = soc_mem_field32_get(unit, view_id, l2x_entry, 913 MAC_BLOCK_ACTION_SETf); 914 *mb_index = soc_format_field32_get(unit, MAC_BLOCK_ACTION_SETfmt, 915 &action_set, MAC_BLOCK_INDEXf); 916 } 917 918 if (process_qos) { 919 action_set = soc_mem_field32_get(unit, view_id, l2x_entry, 920 QOS_ACTION_SETf); 921 if (soc_format_field32_get(unit, FORWARDING_1_QOS_ACTION_SETfmt, 922 &action_set, RPEf)) { 923 l2addr->flags |= BCM_L2_SETPRI; 924 } 925 if (soc_format_field32_get(unit, FORWARDING_1_QOS_ACTION_SETfmt, 926 &action_set, SCPf)) { 927 l2addr->flags |= BCM_L2_COS_SRC_PRI; 928 } 929 930 l2addr->cos_dst = soc_format_field32_get(unit, 931 FORWARDING_1_QOS_ACTION_SETfmt,&action_set, PRIf); 932 l2addr->cos_src = soc_format_field32_get(unit, 933 FORWARDING_1_QOS_ACTION_SETfmt,&action_set, PRIf); 934 } 935 936 if (SOC_CONTROL(unit)->l2x_group_enable) { 937 if (soc_feature(unit, soc_feature_overlaid_address_class) && 938 !BCM_L2_PRE_SET(l2addr->flags)) { 939 l2addr->group |= (l2addr->cos_dst & 0xF) << 6; 940 } 941 } 942 943 if (process_fwd_attributes) { 944 action_set = soc_mem_field32_get(unit, view_id, l2x_entry, 945 FWD_ATTRIBUTES_ACTION_SETf); 946 if (soc_format_field32_get(unit, FORWARDING_1_QOS_ACTION_SETfmt, 947 &action_set, CPUf)) { 948 l2addr->flags |= BCM_L2_COPY_TO_CPU; 949 } 950 951 if (soc_format_field32_get(unit, FORWARDING_1_QOS_ACTION_SETfmt, 952 &action_set, DST_DISCARDf)) { 953 l2addr->flags |= BCM_L2_DISCARD_DST; 954 } 955 956 if (soc_format_field32_get(unit, FORWARDING_1_QOS_ACTION_SETfmt, 957 &action_set, SRC_DISCARDf)) { 958 l2addr->flags |= BCM_L2_DISCARD_SRC; 959 } 960 } 961 962 if (process_fixed) { 963 if (soc_mem_field32_get(unit, view_id, l2x_entry, STATIC_BITf)) { 964 l2addr->flags |= BCM_L2_STATIC; 965 } 966 } 967 968 if (process_table_management) { 969 action_set = soc_mem_field32_get(unit, view_id, l2x_entry, 970 TABLE_MANAGEMENT_ACTION_SETf); 971 if (soc_format_field32_get(unit, TABLE_MANAGEMENT_ACTION_SETfmt, 972 &action_set, PENDINGf)) { 973 l2addr->flags |= BCM_L2_PENDING; 974 } 975 } 976 977 if (soc_mem_field_valid(unit, view_id, HITDAf)) { 978 if (soc_mem_field32_get(unit, view_id, l2x_entry, HITDAf)) { 979 l2addr->flags |= BCM_L2_DES_HIT; 980 l2addr->flags |= BCM_L2_HIT; 981 } 982 } 983 984 if (soc_mem_field_valid(unit, view_id, HITSAf)) { 985 if (soc_mem_field32_get(unit, view_id, l2x_entry, HITSAf)) { 986 l2addr->flags |= BCM_L2_SRC_HIT; 987 l2addr->flags |= BCM_L2_HIT; 988 } 989 } 990 991 if (soc_mem_field_valid(unit, view_id, LOCAL_SAf)) { 992 if (soc_mem_field32_get(unit, view_id, l2x_entry, LOCAL_SAf)) { 993 l2addr->flags |= BCM_L2_NATIVE; 994 } 995 } 996 997 my_station_config = soc_property_get(unit, spn_L2_ENTRY_USED_AS_MY_STATION, 0); 998 if (soc_feature(unit, soc_feature_l2_entry_used_as_my_station) 999 && my_station_config) { 1000 if (soc_feature(unit, soc_feature_mysta_profile)) { 1001 bcm_l2_station_t station; 1002 uint32 mysta_prof_id = 0; 1003 uint32 dest_type3 = DEST_TYPE_INVALID; 1004 my_station_profile_1_entry_t entry_prof; 1005 1006 sal_memset(&station, 0, sizeof(bcm_l2_station_t)); 1007 1008 action_set = soc_mem_field32_get(unit, view_id, l2x_entry, 1009 DESTINATION_ACTION_SETf); 1010 dest_type3 = soc_format_field32_get(unit, DESTINATION_FORMATfmt, 1011 &action_set, DEST_TYPE3f); 1012 mysta_prof_id = soc_format_field32_get(unit, DESTINATION_FORMATfmt, 1013 &action_set, MY_STATION_PROFILE_IDXf); 1014 if (dest_type3 == DEST_TYPE3_MY_STATION) { 1015 _bcm_l2_mysta_profile_entry_get(unit, &entry_prof, 0, mysta_prof_id); 1016 _bcm_l2_mysta_entry_to_station(unit, &entry_prof, MY_STATION_PROFILE_1m, &station); 1017 l2addr->station_flags = station.flags; 1018 } else { 1019 l2addr->station_flags = 0; 1020 } 1021 } 1022 } 1023 1024 return BCM_E_NONE; 1025 } 1026 1027 /* 1028 * Function: 1029 * _bcm_td3_flex_l2_replace_data_mask_setup 1030 * Purpose: 1031 * Setup the replace data structure with the data and mask of field 1032 * being replaced/deleted 1033 * Parameters: 1034 * unit Unit number 1035 * rep Replacement data structure 1036 */ 1037 1038 int 1039 _bcm_td3_flex_l2_replace_data_mask_setup(int unit, _bcm_l2_replace_t *rep) 1040 { 1041 bcm_mac_t mac_mask; 1042 bcm_mac_t mac_data; 1043 int field_len; 1044 int i; 1045 uint32 view_id; 1046 int rv = BCM_E_NONE; 1047 uint32 action_set = 0; 1048 1049 uint32 flex_key_array[64]; 1050 uint32 flex_key_count; 1051 1052 uint8 process_vlan = 0; 1053 uint8 process_vfi = 0; 1054 uint8 process_mac = 0; 1055 1056 sal_memset(&rep->match_mask, 0, sizeof(l2x_entry_t)); 1057 sal_memset(&rep->match_data, 0, sizeof(l2x_entry_t)); 1058 sal_memset(&rep->new_mask, 0, sizeof(l2x_entry_t)); 1059 sal_memset(&rep->new_data, 0, sizeof(l2x_entry_t)); 1060 1061 view_id = rep->view_id; 1062 /* Initialize control field list for this view id. */ 1063 rv = soc_flow_db_mem_view_entry_init(unit, view_id, (uint32*) &rep->match_data); 1064 BCM_IF_ERROR_RETURN(rv); 1065 1066 field_len = soc_mem_field_length(unit, view_id, BASE_VALIDf); 1067 soc_mem_field32_set(unit, view_id, &rep->match_mask, BASE_VALIDf, 1068 (1 << field_len) - 1); 1069 1070 field_len = soc_mem_field_length(unit, view_id, KEY_TYPEf); 1071 soc_mem_field32_set(unit, view_id, &rep->match_mask, KEY_TYPEf, 1072 (1 << field_len) - 1); 1073 1074 field_len = soc_mem_field_length(unit, view_id, DATA_TYPEf); 1075 soc_mem_field32_set(unit, view_id, &rep->match_mask, DATA_TYPEf, 1076 (1 << field_len) - 1); 1077 1078 /* Get KEY field list corresponding to the view id. */ 1079 rv = soc_flow_db_mem_view_field_list_get(unit, 1080 view_id, 1081 SOC_FLOW_DB_FIELD_TYPE_KEY, 1082 128, 1083 flex_key_array, 1084 &flex_key_count); 1085 BCM_IF_ERROR_RETURN(rv); 1086 1087 for (i=0; i<flex_key_count; i++) { 1088 switch (flex_key_array[i]) { 1089 case VFIf: 1090 process_vfi = 1; 1091 break; 1092 case MAC_DAf: 1093 process_mac = 1; 1094 break; 1095 case VLAN_IDf: 1096 process_vlan = 1; 1097 break; 1098 default: 1099 break; 1100 } 1101 } 1102 1103 if (!SOC_MEM_FIELD_VALID(unit, view_id, DESTINATION_ACTION_SETf)) { 1104 return BCM_E_INTERNAL; 1105 } 1106 if (rep->flags & BCM_L2_REPLACE_MATCH_VLAN) { 1107 if (rep->key_vfi != -1) { 1108 if (!process_vfi) return BCM_E_PARAM; 1109 field_len = soc_mem_field_length(unit, view_id, VFIf); 1110 soc_mem_field32_set(unit, view_id, &rep->match_mask, VFIf, 1111 (1 << field_len) - 1); 1112 soc_mem_field32_set(unit, view_id, &rep->match_data, VFIf, 1113 rep->key_vfi); 1114 } else { 1115 if (!process_vlan) return BCM_E_PARAM; 1116 soc_mem_field32_set(unit, view_id, &rep->match_mask, VLAN_IDf, 0xfff); 1117 soc_mem_field32_set(unit, view_id, &rep->match_data, VLAN_IDf, 1118 rep->key_vlan); 1119 } 1120 } 1121 1122 if (rep->flags & BCM_L2_REPLACE_MATCH_MAC) { 1123 if (!process_mac) return BCM_E_PARAM; 1124 sal_memset(&mac_mask, 0xff, sizeof(mac_mask)); 1125 soc_mem_mac_addr_set(unit, view_id, &rep->match_mask, MAC_DAf, 1126 mac_mask); 1127 soc_mem_mac_addr_set(unit, view_id, &rep->match_data, MAC_DAf, 1128 rep->key_mac); 1129 } 1130 1131 if ((rep->flags & BCM_L2_REPLACE_MATCH_UC) && 1132 !(rep->flags & BCM_L2_REPLACE_MATCH_MC)) { 1133 1134 if (!process_mac) return BCM_E_PARAM; 1135 /* The 40th bit of Unicast must be 0 */ 1136 sal_memset(&mac_mask, 0x00, sizeof(mac_mask)); 1137 mac_mask[0] = 0x01; 1138 sal_memset(&mac_data, 0x00, sizeof(mac_data)); 1139 soc_mem_mac_addr_set(unit, view_id, &rep->match_mask, MAC_DAf, 1140 mac_mask); 1141 soc_mem_mac_addr_set(unit, view_id, &rep->match_data, MAC_DAf, 1142 mac_data); 1143 } else if ((rep->flags & BCM_L2_REPLACE_MATCH_MC) && 1144 !(rep->flags & BCM_L2_REPLACE_MATCH_UC)) { 1145 /* The 40th bit of Multicast must be 1 */ 1146 if (!process_mac) return BCM_E_PARAM; 1147 1148 sal_memset(&mac_mask, 0x00, sizeof(mac_mask)); 1149 mac_mask[0] = 0x01; 1150 sal_memset(&mac_data, 0x00, sizeof(mac_data)); 1151 mac_data[0] = 0x01; 1152 soc_mem_mac_addr_set(unit, view_id, &rep->match_mask, MAC_DAf, 1153 mac_mask); 1154 soc_mem_mac_addr_set(unit, view_id, &rep->match_data, MAC_DAf, 1155 mac_data); 1156 } 1157 1158 if (rep->flags & BCM_L2_REPLACE_MATCH_DEST) { 1159 if (rep->match_dest.vp != -1) { 1160 action_set = 0; 1161 field_len = soc_mem_field_length(unit, view_id, DESTINATION_ACTION_SETf); 1162 soc_mem_field32_set(unit, view_id, &rep->match_mask, DESTINATION_ACTION_SETf, 1163 (1 << field_len) - 1); 1164 1165 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 1166 &action_set, DEST_TYPE0f, DEST_TYPE0_DVP); 1167 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 1168 &action_set, DVPf, rep->match_dest.vp); 1169 soc_mem_field32_set(unit, view_id, &rep->match_data, 1170 DESTINATION_ACTION_SETf, action_set); 1171 } else { 1172 action_set = 0; 1173 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 1174 &action_set, DGPPf, 1175 SOC_MEM_FIF_DGPP_MOD_ID_MASK | SOC_MEM_FIF_DGPP_PORT_MASK); 1176 soc_mem_field32_set(unit, view_id, &rep->match_mask, 1177 DESTINATION_ACTION_SETf, action_set); 1178 action_set = 0; 1179 if (rep->match_dest.trunk != -1) { 1180 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 1181 &action_set, DEST_TYPE2f, DEST_TYPE2_LAG); 1182 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 1183 &action_set, LAGf, rep->match_dest.trunk); 1184 soc_mem_field32_set(unit, view_id, &rep->match_data, 1185 DESTINATION_ACTION_SETf, action_set); 1186 } else { 1187 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 1188 &action_set, DEST_TYPE0f, DEST_TYPE0_DGPP); 1189 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 1190 &action_set, DGPPf, 1191 rep->match_dest.module << SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS | 1192 rep->match_dest.port); 1193 soc_mem_field32_set(unit, view_id, &rep->match_data, 1194 DESTINATION_ACTION_SETf, action_set); 1195 /* Ignore multicast mac from bulk delete */ 1196 mac_mask[0] = 0x01; 1197 mac_mask[1] = mac_mask[2] = mac_mask[3] = 1198 mac_mask[4] = mac_mask[5] = 0x00; 1199 soc_mem_mac_addr_set(unit, view_id, &rep->match_mask, 1200 MAC_DAf, mac_mask); 1201 } 1202 } 1203 } 1204 1205 /* BCM_L2_REPLACE_MATCH_STATIC means to replace static as well as 1206 * non-static entries */ 1207 if (!(rep->flags & BCM_L2_REPLACE_MATCH_STATIC) && 1208 (SOC_MEM_FIELD_VALID(unit, view_id, STATIC_BITf))) { 1209 if (rep->int_flags & _BCM_L2_REPLACE_INT_MATCH_ONLY_STATIC) { 1210 soc_mem_field32_set(unit, view_id, &rep->match_mask, STATIC_BITf, 1); 1211 soc_mem_field32_set(unit, view_id, &rep->match_data, STATIC_BITf, 1); 1212 } else { 1213 soc_mem_field32_set(unit, view_id, &rep->match_mask, STATIC_BITf, 1); 1214 /* STATIC_BIT field in data is 0 */ 1215 } 1216 } 1217 /* STATIC_BIT field in mask is 0 */ 1218 1219 if (SOC_MEM_FIELD_VALID(unit, view_id, TABLE_MANAGEMENT_ACTION_SETf)) { 1220 action_set = 0; 1221 soc_format_field32_set(unit, TABLE_MANAGEMENT_ACTION_SETfmt, 1222 &action_set, PENDINGf, 1); 1223 soc_mem_field32_set(unit, view_id, &rep->match_mask, 1224 TABLE_MANAGEMENT_ACTION_SETf, action_set); 1225 if (rep->flags & BCM_L2_REPLACE_PENDING) { 1226 soc_mem_field32_set(unit, view_id, &rep->match_data, 1227 TABLE_MANAGEMENT_ACTION_SETf, action_set); 1228 } 1229 } 1230 1231 if (rep->int_flags & _BCM_L2_REPLACE_INT_MATCH_DISCARD_SRC) { 1232 if (!SOC_MEM_FIELD_VALID(unit, view_id, FWD_ATTRIBUTES_ACTION_SETf)) { 1233 return BCM_E_PARAM; 1234 } 1235 action_set = 0; 1236 soc_format_field32_set(unit, FWD_ATTRIBUTES_ACTION_SETfmt, 1237 &action_set, SRC_DISCARDf, 1); 1238 soc_mem_field32_set(unit, view_id, &rep->match_mask, 1239 FWD_ATTRIBUTES_ACTION_SETf, action_set); 1240 if (rep->key_l2_flags & BCM_L2_DISCARD_SRC) { 1241 soc_mem_field32_set(unit, view_id, &rep->match_data, 1242 FWD_ATTRIBUTES_ACTION_SETf, action_set); 1243 } 1244 } 1245 1246 if (rep->int_flags & _BCM_L2_REPLACE_INT_MATCH_SRC_HIT) { 1247 if (!SOC_MEM_FIELD_VALID(unit, view_id, HITSAf)) { 1248 return BCM_E_PARAM; 1249 } 1250 soc_mem_field32_set(unit, view_id, &rep->match_mask, HITSAf, 1); 1251 if (rep->key_l2_flags & BCM_L2_SRC_HIT) { 1252 soc_mem_field32_set(unit, view_id, &rep->match_data, HITSAf, 1); 1253 } 1254 } 1255 if (rep->int_flags & _BCM_L2_REPLACE_INT_MATCH_DES_HIT) { 1256 if (!SOC_MEM_FIELD_VALID(unit, view_id, HITDAf)) { 1257 return BCM_E_PARAM; 1258 } 1259 soc_mem_field32_set(unit, view_id, &rep->match_mask, HITDAf, 1); 1260 if (rep->key_l2_flags & BCM_L2_DES_HIT) { 1261 soc_mem_field32_set(unit, view_id, &rep->match_data, HITDAf, 1); 1262 } 1263 } 1264 if (SOC_MEM_FIELD_VALID(unit, view_id, LOCAL_SAf)) { 1265 if (rep->int_flags & _BCM_L2_REPLACE_INT_MATCH_NATIVE) { 1266 soc_mem_field32_set(unit, view_id, &rep->match_mask, LOCAL_SAf, 1); 1267 if (rep->key_l2_flags & BCM_L2_NATIVE) { 1268 soc_mem_field32_set(unit, view_id, &rep->match_data, LOCAL_SAf, 1269 1); 1270 } 1271 } 1272 } 1273 if (_CLEAR_ALL_ENTRIES_SRC_OR_DES_HIT_BIT(rep->flags)) { 1274 if (rep->flags & BCM_L2_REPLACE_DES_HIT_CLEAR) { 1275 if (!SOC_MEM_FIELD_VALID(unit, view_id, HITDAf)) { 1276 return BCM_E_PARAM; 1277 } 1278 soc_mem_field32_set(unit, view_id, &rep->match_mask, HITDAf, 1); 1279 soc_mem_field32_set(unit, view_id, &rep->match_data, HITDAf, 1); 1280 } 1281 if (rep->flags & BCM_L2_REPLACE_SRC_HIT_CLEAR) { 1282 if (!SOC_MEM_FIELD_VALID(unit, view_id, HITSAf)) { 1283 return BCM_E_PARAM; 1284 } 1285 soc_mem_field32_set(unit, view_id, &rep->match_mask, HITSAf, 1); 1286 soc_mem_field32_set(unit, view_id, &rep->match_data, HITSAf, 1); 1287 } 1288 } 1289 if (!(rep->flags & (BCM_L2_REPLACE_DELETE | BCM_L2_REPLACE_AGE))) { 1290 if (!_CLEAR_ALL_ENTRIES_SRC_OR_DES_HIT_BIT(rep->flags)) { 1291 if (rep->new_dest.vp != -1) { 1292 action_set = 0; 1293 field_len = soc_mem_field_length(unit, view_id, DESTINATION_ACTION_SETf); 1294 soc_mem_field32_set(unit, view_id, &rep->new_mask, DESTINATION_ACTION_SETf, 1295 (1 << field_len) - 1); 1296 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 1297 &action_set, DEST_TYPE0f, DEST_TYPE0_DVP); 1298 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 1299 &action_set, DVPf, rep->new_dest.vp); 1300 soc_mem_field32_set(unit, view_id, &rep->new_data, 1301 DESTINATION_ACTION_SETf, action_set); 1302 } else { 1303 action_set = 0; 1304 field_len = soc_mem_field_length(unit, view_id, DESTINATION_ACTION_SETf); 1305 soc_mem_field32_set(unit, view_id, &rep->new_mask, DESTINATION_ACTION_SETf, 1306 (1 << field_len) - 1); 1307 if (rep->new_dest.trunk != -1) { 1308 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 1309 &action_set, DEST_TYPE2f, DEST_TYPE2_LAG); 1310 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 1311 &action_set, LAGf, rep->new_dest.trunk); 1312 soc_mem_field32_set(unit, view_id, &rep->new_data, 1313 DESTINATION_ACTION_SETf, action_set); 1314 } else { 1315 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 1316 &action_set, DEST_TYPE0f, DEST_TYPE0_DGPP); 1317 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 1318 &action_set, DGPPf, 1319 rep->new_dest.module << SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS | 1320 rep->new_dest.port); 1321 soc_mem_field32_set(unit, view_id, &rep->new_data, 1322 DESTINATION_ACTION_SETf, action_set); 1323 } 1324 } 1325 } 1326 if (rep->flags & BCM_L2_REPLACE_DES_HIT_CLEAR) { 1327 if (!SOC_MEM_FIELD_VALID(unit, view_id, HITDAf)) { 1328 return BCM_E_PARAM; 1329 } 1330 soc_mem_field32_set(unit, view_id, &rep->new_mask, HITDAf, 1); 1331 } 1332 if (rep->flags & BCM_L2_REPLACE_SRC_HIT_CLEAR) { 1333 if (!SOC_MEM_FIELD_VALID(unit, view_id, HITSAf)) { 1334 return BCM_E_PARAM; 1335 } 1336 soc_mem_field32_set(unit, view_id, &rep->new_mask, HITSAf, 1); 1337 } 1338 } 1339 1340 return BCM_E_NONE; 1341 } 1342 /* 1343 * _bcm_td3_flex_l2_bulk_replace_modport 1344 * Description: 1345 * Match Flex L2 entries with these fields: DEST_TYPE + MODULE_ID + PORT_NUM 1346 * Replace with one of following: 1347 * DEST_TYPE = 0, new MODULE_ID, new PORT_NUM 1348 * DEST_TYPE = 1, new TGID 1349 * Parameters: 1350 * unit device number 1351 * rep_st structure with match/replace information 1352 * Return: 1353 * BCM_E_XXX 1354 */ 1355 int 1356 _bcm_td3_flex_l2_bulk_replace_modport(int unit, _bcm_l2_replace_t *rep_st) 1357 { 1358 l2_bulk_entry_t match_mask; 1359 l2_bulk_entry_t match_data; 1360 l2_bulk_entry_t repl_mask; 1361 l2_bulk_entry_t repl_data; 1362 int field_len; 1363 int rv; 1364 uint32 view_id; 1365 uint32 action_set=0; 1366 1367 sal_memset(&match_mask, 0, sizeof(match_mask)); 1368 sal_memset(&match_data, 0, sizeof(match_data)); 1369 sal_memset(&repl_mask, 0, sizeof(repl_mask)); 1370 sal_memset(&repl_data, 0, sizeof(repl_data)); 1371 1372 view_id = rep_st->view_id; 1373 /* Initialize control field list for this view id. */ 1374 rv = soc_flow_db_mem_view_entry_init(unit, view_id, (uint32*) &match_data); 1375 BCM_IF_ERROR_RETURN(rv); 1376 1377 soc_mem_field32_set(unit, view_id, &match_mask, BASE_VALIDf, 1); 1378 soc_mem_field32_set(unit, view_id, &match_mask, VALIDf, 1); 1379 1380 field_len = soc_mem_field_length(unit, view_id, KEY_TYPEf); 1381 soc_mem_field32_set(unit, view_id, &match_mask, KEY_TYPEf, 1382 (1 << field_len) - 1); 1383 1384 field_len = soc_mem_field_length(unit, view_id, DATA_TYPEf); 1385 soc_mem_field32_set(unit, view_id, &match_mask, DATA_TYPEf, 1386 (1 << field_len) - 1); 1387 1388 action_set = 0; 1389 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 1390 &action_set, DGPPf, 1391 SOC_MEM_FIF_DGPP_MOD_ID_MASK | SOC_MEM_FIF_DGPP_PORT_MASK); 1392 soc_mem_field32_set(unit, view_id, &match_mask, 1393 DESTINATION_ACTION_SETf, action_set); 1394 action_set = 0; 1395 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 1396 &action_set, DEST_TYPE0f, DEST_TYPE0_DGPP); 1397 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 1398 &action_set, DGPPf, 1399 rep_st->match_dest.module << SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS | 1400 rep_st->match_dest.port); 1401 soc_mem_field32_set(unit, view_id, &match_data, 1402 DESTINATION_ACTION_SETf, action_set); 1403 1404 if (!(rep_st->flags & BCM_L2_REPLACE_MATCH_STATIC)) { 1405 soc_mem_field32_set(unit, view_id, &match_mask, 1406 STATIC_BITf, 1); 1407 /* STATIC_BIT field in data is 0 */ 1408 } 1409 1410 if (rep_st->flags & BCM_L2_REPLACE_PENDING) { 1411 if (!soc_mem_field_valid(unit, view_id, TABLE_MANAGEMENT_ACTION_SETf)) { 1412 return BCM_E_PARAM; 1413 } 1414 action_set = 0; 1415 soc_format_field32_set(unit, TABLE_MANAGEMENT_ACTION_SETfmt, 1416 &action_set, PENDINGf, 1); 1417 soc_mem_field32_set(unit, view_id, &match_mask, 1418 TABLE_MANAGEMENT_ACTION_SETf, action_set); 1419 soc_mem_field32_set(unit, view_id, &match_data, 1420 TABLE_MANAGEMENT_ACTION_SETf, action_set); 1421 } 1422 1423 soc_mem_field32_set(unit, view_id, &match_mask, EVEN_PARITYf, 1424 1); 1425 1426 BCM_IF_ERROR_RETURN 1427 (WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, _BCM_L2_BULK_MATCH_MASK_INX, 1428 &match_mask)); 1429 1430 field_len = soc_mem_field_length(unit, L2_BULKm, DEST_TYPEf); 1431 soc_mem_field32_set(unit, L2_BULKm, &repl_mask, DEST_TYPEf, 1432 (1 << field_len) - 1); 1433 1434 action_set = 0; 1435 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 1436 &action_set, DGPPf, 1437 SOC_MEM_FIF_DGPP_MOD_ID_MASK | SOC_MEM_FIF_DGPP_PORT_MASK); 1438 soc_mem_field32_set(unit, view_id, &repl_mask, 1439 DESTINATION_ACTION_SETf, action_set); 1440 action_set = 0; 1441 if (rep_st->new_dest.trunk != -1) { 1442 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 1443 &action_set, DEST_TYPE2f, DEST_TYPE2_LAG); 1444 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 1445 &action_set, LAGf, 1446 rep_st->new_dest.trunk); 1447 } else { 1448 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 1449 &action_set, DEST_TYPE0f, DEST_TYPE0_DGPP); 1450 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 1451 &action_set, DGPPf, 1452 rep_st->new_dest.module << SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS | 1453 rep_st->new_dest.port); 1454 } 1455 soc_mem_field32_set(unit, view_id, &repl_data, 1456 DESTINATION_ACTION_SETf, action_set); 1457 1458 soc_mem_field32_set(unit, L2_BULKm, &repl_mask, EVEN_PARITYf, 1459 1); 1460 BCM_IF_ERROR_RETURN 1461 (WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, _BCM_L2_BULK_REPLACE_MASK_INX, 1462 &repl_mask)); 1463 1464 BCM_IF_ERROR_RETURN 1465 (soc_reg_field32_modify(unit, L2_BULK_CONTROLr, REG_PORT_ANY, ACTIONf, 1466 2)); 1467 BCM_IF_ERROR_RETURN 1468 (soc_reg_field32_modify(unit, L2_BULK_CONTROLr, REG_PORT_ANY, 1469 NUM_ENTRIESf, soc_mem_index_count(unit, view_id))); 1470 1471 /* Replace all entries having EVEN_PARITY == 0 */ 1472 /* EVEN_PARITY field in data is 0 */ 1473 BCM_IF_ERROR_RETURN 1474 (WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, _BCM_L2_BULK_MATCH_DATA_INX, 1475 &match_data)); 1476 1477 soc_mem_field32_set(unit, L2_BULKm, &repl_data, EVEN_PARITYf, 1478 1); 1479 BCM_IF_ERROR_RETURN 1480 (WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, _BCM_L2_BULK_REPLACE_DATA_INX, 1481 &repl_data)); 1482 1483 BCM_IF_ERROR_RETURN(soc_l2x_port_age(unit, L2_BULK_CONTROLr, INVALIDr)); 1484 1485 /* Replace all entries having EVEN_PARITY == 1 */ 1486 soc_mem_field32_set(unit, L2_BULKm, &match_data, EVEN_PARITYf, 1487 1); 1488 BCM_IF_ERROR_RETURN 1489 (WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, _BCM_L2_BULK_MATCH_DATA_INX, 1490 &match_data)); 1491 1492 soc_mem_field32_set(unit, L2_BULKm, &repl_data, EVEN_PARITYf, 1493 0); 1494 BCM_IF_ERROR_RETURN 1495 (WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, _BCM_L2_BULK_REPLACE_DATA_INX, 1496 &repl_data)); 1497 1498 BCM_IF_ERROR_RETURN(soc_l2x_port_age(unit, L2_BULK_CONTROLr, INVALIDr)); 1499 1500 return BCM_E_NONE; 1501 } 1502 1503 #if defined(INCLUDE_L3) 1504 int 1505 _bcm_td3_l2_change_fields_egress_key_set( 1506 int unit, 1507 soc_mem_t mem, 1508 bcm_l2_change_fields_t *l2_info, 1509 uint32 *entry) 1510 { 1511 int rv = BCM_E_NONE; 1512 1513 if (soc_mem_field_valid(unit, mem, BASE_VALIDf)) { 1514 soc_mem_field32_set(unit, mem, entry, BASE_VALIDf, 1); 1515 } else { 1516 soc_mem_field32_set(unit, mem, entry, BASE_VALID_0f, 3); 1517 soc_mem_field32_set(unit, mem, entry, BASE_VALID_1f, 7); 1518 } 1519 1520 soc_mem_field32_set(unit, mem, entry, KEY_TYPEf, 1521 _BCM_TD3_EXLATE_CHANGE_L2_FIELDS_KEY_TYPE); 1522 soc_mem_field32_set(unit, mem, entry, DATA_TYPEf, 1523 _BCM_TD3_EXLATE_CHANGE_L2_FIELDS_DATA_TYPE); 1524 1525 soc_mem_field32_set(unit, mem, entry, 1526 CHANGE_L2_FIELDS__OPAQUE_3f, l2_info->change_l2_fields_class_id); 1527 1528 if (l2_info->flags & BCM_L2_CHANGE_FIELDS_DVP) { 1529 uint32 dvp; 1530 /* validate DVP */ 1531 if (BCM_GPORT_IS_VXLAN_PORT(l2_info->dvp)) { 1532 dvp = BCM_GPORT_VXLAN_PORT_ID_GET(l2_info->dvp); 1533 } 1534 else if (BCM_GPORT_IS_FLOW_PORT(l2_info->dvp)) { 1535 dvp = BCM_GPORT_FLOW_PORT_ID_GET(l2_info->dvp); 1536 } 1537 else if (BCM_GPORT_IS_L2GRE_PORT(l2_info->dvp)) { 1538 dvp = BCM_GPORT_L2GRE_PORT_ID_GET(l2_info->dvp); 1539 } 1540 else if (BCM_GPORT_IS_MIM_PORT(l2_info->dvp)) { 1541 dvp = BCM_GPORT_MIM_PORT_ID_GET(l2_info->dvp); 1542 } 1543 else if (BCM_GPORT_IS_MPLS_PORT(l2_info->dvp)) { 1544 dvp = BCM_GPORT_MPLS_PORT_ID_GET(l2_info->dvp); 1545 } 1546 else { 1547 /* unregonized gport */ 1548 return BCM_E_PARAM; 1549 } 1550 soc_mem_field32_set(unit, mem, entry, 1551 CHANGE_L2_FIELDS__DVPf, dvp); 1552 } 1553 1554 return rv; 1555 } 1556 1557 STATIC int 1558 _bcm_td3_l2_change_fields_tag_set( 1559 int unit, 1560 bcm_l2_change_fields_t *info, 1561 soc_mem_t mem, 1562 uint32 *entry, 1563 int *tpid_index) 1564 { 1565 int action_present = 0; 1566 int action_not_present = 0; 1567 int sd_tag_remark_cfi_set = 0; 1568 int old_tpid_inx = 0; 1569 uint32 profile_index = 0; 1570 soc_field_t vlan_f = CHANGE_L2_FIELDS__VIDf; 1571 soc_field_t pri_f = CHANGE_L2_FIELDS__PCPf; 1572 soc_field_t cfi_f = CHANGE_L2_FIELDS__DEf; 1573 soc_field_t pri_cfi_sel_f = CHANGE_L2_FIELDS__PCP_DE_SELf; 1574 soc_field_t tag_act_f = CHANGE_L2_FIELDS__TAG_ACTION_PROFILE_PTRf; 1575 soc_field_t tpid_f = CHANGE_L2_FIELDS__TPID_INDEXf; 1576 1577 if (info->vlan >= BCM_VLAN_INVALID) { 1578 return BCM_E_PARAM; 1579 } 1580 soc_mem_field32_set(unit, mem, entry, vlan_f, info->vlan); 1581 1582 if (info->pri > BCM_PRIO_MAX) { 1583 return BCM_E_PARAM; 1584 } 1585 soc_mem_field32_set(unit, mem, entry, pri_f, info->pri); 1586 1587 if (info->cfi > 1) { 1588 return BCM_E_PARAM; 1589 } 1590 soc_mem_field32_set(unit, mem, entry, cfi_f, info->cfi); 1591 1592 if (info->flags & BCM_L2_CHANGE_FIELDS_VLAN_ADD) { 1593 sd_tag_remark_cfi_set = TRUE; 1594 action_not_present = 0x1; /* ADD */ 1595 } 1596 1597 if (info->flags & BCM_L2_CHANGE_FIELDS_VLAN_TPID_REPLACE) { 1598 action_present = 0x1; /* REPLACE_VID_TPID */ 1599 1600 } else if (info->flags & BCM_L2_CHANGE_FIELDS_VLAN_REPLACE) { 1601 action_present = 0x2; /* REPLACE_VID_ONLY */ 1602 1603 } else if (info->flags & BCM_L2_CHANGE_FIELDS_VLAN_DELETE) { 1604 action_present = 0x3; /* DELETE */ 1605 1606 } else if (info->flags & BCM_L2_CHANGE_FIELDS_VLAN_PRI_TPID_REPLACE) { 1607 sd_tag_remark_cfi_set = TRUE; 1608 action_present = 0x4; /* REPLACE_VID_PRI_TPID */ 1609 1610 } else if (info->flags & BCM_L2_CHANGE_FIELDS_VLAN_PRI_REPLACE){ 1611 sd_tag_remark_cfi_set = TRUE; 1612 action_present = 0x5; /* REPLACE_VID_PRI */ 1613 1614 } else if (info->flags & BCM_L2_CHANGE_FIELDS_PRI_REPLACE ) { 1615 sd_tag_remark_cfi_set = TRUE; 1616 action_present = 0x6; /* REPLACE_PRI_ONLY */ 1617 1618 } else if (info->flags & BCM_L2_CHANGE_FIELDS_TPID_REPLACE) { 1619 action_present = 0x7; /* REPLACE_TPID_ONLY */ 1620 } 1621 1622 soc_mem_field32_set(unit, mem, entry, pri_cfi_sel_f, sd_tag_remark_cfi_set); 1623 profile_index = soc_mem_field32_get(unit, mem, entry, tag_act_f); 1624 1625 _bcm_td3_sd_tag_action_profile_get(unit, action_present, 1626 action_not_present, &profile_index); 1627 1628 soc_mem_field32_set(unit, mem, entry, tag_act_f, profile_index); 1629 1630 if ((info->flags & BCM_L2_CHANGE_FIELDS_VLAN_ADD) || 1631 (info->flags & BCM_L2_CHANGE_FIELDS_VLAN_TPID_REPLACE) || 1632 (info->flags & BCM_L2_CHANGE_FIELDS_TPID_REPLACE) || 1633 (info->flags & BCM_L2_CHANGE_FIELDS_VLAN_PRI_TPID_REPLACE)) { 1634 if (info->flags & BCM_L2_CHANGE_FIELDS_REPLACE) { 1635 old_tpid_inx = soc_mem_field32_get(unit, mem, entry, tpid_f); 1636 BCM_IF_ERROR_RETURN(_bcm_fb2_outer_tpid_entry_delete(unit, 1637 old_tpid_inx)); 1638 } 1639 1640 /* TPID value is used */ 1641 BCM_IF_ERROR_RETURN(_bcm_fb2_outer_tpid_entry_add(unit, info->tpid, 1642 tpid_index)); 1643 soc_mem_field32_set(unit, mem, entry, tpid_f, *tpid_index); 1644 } 1645 return BCM_E_NONE; 1646 } 1647 1648 STATIC void 1649 _bcm_td3_l2_change_fields_tag_get( 1650 int unit, 1651 bcm_l2_change_fields_t *info, 1652 soc_mem_t mem, 1653 uint32 *entry, 1654 int *tpid_idx) 1655 { 1656 int action_present = 0; 1657 int action_not_present = 0; 1658 int tpid_index = 0; 1659 uint32 profile_index = 0; 1660 int rv = BCM_E_NONE; 1661 soc_field_t vlan_f = CHANGE_L2_FIELDS__VIDf; 1662 soc_field_t pri_f = CHANGE_L2_FIELDS__PCPf; 1663 soc_field_t cfi_f = CHANGE_L2_FIELDS__DEf; 1664 soc_field_t tag_act_f = CHANGE_L2_FIELDS__TAG_ACTION_PROFILE_PTRf; 1665 soc_field_t tpid_f = CHANGE_L2_FIELDS__TPID_INDEXf; 1666 1667 info->vlan = soc_mem_field32_get(unit, mem, entry, vlan_f); 1668 info->pri = soc_mem_field32_get(unit, mem, entry, pri_f); 1669 info->cfi = soc_mem_field32_get(unit, mem, entry, cfi_f); 1670 1671 profile_index = soc_mem_field32_get(unit, mem, entry, tag_act_f); 1672 1673 (void)_bcm_td3_sd_tag_action_get(unit, profile_index, &action_present, 1674 &action_not_present); 1675 1676 if (action_not_present) { 1677 info->flags |= BCM_L2_CHANGE_FIELDS_VLAN_ADD; 1678 } 1679 1680 if (action_present == 0x1) { 1681 info->flags |= BCM_L2_CHANGE_FIELDS_VLAN_TPID_REPLACE; 1682 1683 } else if (action_present == 0x2) { 1684 info->flags |= BCM_L2_CHANGE_FIELDS_VLAN_REPLACE; 1685 1686 } else if (action_present == 0x3) { 1687 info->flags |= BCM_L2_CHANGE_FIELDS_VLAN_DELETE; 1688 1689 } else if (action_present == 0x4) { 1690 info->flags |= BCM_L2_CHANGE_FIELDS_VLAN_PRI_TPID_REPLACE; 1691 1692 } else if (action_present == 0x5) { 1693 info->flags |= BCM_L2_CHANGE_FIELDS_VLAN_PRI_REPLACE; 1694 1695 } else if (action_present == 0x6) { 1696 info->flags |= BCM_L2_CHANGE_FIELDS_PRI_REPLACE; 1697 1698 } else if (action_present == 0x7) { 1699 info->flags |= BCM_L2_CHANGE_FIELDS_TPID_REPLACE; 1700 } 1701 1702 if ((info->flags & BCM_L2_CHANGE_FIELDS_VLAN_ADD) || 1703 (info->flags & BCM_L2_CHANGE_FIELDS_VLAN_TPID_REPLACE) || 1704 (info->flags & BCM_L2_CHANGE_FIELDS_TPID_REPLACE) || 1705 (info->flags & BCM_L2_CHANGE_FIELDS_VLAN_PRI_TPID_REPLACE)) { 1706 tpid_index = soc_mem_field32_get(unit, mem, entry, tpid_f); 1707 1708 rv = _bcm_fb2_outer_tpid_entry_get(unit, &info->tpid, tpid_index); 1709 if (BCM_FAILURE(rv)) { 1710 info->tpid = tpid_index; 1711 } 1712 if (tpid_idx != NULL) { 1713 *tpid_idx = tpid_index; 1714 } 1715 } 1716 } 1717 1718 STATIC int 1719 _bcm_td3_l2_change_fields_egress_entry_set( 1720 int unit, 1721 soc_mem_t mem, 1722 bcm_l2_change_fields_t *l2_info, 1723 uint32 *entry) 1724 { 1725 int rv = BCM_E_NONE; 1726 int index = -1; 1727 uint32 return_entry[SOC_MAX_MEM_WORDS]; 1728 int new_entry_add = FALSE; 1729 uint32 mac_da_field[2]; 1730 int tpid_index = -1; 1731 1732 rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &index, entry, 1733 return_entry, 0); 1734 1735 if (BCM_E_NONE == rv) { 1736 /* found memory entry */ 1737 if (l2_info->flags & BCM_L2_CHANGE_FIELDS_REPLACE) { 1738 sal_memcpy(entry,return_entry,SOC_MAX_MEM_WORDS * 4); 1739 } else { 1740 return BCM_E_EXISTS; 1741 } 1742 } else if (BCM_E_NOT_FOUND == rv) { 1743 if (l2_info->flags & BCM_L2_CHANGE_FIELDS_REPLACE) { 1744 return BCM_E_NOT_FOUND; 1745 } else { 1746 new_entry_add = TRUE; 1747 } 1748 } else { 1749 return rv; 1750 } 1751 1752 soc_mem_mac_addr_set(unit, mem, entry, 1753 CHANGE_L2_FIELDS__MAC_SAf, l2_info->macsa); 1754 1755 SAL_MAC_ADDR_TO_UINT32(l2_info->macda, mac_da_field); 1756 1757 soc_mem_field32_set(unit, mem, entry, 1758 CHANGE_L2_FIELDS__MAC_DA_27_0f, EXTRACT_MAC_DA_27_0(mac_da_field)); 1759 1760 soc_mem_field32_set(unit, mem, entry, 1761 CHANGE_L2_FIELDS__MAC_DA_47_28f, EXTRACT_MAC_DA_47_28(mac_da_field)); 1762 1763 BCM_IF_ERROR_RETURN( 1764 _bcm_td3_l2_change_fields_tag_set( 1765 unit, 1766 l2_info, 1767 mem, 1768 entry, 1769 &tpid_index)); 1770 1771 if (new_entry_add) { 1772 rv = soc_mem_insert(unit, mem, MEM_BLOCK_ALL, entry); 1773 } else { /* replace action */ 1774 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, entry); 1775 } 1776 1777 if (SOC_FAILURE(rv)) { 1778 goto cleanup; 1779 } 1780 return rv; 1781 1782 cleanup: 1783 if (tpid_index != -1) { 1784 (void) _bcm_fb2_outer_tpid_entry_delete(unit, tpid_index); 1785 } 1786 return rv; 1787 } 1788 1789 int 1790 _bcm_td3_l2_change_fields_add( 1791 int unit, 1792 bcm_l2_change_fields_t *l2_info) 1793 { 1794 soc_mem_t mem = EGR_VLAN_XLATE_2_DOUBLEm; 1795 uint32 entry[SOC_MAX_MEM_WORDS]; 1796 int rv; 1797 1798 sal_memset(entry, 0, sizeof(entry)); 1799 1800 BCM_IF_ERROR_RETURN( 1801 _bcm_td3_l2_change_fields_egress_key_set(unit, 1802 mem, l2_info, entry)); 1803 1804 soc_mem_lock(unit,mem); 1805 1806 /* set the match object and attributes and write to memory */ 1807 rv = _bcm_td3_l2_change_fields_egress_entry_set(unit, mem, 1808 l2_info, entry); 1809 1810 soc_mem_unlock(unit,mem); 1811 1812 return rv; 1813 } 1814 1815 STATIC void 1816 _bcm_td3_l2_change_fields_egress_data_get( 1817 int unit, 1818 soc_mem_t mem, 1819 uint32* entry, 1820 bcm_l2_change_fields_t *l2_info) 1821 { 1822 uint32 mac_da_field[2]; 1823 1824 soc_mem_mac_addr_get(unit, mem, entry, CHANGE_L2_FIELDS__MAC_SAf, l2_info->macsa); 1825 1826 mac_da_field[0] = soc_mem_field32_get(unit, mem, entry, 1827 CHANGE_L2_FIELDS__MAC_DA_27_0f); 1828 1829 mac_da_field[1] = soc_mem_field32_get(unit, mem, entry, 1830 CHANGE_L2_FIELDS__MAC_DA_47_28f); 1831 1832 mac_da_field[0] = COMBINE_MAC_DA_32_0(mac_da_field); 1833 mac_da_field[1] = COMBINE_MAC_DA_47_32(mac_da_field); 1834 1835 SAL_MAC_ADDR_FROM_UINT32(l2_info->macda, mac_da_field); 1836 1837 _bcm_td3_l2_change_fields_tag_get(unit, 1838 l2_info, mem, entry, NULL); 1839 } 1840 1841 int 1842 _bcm_td3_l2_change_fields_egress_entry_get( 1843 int unit, 1844 soc_mem_t mem, 1845 uint32* entry, 1846 bcm_l2_change_fields_t *l2_info) 1847 { 1848 int index = -1; 1849 uint32 return_entry[SOC_MAX_MEM_WORDS]; 1850 1851 SOC_IF_ERROR_RETURN(soc_mem_search(unit, mem, MEM_BLOCK_ANY, &index, 1852 entry, return_entry, 0)); 1853 1854 _bcm_td3_l2_change_fields_egress_data_get(unit, 1855 mem, return_entry, l2_info); 1856 1857 return BCM_E_NONE; 1858 } 1859 1860 STATIC int 1861 _bcm_td3_change_l2_fields_entry_parse( 1862 int unit, 1863 soc_mem_t mem, 1864 uint32 *entry, 1865 bcm_l2_change_fields_t *l2_info) 1866 { 1867 uint32 key_type; 1868 uint32 dvp; 1869 1870 key_type = soc_mem_field32_get(unit, mem, entry, KEY_TYPEf); 1871 1872 if (key_type != 0x11) { 1873 return BCM_E_NOT_FOUND; 1874 } 1875 1876 l2_info->change_l2_fields_class_id = soc_mem_field32_get(unit, 1877 mem, entry, CHANGE_L2_FIELDS__OPAQUE_3f); 1878 1879 dvp = soc_mem_field32_get(unit, mem, entry, CHANGE_L2_FIELDS__DVPf); 1880 1881 if (_bcm_vp_used_get(unit, dvp, _bcmVpTypeVxlan)) { 1882 BCM_GPORT_VXLAN_PORT_ID_SET(l2_info->dvp, dvp); 1883 l2_info->flags |= BCM_L2_CHANGE_FIELDS_DVP; 1884 } else if (_bcm_vp_used_get(unit, dvp, _bcmVpTypeFlow)) { 1885 BCM_GPORT_FLOW_PORT_ID_SET(l2_info->dvp, dvp); 1886 l2_info->flags |= BCM_L2_CHANGE_FIELDS_DVP; 1887 } else if (_bcm_vp_used_get(unit, dvp, _bcmVpTypeL2Gre)) { 1888 BCM_GPORT_L2GRE_PORT_ID_SET(l2_info->dvp, dvp); 1889 l2_info->flags |= BCM_L2_CHANGE_FIELDS_DVP; 1890 } else if (_bcm_vp_used_get(unit, dvp, _bcmVpTypeMim)) { 1891 BCM_GPORT_MIM_PORT_ID_SET(l2_info->dvp, dvp); 1892 l2_info->flags |= BCM_L2_CHANGE_FIELDS_DVP; 1893 } else if (_bcm_vp_used_get(unit, dvp, _bcmVpTypeMpls)) { 1894 BCM_GPORT_MPLS_PORT_ID_SET(l2_info->dvp, dvp); 1895 l2_info->flags |= BCM_L2_CHANGE_FIELDS_DVP; 1896 } 1897 1898 _bcm_td3_l2_change_fields_egress_data_get(unit, 1899 mem, entry, l2_info); 1900 1901 return BCM_E_NONE; 1902 } 1903 1904 int _bcm_td3_change_l2_fields_entry_traverse( 1905 int unit, 1906 soc_mem_t mem, 1907 bcm_l2_change_fields_traverse_cb cb, 1908 void *user_data) 1909 { 1910 1911 /* Indexes to iterate over memories, chunks and entries */ 1912 int chnk_idx, ent_idx, chnk_idx_max, mem_idx_max; 1913 int buf_size, chunksize, chnk_end; 1914 /* Buffer to store chunk of table we currently work on */ 1915 uint32 *ls_tbl_chnk; 1916 uint32 *entry; 1917 int valid, rv = BCM_E_NONE; 1918 bcm_l2_change_fields_t l2_info; 1919 1920 if (INVALIDm == mem) { 1921 return BCM_E_MEMORY; 1922 } 1923 if (!soc_mem_index_count(unit, mem)) { 1924 return BCM_E_NONE; 1925 } 1926 1927 chunksize = 256; 1928 1929 buf_size = 4 * SOC_MAX_MEM_FIELD_WORDS * chunksize; 1930 ls_tbl_chnk = soc_cm_salloc(unit, buf_size, "change l2 fields traverse"); 1931 if (NULL == ls_tbl_chnk) { 1932 return BCM_E_MEMORY; 1933 } 1934 1935 mem_idx_max = soc_mem_index_max(unit, mem); 1936 for (chnk_idx = soc_mem_index_min(unit, mem); 1937 chnk_idx <= mem_idx_max; 1938 chnk_idx += chunksize) { 1939 sal_memset((void *)ls_tbl_chnk, 0, buf_size); 1940 1941 chnk_idx_max = 1942 ((chnk_idx + chunksize) <= mem_idx_max) ? 1943 chnk_idx + chunksize - 1: mem_idx_max; 1944 1945 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, 1946 chnk_idx, chnk_idx_max, ls_tbl_chnk); 1947 if (SOC_FAILURE(rv)) { 1948 break; 1949 } 1950 chnk_end = (chnk_idx_max - chnk_idx); 1951 for (ent_idx = 0 ; ent_idx <= chnk_end; ent_idx ++) { 1952 entry = 1953 soc_mem_table_idx_to_pointer(unit, mem, uint32 *, 1954 ls_tbl_chnk, ent_idx); 1955 rv = _bcm_td3_evxlt_entry_valid(unit, mem, entry, &valid); 1956 if (BCM_FAILURE(rv)) { 1957 break; 1958 } 1959 if (!valid) { 1960 continue; 1961 } 1962 1963 bcm_l2_change_fields_t_init(&l2_info); 1964 1965 rv =_bcm_td3_change_l2_fields_entry_parse(unit, mem, entry, &l2_info); 1966 if (rv == BCM_E_NOT_FOUND) { /* not a large scale nat entry */ 1967 continue; 1968 } else if (BCM_FAILURE(rv)) { 1969 break; 1970 } 1971 rv = cb(unit, &l2_info, user_data); 1972 if (BCM_FAILURE(rv)) { 1973 break; 1974 } 1975 } 1976 } 1977 soc_cm_sfree(unit, ls_tbl_chnk); 1978 return rv; 1979 } 1980 #ifdef BCM_WARM_BOOT_SUPPORT 1981 int 1982 _bcm_td3_l2_change_fields_reinit(int unit) 1983 { 1984 /* 1985 * Recover VLAN Tag Action Profile and TPID ref counts from 1986 * EGR_VLAN_XLATE_2_DOUBLE::CHANGE_L2_FIELDS view. 1987 */ 1988 int rv = BCM_E_NONE; 1989 char *egr_xlate_buf = NULL; 1990 int i, index_min, index_max; 1991 uint32 entry_type = 0; 1992 egr_vlan_xlate_2_double_entry_t *egr_xlate_entry; 1993 soc_mem_t egr_mem = EGR_VLAN_XLATE_2_DOUBLEm; 1994 int profile_index, tpid_idx; 1995 1996 egr_xlate_buf = soc_cm_salloc(unit, 1997 SOC_MEM_TABLE_BYTES(unit, EGR_VLAN_XLATE_2_DOUBLEm), "EGR VLAN XLATE buffer"); 1998 1999 if (NULL == egr_xlate_buf) { 2000 rv = BCM_E_MEMORY; 2001 goto cleanup; 2002 } 2003 index_min = soc_mem_index_min(unit, egr_mem); 2004 index_max = soc_mem_index_max(unit, egr_mem); 2005 rv = soc_mem_read_range(unit, egr_mem, MEM_BLOCK_ANY, 2006 index_min, index_max, egr_xlate_buf); 2007 2008 if (SOC_FAILURE(rv)) { 2009 goto cleanup; 2010 } 2011 2012 for (i = index_min; i <= index_max; i++) { 2013 egr_xlate_entry = soc_mem_table_idx_to_pointer(unit, egr_mem, 2014 egr_vlan_xlate_2_double_entry_t *, egr_xlate_buf, i); 2015 2016 /* Check entry type */ 2017 entry_type = soc_mem_field32_get(unit, egr_mem, egr_xlate_entry, 2018 DATA_TYPEf); 2019 2020 if (entry_type == _BCM_TD3_EXLATE_CHANGE_L2_FIELDS_DATA_TYPE) { 2021 profile_index = soc_mem_field32_get(unit, egr_mem, egr_xlate_entry, 2022 CHANGE_L2_FIELDS__TAG_ACTION_PROFILE_PTRf); 2023 2024 if (profile_index != 0) { 2025 _bcm_trx_egr_vlan_action_profile_entry_increment(unit, 2026 profile_index); 2027 } 2028 tpid_idx = soc_mem_field32_get(unit, egr_mem, 2029 egr_xlate_entry, CHANGE_L2_FIELDS__TPID_INDEXf); 2030 2031 rv = _bcm_fb2_outer_tpid_tab_ref_count_add(unit,tpid_idx,1); 2032 if (BCM_FAILURE(rv)) { 2033 goto cleanup; 2034 } 2035 } 2036 } 2037 cleanup: 2038 if (egr_xlate_buf) { 2039 soc_cm_sfree(unit, egr_xlate_buf); 2040 } 2041 return rv; 2042 } 2043 #endif /* BCM_WARM_BOOT_SUPPORT */ 2044 #endif /* INCLUDE_L3 */ 2045 2046 #endif /* BCM_TRIDENT3_SUPPORT */