flexflow_match.c (123438B)
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_match.c 8 * Purpose: Flex flow match 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/virtual.h> 23 #include <bcm_int/esw/trx.h> 24 #include <bcm_int/esw/port.h> 25 #include <bcm_int/esw_dispatch.h> 26 #include <bcm_int/esw/stack.h> 27 #include <bcm_int/esw/vpn.h> 28 #include <bcm_int/esw/flow.h> 29 #include <soc/esw/flow_db.h> 30 #include <include/soc/tnl_term.h> 31 #include <bcm_int/esw/trident3.h> 32 33 #define _BCM_FLOW_FFO_ENTRY_MAX 20 34 #define _BCM_FLOW_TD3_L3_TUNNEL_DOUBLE_WIDE 2 35 #define _BCM_FLOW_TD3_L3_TUNNEL_QUAD_WIDE 1 36 #define _QUAD_ENTRY_MAX (4 * SOC_MAX_MEM_WORDS) 37 38 int _bcm_flow_mem_view_to_flow_info_get(int unit, 39 uint32 mem_view_id, 40 uint32 func_id, 41 uint32 *flow_hndl, 42 uint32 *flow_opt, 43 int instance) 44 { 45 int i; 46 soc_flow_db_ffo_t ffo[_BCM_FLOW_FFO_ENTRY_MAX]; 47 uint32 num_ffo; 48 uint32 match_num = 0; 49 int rv; 50 51 rv = soc_flow_db_mem_view_to_ffo_get(unit,mem_view_id, 52 _BCM_FLOW_FFO_ENTRY_MAX, ffo, &num_ffo); 53 SOC_IF_ERROR_RETURN(rv); 54 55 rv = SOC_E_NOT_FOUND; 56 for (i = 0; i < num_ffo; i++) { 57 if (ffo[i].function_id == func_id) { 58 match_num++; 59 if (match_num == instance) { 60 *flow_hndl = ffo[i].flow_handle; 61 *flow_opt = ffo[i].option_id; 62 rv = SOC_E_NONE; 63 break; 64 } 65 } 66 } 67 return rv; 68 } 69 70 STATIC int 71 _bcm_flow_match_term_entry_to_mem_entry(int unit, soc_mem_t mem, 72 soc_tunnel_term_t *tnl_entry, 73 uint32 *entry) 74 { 75 76 int entry_width = sizeof(tunnel_entry_t); 77 int mode; 78 int i; 79 80 mode = soc_mem_field32_get(unit, mem, 81 (uint32 *)&tnl_entry->entry_arr[0], MODEf); 82 sal_memcpy((uint8 *)entry, &tnl_entry->entry_arr[0],entry_width); 83 if (mode == _BCM_FLOW_TD3_L3_TUNNEL_DOUBLE_WIDE) { 84 sal_memcpy((uint8 *)entry + entry_width, 85 &tnl_entry->entry_arr[1],entry_width); 86 87 } else if (mode == _BCM_FLOW_TD3_L3_TUNNEL_QUAD_WIDE) { 88 for (i = 1; i < 4; i++) { 89 if (i < COUNTOF(tnl_entry->entry_arr)) { 90 sal_memcpy((uint8 *)entry + entry_width * i, 91 &tnl_entry->entry_arr[i],entry_width); 92 } 93 } 94 } 95 return BCM_E_NONE; 96 } 97 98 STATIC int 99 _bcm_flow_match_mem_entry_to_term_entry(int unit, soc_mem_t mem, 100 soc_tunnel_term_t *tnl_entry, 101 uint32 *entry) 102 { 103 104 int entry_width = sizeof(tunnel_entry_t); 105 int mode; 106 int i; 107 108 sal_memcpy(&tnl_entry->entry_arr[0], (uint8 *)entry,entry_width); 109 mode = soc_mem_field32_get(unit, mem, 110 (uint32 *)&tnl_entry->entry_arr[0], MODEf); 111 if (mode == _BCM_FLOW_TD3_L3_TUNNEL_DOUBLE_WIDE) { 112 sal_memcpy(&tnl_entry->entry_arr[1], 113 (uint8 *)entry + entry_width, entry_width); 114 115 } else if (mode == _BCM_FLOW_TD3_L3_TUNNEL_QUAD_WIDE) { 116 for (i = 1; i < 4; i++) { 117 if (i < COUNTOF(tnl_entry->entry_arr)) { 118 sal_memcpy(&tnl_entry->entry_arr[i], 119 (uint8 *)entry + entry_width * i,entry_width); 120 } 121 } 122 } 123 return BCM_E_NONE; 124 } 125 /* 126 * Function: 127 * _bcm_flow_match_untagged_profile_set 128 * Purpose: 129 * Set VLan profile per Physical port entry 130 * Parameters: 131 * unit - (IN) SOC unit # 132 * port - (IN) Physical port 133 * Returns: 134 * BCM_E_XXX 135 */ 136 137 STATIC int 138 _bcm_flow_match_untagged_profile_set (int unit, bcm_port_t port) 139 { 140 int rv=BCM_E_NONE; 141 bcm_vlan_action_set_t action; 142 uint32 ing_profile_idx = 0xffffffff; 143 int old_ing_profile_idx = 0xffffffff; 144 145 #if defined(BCM_TRIDENT3_SUPPORT) 146 if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) { 147 return BCM_E_NONE; 148 } 149 #endif 150 151 bcm_vlan_action_set_t_init(&action); 152 action.ut_outer = 0x0; /* No Op */ 153 action.ut_inner = 0x0; /* No Op */ 154 155 rv = _bcm_trx_vlan_action_profile_entry_add(unit, &action, &ing_profile_idx); 156 if (rv < 0) { 157 return rv; 158 } 159 160 SOC_IF_ERROR_RETURN( 161 _bcm_esw_port_tab_get(unit, port, TAG_ACTION_PROFILE_PTRf, 162 &old_ing_profile_idx)); 163 164 rv = _bcm_esw_port_tab_set(unit, port, _BCM_CPU_TABS_NONE, 165 TAG_ACTION_PROFILE_PTRf, ing_profile_idx); 166 167 if (old_ing_profile_idx != 0x1) { 168 rv = _bcm_trx_vlan_action_profile_entry_delete(unit, 169 old_ing_profile_idx); 170 } 171 172 return rv; 173 } 174 175 /* 176 * Function: 177 * _bcm_flow_match_untagged_profile_reset 178 * Purpose: 179 * Reset VLan profile per Physical port entry 180 * Parameters: 181 * unit - (IN) SOC unit # 182 * port - (IN) Physical port 183 * Returns: 184 * BCM_E_XXX 185 */ 186 187 STATIC int 188 _bcm_flow_match_untagged_profile_reset(int unit, bcm_port_t port) 189 { 190 int rv = BCM_E_NONE; 191 int ing_profile_idx = -1; 192 193 SOC_IF_ERROR_RETURN( 194 _bcm_esw_port_tab_get(unit, port, TAG_ACTION_PROFILE_PTRf, 195 &ing_profile_idx)); 196 rv = _bcm_trx_vlan_action_profile_entry_delete(unit, ing_profile_idx); 197 if (rv < 0) { 198 return rv; 199 } 200 201 rv = _bcm_esw_port_tab_set(unit, port, _BCM_CPU_TABS_NONE, 202 TAG_ACTION_PROFILE_PTRf, 0x1); 203 204 return rv; 205 } 206 207 /* 208 * Function: 209 * _bcm_flow_match_trunk_table_set 210 * Purpose: 211 * Configure Flow Trunk port entry 212 * Parameters: 213 * unit - (IN) Device Number 214 * port - (IN) Trunk member port 215 * tgid - (IN) Trunk group Id 216 * info - (IN) flow_match configuration info 217 * Returns: 218 * BCM_E_XXX 219 */ 220 221 STATIC int 222 _bcm_flow_match_trunk_table_set(int unit, bcm_port_t port, bcm_trunk_t tgid, 223 bcm_flow_match_config_t *info, int *replaced_vp,int *replaced_iif) 224 { 225 source_trunk_map_table_entry_t trunk_map_entry;/*Trunk table entry buffer.*/ 226 bcm_module_t my_modid; 227 int src_trk_idx = -1; 228 int port_type; 229 soc_mem_t mem = SOURCE_TRUNK_MAP_TABLEm; 230 int rv = BCM_E_NONE; 231 int old_vp; 232 int old_iif; 233 234 if (tgid != BCM_TRUNK_INVALID) { 235 port_type = 1; /* TRUNK_PORT_TYPE */ 236 } else { 237 LOG_ERROR(BSL_LS_BCM_FLOW, 238 (BSL_META_U(unit, "Invalid Trunk ID\n"))); 239 return BCM_E_PARAM; 240 } 241 242 /* Get module id for unit. */ 243 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid)); 244 245 /* Get index to source trunk map table */ 246 BCM_IF_ERROR_RETURN(_bcm_esw_src_mod_port_table_index_get(unit, my_modid, 247 port, &src_trk_idx)); 248 249 soc_mem_lock(unit, mem); 250 251 /* Read source trunk map table. */ 252 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, 253 src_trk_idx, &trunk_map_entry); 254 255 if (rv == SOC_E_NONE) { 256 257 /* Set trunk group id. */ 258 soc_mem_field32_set(unit, mem, &trunk_map_entry, SRC_TGIDf, tgid); 259 260 /* Set port is part of Trunk group */ 261 soc_mem_field32_set(unit, mem, &trunk_map_entry, PORT_TYPEf, port_type); 262 263 if (info->valid_elements & BCM_FLOW_MATCH_FLOW_PORT_VALID) { 264 int vp = _SHR_GPORT_FLOW_PORT_ID_GET(info->flow_port); 265 266 if (replaced_vp && (!(*replaced_vp))) { 267 old_vp = soc_mem_field32_get(unit, mem, &trunk_map_entry, 268 SOURCE_VPf); 269 if (old_vp && (old_vp != vp)) { 270 *replaced_vp = old_vp; 271 } 272 } 273 /* Set SVP */ 274 soc_mem_field32_set(unit, mem, &trunk_map_entry, SOURCE_VPf, vp); 275 } 276 277 if (info->valid_elements & BCM_FLOW_MATCH_IIF_VALID) { 278 if (replaced_iif && (!(*replaced_iif))) { 279 old_iif = soc_mem_field32_get(unit, mem, &trunk_map_entry, 280 L3_IIFf); 281 if (old_iif && (old_iif != info->intf_id)) { 282 *replaced_iif = old_iif; 283 } 284 } 285 /* Set IIF */ 286 soc_mem_field32_set(unit, mem, &trunk_map_entry, L3_IIFf, 287 info->intf_id); 288 } 289 290 /* Write entry to hw. */ 291 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, src_trk_idx, 292 &trunk_map_entry); 293 } 294 soc_mem_unlock(unit, mem); 295 296 return rv; 297 } 298 299 /* 300 * Function: 301 * _bcm_flow_match_trunk_table_get 302 * Purpose: 303 * Configure flow Trunk port entry 304 * Parameters: 305 * unit - (IN) Device Number 306 * port - (IN) Trunk member port 307 * tgid - (IN) Trunk group Id 308 * info - (IN) flow_match configuration info 309 * Returns: 310 * BCM_E_XXX 311 */ 312 313 STATIC int 314 _bcm_flow_match_trunk_table_get(int unit, bcm_port_t port, bcm_trunk_t tgid, 315 bcm_flow_match_config_t *info) 316 { 317 source_trunk_map_table_entry_t trunk_map_entry;/*Trunk table entry buffer.*/ 318 bcm_module_t my_modid; 319 int src_trk_idx = -1; 320 soc_mem_t mem = SOURCE_TRUNK_MAP_TABLEm; 321 int rv = BCM_E_NONE; 322 uint32 vp; 323 324 /* Get module id for unit. */ 325 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid)); 326 327 /* Get index to source trunk map table */ 328 BCM_IF_ERROR_RETURN(_bcm_esw_src_mod_port_table_index_get(unit, my_modid, 329 port, &src_trk_idx)); 330 331 /* Read source trunk map table. */ 332 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, 333 src_trk_idx, &trunk_map_entry); 334 SOC_IF_ERROR_RETURN(rv); 335 336 /* Get SVP */ 337 vp = soc_mem_field32_get(unit, mem, &trunk_map_entry, SOURCE_VPf); 338 _SHR_GPORT_FLOW_PORT_ID_SET(info->flow_port,vp); 339 340 /* Get IIF */ 341 info->intf_id = soc_mem_field32_get(unit, mem, &trunk_map_entry, L3_IIFf); 342 343 return rv; 344 } 345 346 /* 347 * Function: 348 * _bcm_flow_match_trunk_table_reset 349 * Purpose: 350 * Reset flow Trunk port entry 351 * Parameters: 352 * unit - (IN) Device Number 353 * port - (IN) Trunk member port 354 * Returns: 355 * BCM_E_XXX 356 */ 357 358 STATIC int 359 _bcm_flow_match_trunk_table_reset(int unit, bcm_port_t port, 360 int *deleted_vp,int *deleted_iif) 361 { 362 source_trunk_map_table_entry_t trunk_map_entry;/*Trunk table entry buffer.*/ 363 bcm_module_t my_modid; 364 int src_trk_idx = -1; 365 int rv = BCM_E_NONE; 366 soc_mem_t mem = SOURCE_TRUNK_MAP_TABLEm; 367 int vp; 368 int iif; 369 370 /* Get module id for unit. */ 371 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid)); 372 373 /* Get index to source trunk map table */ 374 BCM_IF_ERROR_RETURN(_bcm_esw_src_mod_port_table_index_get(unit, my_modid, 375 port, &src_trk_idx)); 376 377 soc_mem_lock(unit, mem); 378 379 /* Read source trunk map table. */ 380 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, 381 src_trk_idx, &trunk_map_entry); 382 if (rv == SOC_E_NONE) { 383 384 /* Set trunk group id. */ 385 soc_mem_field32_set(unit, mem, &trunk_map_entry, SRC_TGIDf, 0); 386 387 vp = soc_mem_field32_get(unit, mem, &trunk_map_entry, SOURCE_VPf); 388 if (deleted_vp && (!(*deleted_vp))) { 389 vp = soc_mem_field32_get(unit, mem, &trunk_map_entry, SOURCE_VPf); 390 if (vp) { 391 *deleted_vp = vp; 392 } 393 } 394 395 /* Set SVP */ 396 soc_mem_field32_set(unit, mem, &trunk_map_entry, SOURCE_VPf, 0); 397 398 if (deleted_iif && (!(*deleted_iif))) { 399 iif = soc_mem_field32_get(unit, mem, &trunk_map_entry, L3_IIFf); 400 if (iif) { 401 *deleted_iif = iif; 402 } 403 } 404 soc_mem_field32_set(unit, mem, &trunk_map_entry, L3_IIFf, 0); 405 406 /* Write entry to hw. */ 407 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, src_trk_idx, 408 &trunk_map_entry); 409 } 410 soc_mem_unlock(unit, mem); 411 412 return rv; 413 } 414 415 /* 416 * Function: 417 * _bcm_flow_match_trunk_add 418 * Purpose: 419 * Assign SVP of flow Trunk port 420 * Parameters: 421 * unit - (IN) Device Number 422 * tgid - (IN) Trunk group Id 423 * info - (IN) flow_match configuration info 424 * Returns: 425 * BCM_E_XXX 426 */ 427 428 STATIC int 429 _bcm_flow_match_trunk_add(int unit, 430 bcm_trunk_t tgid, 431 bcm_flow_match_config_t *info, 432 int *replaced_vp, 433 int *replaced_iif) 434 { 435 int port_idx=0; 436 int local_port_out[SOC_MAX_NUM_PORTS]; 437 int local_member_count=0; 438 int rv = BCM_E_NONE; 439 440 BCM_IF_ERROR_RETURN(_bcm_esw_trunk_local_members_get(unit, tgid, 441 SOC_MAX_NUM_PORTS, local_port_out, &local_member_count)); 442 for (port_idx = 0; port_idx < local_member_count; port_idx++) { 443 rv = _bcm_flow_match_trunk_table_set(unit, 444 local_port_out[port_idx], tgid, info, 445 replaced_vp,replaced_iif); 446 if (BCM_FAILURE(rv)) { 447 goto trunk_cleanup; 448 } 449 rv = _bcm_esw_port_tab_set( 450 unit, local_port_out[port_idx], 451 _BCM_CPU_TABS_NONE, PORT_OPERATIONf, 1); /* L2_SVP */ 452 if (BCM_FAILURE(rv)) { 453 goto trunk_cleanup; 454 } 455 456 rv = _bcm_flow_match_untagged_profile_set(unit, 457 local_port_out[port_idx]); 458 if (BCM_FAILURE(rv)) { 459 goto trunk_cleanup; 460 } 461 } 462 463 return BCM_E_NONE; 464 465 trunk_cleanup: 466 for (; port_idx >= 0; port_idx--) { 467 (void) _bcm_esw_port_tab_set(unit, local_port_out[port_idx], 468 _BCM_CPU_TABS_NONE, PORT_OPERATIONf, 0); 469 (void) _bcm_flow_match_trunk_table_reset(unit, 470 local_port_out[port_idx],NULL,NULL); 471 } 472 return rv; 473 } 474 475 /* 476 * Function: 477 * _bcm_flow_match_trunk_delete 478 * Purpose: 479 * Remove SVP of flow Trunk port 480 * Parameters: 481 * unit - (IN) Device Number 482 * tgid - (IN) Trunk group Id 483 * info - (IN) flow_match configuration info 484 * Returns: 485 * BCM_E_XXX 486 */ 487 488 STATIC int 489 _bcm_flow_match_trunk_delete(int unit, 490 bcm_trunk_t tgid, 491 bcm_flow_match_config_t *info, 492 int *deleted_vp, 493 int *deleted_iif) 494 { 495 int port_idx=0; 496 int local_port_out[SOC_MAX_NUM_PORTS]; 497 int local_member_count=0; 498 int rv = BCM_E_NONE; 499 500 BCM_IF_ERROR_RETURN(_bcm_esw_trunk_local_members_get(unit, tgid, 501 SOC_MAX_NUM_PORTS, local_port_out, &local_member_count)); 502 503 for (port_idx = 0; port_idx < local_member_count; port_idx++) { 504 rv = _bcm_flow_match_trunk_table_reset(unit, local_port_out[port_idx], 505 deleted_vp,deleted_iif); 506 if (BCM_FAILURE(rv)) { 507 goto trunk_cleanup; 508 } 509 rv = _bcm_esw_port_tab_set(unit, local_port_out[port_idx], 510 _BCM_CPU_TABS_NONE, PORT_OPERATIONf, 0); 511 if (BCM_FAILURE(rv)) { 512 goto trunk_cleanup; 513 } 514 515 rv = _bcm_flow_match_untagged_profile_reset(unit, 516 local_port_out[port_idx]); 517 if (BCM_FAILURE(rv)) { 518 goto trunk_cleanup; 519 } 520 } 521 522 return BCM_E_NONE; 523 524 trunk_cleanup: 525 for (;port_idx >= 0; port_idx--) { 526 (void)_bcm_esw_port_tab_set(unit, local_port_out[port_idx], 527 _BCM_CPU_TABS_NONE, PORT_OPERATIONf, 0x1); 528 (void) _bcm_flow_match_trunk_table_set(unit, local_port_out[port_idx], 529 tgid, info,NULL,NULL); 530 } 531 return rv; 532 } 533 534 /* 535 * Function: 536 * _bcm_flow_match_trunk_get 537 * Purpose: 538 * Assign SVP of flow Trunk port 539 * Parameters: 540 * unit - (IN) Device Number 541 * tgid - (IN) Trunk group Id 542 * info - (IN) flow_match configuration info 543 * Returns: 544 * BCM_E_XXX 545 */ 546 547 STATIC int 548 _bcm_flow_match_trunk_get(int unit, 549 bcm_trunk_t tgid, 550 bcm_flow_match_config_t *info) 551 { 552 int local_port_out[SOC_MAX_NUM_PORTS]; 553 int local_member_count=0; 554 int rv = BCM_E_NONE; 555 556 BCM_IF_ERROR_RETURN(_bcm_esw_trunk_local_members_get(unit, tgid, 557 SOC_MAX_NUM_PORTS, local_port_out, &local_member_count)); 558 559 /* get from the first port */ 560 rv = _bcm_flow_match_trunk_table_get(unit, 561 local_port_out[0], tgid, info); 562 BCM_IF_ERROR_RETURN(rv); 563 return BCM_E_NONE; 564 } 565 566 /* 567 * Function: 568 * _bcm_flow_match_fixed_view_entry_init 569 * Purpose: 570 * initialize the fixed view memory entry 571 * Parameters: 572 * unit - (IN) Device Number 573 * mem - (IN) memory id 574 * info - (IN) flow_match configuration info 575 * key_type - (IN) the fixed key type 576 * entry - (OUT) point to the entry to be initialized 577 * Returns: 578 * BCM_E_XXX 579 */ 580 STATIC int 581 _bcm_flow_match_fixed_view_entry_init(int unit, 582 soc_mem_t mem, 583 bcm_flow_match_config_t *info, 584 uint32 key_type, 585 uint32 *entry) 586 { 587 int rv = BCM_E_NONE; 588 589 soc_mem_field32_set(unit,mem, entry, KEY_TYPEf, key_type); 590 if (key_type == _BCM_FLOW_MATCH_KEY_TYPE_VXLAN_FLEX_VNID) { 591 soc_mem_field32_set(unit, mem, entry, DATA_TYPEf, 592 _BCM_FLOW_MATCH_KEY_TYPE_VXLAN_FLEX_SIP_VNID); 593 } else if (key_type == _BCM_FLOW_MATCH_KEY_TYPE_VXLAN_SIP) { 594 soc_mem_field32_set(unit, mem, entry, DATA_TYPEf, 595 _BCM_VXLAN_FLEX_DATA_TYPE_IPV4_SIP); 596 } else { 597 soc_mem_field32_set(unit, mem, entry, DATA_TYPEf, key_type); 598 } 599 600 if (soc_mem_field_valid(unit, mem, BASE_VALIDf)) { 601 soc_mem_field32_set(unit, mem, entry, BASE_VALIDf, 1); 602 } else { 603 soc_mem_field32_set(unit, mem, entry, BASE_VALID_0f, 3); 604 soc_mem_field32_set(unit, mem, entry, BASE_VALID_1f, 7); 605 } 606 607 return rv; 608 } 609 610 STATIC int 611 _bcm_flow_match_sgpp_ctrl_set(int unit, 612 bcm_flow_match_config_t *info, 613 uint32 num_of_fields, 614 bcm_flow_logical_field_t *field, 615 int clear_action) 616 { 617 soc_mem_t sgpp_view_id; 618 int rv, i, j; 619 uint32 entry[SOC_MAX_MEM_WORDS]; 620 bcm_module_t mod_out = -1; 621 bcm_port_t port_out = -1; 622 bcm_trunk_t trunk_id = -1; 623 int gport_id=-1; 624 int src_trk_idx=0; /*Source Trunk table index.*/ 625 soc_mem_t mem; 626 int ctrl_profile1 = 0, ctrl_profile0 = 0; 627 int edit_ctrl_id = 0, vxlt_ctrl_id = 0; 628 int gbp_sel = 0; 629 uint32 data_array[_BCM_FLOW_LOGICAL_FIELD_MAX]; 630 uint32 data_count; 631 uint32 values[4]; 632 soc_field_t fields[4]; 633 int field_cnt = 0; 634 soc_flow_db_mem_view_info_t vinfo; 635 636 /* currently don't handle trunk port yet */ 637 if (BCM_GPORT_IS_TRUNK(info->port)) { 638 return BCM_E_UNAVAIL; 639 } 640 641 sal_memset(entry, 0, sizeof(entry)); 642 rv = soc_flow_db_ffo_to_mem_view_id_get(unit,info->flow_handle, info->flow_option, 643 SOC_FLOW_DB_FUNC_SGPP_CONTROL_ID, (uint32 *)&sgpp_view_id); 644 SOC_IF_ERROR_RETURN(rv); 645 646 soc_flow_db_mem_view_entry_init(unit,sgpp_view_id,entry); 647 if (SOC_MEM_FIELD_VALID(unit, sgpp_view_id, CTRL_PROFILE_IDX_1f)) { 648 ctrl_profile1 = soc_mem_field32_get(unit, sgpp_view_id, entry, 649 CTRL_PROFILE_IDX_1f); 650 } 651 if (SOC_MEM_FIELD_VALID(unit, sgpp_view_id, CTRL_PROFILE_IDX_0f)) { 652 ctrl_profile0 = soc_mem_field32_get(unit, sgpp_view_id, entry, 653 CTRL_PROFILE_IDX_0f); 654 } 655 if (SOC_MEM_FIELD_VALID(unit, sgpp_view_id, EDIT_CTRL_IDf)) { 656 edit_ctrl_id = soc_mem_field32_get(unit, sgpp_view_id, entry, 657 EDIT_CTRL_IDf); 658 if (clear_action) { 659 edit_ctrl_id = 0; /* clear to default */ 660 } 661 fields[field_cnt] = EDIT_CTRL_IDf; 662 values[field_cnt++] = edit_ctrl_id; 663 664 } 665 if (SOC_MEM_FIELD_VALID(unit, sgpp_view_id, VXLT_CTRL_IDf)) { 666 vxlt_ctrl_id = soc_mem_field32_get(unit, sgpp_view_id, entry, 667 VXLT_CTRL_IDf); 668 if (clear_action) { 669 vxlt_ctrl_id = 0; /* clear to default */ 670 } 671 fields[field_cnt] = VXLT_CTRL_IDf; 672 values[field_cnt++] = vxlt_ctrl_id; 673 674 } 675 if (info->valid_elements & BCM_FLOW_MATCH_FLEX_DATA_VALID) { 676 if (SOC_MEM_FIELD_VALID(unit, sgpp_view_id, IDf)) { 677 gbp_sel = soc_mem_field32_get(unit, sgpp_view_id, entry, 678 IDf); 679 } 680 } 681 BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, info->port, 682 &mod_out, &port_out, &trunk_id, &gport_id)); 683 684 /* Get index to source trunk map table */ 685 BCM_IF_ERROR_RETURN(_bcm_esw_src_mod_port_table_index_get(unit, mod_out, 686 port_out, &src_trk_idx)); 687 688 rv = soc_flow_db_mem_view_info_get(unit, sgpp_view_id, &vinfo); 689 BCM_IF_ERROR_RETURN(rv); 690 691 mem = vinfo.mem; 692 soc_mem_lock(unit,mem); 693 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, src_trk_idx, entry); 694 if (SOC_SUCCESS(rv)) { 695 if (SOC_MEM_FIELD_VALID(unit, sgpp_view_id, CTRL_PROFILE_IDX_1f)) { 696 if (clear_action) { 697 ctrl_profile1 = 0; /* clear to default */ 698 } 699 soc_mem_field32_set(unit, sgpp_view_id, entry, CTRL_PROFILE_IDX_1f, 700 ctrl_profile1); 701 } 702 if (SOC_MEM_FIELD_VALID(unit, sgpp_view_id, CTRL_PROFILE_IDX_0f)) { 703 if (clear_action) { 704 ctrl_profile0 = 0; /* clear to default */ 705 } 706 soc_mem_field32_set(unit, sgpp_view_id, entry, CTRL_PROFILE_IDX_0f, 707 ctrl_profile0); 708 } 709 if (info->valid_elements & BCM_FLOW_MATCH_FLEX_DATA_VALID) { 710 if (SOC_MEM_FIELD_VALID(unit, sgpp_view_id, IDf)) { 711 if (clear_action) { 712 gbp_sel = 0; /* clear to default */ 713 } 714 soc_mem_field32_set(unit, sgpp_view_id, entry, IDf, 715 gbp_sel); 716 } 717 /* Get logical PDD field list for this view id. */ 718 rv = soc_flow_db_mem_view_field_list_get(unit, sgpp_view_id, 719 SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA, 720 _BCM_FLOW_LOGICAL_FIELD_MAX, 721 data_array, &data_count); 722 BCM_IF_ERROR_RETURN(rv); 723 for (j = 0; j < num_of_fields; j++) { 724 for (i = 0; i < data_count; i++) { 725 if (field[j].id == data_array[i]) { 726 if (clear_action) { 727 field[j].value = 0; /* clear to default */ 728 } 729 soc_mem_field32_set(unit, sgpp_view_id, entry, field[j].id, 730 field[j].value); 731 break; 732 } 733 } 734 } 735 } 736 rv = soc_mem_write(unit, mem, MEM_BLOCK_ANY, src_trk_idx, entry); 737 } 738 739 soc_mem_unlock(unit,mem); 740 741 mem = EGR_LPORT_PROFILEm; 742 soc_mem_lock(unit,mem); 743 if (soc_feature(unit, soc_feature_egr_lport_tab_profile)) { 744 rv = bcm_esw_port_egr_lport_fields_set(unit, info->port, 745 mem, field_cnt, fields, values); 746 } 747 soc_mem_unlock(unit,mem); 748 return rv; 749 } 750 751 STATIC 752 void _bcm_flow_match_default_option_get( 753 int unit, 754 bcm_flow_match_config_t *info, 755 char **option_str) 756 { 757 *option_str = NULL; 758 759 if (info->criteria == BCM_FLOW_MATCH_CRITERIA_SIP) { 760 if (info->valid_elements & (BCM_FLOW_MATCH_SIP_VALID | 761 BCM_FLOW_MATCH_FLOW_PORT_VALID)) { 762 *option_str = "LOOKUP_IPV4_SIP_ASSIGN_SVP"; 763 } else if (info->valid_elements & (BCM_FLOW_MATCH_SIP_V6_VALID | 764 BCM_FLOW_MATCH_FLOW_PORT_VALID)) { 765 *option_str = "LOOKUP_IPV6_SIP_ASSIGN_SVP"; 766 } 767 } else if (info->criteria == BCM_FLOW_MATCH_CRITERIA_VN_ID) { 768 if (info->valid_elements & (BCM_FLOW_MATCH_VNID_VALID | 769 BCM_FLOW_MATCH_VPN_VALID)) { 770 *option_str = "LOOKUP_VNID_ASSIGN_VFI"; 771 } else if (info->valid_elements & (BCM_FLOW_MATCH_VNID_VALID | 772 BCM_FLOW_MATCH_IIF_VALID)) { 773 *option_str = "LOOKUP_VNID_ASSIGN_L3_IIF"; 774 } 775 } else if (info->criteria == BCM_FLOW_MATCH_CRITERIA_MPLS_LABEL) { 776 *option_str = "LOOKUP_MPLS_LABEL_ASSIGN_SVP"; 777 } 778 } 779 780 /* 781 * Function: 782 * _bcm_flow_match_entry_set 783 * Purpose: 784 * Set flow Match Entry 785 * Parameters: 786 * unit - (IN) Device Number 787 * info - (IN) flow_match configuration info 788 * field - (IN) array of logical fields 789 * num_of_fields -(IN) the size of the above array 790 * mem - (IN) memory id 791 * entry - (IN) point to the match entry 792 * Returns: 793 * BCM_E_XXX 794 */ 795 796 STATIC int 797 _bcm_flow_match_entry_set(int unit, 798 bcm_flow_match_config_t *info, 799 bcm_flow_logical_field_t *field, 800 int num_of_fields, 801 soc_flow_db_mem_view_info_t *view_info, 802 uint32 *entry, 803 int *replaced_iif, 804 int *replaced_vp) 805 { 806 int rv = BCM_E_NONE; 807 int i; 808 int j; 809 int index = -1; 810 int action_type; 811 uint32 return_entry[_QUAD_ENTRY_MAX]; 812 int vp = _SHR_GPORT_FLOW_PORT_ID_GET(info->flow_port); 813 int new_entry_add = FALSE; 814 soc_mem_t mem; 815 soc_tunnel_term_t tnl_entry; 816 soc_tunnel_term_t tnl_return_entry; 817 uint32 action_set; 818 819 sal_memset(&tnl_entry, 0, sizeof(soc_tunnel_term_t)); 820 sal_memset(&tnl_return_entry, 0, sizeof(soc_tunnel_term_t)); 821 822 mem = _BCM_FLOW_IS_FLEX_VIEW(info)? 823 view_info->mem_view_id: view_info->mem; 824 825 if (replaced_iif != NULL) { 826 *replaced_iif = 0; 827 } 828 if (replaced_vp != NULL) { 829 *replaced_vp = 0; 830 } 831 if (view_info->mem == L3_TUNNELm) { /* TCAM */ 832 rv = _bcm_flow_match_mem_entry_to_term_entry(unit, mem, 833 &tnl_entry, entry); 834 BCM_IF_ERROR_RETURN(rv); 835 rv = soc_tunnel_term_match(unit,&tnl_entry, 836 &tnl_return_entry, &index); 837 } else { /* hash table */ 838 rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &index, entry, 839 return_entry, 0); 840 } 841 if (BCM_E_NONE == rv) { 842 /* found memory entry */ 843 if (info->options & BCM_FLOW_MATCH_OPTION_REPLACE) { 844 if (view_info->mem == L3_TUNNELm) { 845 BCM_IF_ERROR_RETURN( 846 _bcm_flow_match_term_entry_to_mem_entry(unit, mem, 847 &tnl_return_entry, return_entry)); 848 } 849 sal_memcpy(entry,return_entry,sizeof(return_entry)); 850 } else { 851 LOG_ERROR(BSL_LS_BCM_FLOW, 852 (BSL_META_U(unit, "Entry with same key already exists\n"))); 853 return BCM_E_EXISTS; 854 } 855 } else if (BCM_E_NOT_FOUND == rv) { 856 if (info->options & BCM_FLOW_MATCH_OPTION_REPLACE) { 857 LOG_ERROR(BSL_LS_BCM_FLOW, 858 (BSL_META_U(unit, "Entry doesn't exist\n"))); 859 return BCM_E_NOT_FOUND; 860 } else { 861 new_entry_add = TRUE; 862 } 863 } else { 864 return rv; 865 } 866 867 /* data fields: flex view uses PDD */ 868 action_type = 0; 869 if (info->valid_elements & BCM_FLOW_MATCH_FLOW_PORT_VALID) { 870 if (_BCM_FLOW_IS_FLEX_VIEW(info)) { 871 if (!SOC_MEM_FIELD_VALID(unit, mem, SVP_ACTION_SETf)) { 872 return BCM_E_PARAM; 873 } 874 if (new_entry_add == FALSE && replaced_vp != NULL) { 875 action_set = soc_mem_field32_get(unit, mem, entry, 876 SVP_ACTION_SETf); 877 *replaced_vp = soc_format_field32_get(unit, SVP_ACTION_SETfmt, 878 &action_set, SVPf); 879 } 880 action_set = 0; 881 soc_format_field32_set(unit, SVP_ACTION_SETfmt, 882 &action_set, SVPf, vp); 883 soc_mem_field32_set(unit, mem, entry, SVP_ACTION_SETf, action_set); 884 } else { 885 if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) { 886 soc_field_t svp_f = VXLAN_SIP__SVPf; 887 888 if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) { 889 svp_f = VXLAN_FLEX_IPV4_SIP__SVPf; 890 } 891 if (!SOC_MEM_FIELD_VALID(unit, mem, svp_f)) { 892 return BCM_E_PARAM; 893 } 894 if (new_entry_add == FALSE && replaced_vp != NULL) { 895 *replaced_vp = soc_mem_field32_get(unit, mem, entry, 896 svp_f); 897 } 898 soc_mem_field32_set(unit, mem, entry, svp_f, vp); 899 } else if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) { 900 if (!SOC_MEM_FIELD_VALID(unit, mem, L2GRE_SIP__SVPf)) { 901 return BCM_E_PARAM; 902 } 903 if (new_entry_add == FALSE && replaced_vp != NULL) { 904 *replaced_vp = soc_mem_field32_get(unit, mem, entry, 905 L2GRE_SIP__SVPf); 906 } 907 soc_mem_field32_set(unit, mem, entry, L2GRE_SIP__SVPf, vp); 908 } else { 909 if (!SOC_MEM_FIELD_VALID(unit, mem, XLATE__SOURCE_VPf)) { 910 return BCM_E_PARAM; 911 } 912 if (new_entry_add == FALSE && replaced_vp != NULL) { 913 *replaced_vp = soc_mem_field32_get(unit, mem, entry, 914 XLATE__SOURCE_VPf); 915 } 916 action_type = 1; /*SVP */ 917 soc_mem_field32_set(unit, mem, entry, XLATE__MPLS_ACTIONf, 918 action_type); 919 soc_mem_field32_set(unit, mem, entry, XLATE__SOURCE_VPf, vp); 920 } 921 } 922 } 923 924 /* get the replaced iif if replace action */ 925 if (info->valid_elements & BCM_FLOW_MATCH_IIF_VALID) { 926 if (_BCM_FLOW_IS_FLEX_VIEW(info)) { 927 if (!SOC_MEM_FIELD_VALID(unit, mem, L3_IIF_ACTION_SETf)) { 928 return BCM_E_PARAM; 929 } 930 if (new_entry_add == FALSE && replaced_iif != NULL) { 931 *replaced_iif = soc_mem_field32_get(unit, mem, entry, 932 L3_IIF_ACTION_SETf); 933 } 934 soc_mem_field32_set(unit, mem, entry, L3_IIF_ACTION_SETf, 935 info->intf_id); 936 } else { 937 if (!SOC_MEM_FIELD_VALID(unit, mem, XLATE__L3_IIFf)) { 938 return BCM_E_PARAM; 939 } 940 if (new_entry_add == FALSE && replaced_iif != NULL) { 941 *replaced_iif = soc_mem_field32_get(unit, mem, entry, 942 XLATE__L3_IIFf); 943 } 944 action_type |= 0x2; /* IIF */ 945 soc_mem_field32_set(unit, mem, entry, XLATE__MPLS_ACTIONf, 946 action_type); 947 soc_mem_field32_set(unit, mem, entry,XLATE__L3_IIFf, info->intf_id); 948 } 949 } 950 951 if (info->valid_elements & BCM_FLOW_MATCH_VPN_VALID) { 952 int vfi = 0; 953 BCM_IF_ERROR_RETURN( 954 (bcmi_esw_flow_vpn_is_valid(unit, info->vpn))); 955 _BCM_FLOW_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, info->vpn); 956 if (_BCM_FLOW_IS_FLEX_VIEW(info)) { 957 if (!SOC_MEM_FIELD_VALID(unit, mem, VFI_ACTION_SETf)) { 958 return BCM_E_PARAM; 959 } 960 soc_mem_field32_set(unit, mem, entry, VFI_ACTION_SETf, vfi); 961 } else { 962 if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) { 963 if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) { 964 if (!SOC_MEM_FIELD_VALID(unit, mem, VXLAN_FLEX__VFI_ACTION_SETf)) { 965 return BCM_E_PARAM; 966 } 967 soc_mem_field32_set(unit, mem, entry, VXLAN_FLEX__VFI_ACTION_SETf, vfi); 968 } else { 969 if (!SOC_MEM_FIELD_VALID(unit, mem, VXLAN_VN_ID__VFIf)) { 970 return BCM_E_PARAM; 971 } 972 soc_mem_field32_set(unit, mem, entry, VXLAN_VN_ID__VFIf, vfi); 973 } 974 } else if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) { 975 if (!SOC_MEM_FIELD_VALID(unit, mem, L2GRE_VPNID__VFIf)) { 976 return BCM_E_PARAM; 977 } 978 soc_mem_field32_set(unit, mem, entry, L2GRE_VPNID__VFIf, vfi); 979 } else { 980 if (!SOC_MEM_FIELD_VALID(unit, mem, XLATE__VFIf)) { 981 return BCM_E_PARAM; 982 } 983 soc_mem_field32_set(unit, mem, entry, XLATE__VFIf, vfi); 984 } 985 } 986 } 987 988 if (info->valid_elements & BCM_FLOW_MATCH_VLAN_VALID) { 989 if (_BCM_FLOW_IS_FLEX_VIEW(info)) { 990 if (SOC_MEM_FIELD_VALID(unit, mem, TAG_ACTION_SETf)) { 991 uint32 profile = 0; 992 993 action_set = 0; 994 action_set = soc_mem_field32_get(unit, mem, entry, 995 TAG_ACTION_SETf); 996 profile = soc_format_field32_get(unit, TAG_ACTION_SETfmt, 997 &action_set, ING_TAG_ACTION_PROFILE_IDXf); 998 _bcm_td3_def_vlan_profile_get(unit, &profile); 999 soc_format_field32_set(unit, TAG_ACTION_SETfmt, 1000 &action_set, ING_TAG_ACTION_PROFILE_IDXf, profile); 1001 soc_mem_field32_set(unit, mem, entry, TAG_ACTION_SETf, 1002 action_set); 1003 1004 action_set = 0; 1005 soc_format_field32_set(unit, OVLAN_ACTION_SETfmt, 1006 &action_set, VLAN_IDf, info->vlan); 1007 soc_mem_field32_set(unit, mem, entry, OVLAN_ACTION_SETf, 1008 action_set); 1009 } 1010 } else if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) { 1011 if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) { 1012 if (soc_mem_field_valid(unit, mem, VXLAN_FLEX__OVIDf)) { 1013 uint32 profile = 0; 1014 soc_field_t vlan_act_f = VXLAN_FLEX__ING_TAG_ACTION_PROFILE_IDXf; 1015 1016 if (soc_mem_field_valid(unit, mem, vlan_act_f)) { 1017 profile = soc_mem_field32_get(unit, mem, entry, vlan_act_f); 1018 _bcm_td3_def_vlan_profile_get(unit, &profile); 1019 soc_mem_field32_set(unit, mem, entry, vlan_act_f, profile); 1020 } 1021 soc_mem_field32_set(unit, mem, entry, VXLAN_FLEX__OVIDf, info->vlan); 1022 } 1023 } 1024 } 1025 } 1026 1027 if (info->valid_elements & BCM_FLOW_MATCH_FLEX_DATA_VALID) { 1028 uint32 data_ids[_BCM_FLOW_LOGICAL_FIELD_MAX]; 1029 uint32 cnt; 1030 rv = soc_flow_db_mem_view_field_list_get(unit, 1031 mem, 1032 SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA, 1033 _BCM_FLOW_LOGICAL_FIELD_MAX, data_ids, &cnt); 1034 BCM_IF_ERROR_RETURN(rv); 1035 for (i = 0; i < num_of_fields; i++) { 1036 for (j = 0; j < cnt; j++) { 1037 if (field[i].id == data_ids[j]) { 1038 soc_mem_field32_set(unit, mem, entry, 1039 field[i].id, field[i].value); 1040 break; 1041 } 1042 } 1043 } 1044 } 1045 1046 if (view_info->mem == L3_TUNNELm) { 1047 rv = _bcm_flow_match_mem_entry_to_term_entry(unit, mem, 1048 &tnl_entry, entry); 1049 if (BCM_SUCCESS(rv)) { 1050 rv = soc_tunnel_term_insert(unit, &tnl_entry, (uint32 *)&index); 1051 } 1052 } else { /* hash */ 1053 if (new_entry_add) { 1054 rv = soc_mem_insert(unit, mem, MEM_BLOCK_ALL, entry); 1055 } else { 1056 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, entry); 1057 } 1058 } 1059 BCM_IF_ERROR_RETURN(rv); 1060 return rv; 1061 } 1062 1063 /* 1064 * Function: 1065 * _bcm_flow_match_entry_get 1066 * Purpose: 1067 * Get the flow Match Entry based on the given key 1068 * Parameters: 1069 * unit - (IN) Device Number 1070 * info - (OUT) flow_match configuration info 1071 * field - (OUT) array of logical fields 1072 * num_of_fields -(IN) the size of the above array 1073 * mem - (IN) memory id 1074 * entry - (IN) point to the match entry 1075 * Returns: 1076 * BCM_E_XXX 1077 */ 1078 1079 STATIC int 1080 _bcm_flow_match_entry_data_get(int unit, 1081 bcm_flow_match_config_t *info, 1082 bcm_flow_logical_field_t *field, 1083 int num_of_fields, 1084 soc_mem_t mem, 1085 uint32 *entry) 1086 { 1087 int rv = BCM_E_NONE; 1088 int i; 1089 int j; 1090 int vp = 0; 1091 int vfi = 0; 1092 _bcm_flow_bookkeeping_t *flow_info; 1093 uint32 action_set; 1094 1095 flow_info = FLOW_INFO(unit); 1096 1097 /* data fields: flex view uses PDD */ 1098 if (_BCM_FLOW_IS_FLEX_VIEW(info)) { 1099 if (SOC_MEM_FIELD_VALID(unit,mem,SVP_ACTION_SETf)) { 1100 action_set = soc_mem_field32_get(unit, mem, entry, 1101 SVP_ACTION_SETf); 1102 vp = soc_format_field32_get(unit, SVP_ACTION_SETfmt, 1103 &action_set, SVPf); 1104 } 1105 if (SOC_MEM_FIELD_VALID(unit, mem, OVLAN_ACTION_SETf)) { 1106 action_set = soc_mem_field32_get(unit, mem, entry, 1107 OVLAN_ACTION_SETf); 1108 info->vlan = soc_format_field32_get(unit, OVLAN_ACTION_SETfmt, 1109 &action_set, VLAN_IDf); 1110 } 1111 } else { 1112 if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) { 1113 if (soc_mem_field_valid(unit, mem, VXLAN_SIP__SVPf)) { 1114 vp = soc_mem_field32_get(unit, mem, entry, VXLAN_SIP__SVPf); 1115 } 1116 if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) { 1117 if (soc_mem_field_valid(unit, mem, VXLAN_FLEX_IPV4_SIP__SVPf)) { 1118 vp = soc_mem_field32_get(unit, mem, entry, VXLAN_FLEX_IPV4_SIP__SVPf); 1119 } 1120 if (soc_mem_field_valid(unit, mem, VXLAN_FLEX__OVIDf)) { 1121 info->vlan = soc_mem_field32_get(unit, mem, entry, VXLAN_FLEX__OVIDf); 1122 } 1123 } 1124 } else if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) { 1125 vp = soc_mem_field32_get(unit, mem, entry, L2GRE_SIP__SVPf); 1126 } else { 1127 if (SOC_MEM_FIELD_VALID(unit,mem,XLATE__SOURCE_VPf)) { 1128 vp = soc_mem_field32_get(unit, mem, entry, XLATE__SOURCE_VPf); 1129 } 1130 } 1131 } 1132 if (flow_info->vp_ref_cnt[vp]) { 1133 _SHR_GPORT_FLOW_PORT_ID_SET(info->flow_port,vp); 1134 info->valid_elements |= BCM_FLOW_MATCH_FLOW_PORT_VALID; 1135 } 1136 if (_BCM_FLOW_IS_FLEX_VIEW(info)) { 1137 if (SOC_MEM_FIELD_VALID(unit,mem,L3_IIF_ACTION_SETf)) { 1138 info->intf_id = soc_mem_field32_get(unit, mem, entry, 1139 L3_IIF_ACTION_SETf); 1140 } 1141 } else { 1142 if (SOC_MEM_FIELD_VALID(unit,mem,XLATE__L3_IIFf)) { 1143 info->intf_id = soc_mem_field32_get(unit, mem, entry, 1144 XLATE__L3_IIFf); 1145 } 1146 } 1147 if (flow_info->iif_ref_cnt[info->intf_id]) { 1148 info->valid_elements |= BCM_FLOW_MATCH_IIF_VALID; 1149 } 1150 1151 if (_BCM_FLOW_IS_FLEX_VIEW(info)) { 1152 if (SOC_MEM_FIELD_VALID(unit,mem,VFI_ACTION_SETf)) { 1153 vfi = soc_mem_field32_get(unit, mem, entry, VFI_ACTION_SETf); 1154 } 1155 } else { 1156 if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) { 1157 if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) { 1158 if (soc_mem_field_valid(unit, mem, VXLAN_FLEX__VFI_ACTION_SETf)) { 1159 vfi = soc_mem_field32_get(unit, mem, entry, VXLAN_FLEX__VFI_ACTION_SETf); 1160 } 1161 } 1162 if (soc_mem_field_valid(unit, mem, VXLAN_VN_ID__VFIf)) { 1163 vfi = soc_mem_field32_get(unit, mem, entry, VXLAN_VN_ID__VFIf); 1164 } 1165 } else if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) { 1166 vfi = soc_mem_field32_get(unit, mem, entry, L2GRE_VPNID__VFIf); 1167 } else { 1168 if (SOC_MEM_FIELD_VALID(unit,mem,XLATE__VFIf)) { 1169 vfi = soc_mem_field32_get(unit, mem, entry, XLATE__VFIf); 1170 } 1171 } 1172 } 1173 if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeFlow)) { 1174 info->valid_elements |= BCM_FLOW_MATCH_VPN_VALID; 1175 } 1176 _BCM_FLOW_VPN_SET(info->vpn,_BCM_VPN_TYPE_VFI,vfi); 1177 1178 if (_BCM_FLOW_IS_FLEX_VIEW(info) && (field != NULL)) { 1179 uint32 data_ids[_BCM_FLOW_LOGICAL_FIELD_MAX]; 1180 uint32 cnt; 1181 rv = soc_flow_db_mem_view_field_list_get(unit, 1182 mem, 1183 SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA, 1184 _BCM_FLOW_LOGICAL_FIELD_MAX, data_ids, &cnt); 1185 BCM_IF_ERROR_RETURN(rv); 1186 for (i = 0; i < num_of_fields; i++) { 1187 for (j = 0; j < cnt; j++) { 1188 if (field[i].id == data_ids[j]) { 1189 field[i].value = soc_mem_field32_get(unit, mem, entry, 1190 field[i].id); 1191 break; 1192 } 1193 } 1194 } 1195 } 1196 1197 return BCM_E_NONE; 1198 } 1199 /* 1200 * Function: 1201 * _bcm_flow_match_entry_get 1202 * Purpose: 1203 * Get the flow Match Entry based on the given key 1204 * Parameters: 1205 * unit - (IN) Device Number 1206 * info - (IN/OUT) flow_match configuration info 1207 * field - (IN/OUT) array of logical fields 1208 * num_of_fields -(IN) the size of the above array 1209 * mem - (IN) memory id 1210 * entry - (IN) point to the match entry 1211 * Returns: 1212 * BCM_E_XXX 1213 * Parameters: 1214 * IN : Unit 1215 * IN : entry 1216 * Returns: 1217 * BCM_E_XXX 1218 */ 1219 1220 STATIC int 1221 _bcm_flow_match_entry_get(int unit, 1222 bcm_flow_match_config_t *info, 1223 bcm_flow_logical_field_t *field, 1224 int num_of_fields, 1225 soc_flow_db_mem_view_info_t *view_info, 1226 uint32 *entry) 1227 { 1228 int index = -1; 1229 uint32 return_entry[_QUAD_ENTRY_MAX]; 1230 int rv = BCM_E_NONE; 1231 soc_mem_t mem; 1232 soc_tunnel_term_t tnl_entry; 1233 soc_tunnel_term_t tnl_return_entry; 1234 1235 if (view_info->mem == L3_TUNNELm) { 1236 rv = _bcm_flow_match_mem_entry_to_term_entry(unit, view_info->mem, 1237 &tnl_entry, entry); 1238 BCM_IF_ERROR_RETURN(rv); 1239 rv = soc_tunnel_term_match(unit,&tnl_entry, &tnl_return_entry, &index); 1240 rv = _bcm_flow_match_term_entry_to_mem_entry(unit, view_info->mem, 1241 &tnl_return_entry, return_entry); 1242 BCM_IF_ERROR_RETURN(rv); 1243 } else { 1244 SOC_IF_ERROR_RETURN(soc_mem_search(unit, view_info->mem, 1245 MEM_BLOCK_ANY, &index, entry, return_entry, 0)); 1246 } 1247 mem = _BCM_FLOW_IS_FLEX_VIEW(info)? view_info->mem_view_id: 1248 view_info->mem; 1249 rv = _bcm_flow_match_entry_data_get(unit,info,field,num_of_fields, 1250 mem,return_entry); 1251 BCM_IF_ERROR_RETURN(rv); 1252 return rv; 1253 } 1254 1255 /* 1256 * Function: 1257 * _bcm_flow_match_entry_key_set 1258 * Purpose: 1259 * Set flow Match Entry Key 1260 * Parameters: 1261 * unit - (IN) Device Number 1262 * info - (IN) flow_match configuration info 1263 * field - (IN) array of logical fields 1264 * num_of_fields -(IN) the size of the above array 1265 * mem - (IN) memory id 1266 * entry - (IN) point to the match entry 1267 * Returns: 1268 * BCM_E_XXX 1269 */ 1270 1271 STATIC 1272 int _bcm_flow_match_entry_key_set(int unit, 1273 bcm_flow_match_config_t *info, 1274 bcm_flow_logical_field_t *field, 1275 int num_of_fields, 1276 soc_mem_t mem_id, 1277 uint32 *entry) 1278 { 1279 int i; 1280 int j; 1281 bcm_module_t mod_out = -1; 1282 bcm_port_t port_out = -1; 1283 bcm_trunk_t trunk_id = -1; 1284 bcm_port_t gport_id = -1; 1285 soc_field_t ovid_f; 1286 soc_field_t ivid_f; 1287 soc_field_t sip_f; 1288 soc_field_t vnid_f; 1289 soc_field_t t_f; 1290 soc_field_t tgid_f; 1291 soc_field_t module_id_f; 1292 soc_field_t port_num_f; 1293 soc_field_t lbl_f; 1294 int rv; 1295 1296 /* validate parameters */ 1297 1298 /* XXX check if ELAN/ELINE handle differently */ 1299 1300 if (_BCM_FLOW_IS_FLEX_VIEW(info)) { 1301 t_f = Tf; 1302 tgid_f = TGIDf; 1303 module_id_f = MODULE_IDf; 1304 port_num_f = PORT_NUMf; 1305 ovid_f = OVIDf; 1306 ivid_f = IVIDf; 1307 } else { 1308 t_f = XLATE__Tf; 1309 tgid_f = XLATE__TGIDf; 1310 module_id_f = XLATE__MODULE_IDf; 1311 port_num_f = XLATE__PORT_NUMf; 1312 ovid_f = XLATE__OVIDf; 1313 ivid_f = XLATE__IVIDf; 1314 } 1315 if (info->valid_elements & BCM_FLOW_MATCH_PORT_VALID) { 1316 rv = _bcm_esw_gport_resolve(unit, info->port, &mod_out, 1317 &port_out, &trunk_id, &gport_id); 1318 BCM_IF_ERROR_RETURN(rv); 1319 } 1320 if (info->criteria == BCM_FLOW_MATCH_CRITERIA_PORT_VLAN || 1321 info->criteria == BCM_FLOW_MATCH_CRITERIA_PORT_INNER_VLAN || 1322 info->criteria == BCM_FLOW_MATCH_CRITERIA_PORT_VLAN_STACKED || 1323 info->criteria == BCM_FLOW_MATCH_CRITERIA_VLAN_PRI) { 1324 if (info->valid_elements & BCM_FLOW_MATCH_PORT_VALID) { 1325 if (BCM_GPORT_IS_TRUNK(info->port)) { 1326 if (!(SOC_MEM_FIELD_VALID(unit, mem_id, t_f) && 1327 SOC_MEM_FIELD_VALID(unit, mem_id, tgid_f))) { 1328 return BCM_E_PARAM; 1329 } 1330 soc_mem_field32_set(unit,mem_id, entry, t_f, 1); 1331 soc_mem_field32_set(unit,mem_id, entry, tgid_f, trunk_id); 1332 } else { 1333 if (mod_out != -1) { 1334 if (!SOC_MEM_FIELD_VALID(unit, mem_id, module_id_f)) { 1335 return BCM_E_PARAM; 1336 } 1337 1338 soc_mem_field32_set(unit, mem_id, entry, module_id_f, 1339 mod_out); 1340 } 1341 if (!SOC_MEM_FIELD_VALID(unit, mem_id, port_num_f)) { 1342 return BCM_E_PARAM; 1343 } 1344 soc_mem_field32_set(unit,mem_id, entry, port_num_f, port_out); 1345 } 1346 } 1347 if (!SOC_MEM_FIELD_VALID(unit,mem_id,SOURCE_TYPEf)) { 1348 return BCM_E_PARAM; 1349 } 1350 soc_mem_field32_set(unit, mem_id, entry, SOURCE_TYPEf, 1); 1351 } 1352 1353 if (info->criteria == BCM_FLOW_MATCH_CRITERIA_PORT_VLAN ) { 1354 if (!BCM_VLAN_VALID(info->vlan)) { 1355 LOG_ERROR(BSL_LS_BCM_FLOW, 1356 (BSL_META_U(unit, "Invalid vlan\n"))); 1357 return BCM_E_PARAM; 1358 } 1359 if (!SOC_MEM_FIELD_VALID(unit, mem_id, ovid_f)) { 1360 return BCM_E_PARAM; 1361 } 1362 soc_mem_field32_set(unit,mem_id, entry, ovid_f, info->vlan); 1363 1364 } else if (info->criteria == BCM_FLOW_MATCH_CRITERIA_PORT_INNER_VLAN) { 1365 if (!BCM_VLAN_VALID(info->inner_vlan)) { 1366 LOG_ERROR(BSL_LS_BCM_FLOW, 1367 (BSL_META_U(unit, "Invalid inner vlan\n"))); 1368 return BCM_E_PARAM; 1369 } 1370 if (!SOC_MEM_FIELD_VALID(unit, mem_id, ivid_f)) { 1371 return BCM_E_PARAM; 1372 } 1373 soc_mem_field32_set(unit,mem_id, entry, ivid_f, info->inner_vlan); 1374 1375 } else if (info->criteria == BCM_FLOW_MATCH_CRITERIA_PORT_VLAN_STACKED) { 1376 if (!BCM_VLAN_VALID(info->vlan) || 1377 !BCM_VLAN_VALID(info->inner_vlan)) { 1378 LOG_ERROR(BSL_LS_BCM_FLOW, 1379 (BSL_META_U(unit, "Invalid either outer vlan or inner vlan\n"))); 1380 return BCM_E_PARAM; 1381 } 1382 1383 if (!(SOC_MEM_FIELD_VALID(unit, mem_id, ovid_f) && 1384 SOC_MEM_FIELD_VALID(unit, mem_id, ivid_f))) { 1385 return BCM_E_PARAM; 1386 } 1387 soc_mem_field32_set(unit,mem_id, entry, ovid_f, info->vlan); 1388 soc_mem_field32_set(unit,mem_id, entry, ivid_f, info->inner_vlan); 1389 1390 } else if (info->criteria == BCM_FLOW_MATCH_CRITERIA_VLAN_PRI) { 1391 1392 /* match_vlan : Bits 12-15 contains VLAN_PRI + CFI, vlan=BCM_E_NONE */ 1393 if (!SOC_MEM_FIELD_VALID(unit, mem_id, OTAGf)) { 1394 return BCM_E_PARAM; 1395 } 1396 soc_mem_field32_set(unit,mem_id, entry, OTAGf, info->vlan); 1397 1398 } else if (info->criteria == BCM_FLOW_MATCH_CRITERIA_SIP) { 1399 if (_BCM_FLOW_IS_FLEX_VIEW(info)) { 1400 ovid_f = OVIDf; 1401 if (SOC_MEM_FIELD_VALID(unit,mem_id,IPV4__SIPf)) { 1402 sip_f = IPV4__SIPf; 1403 } else { 1404 sip_f = SIPf; 1405 } 1406 } else { 1407 if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) { 1408 ovid_f = VXLAN_SIP__OVIDf; 1409 sip_f = VXLAN_SIP__SIPf; 1410 if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) { 1411 sip_f = VXLAN_FLEX_IPV4_SIP__SIPf; 1412 } 1413 } else if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) { 1414 sip_f = L2GRE_SIP__SIPf; 1415 } else { 1416 LOG_ERROR(BSL_LS_BCM_FLOW, 1417 (BSL_META_U(unit, "Invalid legacy flow handle\n"))); 1418 return BCM_E_PARAM; 1419 } 1420 } 1421 if (soc_feature(unit, soc_feature_vrf_aware_vxlan_termination) && 1422 (info->valid_elements & BCM_FLOW_MATCH_VLAN_VALID)) { 1423 VLAN_CHK_ID(unit,info->vlan); 1424 if (!SOC_MEM_FIELD_VALID(unit, mem_id, ovid_f)) { 1425 return BCM_E_PARAM; 1426 } 1427 soc_mem_field32_set(unit,mem_id, entry, ovid_f, info->vlan); 1428 } 1429 if (!SOC_MEM_FIELD_VALID(unit, mem_id, sip_f)) { 1430 return BCM_E_PARAM; 1431 } 1432 soc_mem_field32_set(unit,mem_id, entry, sip_f, info->sip); 1433 1434 } else if (info->criteria == BCM_FLOW_MATCH_CRITERIA_VN_ID || 1435 info->criteria == BCM_FLOW_MATCH_CRITERIA_SIP_VNID) { 1436 1437 if (_BCM_FLOW_IS_FLEX_VIEW(info)) { 1438 ovid_f = OVIDf; 1439 vnid_f = VNIDf; 1440 if (SOC_MEM_FIELD_VALID(unit,mem_id,IPV4__SIPf)) { 1441 sip_f = IPV4__SIPf; 1442 } else { 1443 sip_f = SIPf; 1444 } 1445 } else { 1446 if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) { 1447 if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) { 1448 ovid_f = VXLAN_FLEX__OVIDf; 1449 sip_f = VXLAN_FLEX__SIPf; 1450 vnid_f = VXLAN_FLEX__VNIDf; 1451 } else { 1452 ovid_f = VXLAN_VN_ID__OVIDf; 1453 sip_f = VXLAN_VN_ID__SIPf; 1454 vnid_f = VXLAN_VN_ID__VN_IDf; 1455 } 1456 } else if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) { 1457 vnid_f = L2GRE_VPNID__VPNIDf; 1458 sip_f = L2GRE_VPNID__SIPf; 1459 } else { 1460 LOG_ERROR(BSL_LS_BCM_FLOW, 1461 (BSL_META_U(unit, "Invalid legacy flow handle\n"))); 1462 return BCM_E_PARAM; 1463 } 1464 } 1465 if (!SOC_MEM_FIELD_VALID(unit, mem_id, vnid_f)) { 1466 return BCM_E_PARAM; 1467 } 1468 soc_mem_field32_set(unit, mem_id, entry, vnid_f, info->vnid); 1469 if (info->criteria == BCM_FLOW_MATCH_CRITERIA_SIP_VNID) { 1470 if (!SOC_MEM_FIELD_VALID(unit, mem_id, sip_f)) { 1471 return BCM_E_PARAM; 1472 } 1473 soc_mem_field32_set(unit,mem_id, entry, sip_f, info->sip); 1474 } 1475 1476 if (soc_feature(unit,soc_feature_vrf_aware_vxlan_termination) && 1477 (info->valid_elements & BCM_FLOW_MATCH_VLAN_VALID)) { 1478 VLAN_CHK_ID(unit, info->vlan); 1479 if (!SOC_MEM_FIELD_VALID(unit, mem_id, ovid_f)) { 1480 return BCM_E_PARAM; 1481 } 1482 soc_mem_field32_set(unit,mem_id, entry, ovid_f, info->vlan); 1483 } 1484 } else if (info->criteria == BCM_FLOW_MATCH_CRITERIA_MPLS_LABEL) { 1485 if (_BCM_FLOW_IS_FLEX_VIEW(info)) { 1486 if (SOC_MEM_FIELD_VALID(unit, mem_id, MPLS_LABEL_1f)) { 1487 lbl_f = MPLS_LABEL_1f; 1488 } else if (SOC_MEM_FIELD_VALID(unit, mem_id, MPLS_LABEL_2f)) { 1489 lbl_f = MPLS_LABEL_2f; 1490 } else { 1491 LOG_ERROR(BSL_LS_BCM_FLOW, 1492 (BSL_META_U(unit, "mpls_label field not found\n"))); 1493 return BCM_E_PARAM; 1494 } 1495 soc_mem_field32_set(unit,mem_id, entry, lbl_f, info->mpls_label); 1496 } else { 1497 LOG_ERROR(BSL_LS_BCM_FLOW, 1498 (BSL_META_U(unit, "mpls_label only supported for flex view\n"))); 1499 return BCM_E_PARAM; 1500 } 1501 } else if (info->criteria == BCM_FLOW_MATCH_CRITERIA_FLEX) { 1502 uint32 key_ids[_BCM_FLOW_LOGICAL_FIELD_MAX]; 1503 uint32 cnt; 1504 1505 ovid_f = OVIDf; 1506 vnid_f = VNIDf; 1507 1508 rv = soc_flow_db_mem_view_field_list_get(unit, 1509 mem_id, 1510 SOC_FLOW_DB_FIELD_TYPE_LOGICAL_KEY, 1511 _BCM_FLOW_LOGICAL_FIELD_MAX, key_ids, &cnt); 1512 if (rv != SOC_E_NONE && rv != SOC_E_NOT_FOUND) { 1513 return rv; 1514 } 1515 if (rv == SOC_E_NONE) { 1516 for (i = 0; i < num_of_fields; i++) { 1517 for (j = 0; j < cnt; j++) { 1518 if (field[i].id == key_ids[j]) { 1519 soc_mem_field32_set(unit, mem_id, entry, 1520 field[i].id, field[i].value); 1521 break; 1522 } 1523 } 1524 } 1525 } 1526 rv = SOC_E_NONE; 1527 if (info->valid_elements & BCM_FLOW_MATCH_VNID_VALID) { 1528 if (!SOC_MEM_FIELD_VALID(unit,mem_id,vnid_f)) { 1529 return SOC_E_PARAM; 1530 } 1531 soc_mem_field32_set(unit,mem_id, entry, vnid_f, info->vnid); 1532 } 1533 if (info->valid_elements & BCM_FLOW_MATCH_VLAN_VALID) { 1534 if (!SOC_MEM_FIELD_VALID(unit,mem_id,ovid_f)) { 1535 return SOC_E_PARAM; 1536 } 1537 soc_mem_field32_set(unit,mem_id, entry, ovid_f, info->vlan); 1538 } 1539 if (info->valid_elements & BCM_FLOW_MATCH_INNER_VLAN_VALID) { 1540 if (!SOC_MEM_FIELD_VALID(unit,mem_id,ivid_f)) { 1541 return SOC_E_PARAM; 1542 } 1543 soc_mem_field32_set(unit,mem_id, entry, ivid_f, info->inner_vlan); 1544 } 1545 if (info->valid_elements & BCM_FLOW_MATCH_PORT_VALID) { 1546 if (BCM_GPORT_IS_TRUNK(info->port)) { 1547 if (!(SOC_MEM_FIELD_VALID(unit,mem_id,t_f) && 1548 SOC_MEM_FIELD_VALID(unit,mem_id,tgid_f))) { 1549 if (SOC_MEM_FIELD_VALID(unit,mem_id,SGLP_16f && 1550 SOC_MEM_FIELD_VALID(unit,mem_id,SGLP_15_0f))) { 1551 t_f = SGLP_16f; 1552 tgid_f = SGLP_15_0f; 1553 } else { 1554 return SOC_E_PARAM; 1555 } 1556 } 1557 1558 soc_mem_field32_set(unit,mem_id, entry, t_f, 1); 1559 soc_mem_field32_set(unit,mem_id, entry, tgid_f, trunk_id); 1560 } else { 1561 if ((SOC_MEM_FIELD_VALID(unit,mem_id,module_id_f) && 1562 SOC_MEM_FIELD_VALID(unit,mem_id,port_num_f))) { 1563 soc_mem_field32_set(unit,mem_id, entry, module_id_f, 1564 mod_out); 1565 soc_mem_field32_set(unit,mem_id, entry, port_num_f, 1566 port_out); 1567 } else if (SOC_MEM_FIELD_VALID(unit,mem_id,SGPPf)) { 1568 soc_mem_field32_set(unit,mem_id, entry, SGPPf, 1569 port_out | (mod_out << 8)); 1570 } else if (SOC_MEM_FIELD_VALID(unit,mem_id,SGLP_15_0f)) { 1571 soc_mem_field32_set(unit,mem_id, entry, SGLP_15_0f, 1572 port_out | (mod_out << 8)); 1573 } else { 1574 return SOC_E_PARAM; 1575 } 1576 } 1577 } 1578 if (info->valid_elements & BCM_FLOW_MATCH_SIP_VALID) { 1579 if (SOC_MEM_FIELD_VALID(unit,mem_id,SIPf)) { 1580 sip_f = SIPf; 1581 } else if (SOC_MEM_FIELD_VALID(unit,mem_id,IPV4__SIPf)) { 1582 sip_f = IPV4__SIPf; 1583 } else { 1584 return SOC_E_PARAM; 1585 } 1586 soc_mem_field32_set(unit,mem_id, entry, sip_f, info->sip); 1587 } 1588 if (info->valid_elements & BCM_FLOW_MATCH_SIP_V6_VALID) { 1589 if (!SOC_MEM_FIELD_VALID(unit,mem_id,IPV6__SIPf)) { 1590 return SOC_E_PARAM; 1591 } 1592 soc_mem_ip6_addr_set(unit, mem_id, entry,IPV6__SIPf, 1593 info->sip6, 0); 1594 } 1595 if (info->valid_elements & BCM_FLOW_MATCH_DIP_VALID) { 1596 if (!SOC_MEM_FIELD_VALID(unit,mem_id,IPV4__DIPf)) { 1597 return SOC_E_PARAM; 1598 } 1599 soc_mem_field32_set(unit,mem_id, entry, IPV4__DIPf, info->dip); 1600 } 1601 if (info->valid_elements & BCM_FLOW_MATCH_DIP_V6_VALID) { 1602 if (!SOC_MEM_FIELD_VALID(unit,mem_id,IPV6__DIPf)) { 1603 return SOC_E_PARAM; 1604 } 1605 soc_mem_ip6_addr_set(unit, mem_id, entry,IPV6__DIPf, info->dip6, 0); 1606 } 1607 if (info->valid_elements & BCM_FLOW_MATCH_PROTOCOL_VALID) { 1608 if (!SOC_MEM_FIELD_VALID(unit,mem_id,IPV4__PROTOCOLf)) { 1609 return SOC_E_PARAM; 1610 } 1611 soc_mem_field32_set(unit,mem_id, entry, IPV4__PROTOCOLf, 1612 info->protocol); 1613 } 1614 if (info->valid_elements & BCM_FLOW_MATCH_UDP_SRC_PORT_VALID) { 1615 if (!SOC_MEM_FIELD_VALID(unit,mem_id,L4_SRC_PORTf)) { 1616 return SOC_E_PARAM; 1617 } 1618 soc_mem_field32_set(unit,mem_id, entry, L4_SRC_PORTf, 1619 info->udp_src_port); 1620 } 1621 if (info->valid_elements & BCM_FLOW_MATCH_UDP_DST_PORT_VALID) { 1622 if (!SOC_MEM_FIELD_VALID(unit,mem_id,L4_DST_PORTf)) { 1623 return SOC_E_PARAM; 1624 } 1625 soc_mem_field32_set(unit,mem_id, entry, L4_DST_PORTf, 1626 info->udp_dst_port); 1627 } 1628 } 1629 return BCM_E_NONE; 1630 } 1631 1632 /* 1633 * Function: 1634 * _bcm_flow_match_port_ctrl 1635 * Purpose: 1636 * Perform SET/GET/DELETE actions for port match criteria 1637 * Parameters: 1638 * unit - (IN) Device Number 1639 * info - (IN) flow_match configuration info 1640 * action - (IN) action id 1641 * Returns: 1642 * BCM_E_XXX 1643 */ 1644 1645 int _bcm_flow_match_port_ctrl( 1646 int unit, 1647 bcm_flow_match_config_t *info, 1648 int action, 1649 int *replaced_vp, 1650 int *replaced_iif) 1651 { 1652 bcm_module_t mod_out = -1; 1653 bcm_port_t port_out = -1; 1654 bcm_trunk_t trunk_id = -1; 1655 int gport_id=-1; 1656 int src_trk_idx=0; /*Source Trunk table index.*/ 1657 int vp = 0; 1658 int rv = BCM_E_NONE; 1659 uint32 port_op = 0; 1660 source_trunk_map_table_entry_t stm_entry; 1661 soc_mem_t mem; 1662 int old_vp = 0; 1663 int old_iif = 0; 1664 1665 if (replaced_vp != NULL) { 1666 *replaced_vp = 0; 1667 } 1668 if (replaced_iif != NULL) { 1669 *replaced_iif = 0; 1670 } 1671 1672 if (action == _BCM_FLOW_MATCH_PORT_CTRL_SET) { 1673 port_op = 1; 1674 vp = _SHR_GPORT_FLOW_PORT_ID_GET(info->flow_port); 1675 } 1676 1677 BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, info->port, 1678 &mod_out, &port_out, &trunk_id, &gport_id)); 1679 if (BCM_GPORT_IS_TRUNK(info->port)) { 1680 if (action == _BCM_FLOW_MATCH_PORT_CTRL_SET) { 1681 BCM_IF_ERROR_RETURN(_bcm_flow_match_trunk_add(unit, trunk_id, 1682 info,replaced_vp,replaced_iif)); 1683 } else if (action == _BCM_FLOW_MATCH_PORT_CTRL_DELETE) { 1684 BCM_IF_ERROR_RETURN(_bcm_flow_match_trunk_delete(unit, trunk_id, 1685 info,replaced_vp,replaced_iif)); 1686 } else { 1687 BCM_IF_ERROR_RETURN(_bcm_flow_match_trunk_get(unit, trunk_id, 1688 info)); 1689 } 1690 } else { 1691 int is_local; 1692 1693 BCM_IF_ERROR_RETURN 1694 ( _bcm_esw_modid_is_local(unit, mod_out, &is_local)); 1695 1696 /* Get index to source trunk map table */ 1697 BCM_IF_ERROR_RETURN( 1698 _bcm_esw_src_mod_port_table_index_get(unit, mod_out, 1699 port_out, &src_trk_idx)); 1700 1701 mem = SOURCE_TRUNK_MAP_TABLEm; 1702 if (action != _BCM_FLOW_MATCH_PORT_CTRL_GET) { 1703 soc_mem_lock(unit,mem); 1704 } 1705 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, src_trk_idx, &stm_entry); 1706 old_vp = soc_mem_field32_get(unit, mem, &stm_entry, SOURCE_VPf); 1707 old_iif = soc_mem_field32_get(unit, mem, &stm_entry, L3_IIFf); 1708 if (rv == SOC_E_NONE) { 1709 if (action == _BCM_FLOW_MATCH_PORT_CTRL_SET) { 1710 /* Enable SVP Mode */ 1711 if (info->valid_elements & BCM_FLOW_MATCH_FLOW_PORT_VALID) { 1712 if (replaced_vp && old_vp && (old_vp != vp)) { 1713 /* replace action */ 1714 *replaced_vp = old_vp; 1715 } 1716 soc_mem_field32_set(unit, mem, &stm_entry, SOURCE_VPf, 1717 vp); 1718 } 1719 if (info->valid_elements & BCM_FLOW_MATCH_IIF_VALID) { 1720 if (replaced_iif && old_iif && (old_iif != info->intf_id)) { 1721 /* replace action */ 1722 *replaced_iif = old_iif; 1723 } 1724 soc_mem_field32_set(unit, mem, &stm_entry, L3_IIFf, 1725 info->intf_id); 1726 } 1727 } else if (action == _BCM_FLOW_MATCH_PORT_CTRL_DELETE) { 1728 if (replaced_vp) { 1729 *replaced_vp = old_vp; 1730 } 1731 if (replaced_iif) { 1732 *replaced_iif = old_iif; 1733 } 1734 soc_mem_field32_set(unit, mem, &stm_entry, SOURCE_VPf, 0); 1735 soc_mem_field32_set(unit, mem, &stm_entry, L3_IIFf, 0); 1736 } else { /* _BCM_FLOW_MATCH_PORT_CTRL_GET */ 1737 _SHR_GPORT_FLOW_PORT_ID_SET(info->flow_port,old_vp); 1738 info->intf_id = old_iif; 1739 } 1740 } 1741 if (action != _BCM_FLOW_MATCH_PORT_CTRL_GET) { 1742 if (rv == SOC_E_NONE) { 1743 rv = soc_mem_write(unit, mem, MEM_BLOCK_ANY, src_trk_idx, 1744 &stm_entry); 1745 } 1746 soc_mem_unlock(unit,mem); 1747 } 1748 BCM_IF_ERROR_RETURN(rv); 1749 1750 if (is_local) { 1751 if (action != _BCM_FLOW_MATCH_PORT_CTRL_GET) { 1752 rv = _bcm_esw_port_tab_set( 1753 unit, info->port, _BCM_CPU_TABS_NONE, 1754 PORT_OPERATIONf, port_op); /* L2_SVP */ 1755 BCM_IF_ERROR_RETURN(rv); 1756 } 1757 1758 if (action == _BCM_FLOW_MATCH_PORT_CTRL_SET) { 1759 /* Set TAG_ACTION_PROFILE_PTR */ 1760 rv = _bcm_flow_match_untagged_profile_set( 1761 unit, info->port); 1762 } else if (action == _BCM_FLOW_MATCH_PORT_CTRL_DELETE) { 1763 rv = _bcm_flow_match_untagged_profile_reset(unit,info->port); 1764 } 1765 BCM_IF_ERROR_RETURN(rv); 1766 } 1767 } 1768 return rv; 1769 } 1770 1771 /* 1772 * Function: 1773 * _bcm_flow_match_key_set 1774 * Purpose: 1775 * Set the key for a flow match entry 1776 * Parameters: 1777 * unit - (IN) Device Number 1778 * info - (IN) flow_match configuration info 1779 * field - (IN) array of logical fields 1780 * num_of_fields -(IN) the size of the above array 1781 * entry - (IN) point to the match entry 1782 * mem - (IN) memory id 1783 * Returns: 1784 * BCM_E_XXX 1785 */ 1786 1787 STATIC 1788 int _bcm_flow_match_key_set( 1789 int unit, 1790 bcm_flow_match_config_t *info, 1791 bcm_flow_logical_field_t *field, 1792 uint32 num_of_fields, 1793 uint32 *entry, 1794 soc_flow_db_mem_view_info_t *view_info) 1795 { 1796 int rv; 1797 soc_mem_t mem_view_id; 1798 uint32 key_type = 0; 1799 soc_mem_t mem_id = 0; 1800 soc_flow_db_mem_view_info_t vinfo; 1801 1802 if (view_info == NULL) { 1803 return BCM_E_INTERNAL; 1804 } 1805 1806 if (info->criteria <= BCM_FLOW_MATCH_CRITERIA_INVALID || 1807 info->criteria >= BCM_FLOW_MATCH_CRITERIA_COUNT) { 1808 return BCM_E_PARAM; 1809 } 1810 1811 /* validate parameters */ 1812 1813 if (info->criteria == BCM_FLOW_MATCH_CRITERIA_PORT_VLAN) { 1814 mem_id = VLAN_XLATE_1_DOUBLEm; /* fixed view */ 1815 key_type = TR_VLXLT_HASH_KEY_TYPE_OVID; 1816 } else if (info->criteria == BCM_FLOW_MATCH_CRITERIA_PORT_INNER_VLAN) { 1817 mem_id = VLAN_XLATE_1_DOUBLEm; 1818 key_type = TR_VLXLT_HASH_KEY_TYPE_IVID; 1819 } else if (info->criteria == BCM_FLOW_MATCH_CRITERIA_PORT_VLAN_STACKED) { 1820 mem_id = VLAN_XLATE_1_DOUBLEm; 1821 key_type = TR_VLXLT_HASH_KEY_TYPE_IVID_OVID; 1822 } else if (info->criteria == BCM_FLOW_MATCH_CRITERIA_VLAN_PRI) { 1823 mem_id = VLAN_XLATE_1_DOUBLEm; 1824 key_type = TR_VLXLT_HASH_KEY_TYPE_PRI_CFI; 1825 } else if (info->criteria == BCM_FLOW_MATCH_CRITERIA_VN_ID) { 1826 mem_id = MPLS_ENTRYm; /* fixed view */ 1827 if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) { 1828 if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) { 1829 mem_id = VLAN_XLATE_1_DOUBLEm; 1830 key_type = _BCM_FLOW_MATCH_KEY_TYPE_VXLAN_FLEX_VNID; 1831 } else { 1832 key_type = _BCM_FLOW_MATCH_KEY_TYPE_VXLAN_VNID; 1833 } 1834 } else { 1835 key_type = _BCM_FLOW_MATCH_KEY_TYPE_L2GRE_VPNID; 1836 } 1837 } else if (info->criteria == BCM_FLOW_MATCH_CRITERIA_SIP) { 1838 mem_id = MPLS_ENTRYm; /* fixed view */ 1839 if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) { 1840 if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) { 1841 mem_id = MPLS_ENTRY_SINGLEm; 1842 } 1843 key_type = _BCM_FLOW_MATCH_KEY_TYPE_VXLAN_SIP; 1844 } else { 1845 key_type = _BCM_FLOW_MATCH_KEY_TYPE_L2GRE_SIP; 1846 } 1847 } else if (info->criteria == BCM_FLOW_MATCH_CRITERIA_SIP_VNID) { 1848 mem_id = MPLS_ENTRYm; /* fixed view */ 1849 if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) { 1850 if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) { 1851 mem_id = VLAN_XLATE_1_DOUBLEm; 1852 key_type = _BCM_FLOW_MATCH_KEY_TYPE_VXLAN_FLEX_SIP_VNID; 1853 } else { 1854 key_type = _BCM_FLOW_MATCH_KEY_TYPE_VXLAN_SIP_VNID; 1855 } 1856 } else { 1857 key_type = _BCM_FLOW_MATCH_KEY_TYPE_L2GRE_SIP_VPNID; 1858 } 1859 } 1860 1861 view_info->mem = mem_id; 1862 view_info->type = 0; 1863 view_info->mem_view_id = 0; 1864 1865 /* get the physical memory view */ 1866 if (!_BCM_FLOW_IS_FLEX_VIEW(info)) { 1867 rv = _bcm_flow_match_fixed_view_entry_init(unit, mem_id, 1868 info, key_type, entry); 1869 BCM_IF_ERROR_RETURN(rv); 1870 } else { 1871 char *option_str; 1872 uint32 dft_option_id; 1873 uint32 option_id; 1874 1875 option_id = info->flow_option; 1876 if (!option_id) { 1877 _bcm_flow_match_default_option_get(unit,info, &option_str); 1878 if (option_str != NULL) { 1879 rv = soc_flow_db_flow_option_id_get(unit, info->flow_handle, 1880 option_str, &dft_option_id); 1881 if (rv == SOC_E_NONE) { 1882 option_id = dft_option_id; 1883 } 1884 } 1885 } 1886 rv = soc_flow_db_ffo_to_mem_view_id_get(unit,info->flow_handle, 1887 option_id, 1888 SOC_FLOW_DB_FUNC_MATCH_ID, (uint32 *)&mem_view_id); 1889 BCM_IF_ERROR_RETURN(rv); 1890 rv = soc_flow_db_mem_view_info_get(unit, mem_view_id, &vinfo); 1891 BCM_IF_ERROR_RETURN(rv); 1892 view_info->type = vinfo.type; 1893 view_info->mem_view_id = mem_view_id; 1894 view_info->mem = vinfo.mem; 1895 1896 /* flex view, initialize all control fields such as data_type */ 1897 soc_flow_db_mem_view_entry_init(unit,mem_view_id,entry); 1898 if (vinfo.mem == L3_TUNNELm) { 1899 /* only available for flex */ 1900 if ((info->criteria != BCM_FLOW_MATCH_CRITERIA_FLEX) || 1901 (!_BCM_FLOW_IS_FLEX_VIEW(info))) { 1902 return BCM_E_PARAM; 1903 } 1904 } 1905 mem_id = mem_view_id; 1906 } 1907 1908 rv = _bcm_flow_match_entry_key_set(unit,info,field,num_of_fields, 1909 mem_id, entry); 1910 1911 /* BCM_FLOW_MATCH_CRITERIA_FLEX 1912 * flex key -- flex view 1913 * key comprises of logical fields and fixed fields selected 1914 * by valid_elements 1915 * 1916 * BCM_FLOW_MATCH_CRITERIA_XXX other than FLEX 1917 * fixed key -- fixed view or flex view. 1918 * key comprises of fixed fields in the parameter structure. Should be 1919 * determined by MATCH_CRITERIA. valid_elements can be used as parameter 1920 * checking in this case. 1921 * 1922 * The objects or attributes selected for the match should be determined by 1923 * the valid_elements 1924 */ 1925 1926 return rv; 1927 1928 } 1929 1930 /* 1931 * Function: 1932 * _bcm_flow_match_info_save 1933 * Purpose: 1934 * Save flow Match info 1935 * Parameters: 1936 * unit - (IN) Device Number 1937 * vp - (IN) flow port 1938 * info - (IN) flow_match configuration info 1939 * Returns: 1940 * BCM_E_XXX 1941 */ 1942 1943 STATIC void 1944 _bcm_flow_match_info_save(int unit, 1945 int vp, 1946 bcm_flow_match_config_t *info) 1947 { 1948 _bcm_flow_bookkeeping_t *flow_info; 1949 bcm_flow_match_vp_t* match_key; 1950 1951 flow_info = FLOW_INFO(unit); 1952 match_key = &flow_info->match_key[vp]; 1953 match_key->vlan = info->vlan; 1954 match_key->inner_vlan = info->inner_vlan; 1955 match_key->port = info->port; 1956 match_key->sip = info->sip; 1957 sal_memcpy(match_key->sip6, info->sip6, 1958 BCM_IP6_ADDRLEN); 1959 match_key->criteria = info->criteria; 1960 match_key->flow_handle = info->flow_handle; 1961 match_key->flow_option = info->flow_option; 1962 1963 match_key->mpls_label = info->mpls_label; 1964 match_key->vnid = info->vnid; 1965 } 1966 1967 /* 1968 * Function: 1969 * _bcm_flow_match_info_clear 1970 * Purpose: 1971 * Clear flow Match Entry 1972 * Parameters: 1973 * unit - (IN) Device Number 1974 * VP - (IN) flow VP 1975 * Returns: 1976 * BCM_E_XXX 1977 */ 1978 1979 STATIC void 1980 _bcm_flow_match_info_clear(int unit, 1981 int vp) 1982 { 1983 _bcm_flow_bookkeeping_t *flow_info; 1984 bcm_flow_match_vp_t* match_key; 1985 1986 flow_info = FLOW_INFO(unit); 1987 match_key = &flow_info->match_key[vp]; 1988 1989 if (match_key != NULL) { 1990 sal_memset(match_key, 0, sizeof(*match_key)); 1991 } 1992 } 1993 1994 /* 1995 * Function: 1996 * bcmi_esw_flow_match_add 1997 * Purpose: 1998 * Add a flow match entry 1999 * Parameters: 2000 * unit - (IN) Device Number 2001 * info - (IN) Flow match config descriptor 2002 * num_of_fields - (IN) number of logical fields 2003 * field - (IN) logical field array 2004 * Returns: 2005 * BCM_E_XXX 2006 */ 2007 2008 int bcmi_esw_flow_match_add( 2009 int unit, 2010 bcm_flow_match_config_t *info, 2011 uint32 num_of_fields, 2012 bcm_flow_logical_field_t *field) 2013 { 2014 /* L3_TUNNELm could support 4 entry wide view definition */ 2015 uint32 entry[_QUAD_ENTRY_MAX]; 2016 int rv; 2017 _bcm_flow_bookkeeping_t *flow_info; 2018 int replaced_iif; 2019 int replaced_vp; 2020 int vp; 2021 soc_flow_db_mem_view_info_t view_info; 2022 2023 if (info == NULL) { 2024 return BCM_E_PARAM; 2025 } 2026 2027 flow_info = FLOW_INFO(unit); 2028 2029 /* validate the vp */ 2030 if (info->valid_elements & BCM_FLOW_MATCH_FLOW_PORT_VALID) { 2031 vp = _SHR_GPORT_FLOW_PORT_ID_GET(info->flow_port); 2032 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeFlow)) { 2033 LOG_ERROR(BSL_LS_BCM_FLOW, 2034 (BSL_META_U(unit, "flow port ID is not valid\n"))); 2035 2036 return BCM_E_PORT; 2037 } 2038 } 2039 2040 /* port match doesn't use hash table */ 2041 if (info->criteria == BCM_FLOW_MATCH_CRITERIA_PORT) { 2042 /* check if this match set flow specific controls on the given port*/ 2043 if (_BCM_FLOW_IS_FLEX_VIEW(info) && 2044 info->valid_elements & BCM_FLOW_MATCH_PORT_VALID) { 2045 rv = _bcm_flow_match_sgpp_ctrl_set(unit,info,num_of_fields,field,FALSE); 2046 BCM_IF_ERROR_RETURN(rv); 2047 } 2048 2049 BCM_IF_ERROR_RETURN(_bcm_flow_match_port_ctrl(unit,info, 2050 _BCM_FLOW_MATCH_PORT_CTRL_SET,&replaced_vp,&replaced_iif)); 2051 2052 bcmi_esw_flow_lock(unit); 2053 /* update the iif reference counter */ 2054 if (info->valid_elements & BCM_FLOW_MATCH_IIF_VALID) { 2055 if (info->intf_id) { 2056 flow_info->iif_ref_cnt[info->intf_id]++; 2057 } 2058 if (replaced_iif) { 2059 if (flow_info->iif_ref_cnt[replaced_iif]) { 2060 flow_info->iif_ref_cnt[replaced_iif]--; 2061 } 2062 } 2063 } 2064 if (info->valid_elements & BCM_FLOW_MATCH_FLOW_PORT_VALID) { 2065 vp = _SHR_GPORT_FLOW_PORT_ID_GET(info->flow_port); 2066 if (vp) { 2067 flow_info->vp_ref_cnt[vp]++; 2068 } 2069 _bcm_flow_match_info_save(unit, vp, info); 2070 if (replaced_vp) { 2071 if (flow_info->vp_ref_cnt[replaced_vp]) { 2072 flow_info->vp_ref_cnt[replaced_vp]--; 2073 } 2074 } 2075 } 2076 bcmi_esw_flow_unlock(unit); 2077 return BCM_E_NONE; 2078 } 2079 2080 sal_memset(entry, 0, sizeof(entry)); 2081 BCM_IF_ERROR_RETURN(_bcm_flow_match_key_set(unit,info,field, 2082 num_of_fields,entry,&view_info)); 2083 2084 soc_mem_lock(unit,view_info.mem); 2085 /* set the match object and attributes and write to memory */ 2086 rv = _bcm_flow_match_entry_set(unit,info,field, 2087 num_of_fields, 2088 &view_info, 2089 entry,&replaced_iif,&replaced_vp); 2090 soc_mem_unlock(unit,view_info.mem); 2091 2092 bcmi_esw_flow_lock(unit); 2093 /* update the iif reference counter */ 2094 if (BCM_SUCCESS(rv)) { 2095 if (info->valid_elements & BCM_FLOW_MATCH_IIF_VALID) { 2096 flow_info->iif_ref_cnt[info->intf_id]++; 2097 if (info->options & BCM_FLOW_MATCH_OPTION_REPLACE) { 2098 if (flow_info->iif_ref_cnt[replaced_iif]) { 2099 flow_info->iif_ref_cnt[replaced_iif]--; 2100 } 2101 } 2102 } 2103 if (info->valid_elements & BCM_FLOW_MATCH_FLOW_PORT_VALID) { 2104 vp = _SHR_GPORT_FLOW_PORT_ID_GET(info->flow_port); 2105 flow_info->vp_ref_cnt[vp]++; 2106 _bcm_flow_match_info_save(unit, vp, info); 2107 if (info->options & BCM_FLOW_MATCH_OPTION_REPLACE) { 2108 if (flow_info->vp_ref_cnt[replaced_vp]) { 2109 flow_info->vp_ref_cnt[replaced_vp]--; 2110 } 2111 } 2112 } 2113 } 2114 if (!(info->options & BCM_FLOW_MATCH_OPTION_REPLACE)) { 2115 if (view_info.mem == VLAN_XLATE_1_DOUBLEm) { 2116 flow_info->mem_use_cnt[_BCM_FLOW_VXLT1_INX]++; 2117 } else if (view_info.mem == VLAN_XLATE_2_DOUBLEm) { 2118 flow_info->mem_use_cnt[_BCM_FLOW_VXLT2_INX]++; 2119 } else if ((view_info.mem == MPLS_ENTRYm) || (view_info.mem == MPLS_ENTRY_SINGLEm)) { 2120 flow_info->mem_use_cnt[_BCM_FLOW_MPLS_INX]++; 2121 } else if (view_info.mem == L3_TUNNELm) { 2122 flow_info->mem_use_cnt[_BCM_FLOW_TNL_INX]++; 2123 } 2124 } 2125 bcmi_esw_flow_unlock(unit); 2126 return rv; 2127 } 2128 2129 /* 2130 * Function: 2131 * _bcm_flow_match_profile_delete 2132 * Purpose: 2133 * Delete a profile in flow match entry based on the given info 2134 * Parameters: 2135 * unit - (IN) Device Number 2136 * mem - (IN) mempru ID 2137 * mem_view - (IN) memory view ID 2138 * key_data - (IN) entry key 2139 * Returns: 2140 * BCM_E_XXX 2141 */ 2142 STATIC int 2143 _bcm_flow_match_profile_delete( 2144 int unit, 2145 soc_mem_t mem, 2146 soc_mem_t mem_view, 2147 void *key_data) 2148 { 2149 soc_format_t tag_profile_fmt = TAG_ACTION_SETfmt; 2150 soc_field_t tag_profile_fmt_f = TAG_ACTION_SETf; 2151 soc_field_t tag_act_f = ING_TAG_ACTION_PROFILE_IDXf; 2152 uint32 tag_profile_set = 0; 2153 uint32 profile_index = 0; 2154 uint32 return_entry[SOC_MAX_MEM_WORDS]; 2155 int index = 0; 2156 int rv = BCM_E_NONE; 2157 2158 BCM_IF_ERROR_RETURN(soc_mem_search(unit, mem, MEM_BLOCK_ANY, &index, 2159 key_data, return_entry, 0)); 2160 if (soc_flow_db_mem_view_is_valid(unit, mem_view) && 2161 soc_mem_field_valid(unit, mem_view, tag_profile_fmt_f)) { 2162 tag_profile_set = soc_mem_field32_get(unit, mem_view, return_entry, 2163 tag_profile_fmt_f); 2164 profile_index = soc_format_field32_get(unit, tag_profile_fmt, 2165 &tag_profile_set, tag_act_f); 2166 } else if (soc_mem_field_valid(unit, mem, tag_act_f)) { 2167 tag_profile_set = soc_mem_field32_get(unit, mem, return_entry, 2168 tag_act_f); 2169 } 2170 2171 if ((profile_index != 0) && (profile_index != 1)) { 2172 rv = _bcm_trx_vlan_action_profile_entry_delete(unit, 2173 profile_index); 2174 } 2175 return rv; 2176 } 2177 2178 2179 /* 2180 * Function: 2181 * bcmi_esw_flow_match_delete 2182 * Purpose: 2183 * Delete a flow match entry based on the given key 2184 * Parameters: 2185 * unit - (IN) Device Number 2186 * info - (IN) Flow match config descriptor 2187 * num_of_fields - (IN) number of logical fields 2188 * field - (IN) logical field array 2189 * Returns: 2190 * BCM_E_XXX 2191 */ 2192 2193 int bcmi_esw_flow_match_delete( 2194 int unit, 2195 bcm_flow_match_config_t *info, 2196 uint32 num_of_fields, 2197 bcm_flow_logical_field_t *field) 2198 { 2199 uint32 entry[_QUAD_ENTRY_MAX]; 2200 _bcm_flow_bookkeeping_t *flow_info; 2201 int vp; 2202 int deleted_vp; 2203 int deleted_iif; 2204 soc_flow_db_mem_view_info_t view_info; 2205 soc_tunnel_term_t key; 2206 int rv; 2207 2208 if (info == NULL) { 2209 return BCM_E_PARAM; 2210 } 2211 flow_info = FLOW_INFO(unit); 2212 2213 /* port match doesn't use hash table */ 2214 if (info->criteria == BCM_FLOW_MATCH_CRITERIA_PORT) { 2215 /* Check if delete the flow specfic sgpp control on a specfic port */ 2216 if (_BCM_FLOW_IS_FLEX_VIEW(info) && 2217 info->valid_elements & BCM_FLOW_MATCH_PORT_VALID) { 2218 rv = _bcm_flow_match_sgpp_ctrl_set(unit,info,num_of_fields,field,TRUE); 2219 BCM_IF_ERROR_RETURN(rv); 2220 } 2221 /* perform delete action */ 2222 BCM_IF_ERROR_RETURN(_bcm_flow_match_port_ctrl(unit,info, 2223 _BCM_FLOW_MATCH_PORT_CTRL_DELETE,&deleted_vp, 2224 &deleted_iif)); 2225 bcmi_esw_flow_lock(unit); 2226 if (info->intf_id) { 2227 if (flow_info->iif_ref_cnt[info->intf_id]) { 2228 flow_info->iif_ref_cnt[info->intf_id]--; 2229 } 2230 } 2231 vp = _SHR_GPORT_FLOW_PORT_ID_GET(info->flow_port); 2232 if (vp) { 2233 if (flow_info->vp_ref_cnt[vp]) { 2234 flow_info->vp_ref_cnt[vp]--; 2235 } 2236 } 2237 bcmi_esw_flow_unlock(unit); 2238 if (deleted_vp) { 2239 _bcm_flow_match_info_clear(unit, deleted_vp); 2240 } 2241 return BCM_E_NONE; 2242 } 2243 2244 sal_memset(entry, 0, sizeof(entry)); 2245 BCM_IF_ERROR_RETURN(_bcm_flow_match_key_set(unit,info,field, 2246 num_of_fields,entry,&view_info)); 2247 if (view_info.mem == L3_TUNNELm) { 2248 rv = _bcm_flow_match_mem_entry_to_term_entry(unit, view_info.mem, 2249 &key, entry); 2250 BCM_IF_ERROR_RETURN(rv); 2251 } 2252 BCM_IF_ERROR_RETURN(_bcm_flow_match_entry_get(unit,info,field, 2253 num_of_fields, 2254 &view_info, 2255 entry)); 2256 2257 if (view_info.mem == L3_TUNNELm) { 2258 BCM_IF_ERROR_RETURN(soc_tunnel_term_delete(unit, &key)); 2259 } else { 2260 BCM_IF_ERROR_RETURN(_bcm_flow_match_profile_delete(unit, view_info.mem, 2261 view_info.mem_view_id, entry)); 2262 BCM_IF_ERROR_RETURN(soc_mem_delete(unit, view_info.mem, 2263 MEM_BLOCK_ANY, entry)); 2264 } 2265 2266 bcmi_esw_flow_lock(unit); 2267 if (info->intf_id) { 2268 if (flow_info->iif_ref_cnt[info->intf_id]) { 2269 flow_info->iif_ref_cnt[info->intf_id]--; 2270 } 2271 } 2272 vp = _SHR_GPORT_FLOW_PORT_ID_GET(info->flow_port); 2273 if (vp) { 2274 if (flow_info->vp_ref_cnt[vp]) { 2275 flow_info->vp_ref_cnt[vp]--; 2276 } 2277 } 2278 if (view_info.mem == VLAN_XLATE_1_DOUBLEm) { 2279 if (flow_info->mem_use_cnt[_BCM_FLOW_VXLT1_INX]) { 2280 flow_info->mem_use_cnt[_BCM_FLOW_VXLT1_INX]--; 2281 } 2282 } else if (view_info.mem == VLAN_XLATE_2_DOUBLEm) { 2283 if (flow_info->mem_use_cnt[_BCM_FLOW_VXLT2_INX]) { 2284 flow_info->mem_use_cnt[_BCM_FLOW_VXLT2_INX]--; 2285 } 2286 } else if ((view_info.mem == MPLS_ENTRYm) || (view_info.mem == MPLS_ENTRY_SINGLEm)) { 2287 if (flow_info->mem_use_cnt[_BCM_FLOW_MPLS_INX]) { 2288 flow_info->mem_use_cnt[_BCM_FLOW_MPLS_INX]--; 2289 } 2290 } else if (view_info.mem == L3_TUNNELm) { 2291 if (flow_info->mem_use_cnt[_BCM_FLOW_TNL_INX]) { 2292 flow_info->mem_use_cnt[_BCM_FLOW_TNL_INX]--; 2293 } 2294 } 2295 bcmi_esw_flow_unlock(unit); 2296 if (vp) { 2297 _bcm_flow_match_info_clear(unit, vp); 2298 } 2299 return BCM_E_NONE; 2300 } 2301 2302 /* 2303 * Function: 2304 * bcmi_esw_flow_match_get 2305 * Purpose: 2306 * Delete a flow match entry based on the given key 2307 * Parameters: 2308 * unit - (IN) Device Number 2309 * info - (IN) Flow match config descriptor 2310 * num_of_fields - (IN) number of logical fields 2311 * field - (IN) logical field array 2312 * Returns: 2313 * BCM_E_XXX 2314 */ 2315 2316 int bcmi_esw_flow_match_get( 2317 int unit, 2318 bcm_flow_match_config_t *info, 2319 uint32 num_of_fields, 2320 bcm_flow_logical_field_t *field) 2321 { 2322 uint32 entry[_QUAD_ENTRY_MAX]; 2323 soc_flow_db_mem_view_info_t view_info; 2324 2325 if (info == NULL) { 2326 return BCM_E_PARAM; 2327 } 2328 /* port match doesn't use hash table */ 2329 if (info->criteria == BCM_FLOW_MATCH_CRITERIA_PORT) { 2330 /* perform delete action */ 2331 BCM_IF_ERROR_RETURN(_bcm_flow_match_port_ctrl(unit,info, 2332 _BCM_FLOW_MATCH_PORT_CTRL_GET,NULL,NULL)); 2333 return BCM_E_NONE; 2334 } 2335 2336 sal_memset(entry, 0, sizeof(entry)); 2337 BCM_IF_ERROR_RETURN(_bcm_flow_match_key_set(unit,info,field, 2338 num_of_fields,entry,&view_info)); 2339 2340 BCM_IF_ERROR_RETURN(_bcm_flow_match_entry_get(unit,info,field, 2341 num_of_fields, 2342 &view_info, 2343 entry)); 2344 return BCM_E_NONE; 2345 } 2346 2347 STATIC int 2348 _bcm_flow_match_entry_valid(int unit, soc_mem_t mem, uint32 *entry, int *valid) 2349 { 2350 if (INVALIDm == mem) { 2351 return BCM_E_MEMORY; 2352 } 2353 2354 if ((NULL == entry) || (NULL == valid)) { 2355 return BCM_E_PARAM; 2356 } 2357 *valid = TRUE; 2358 if (SOC_MEM_FIELD_VALID(unit,mem,BASE_VALID_0f)) { 2359 if (!soc_mem_field32_get(unit, mem, entry, BASE_VALID_0f)) { 2360 *valid = FALSE; 2361 } 2362 } 2363 if (SOC_MEM_FIELD_VALID(unit,mem,BASE_VALID_1f)) { 2364 if (!soc_mem_field32_get(unit, mem, entry, BASE_VALID_1f)) { 2365 *valid = FALSE; 2366 } 2367 } 2368 if (SOC_MEM_FIELD_VALID(unit,mem,VALIDf)) { 2369 if (!soc_mem_field32_get(unit, mem, entry, VALIDf)) { 2370 *valid = FALSE; 2371 } 2372 } 2373 return BCM_E_NONE; 2374 } 2375 2376 /* 2377 * Function : 2378 * _bcm_flow_match_entry_parse 2379 * Description : 2380 * Convert the memory entry field data to the flow match configuration 2381 * parameters. 2382 * Parameters : 2383 * unit - (IN) Device Number 2384 * mem - (IN) memory id. 2385 * entry - (IN) HW entry. 2386 * info - (OUT) Flow match config descriptor 2387 * num_of_fields - (OUT) number of logical fields 2388 * field - (OUT) logical field array 2389 */ 2390 int 2391 _bcm_flow_match_entry_parse(int unit, soc_mem_t mem, uint32 *entry, 2392 bcm_flow_match_config_t *info, 2393 uint32 *num_of_fields, 2394 bcm_flow_logical_field_t *field) 2395 { 2396 int data_type; 2397 int key_type; 2398 bcm_module_t mod_out = -1; 2399 bcm_port_t port_out = -1; 2400 bcm_trunk_t trunk_id = -1; 2401 uint32 trunk_bit = 0; 2402 soc_field_t ovid_f; 2403 soc_field_t otag_f; 2404 soc_field_t ivid_f; 2405 soc_field_t sip_f; 2406 soc_field_t dip_f; 2407 soc_field_t vnid_f; 2408 soc_field_t t_f; 2409 soc_field_t tgid_f; 2410 soc_field_t module_id_f; 2411 soc_field_t port_num_f; 2412 uint32 field_id[_BCM_FLOW_LOGICAL_FIELD_MAX]; 2413 uint32 cnt; 2414 uint32 data_cnt; 2415 int i; 2416 int rv; 2417 soc_mem_t mem_view_id; 2418 int is_flex_view; 2419 2420 key_type = 0; 2421 data_type = 0; 2422 vnid_f = VXLAN_VN_ID__VN_IDf; 2423 sip_f = SIPf; 2424 is_flex_view = FALSE; 2425 2426 if (SOC_MEM_FIELD_VALID(unit,mem,KEY_TYPEf)) { 2427 key_type = soc_mem_field32_get(unit, mem, entry, KEY_TYPEf); 2428 } 2429 if (SOC_MEM_FIELD_VALID(unit,mem,DATA_TYPEf)) { 2430 data_type = soc_mem_field32_get(unit, mem, entry, DATA_TYPEf); 2431 } 2432 2433 /* find the memory view based on the memory and key type */ 2434 rv = soc_flow_db_mem_to_view_id_get (unit, mem, key_type, data_type, 2435 0, NULL, (uint32 *)&mem_view_id); 2436 2437 if (rv != SOC_E_NONE && rv != SOC_E_NOT_FOUND) { 2438 return rv; 2439 } 2440 if (rv == SOC_E_NOT_FOUND) { /* fixed view */ 2441 /* match action in L3_TUNNELm only available for flex view */ 2442 if (mem == L3_TUNNELm) { 2443 return SOC_E_NOT_FOUND; 2444 } 2445 rv = SOC_E_NONE; 2446 if (mem == VLAN_XLATE_1_DOUBLEm || mem == VLAN_XLATE_2_DOUBLEm) { 2447 switch (key_type) { 2448 case TR_VLXLT_HASH_KEY_TYPE_OVID: 2449 info->criteria = BCM_FLOW_MATCH_CRITERIA_PORT_VLAN; 2450 info->valid_elements |= BCM_FLOW_MATCH_PORT_VALID | 2451 BCM_FLOW_MATCH_VLAN_VALID; 2452 break; 2453 2454 case TR_VLXLT_HASH_KEY_TYPE_IVID: 2455 info->criteria = BCM_FLOW_MATCH_CRITERIA_PORT_INNER_VLAN; 2456 info->valid_elements |= BCM_FLOW_MATCH_PORT_VALID | 2457 BCM_FLOW_MATCH_INNER_VLAN_VALID; 2458 break; 2459 2460 case TR_VLXLT_HASH_KEY_TYPE_IVID_OVID: 2461 info->criteria = BCM_FLOW_MATCH_CRITERIA_PORT_VLAN_STACKED; 2462 info->valid_elements |= BCM_FLOW_MATCH_PORT_VALID | 2463 BCM_FLOW_MATCH_VLAN_VALID | 2464 BCM_FLOW_MATCH_INNER_VLAN_VALID; 2465 break; 2466 2467 case TR_VLXLT_HASH_KEY_TYPE_PRI_CFI: 2468 info->criteria = BCM_FLOW_MATCH_CRITERIA_VLAN_PRI; 2469 info->valid_elements |= BCM_FLOW_MATCH_PORT_VALID | 2470 BCM_FLOW_MATCH_VLAN_VALID; 2471 break; 2472 case _BCM_FLOW_MATCH_KEY_TYPE_VXLAN_FLEX_VNID: 2473 info->criteria = BCM_FLOW_MATCH_CRITERIA_VN_ID; 2474 info->flow_handle = SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN; 2475 info->valid_elements |= BCM_FLOW_MATCH_VNID_VALID; 2476 break; 2477 case _BCM_FLOW_MATCH_KEY_TYPE_VXLAN_FLEX_SIP_VNID: 2478 info->criteria = BCM_FLOW_MATCH_CRITERIA_SIP_VNID; 2479 info->flow_handle = SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN; 2480 info->valid_elements |= BCM_FLOW_MATCH_SIP_VALID | 2481 BCM_FLOW_MATCH_VNID_VALID; 2482 break; 2483 default: 2484 /* not used by the flow_match functions */ 2485 return BCM_E_NOT_FOUND; 2486 break; 2487 } 2488 } else if (mem == MPLS_ENTRYm) { 2489 switch (key_type) { 2490 case _BCM_FLOW_MATCH_KEY_TYPE_VXLAN_VNID: 2491 info->criteria = BCM_FLOW_MATCH_CRITERIA_VN_ID; 2492 info->flow_handle = SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN; 2493 info->valid_elements |= BCM_FLOW_MATCH_VNID_VALID; 2494 break; 2495 case _BCM_FLOW_MATCH_KEY_TYPE_L2GRE_VPNID: 2496 info->criteria = BCM_FLOW_MATCH_CRITERIA_VN_ID; 2497 info->flow_handle = SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE; 2498 info->valid_elements |= BCM_FLOW_MATCH_VNID_VALID; 2499 break; 2500 case _BCM_FLOW_MATCH_KEY_TYPE_VXLAN_SIP: 2501 info->criteria = BCM_FLOW_MATCH_CRITERIA_SIP; 2502 info->flow_handle = SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN; 2503 info->valid_elements |= BCM_FLOW_MATCH_SIP_VALID; 2504 info->vlan = soc_mem_field32_get(unit, mem, 2505 entry, VXLAN_SIP__OVIDf); 2506 break; 2507 case _BCM_FLOW_MATCH_KEY_TYPE_L2GRE_SIP: 2508 info->criteria = BCM_FLOW_MATCH_CRITERIA_SIP; 2509 info->flow_handle = SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE; 2510 info->valid_elements |= BCM_FLOW_MATCH_SIP_VALID; 2511 break; 2512 case _BCM_FLOW_MATCH_KEY_TYPE_VXLAN_SIP_VNID: 2513 info->criteria = BCM_FLOW_MATCH_CRITERIA_SIP_VNID; 2514 info->flow_handle = SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN; 2515 info->valid_elements |= BCM_FLOW_MATCH_SIP_VALID | 2516 BCM_FLOW_MATCH_VNID_VALID; 2517 break; 2518 case _BCM_FLOW_MATCH_KEY_TYPE_L2GRE_SIP_VPNID: 2519 info->criteria = BCM_FLOW_MATCH_CRITERIA_SIP_VNID; 2520 info->flow_handle = SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE; 2521 info->valid_elements |= BCM_FLOW_MATCH_SIP_VALID | 2522 BCM_FLOW_MATCH_VNID_VALID; 2523 break; 2524 2525 default: 2526 /* not used by the flow_match functions */ 2527 return BCM_E_NOT_FOUND; 2528 break; 2529 } 2530 } else if (mem == MPLS_ENTRY_SINGLEm) { 2531 switch (key_type) { 2532 case _BCM_FLOW_MATCH_KEY_TYPE_VXLAN_SIP: 2533 info->criteria = BCM_FLOW_MATCH_CRITERIA_SIP; 2534 info->flow_handle = SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN; 2535 info->valid_elements |= BCM_FLOW_MATCH_SIP_VALID; 2536 break; 2537 default: 2538 /* not used by the flow_match functions */ 2539 return BCM_E_NOT_FOUND; 2540 break; 2541 } 2542 } 2543 } else { /* flex view found */ 2544 uint32 port_ovid_ids[3]; 2545 uint32 port_ivid_ids[3]; 2546 uint32 port_dtag_ids[4]; 2547 uint32 otag_id[1]; 2548 uint32 sip_id[1]; 2549 uint32 vnid_id[1]; 2550 uint32 vnid_sip_ids[2]; 2551 2552 is_flex_view = TRUE; 2553 port_ovid_ids[0] = MODULE_IDf; 2554 port_ovid_ids[1] = PORT_NUMf; 2555 port_ovid_ids[2] = OVIDf; 2556 2557 port_ivid_ids[0] = MODULE_IDf; 2558 port_ivid_ids[1] = PORT_NUMf; 2559 port_ivid_ids[2] = IVIDf; 2560 2561 port_dtag_ids[0] = MODULE_IDf; 2562 port_dtag_ids[1] = PORT_NUMf; 2563 port_dtag_ids[2] = OVIDf; 2564 port_dtag_ids[3] = IVIDf; 2565 2566 otag_id[0] = OTAGf; 2567 vnid_id[0] = VNIDf; 2568 vnid_sip_ids[1] = VNIDf; 2569 if (SOC_MEM_FIELD_VALID(unit,mem_view_id,IPV4__SIPf)) { 2570 sip_id[0] = IPV4__SIPf; 2571 vnid_sip_ids[0] = IPV4__SIPf; 2572 } else { 2573 sip_id[0] = SIPf; 2574 vnid_sip_ids[0] = SIPf; 2575 } 2576 rv = _bcm_flow_mem_view_to_flow_info_get(unit, mem_view_id, 2577 SOC_FLOW_DB_FUNC_MATCH_ID, 2578 &info->flow_handle, &info->flow_option, 1); 2579 SOC_IF_ERROR_RETURN(rv); 2580 2581 mem = mem_view_id; 2582 if (_bcm_flow_key_is_valid(unit, mem, port_ovid_ids, 3)) { 2583 info->criteria = BCM_FLOW_MATCH_CRITERIA_PORT_VLAN; 2584 info->valid_elements |= BCM_FLOW_MATCH_PORT_VALID | 2585 BCM_FLOW_MATCH_VLAN_VALID; 2586 } else if (_bcm_flow_key_is_valid(unit, mem, port_ivid_ids,3)) { 2587 info->criteria = BCM_FLOW_MATCH_CRITERIA_PORT_INNER_VLAN; 2588 info->valid_elements |= BCM_FLOW_MATCH_PORT_VALID | 2589 BCM_FLOW_MATCH_INNER_VLAN_VALID; 2590 } else if (_bcm_flow_key_is_valid(unit, mem, port_dtag_ids,4)) { 2591 info->criteria = BCM_FLOW_MATCH_CRITERIA_PORT_VLAN_STACKED; 2592 info->valid_elements |= BCM_FLOW_MATCH_PORT_VALID | 2593 BCM_FLOW_MATCH_VLAN_VALID | 2594 BCM_FLOW_MATCH_INNER_VLAN_VALID; 2595 } else if (_bcm_flow_key_is_valid(unit, mem, otag_id, 1)) { 2596 info->criteria = BCM_FLOW_MATCH_CRITERIA_VLAN_PRI; 2597 info->valid_elements |= BCM_FLOW_MATCH_PORT_VALID | 2598 BCM_FLOW_MATCH_VLAN_VALID; 2599 } else if (_bcm_flow_key_is_valid(unit, mem, vnid_id, 1)) { 2600 info->criteria = BCM_FLOW_MATCH_CRITERIA_VN_ID; 2601 info->valid_elements |= BCM_FLOW_MATCH_VNID_VALID; 2602 } else if (_bcm_flow_key_is_valid(unit, mem, sip_id, 1)) { 2603 info->criteria = BCM_FLOW_MATCH_CRITERIA_SIP; 2604 info->valid_elements |= BCM_FLOW_MATCH_SIP_VALID; 2605 } else if (_bcm_flow_key_is_valid(unit, mem, vnid_sip_ids, 1)) { 2606 info->criteria = BCM_FLOW_MATCH_CRITERIA_SIP_VNID; 2607 info->valid_elements |= BCM_FLOW_MATCH_SIP_VALID | 2608 BCM_FLOW_MATCH_VNID_VALID; 2609 } else { 2610 info->criteria = BCM_FLOW_MATCH_CRITERIA_FLEX; 2611 info->valid_elements |= BCM_FLOW_MATCH_FLEX_KEY_VALID; 2612 } 2613 } 2614 2615 /* retrieve the key fields */ 2616 if (is_flex_view) { /* flex view */ 2617 t_f = Tf; 2618 tgid_f = TGIDf; 2619 module_id_f = MODULE_IDf; 2620 port_num_f = PORT_NUMf; 2621 ovid_f = OVIDf; 2622 ivid_f = IVIDf; 2623 otag_f = OTAGf; 2624 } else { /* fix key type */ 2625 t_f = XLATE__Tf; 2626 tgid_f = XLATE__TGIDf; 2627 module_id_f = XLATE__MODULE_IDf; 2628 port_num_f = XLATE__PORT_NUMf; 2629 ovid_f = XLATE__OVIDf; 2630 ivid_f = XLATE__IVIDf; 2631 otag_f = XLATE__OTAGf; 2632 } 2633 if (info->criteria == BCM_FLOW_MATCH_CRITERIA_VLAN_PRI) { 2634 if (SOC_MEM_FIELD_VALID(unit,mem,otag_f)) { 2635 info->vlan = soc_mem_field32_get(unit, mem, entry, otag_f); 2636 } 2637 } else { 2638 if (SOC_MEM_FIELD_VALID(unit,mem,ovid_f)) { 2639 info->vlan = soc_mem_field32_get(unit, mem, entry, ovid_f); 2640 } 2641 } 2642 if (SOC_MEM_FIELD_VALID(unit,mem,ivid_f)) { 2643 info->inner_vlan = soc_mem_field32_get(unit, mem, entry, ivid_f); 2644 } 2645 if (SOC_MEM_FIELD_VALID(unit,mem,t_f)) { 2646 trunk_bit = soc_mem_field32_get(unit,mem, entry, t_f); 2647 } 2648 if (trunk_bit) { 2649 if (SOC_MEM_FIELD_VALID(unit,mem,tgid_f)) { 2650 trunk_id = soc_mem_field32_get(unit,mem, entry, tgid_f); 2651 BCM_GPORT_TRUNK_SET(info->port,trunk_id); 2652 info->valid_elements |= BCM_FLOW_MATCH_PORT_VALID; 2653 } 2654 } else { 2655 if (SOC_MEM_FIELD_VALID(unit,mem,module_id_f)) { 2656 mod_out = soc_mem_field32_get(unit,mem, entry, module_id_f); 2657 if (SOC_MEM_FIELD_VALID(unit,mem,port_num_f)) { 2658 port_out= soc_mem_field32_get(unit,mem, entry, port_num_f); 2659 } 2660 if (mod_out != -1 && port_out != 1) { 2661 BCM_GPORT_MODPORT_SET(info->port,mod_out,port_out); 2662 info->valid_elements |= BCM_FLOW_MATCH_PORT_VALID; 2663 } 2664 } 2665 } 2666 if (SOC_MEM_FIELD_VALID(unit,mem,SGPPf)) { 2667 uint32 sgpp; 2668 2669 sgpp = soc_mem_field32_get(unit,mem, entry, SGPPf); 2670 port_out = sgpp & 0xff; 2671 mod_out = (sgpp >> 8) & 0xff; 2672 BCM_GPORT_MODPORT_SET(info->port,mod_out,port_out); 2673 info->valid_elements |= BCM_FLOW_MATCH_PORT_VALID; 2674 } 2675 2676 if (info->criteria == BCM_FLOW_MATCH_CRITERIA_SIP) { 2677 if (is_flex_view) { 2678 ovid_f = OVIDf; 2679 vnid_f = VNIDf; 2680 if (SOC_MEM_FIELD_VALID(unit,mem,IPV4__SIPf)) { 2681 sip_f = IPV4__SIPf; 2682 } else { 2683 sip_f = SIPf; 2684 } 2685 } else { 2686 if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) { 2687 if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) { 2688 sip_f = VXLAN_FLEX_IPV4_SIP__SIPf; 2689 } else { 2690 ovid_f = VXLAN_SIP__OVIDf; 2691 sip_f = VXLAN_SIP__SIPf; 2692 } 2693 } else if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) { 2694 sip_f = L2GRE_SIP__SIPf; 2695 } else { 2696 LOG_ERROR(BSL_LS_BCM_FLOW, 2697 (BSL_META_U(unit, "Invalid legacy flow handle\n"))); 2698 return BCM_E_PARAM; 2699 } 2700 } 2701 if (soc_feature(unit, soc_feature_vrf_aware_vxlan_termination)) { 2702 if (SOC_MEM_FIELD_VALID(unit,mem,ovid_f)) { 2703 info->vlan = soc_mem_field32_get(unit,mem, entry, ovid_f); 2704 info->valid_elements |= BCM_FLOW_MATCH_VLAN_VALID; 2705 } 2706 } 2707 info->sip = soc_mem_field32_get(unit,mem, entry, sip_f); 2708 info->valid_elements |= BCM_FLOW_MATCH_SIP_VALID; 2709 } else if (info->criteria == BCM_FLOW_MATCH_CRITERIA_VN_ID || 2710 info->criteria == BCM_FLOW_MATCH_CRITERIA_SIP_VNID) { 2711 if (is_flex_view) { 2712 ovid_f = OVIDf; 2713 vnid_f = VNIDf; 2714 if (SOC_MEM_FIELD_VALID(unit,mem,IPV4__SIPf)) { 2715 sip_f = IPV4__SIPf; 2716 } else { 2717 sip_f = SIPf; 2718 } 2719 } else { 2720 if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) { 2721 if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) { 2722 ovid_f = VXLAN_FLEX__OVIDf; 2723 sip_f = VXLAN_FLEX__SIPf; 2724 vnid_f = VXLAN_FLEX__VNIDf; 2725 } else { 2726 ovid_f = VXLAN_VN_ID__OVIDf; 2727 sip_f = VXLAN_VN_ID__SIPf; 2728 vnid_f = VXLAN_VN_ID__VN_IDf; 2729 } 2730 } else if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) { 2731 vnid_f = L2GRE_VPNID__VPNIDf; 2732 sip_f = L2GRE_VPNID__SIPf; 2733 } else { 2734 LOG_ERROR(BSL_LS_BCM_FLOW, 2735 (BSL_META_U(unit, "Invalid legacy flow handle\n"))); 2736 return BCM_E_PARAM; 2737 } 2738 } 2739 info->vnid = soc_mem_field32_get(unit, mem, entry, vnid_f); 2740 info->valid_elements |= BCM_FLOW_MATCH_VNID_VALID; 2741 if (info->criteria == BCM_FLOW_MATCH_CRITERIA_SIP_VNID) { 2742 info->sip = soc_mem_field32_get(unit,mem, entry, sip_f); 2743 info->valid_elements |= BCM_FLOW_MATCH_SIP_VALID; 2744 } 2745 if (SOC_MEM_FIELD_VALID(unit,mem,ovid_f)) { 2746 info->vlan = soc_mem_field32_get(unit,mem, entry, ovid_f); 2747 info->valid_elements |= BCM_FLOW_MATCH_VLAN_VALID; 2748 } else if (SOC_MEM_FIELD_VALID(unit, mem, OVLAN_ACTION_SETf)) { 2749 uint32 action_set = soc_mem_field32_get(unit, mem, entry, OVLAN_ACTION_SETf); 2750 info->vlan = soc_format_field32_get(unit, OVLAN_ACTION_SETfmt, &action_set, VLAN_IDf); 2751 info->valid_elements |= BCM_FLOW_MATCH_VLAN_VALID; 2752 } 2753 2754 } else if (info->criteria == BCM_FLOW_MATCH_CRITERIA_FLEX) { 2755 rv = soc_flow_db_mem_view_field_list_get(unit, 2756 mem, 2757 SOC_FLOW_DB_FIELD_TYPE_LOGICAL_KEY, 2758 _BCM_FLOW_LOGICAL_FIELD_MAX, field_id, &cnt); 2759 SOC_IF_ERROR_RETURN(rv); 2760 if (cnt >= _BCM_FLOW_LOGICAL_FIELD_MAX) { 2761 LOG_ERROR(BSL_LS_BCM_FLOW, 2762 (BSL_META_U(unit, 2763 "Exceed max logical array size: %d\n"),cnt)); 2764 return BCM_E_PARAM; 2765 } 2766 for (i = 0; i < cnt; i++) { 2767 field[i].id = field_id[i]; 2768 field[i].value = soc_mem_field32_get(unit,mem, entry, 2769 field[i].id); 2770 } 2771 2772 if (SOC_MEM_FIELD_VALID(unit,mem,vnid_f)) { 2773 info->vnid = soc_mem_field32_get(unit,mem, entry, vnid_f); 2774 info->valid_elements |= BCM_FLOW_MATCH_VNID_VALID; 2775 } 2776 if (SOC_MEM_FIELD_VALID(unit,mem,ovid_f)) { 2777 info->vlan = soc_mem_field32_get(unit,mem, entry, ovid_f); 2778 info->valid_elements |= BCM_FLOW_MATCH_VLAN_VALID; 2779 } 2780 if (SOC_MEM_FIELD_VALID(unit,mem,ivid_f)) { 2781 info->inner_vlan = soc_mem_field32_get(unit,mem, entry, ivid_f); 2782 info->valid_elements |= BCM_FLOW_MATCH_INNER_VLAN_VALID; 2783 } 2784 if (SOC_MEM_FIELD_VALID(unit,mem,IPV4__SIPf)) { 2785 sip_f = IPV4__SIPf; 2786 } else { 2787 sip_f = SIPf; 2788 } 2789 if (SOC_MEM_FIELD_VALID(unit,mem,sip_f)) { 2790 info->sip = soc_mem_field32_get(unit,mem, entry, sip_f); 2791 info->valid_elements |= BCM_FLOW_MATCH_SIP_VALID; 2792 } 2793 if (SOC_MEM_FIELD_VALID(unit,mem,IPV6__SIPf)) { 2794 soc_mem_ip6_addr_get(unit, mem, entry,IPV6__SIPf, info->sip6, 0); 2795 info->valid_elements |= BCM_FLOW_MATCH_SIP_V6_VALID; 2796 } 2797 2798 if (SOC_MEM_FIELD_VALID(unit,mem,IPV4__DIPf)) { 2799 dip_f = IPV4__DIPf; 2800 } else { 2801 dip_f = DIPf; 2802 } 2803 if (SOC_MEM_FIELD_VALID(unit,mem,dip_f)) { 2804 info->dip = soc_mem_field32_get(unit,mem, entry, dip_f); 2805 info->valid_elements |= BCM_FLOW_MATCH_DIP_VALID; 2806 } 2807 if (SOC_MEM_FIELD_VALID(unit,mem,IPV6__DIPf)) { 2808 soc_mem_ip6_addr_get(unit, mem, entry,IPV6__DIPf, info->dip6, 0); 2809 info->valid_elements |= BCM_FLOW_MATCH_DIP_V6_VALID; 2810 } 2811 if (SOC_MEM_FIELD_VALID(unit,mem,IPV4__PROTOCOLf)) { 2812 info->protocol = soc_mem_field32_get(unit,mem, entry, 2813 IPV4__PROTOCOLf); 2814 info->valid_elements |= BCM_FLOW_MATCH_PROTOCOL_VALID; 2815 } 2816 if (SOC_MEM_FIELD_VALID(unit,mem,L4_SRC_PORTf)) { 2817 info->udp_src_port = soc_mem_field32_get(unit,mem, entry, 2818 L4_SRC_PORTf); 2819 info->valid_elements |= BCM_FLOW_MATCH_UDP_SRC_PORT_VALID; 2820 } 2821 if (SOC_MEM_FIELD_VALID(unit,mem,L4_DST_PORTf)) { 2822 info->udp_dst_port = soc_mem_field32_get(unit,mem, entry, 2823 L4_DST_PORTf); 2824 info->valid_elements |= BCM_FLOW_MATCH_UDP_DST_PORT_VALID; 2825 } 2826 } 2827 2828 if (info->criteria != BCM_FLOW_MATCH_CRITERIA_FLEX) { 2829 cnt = 0; 2830 } 2831 2832 data_cnt = 0; 2833 if (is_flex_view) { /* flex view */ 2834 /* retrieve the data fields, cnt: number of key fields */ 2835 rv = soc_flow_db_mem_view_field_list_get(unit, 2836 mem, 2837 SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA, 2838 _BCM_FLOW_LOGICAL_FIELD_MAX - cnt, field_id, &data_cnt); 2839 if (rv != SOC_E_NONE && rv != SOC_E_NOT_FOUND) { 2840 return rv; 2841 } 2842 2843 if (data_cnt >= _BCM_FLOW_LOGICAL_FIELD_MAX - cnt) { 2844 LOG_ERROR(BSL_LS_BCM_FLOW, 2845 (BSL_META_U(unit, 2846 "Exceed default logical array size: %d\n"),cnt + data_cnt)); 2847 return BCM_E_PARAM; 2848 } 2849 for (i = 0; i < data_cnt; i++) { 2850 field[i+cnt].id = field_id[i]; 2851 } 2852 if (!_BCM_FLOW_IS_FLEX_VIEW(info)) { 2853 /* flow_handle is not properly set, use default flex handle*/ 2854 info->flow_handle = SOC_FLOW_DB_FLOW_ID_START; 2855 } 2856 } 2857 rv = _bcm_flow_match_entry_data_get(unit, info, field+cnt, 2858 data_cnt, mem, entry); 2859 BCM_IF_ERROR_RETURN(rv); 2860 *num_of_fields = cnt + data_cnt; 2861 if (data_cnt) { 2862 info->valid_elements |= BCM_FLOW_MATCH_FLEX_DATA_VALID; 2863 } 2864 2865 /* non-flow match APIs could also use the same key type to add the entries 2866 * to this table. Make sure the right entries are traversed by validating 2867 * the objects. 2868 */ 2869 if (!(info->valid_elements & (BCM_FLOW_MATCH_FLOW_PORT_VALID | 2870 BCM_FLOW_MATCH_IIF_VALID | 2871 BCM_FLOW_MATCH_VPN_VALID | 2872 BCM_FLOW_MATCH_FLEX_DATA_VALID))) { 2873 return BCM_E_NOT_FOUND; 2874 } 2875 return BCM_E_NONE; 2876 } 2877 2878 /* 2879 * Function: 2880 * _bcm_flow_match_trunk_mem_traverse 2881 * Purpose: 2882 * Read the source trunk memory table and call the user callback function 2883 * on each entry. 2884 * Parameters: 2885 * unit - (IN) Device Number 2886 * cb - (IN) user callback function 2887 * user_data - (IN) user context data 2888 * Returns: 2889 * BCM_E_XXX 2890 */ 2891 2892 STATIC int 2893 _bcm_flow_match_trunk_mem_traverse(int unit, 2894 bcm_flow_match_traverse_cb cb, 2895 void *user_data) 2896 { 2897 /* Indexes to iterate over memories, chunks and entries */ 2898 int ent_idx; 2899 int buf_size, cfg_buf_size; 2900 uint32 *trunk_map_tbl; 2901 source_trunk_map_table_entry_t *entry; 2902 bcm_module_t local_modid; 2903 int mod_base; 2904 bcm_flow_match_config_t *info; 2905 uint32 port_type; 2906 uint32 tgid; 2907 uint32 svp; 2908 int i,j,cnt; 2909 int tid_found; 2910 int rv = BCM_E_NONE; 2911 soc_mem_t mem = SOURCE_TRUNK_MAP_TABLEm; 2912 uint32 iif; 2913 _bcm_flow_bookkeeping_t *flow_info; 2914 2915 flow_info = FLOW_INFO(unit); 2916 2917 if (!soc_mem_index_count(unit, mem)) { 2918 return BCM_E_NONE; 2919 } 2920 2921 /* Get local module id. */ 2922 rv = bcm_esw_stk_my_modid_get(unit, &local_modid); 2923 BCM_IF_ERROR_RETURN(rv); 2924 rv = _bcm_esw_src_modid_base_index_get(unit,local_modid,TRUE,&mod_base); 2925 BCM_IF_ERROR_RETURN(rv); 2926 2927 /* validate the port index range */ 2928 if ((mod_base + SOC_MODPORT_MAX(unit)) > 2929 (soc_mem_index_max(unit, mem) + 1)) { 2930 return BCM_E_PARAM; 2931 } 2932 buf_size = sizeof(source_trunk_map_table_entry_t) * SOC_MODPORT_MAX(unit); 2933 trunk_map_tbl = soc_cm_salloc(unit, buf_size, 2934 "flow match trunk map traverse"); 2935 if (NULL == trunk_map_tbl) { 2936 return BCM_E_MEMORY; 2937 } 2938 2939 /* allocate match config buffer */ 2940 cfg_buf_size = sizeof(bcm_flow_match_config_t) * SOC_MODPORT_MAX(unit); 2941 info = sal_alloc(cfg_buf_size, 2942 "flow match trunk map traverse config"); 2943 if (NULL == info) { 2944 soc_cm_sfree(unit, trunk_map_tbl); 2945 return BCM_E_MEMORY; 2946 } 2947 2948 sal_memset((void *)trunk_map_tbl, 0, buf_size); 2949 sal_memset((void *)info, 0, cfg_buf_size); 2950 2951 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, mod_base, 2952 mod_base + SOC_MODPORT_MAX(unit) - 1, trunk_map_tbl); 2953 if (SOC_FAILURE(rv)) { 2954 soc_cm_sfree(unit, trunk_map_tbl); 2955 sal_free(info); 2956 return BCM_E_MEMORY; 2957 } 2958 cnt = 0; 2959 for (ent_idx = 0; ent_idx < SOC_MODPORT_MAX(unit); ent_idx ++) { 2960 entry = soc_mem_table_idx_to_pointer(unit, mem, 2961 source_trunk_map_table_entry_t *, 2962 trunk_map_tbl, ent_idx); 2963 port_type = soc_mem_field32_get(unit, mem, entry, PORT_TYPEf); 2964 tgid = soc_mem_field32_get(unit, mem, entry, SRC_TGIDf); 2965 svp = soc_mem_field32_get(unit, mem, entry, SOURCE_VPf); 2966 iif = soc_mem_field32_get(unit, mem, entry, L3_IIFf); 2967 2968 /* skip the entries not added by flow api */ 2969 if (flow_info->iif_ref_cnt[iif] || flow_info->vp_ref_cnt[svp]) { 2970 if (port_type == 1) { /* trunk port type */ 2971 BCM_GPORT_TRUNK_SET((info + cnt)->port,tgid); 2972 } else { 2973 BCM_GPORT_MODPORT_SET((info + cnt)->port,local_modid,ent_idx); 2974 } 2975 _SHR_GPORT_FLOW_PORT_ID_SET((info + cnt)->flow_port,svp); 2976 (info + cnt)->criteria = BCM_FLOW_MATCH_CRITERIA_PORT; 2977 cnt++; 2978 } 2979 } 2980 2981 /* invoke the callback functions on each entry */ 2982 for (i = 0; i < cnt; i++) { 2983 /* skip the same trunk id */ 2984 tid_found = FALSE; 2985 for (j = 0; j < i; j++) { 2986 if (info[j].port == info[i].port) { 2987 tid_found = TRUE; 2988 break; 2989 } 2990 } 2991 if (tid_found) { 2992 continue; 2993 } 2994 rv = cb(unit,info + i,0,NULL,user_data); 2995 if (BCM_FAILURE(rv)) { 2996 soc_cm_sfree(unit, trunk_map_tbl); 2997 sal_free(info); 2998 return rv; 2999 } 3000 } 3001 3002 soc_cm_sfree(unit, trunk_map_tbl); 3003 sal_free(info); 3004 return rv; 3005 } 3006 3007 /* 3008 * Function: 3009 * _bcm_flow_match_traverse_mem 3010 * Purpose: 3011 * Read the given memory table and call the user callback function on 3012 * each entry. 3013 * Parameters: 3014 * unit - (IN) Device Number 3015 * mem - (IN) the memory id 3016 * cb - (IN) user callback function 3017 * user_data - (IN) user context data 3018 * Returns: 3019 * BCM_E_XXX 3020 */ 3021 3022 STATIC int 3023 _bcm_flow_match_traverse_mem(int unit, soc_mem_t mem, 3024 bcm_flow_match_traverse_cb cb, 3025 void *user_data) 3026 { 3027 /* Indexes to iterate over memories, chunks and entries */ 3028 int chnk_idx, ent_idx, chnk_idx_max, mem_idx_max; 3029 int buf_size, chunksize, chnk_end; 3030 /* Buffer to store chunk of table we currently work on */ 3031 uint32 *vt_tbl_chnk; 3032 uint32 *entry; 3033 int valid, rv = BCM_E_NONE; 3034 bcm_flow_match_config_t info; 3035 uint32 num_of_fields = _BCM_FLOW_LOGICAL_FIELD_MAX; 3036 bcm_flow_logical_field_t field[_BCM_FLOW_LOGICAL_FIELD_MAX]; 3037 3038 if (INVALIDm == mem) { 3039 return BCM_E_MEMORY; 3040 } 3041 if (!soc_mem_index_count(unit, mem)) { 3042 return BCM_E_NONE; 3043 } 3044 3045 chunksize = soc_property_get(unit, spn_VLANDELETE_CHUNKS, 3046 VLAN_MEM_CHUNKS_DEFAULT); 3047 3048 buf_size = 4 * SOC_MAX_MEM_FIELD_WORDS * chunksize; 3049 vt_tbl_chnk = soc_cm_salloc(unit, buf_size, "flow match traverse"); 3050 if (NULL == vt_tbl_chnk) { 3051 return BCM_E_MEMORY; 3052 } 3053 3054 mem_idx_max = soc_mem_index_max(unit, mem); 3055 for (chnk_idx = soc_mem_index_min(unit, mem); 3056 chnk_idx <= mem_idx_max; 3057 chnk_idx += chunksize) { 3058 sal_memset((void *)vt_tbl_chnk, 0, buf_size); 3059 3060 chnk_idx_max = 3061 ((chnk_idx + chunksize) <= mem_idx_max) ? 3062 chnk_idx + chunksize - 1: mem_idx_max; 3063 3064 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, 3065 chnk_idx, chnk_idx_max, vt_tbl_chnk); 3066 if (SOC_FAILURE(rv)) { 3067 break; 3068 } 3069 chnk_end = (chnk_idx_max - chnk_idx); 3070 for (ent_idx = 0 ; ent_idx <= chnk_end; ent_idx ++) { 3071 entry = 3072 soc_mem_table_idx_to_pointer(unit, mem, uint32 *, 3073 vt_tbl_chnk, ent_idx); 3074 rv = _bcm_flow_match_entry_valid(unit, mem, entry, &valid); 3075 if (BCM_FAILURE(rv)) { 3076 break; 3077 } 3078 if (!valid) { 3079 continue; 3080 } 3081 bcm_flow_match_config_t_init(&info); 3082 rv = _bcm_flow_match_entry_parse(unit, mem, entry, &info, 3083 &num_of_fields,field); 3084 if (rv == BCM_E_NOT_FOUND) { /* for entries not exposed to user */ 3085 continue; 3086 } else if (BCM_FAILURE(rv)) { 3087 break; 3088 } 3089 rv = cb(unit, &info, num_of_fields,field,user_data); 3090 if (BCM_FAILURE(rv)) { 3091 break; 3092 } 3093 } 3094 } 3095 soc_cm_sfree(unit, vt_tbl_chnk); 3096 return rv; 3097 } 3098 3099 /* 3100 * Function: 3101 * _bcm_flow_match_traverse_tcam 3102 * Purpose: 3103 * Read the given memory table and call the user callback function on 3104 * each entry. 3105 * Parameters: 3106 * unit - (IN) Device Number 3107 * mem - (IN) the memory id 3108 * cb - (IN) user callback function 3109 * user_data - (IN) user context data 3110 * Returns: 3111 * BCM_E_XXX 3112 */ 3113 3114 STATIC int 3115 _bcm_flow_match_traverse_tcam(int unit, soc_mem_t mem, 3116 bcm_flow_match_traverse_cb cb, 3117 void *user_data) 3118 { 3119 /* Indexes to iterate over memories, chunks and entries */ 3120 int idx,mem_idx_max; 3121 int i; 3122 uint32 entry[_QUAD_ENTRY_MAX]; 3123 int valid, rv = BCM_E_NONE; 3124 bcm_flow_match_config_t info; 3125 uint32 num_of_fields = _BCM_FLOW_LOGICAL_FIELD_MAX; 3126 bcm_flow_logical_field_t field[_BCM_FLOW_LOGICAL_FIELD_MAX]; 3127 soc_tunnel_term_t tnl_entry; 3128 int entry_width = sizeof(tunnel_entry_t); 3129 int mode; 3130 3131 if (INVALIDm == mem) { 3132 return BCM_E_MEMORY; 3133 } 3134 3135 idx = soc_mem_index_min(unit, mem); 3136 mem_idx_max = soc_mem_index_max(unit, mem); 3137 if ((idx < 0) || (mem_idx_max < 0)) { 3138 return BCM_E_MEMORY; 3139 } 3140 while (idx <= mem_idx_max) { 3141 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, idx, 3142 (uint32 *)&tnl_entry.entry_arr[0]); 3143 SOC_IF_ERROR_RETURN(rv); 3144 3145 rv = _bcm_flow_match_entry_valid(unit, mem, 3146 (uint32 *)&tnl_entry.entry_arr[0], &valid); 3147 if (BCM_FAILURE(rv)) { 3148 break; 3149 } 3150 if (!valid) { 3151 idx++; 3152 continue; 3153 } 3154 /* copy to the memory view format */ 3155 sal_memcpy(entry,&tnl_entry.entry_arr[0],entry_width); 3156 3157 /* mode: 3158 * 0 -- single wide 3159 * 2 -- double wide 3160 * 1 -- quad wide 3161 */ 3162 mode = soc_mem_field32_get(unit, mem, 3163 (uint32 *)&tnl_entry.entry_arr[0], MODEf); 3164 3165 if (mode == _BCM_FLOW_TD3_L3_TUNNEL_DOUBLE_WIDE) { 3166 idx++; 3167 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, idx, 3168 (uint32 *)&tnl_entry.entry_arr[1]); 3169 SOC_IF_ERROR_RETURN(rv); 3170 sal_memcpy((uint8 *)entry + entry_width, 3171 &tnl_entry.entry_arr[1],entry_width); 3172 3173 } else if (mode == _BCM_FLOW_TD3_L3_TUNNEL_QUAD_WIDE) { 3174 for (i = 1; (i < COUNTOF(tnl_entry.entry_arr)) && 3175 (i < SOC_TNL_TERM_ENTRY_WIDTH_QUAD); i++) { 3176 idx++; 3177 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, idx, 3178 (uint32 *)&tnl_entry.entry_arr[i]); 3179 SOC_IF_ERROR_RETURN(rv); 3180 sal_memcpy((uint8 *)entry + entry_width * i, 3181 &tnl_entry.entry_arr[i],entry_width); 3182 } 3183 } 3184 idx++; 3185 3186 bcm_flow_match_config_t_init(&info); 3187 rv = _bcm_flow_match_entry_parse(unit, mem, entry, &info, 3188 &num_of_fields,field); 3189 if (rv == BCM_E_NOT_FOUND) { /* for entries not exposed to user */ 3190 continue; 3191 } else if (BCM_FAILURE(rv)) { 3192 break; 3193 } 3194 rv = cb(unit, &info, num_of_fields,field,user_data); 3195 if (BCM_FAILURE(rv)) { 3196 break; 3197 } 3198 } 3199 return rv; 3200 } 3201 3202 /* 3203 * Function: 3204 * bcmi_esw_flow_match_traverse 3205 * Purpose: 3206 * Traverse flow match entries and call the user callback function on 3207 * each entry. 3208 * Parameters: 3209 * unit - (IN) Device Number 3210 * info - (IN) Flow match config descriptor 3211 * num_of_fields - (IN) number of logical fields 3212 * field - (IN) logical field array 3213 * cb - (IN) user callback function 3214 * user_data - (IN) user context data 3215 * Returns: 3216 * BCM_E_XXX 3217 */ 3218 3219 int bcmi_esw_flow_match_traverse( 3220 int unit, 3221 bcm_flow_match_traverse_cb cb, 3222 void *user_data) 3223 { 3224 /* XXX remove info, num_of_fields, field parameters. Add option field 3225 * to select traverse the port table or hash table: vxlate/mpls 3226 */ 3227 soc_mem_t mem; 3228 int rv; 3229 _bcm_flow_bookkeeping_t *flow_info; 3230 3231 if (cb == NULL) { 3232 return BCM_E_PARAM; 3233 } 3234 flow_info = FLOW_INFO(unit); 3235 3236 /* traverse the port table */ 3237 rv = _bcm_flow_match_trunk_mem_traverse(unit, cb, user_data); 3238 BCM_IF_ERROR_RETURN(rv); 3239 3240 /* traverse the vlan_xlate_1 first */ 3241 if (flow_info->mem_use_cnt[_BCM_FLOW_VXLT1_INX]) { 3242 mem = VLAN_XLATE_1_DOUBLEm; 3243 rv = _bcm_flow_match_traverse_mem(unit, mem, cb, user_data); 3244 BCM_IF_ERROR_RETURN(rv); 3245 } 3246 3247 /* traverse the vlan_xlate_2 */ 3248 if (flow_info->mem_use_cnt[_BCM_FLOW_VXLT2_INX]) { 3249 mem = VLAN_XLATE_2_DOUBLEm; 3250 rv = _bcm_flow_match_traverse_mem(unit, mem, cb, user_data); 3251 BCM_IF_ERROR_RETURN(rv); 3252 } 3253 3254 /* traverse the mpls_entry next */ 3255 if (flow_info->mem_use_cnt[_BCM_FLOW_MPLS_INX]) { 3256 mem = MPLS_ENTRYm; 3257 rv = _bcm_flow_match_traverse_mem(unit, mem, cb, user_data); 3258 BCM_IF_ERROR_RETURN(rv); 3259 3260 mem = MPLS_ENTRY_SINGLEm; 3261 rv = _bcm_flow_match_traverse_mem(unit, mem, cb, user_data); 3262 BCM_IF_ERROR_RETURN(rv); 3263 } 3264 3265 /* traverse the l3_tunnel */ 3266 if (flow_info->mem_use_cnt[_BCM_FLOW_TNL_INX]) { 3267 mem = L3_TUNNELm; 3268 rv = _bcm_flow_match_traverse_tcam(unit, mem, cb, user_data); 3269 BCM_IF_ERROR_RETURN(rv); 3270 } 3271 3272 return rv; 3273 } 3274 3275 /* 3276 * Function: 3277 * bcmi_esw_flow_match_svp_replace 3278 * Purpose: 3279 * replace SVP in a flow match 3280 * Parameters: 3281 * unit - (IN) Device Number 3282 * gport - (IN) Flow gport 3283 * new_vp - (IN) new VP used to repalce 3284 * Returns: 3285 * BCM_E_XXX 3286 */ 3287 int bcmi_esw_flow_match_svp_replace( 3288 int unit, 3289 int gport, 3290 int new_vp) 3291 { 3292 /* L3_TUNNELm could support 4 entry wide view definition */ 3293 uint32 entry[_QUAD_ENTRY_MAX]; 3294 int rv; 3295 _bcm_flow_bookkeeping_t *flow_info; 3296 int replaced_vp; 3297 int vp; 3298 soc_flow_db_mem_view_info_t view_info; 3299 bcm_flow_match_vp_t* match_key; 3300 bcm_flow_match_config_t *info; 3301 3302 flow_info = FLOW_INFO(unit); 3303 3304 /* validate the vp */ 3305 vp = _SHR_GPORT_FLOW_PORT_ID_GET(gport); 3306 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeFlow)) { 3307 LOG_ERROR(BSL_LS_BCM_FLOW, 3308 (BSL_META_U(unit, "flow port ID is not valid\n"))); 3309 3310 return BCM_E_PORT; 3311 } 3312 3313 match_key = &flow_info->match_key[vp]; 3314 info = sal_alloc(sizeof(*info), 3315 "flow match svp replace"); 3316 if (NULL == info) { 3317 return BCM_E_MEMORY; 3318 } 3319 sal_memset(info, 0, sizeof(*info)); 3320 if (match_key->vlan) { 3321 info->valid_elements |= BCM_FLOW_MATCH_VLAN_VALID; 3322 info->vlan = match_key->vlan; 3323 } 3324 if (match_key->inner_vlan) { 3325 info->valid_elements |= BCM_FLOW_MATCH_INNER_VLAN_VALID; 3326 info->inner_vlan= match_key->inner_vlan; 3327 } 3328 if (match_key->port) { 3329 info->valid_elements |= BCM_FLOW_MATCH_PORT_VALID; 3330 info->port = match_key->port; 3331 } 3332 if (match_key->sip) { 3333 info->valid_elements |= BCM_FLOW_MATCH_SIP_VALID; 3334 info->sip = match_key->sip; 3335 } 3336 if (bcmi_flow_ip6_addr_is_valid(match_key->sip6)) { 3337 info->valid_elements |= BCM_FLOW_MATCH_SIP_V6_VALID; 3338 sal_memcpy(info->sip6, match_key->sip6, BCM_IP6_ADDRLEN); 3339 } 3340 info->criteria = match_key->criteria; 3341 info->flow_handle = match_key->flow_handle; 3342 info->flow_option = match_key->flow_option; 3343 3344 _SHR_GPORT_FLOW_PORT_ID_SET(info->flow_port,new_vp); 3345 info->valid_elements |= BCM_FLOW_MATCH_FLOW_PORT_VALID; 3346 info->options = BCM_FLOW_MATCH_OPTION_REPLACE; 3347 3348 /* port match doesn't use hash table */ 3349 if (info->criteria == BCM_FLOW_MATCH_CRITERIA_PORT) { 3350 rv = _bcm_flow_match_port_ctrl(unit,info, 3351 _BCM_FLOW_MATCH_PORT_CTRL_SET,&replaced_vp,NULL); 3352 if (SOC_FAILURE(rv)) { 3353 sal_free(info); 3354 return rv; 3355 } 3356 bcmi_esw_flow_lock(unit); 3357 if (info->valid_elements & BCM_FLOW_MATCH_FLOW_PORT_VALID) { 3358 vp = _SHR_GPORT_FLOW_PORT_ID_GET(info->flow_port); 3359 if (vp) { 3360 flow_info->vp_ref_cnt[vp]++; 3361 } 3362 if (replaced_vp) { 3363 if (flow_info->vp_ref_cnt[replaced_vp]) { 3364 flow_info->vp_ref_cnt[replaced_vp]--; 3365 } 3366 } 3367 } 3368 bcmi_esw_flow_unlock(unit); 3369 sal_free(info); 3370 return BCM_E_NONE; 3371 } 3372 3373 sal_memset(entry, 0, sizeof(entry)); 3374 rv = _bcm_flow_match_key_set(unit,info,NULL, 3375 0,entry,&view_info); 3376 if (SOC_FAILURE(rv)) { 3377 sal_free(info); 3378 return rv; 3379 } 3380 3381 soc_mem_lock(unit,view_info.mem); 3382 /* set the match object and attributes and write to memory */ 3383 rv = _bcm_flow_match_entry_set(unit,info,NULL, 3384 0, 3385 &view_info, 3386 entry, NULL ,&replaced_vp); 3387 soc_mem_unlock(unit,view_info.mem); 3388 3389 bcmi_esw_flow_lock(unit); 3390 if (BCM_SUCCESS(rv)) { 3391 if (info->valid_elements & BCM_FLOW_MATCH_FLOW_PORT_VALID) { 3392 vp = _SHR_GPORT_FLOW_PORT_ID_GET(info->flow_port); 3393 flow_info->vp_ref_cnt[vp]++; 3394 if (info->options & BCM_FLOW_MATCH_OPTION_REPLACE) { 3395 if (flow_info->vp_ref_cnt[replaced_vp]) { 3396 flow_info->vp_ref_cnt[replaced_vp]--; 3397 } 3398 } 3399 } 3400 } 3401 bcmi_esw_flow_unlock(unit); 3402 sal_free(info); 3403 return rv; 3404 } 3405 3406 /* 3407 * Function: 3408 * bcmi_esw_flow_match_get 3409 * Purpose: 3410 * get VP_LAG SVP from a flow match entry 3411 * Parameters: 3412 * unit - (IN) Device Number 3413 * gport - (IN) Flow gport 3414 * vp_lag_vp - (IN) ptr of vp lag VP 3415 * Returns: 3416 * BCM_E_XXX 3417 */ 3418 3419 int bcmi_esw_flow_match_svp_get( 3420 int unit, 3421 bcm_gport_t gport, 3422 int* vp_lag_vp) 3423 { 3424 _bcm_flow_bookkeeping_t *flow_info; 3425 bcm_flow_match_vp_t* match_key; 3426 bcm_flow_match_config_t *info; 3427 int vp; 3428 int rv; 3429 3430 flow_info = FLOW_INFO(unit); 3431 3432 /* validate the vp */ 3433 vp = _SHR_GPORT_FLOW_PORT_ID_GET(gport); 3434 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeFlow)) { 3435 LOG_ERROR(BSL_LS_BCM_FLOW, 3436 (BSL_META_U(unit, "flow port ID is not valid\n"))); 3437 return BCM_E_PORT; 3438 } 3439 3440 match_key = &flow_info->match_key[vp]; 3441 info = sal_alloc(sizeof(*info), 3442 "flow match svp get"); 3443 if (NULL == info) { 3444 return BCM_E_MEMORY; 3445 } 3446 sal_memset(info, 0, sizeof(*info)); 3447 if (match_key->vlan) { 3448 info->valid_elements |= BCM_FLOW_MATCH_VLAN_VALID; 3449 info->vlan = match_key->vlan; 3450 } 3451 if (match_key->inner_vlan) { 3452 info->valid_elements |= BCM_FLOW_MATCH_INNER_VLAN_VALID; 3453 info->inner_vlan= match_key->inner_vlan; 3454 } 3455 if (match_key->port) { 3456 info->valid_elements |= BCM_FLOW_MATCH_PORT_VALID; 3457 info->port = match_key->port; 3458 } 3459 if (match_key->sip) { 3460 info->valid_elements |= BCM_FLOW_MATCH_SIP_VALID; 3461 info->sip = match_key->sip; 3462 } 3463 if (bcmi_flow_ip6_addr_is_valid(match_key->sip6)) { 3464 info->valid_elements |= BCM_FLOW_MATCH_SIP_V6_VALID; 3465 sal_memcpy(info->sip6, match_key->sip6, BCM_IP6_ADDRLEN); 3466 } 3467 info->criteria = match_key->criteria; 3468 info->flow_handle = match_key->flow_handle; 3469 info->flow_option = match_key->flow_option; 3470 3471 rv = bcmi_esw_flow_match_get(unit, info, 0, NULL); 3472 if (SOC_FAILURE(rv)) { 3473 sal_free(info); 3474 return rv; 3475 } 3476 3477 if (info->valid_elements & BCM_FLOW_MATCH_FLOW_PORT_VALID) { 3478 *vp_lag_vp = _SHR_GPORT_FLOW_PORT_ID_GET(info->flow_port); 3479 } else { 3480 sal_free(info); 3481 return BCM_E_NOT_FOUND; 3482 } 3483 3484 sal_free(info); 3485 return BCM_E_NONE; 3486 } 3487 3488 3489 #endif /* INCLUDE_L3 */ 3490