proxy.c (98742B)
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 8 9 #include <shared/bsl.h> 10 11 #include <soc/defs.h> 12 #include <soc/mem.h> 13 #include <soc/drv.h> 14 #include <sal/core/libc.h> 15 #include <sal/core/sync.h> 16 #include <soc/scache.h> 17 18 #ifdef INCLUDE_L3 19 #include <soc/drv.h> 20 #include <soc/mem.h> 21 #include <soc/util.h> 22 #include <soc/l3x.h> 23 #include <bcm/error.h> 24 #include <bcm/proxy.h> 25 #include <bcm/types.h> 26 #include <bcm/l3.h> 27 28 #include <bcm_int/esw/port.h> 29 #include <bcm_int/esw/mbcm.h> 30 #include <bcm_int/esw/firebolt.h> 31 #include <bcm_int/api_xlate_port.h> 32 #include <bcm_int/esw_dispatch.h> 33 #include <bcm_int/esw/l3.h> 34 #include <bcm_int/esw/stack.h> 35 #include <bcm_int/esw/proxy.h> 36 37 #ifdef BCM_WARM_BOOT_SUPPORT 38 #include <bcm_int/esw/switch.h> 39 #endif /* BCM_WARM_BOOT_SUPPORT */ 40 41 #if defined(BCM_TRIDENT2_SUPPORT) 42 #include <bcm_int/esw/trident2.h> 43 #endif /* BCM_TRIDENT_SUPPORT*/ 44 45 #define _BCM_PROXY_INFO_ENTRY_CREATED 0x00000001 46 #define _BCM_PROXY_INFO_GROUP_CREATED 0x00000002 47 #define _BCM_PROXY_INFO_FILTER_CREATED 0x00000004 48 #define _BCM_PROXY_INFO_INSTALLED 0x00000008 49 #define _BCM_PROXY_INFO_SERVER 0x00000010 50 51 #define _BCM_PROXY_SERVER_INSTANCES 3 52 #define _BCM_PROXY_BUD_NODE_0 0 53 #define _BCM_PROXY_BUD_NODE_1 1 54 #define _BCM_PROXY_HYBRID 2 55 56 #ifdef BCM_WARM_BOOT_SUPPORT 57 /* Warm boot scache version to store 58 * server_gport and server_gport_mask information. 59 */ 60 #define BCM_PROXY_WB_VERSION_1_0 SOC_SCACHE_VERSION(1,0) 61 #define BCM_PROXY_WB_DEFAULT_VERSION BCM_PROXY_WB_VERSION_1_0 62 #endif 63 64 #define _LOCK(unit) _bcm_proxy_control[unit].proxy_lock 65 66 #define _BCM_PROXY_LOCK(unit) \ 67 _LOCK(unit) ? sal_mutex_take(_LOCK(unit), sal_mutex_FOREVER) : -1 68 69 #define _BCM_PROXY_UNLOCK(unit) sal_mutex_give(_LOCK(unit)) 70 71 static bcmi_proxy_bookkeep_t proxy_bookkeep[BCM_MAX_NUM_UNITS]; 72 static int proxy_internal_initialized[BCM_MAX_NUM_UNITS] = {0}; 73 74 #define CHECK_PROXY_INIT(unit) \ 75 if (!proxy_internal_initialized[unit]) \ 76 return BCM_E_INIT 77 typedef struct _bcm_proxy_info_s { 78 int flags; /* _BCM_PROXY_INFO_* */ 79 bcm_port_t client_port; 80 bcm_proxy_proto_type_t proto_type; 81 bcm_module_t server_modid; 82 bcm_port_t server_port; 83 bcm_proxy_mode_t mode; 84 bcm_field_entry_t eid; 85 bcm_field_group_t gid; 86 struct _bcm_proxy_info_s *next; 87 } _bcm_proxy_info_t; 88 89 typedef struct _bcm_proxy_control_s { 90 sal_mutex_t proxy_lock; 91 _bcm_proxy_info_t *proxy_list; 92 int num_clients; 93 } _bcm_proxy_control_t; 94 95 typedef int (*proxy_install_method_t)(int unit, 96 _bcm_proxy_info_t *dst, 97 _bcm_proxy_info_t *src); 98 99 typedef int (*proxy_uninstall_method_t)(int unit, 100 _bcm_proxy_info_t *src); 101 102 typedef int (*proxy_match_method_t)(_bcm_proxy_info_t *dst, 103 _bcm_proxy_info_t *src); 104 105 typedef struct { 106 proxy_install_method_t install; 107 proxy_uninstall_method_t uninstall; 108 proxy_match_method_t match; 109 } _bcm_proxy_ifc_t; 110 111 STATIC int 112 _bcm_esw_proxy_client_install_xgs3(int unit, _bcm_proxy_info_t *info); 113 114 STATIC int 115 _bcm_esw_proxy_client_install(int unit, 116 _bcm_proxy_info_t *dst, 117 _bcm_proxy_info_t *src); 118 119 STATIC int 120 _bcm_esw_proxy_client_uninstall_xgs3(int unit, _bcm_proxy_info_t *info); 121 122 STATIC int 123 _bcm_esw_proxy_client_uninstall(int unit, _bcm_proxy_info_t *info); 124 125 STATIC int 126 _bcm_esw_proxy_client_match(_bcm_proxy_info_t *dst, _bcm_proxy_info_t *src); 127 128 STATIC int 129 _bcm_esw_proxy_server_install(int unit, 130 _bcm_proxy_info_t *dst, 131 _bcm_proxy_info_t *src); 132 133 STATIC int 134 _bcm_esw_proxy_server_uninstall(int unit, 135 _bcm_proxy_info_t *src); 136 137 STATIC int 138 _bcm_esw_proxy_server_match(_bcm_proxy_info_t *dst, _bcm_proxy_info_t *src); 139 140 static _bcm_proxy_control_t _bcm_proxy_control[BCM_MAX_NUM_UNITS]; 141 142 STATIC 143 _bcm_proxy_ifc_t client_methods = { 144 _bcm_esw_proxy_client_install, 145 _bcm_esw_proxy_client_uninstall, 146 _bcm_esw_proxy_client_match, 147 }; 148 149 STATIC 150 _bcm_proxy_ifc_t server_methods = { 151 _bcm_esw_proxy_server_install, 152 _bcm_esw_proxy_server_uninstall, 153 _bcm_esw_proxy_server_match, 154 }; 155 156 /***************************************************************** Utilities */ 157 158 /* 159 * Function: 160 * _bcm_esw_proxy_gport_resolve 161 * Purpose: 162 * Decodes gport into port and module id 163 * Parameters: 164 * unit - BCM Unit number 165 * gport - GPORT 166 * port_out - (OUT) port encoded into gport 167 * modid_out - (OUT) modid encoded into gport 168 * isLocal - Indicator that port encoded in gport must be local 169 * Returns: 170 * BCM_E_XXX 171 */ 172 STATIC int 173 _bcm_esw_proxy_gport_resolve(int unit, bcm_gport_t gport, 174 bcm_port_t *port_out, 175 bcm_module_t *modid_out, int isLocal) 176 { 177 178 bcm_port_t port; 179 bcm_module_t modid; 180 bcm_trunk_t tgid; 181 int id; 182 183 if (NULL == port_out || NULL == modid_out) { 184 return BCM_E_PARAM; 185 } 186 187 BCM_IF_ERROR_RETURN( 188 _bcm_esw_gport_resolve(unit, gport, &modid, &port, &tgid, &id)); 189 190 if ((-1 != id) || (BCM_TRUNK_INVALID != tgid)){ 191 return BCM_E_PORT; 192 } 193 194 if (isLocal) { 195 int ismymodid; 196 BCM_IF_ERROR_RETURN( 197 _bcm_esw_modid_is_local(unit, modid, &ismymodid)); 198 if (ismymodid != TRUE) { 199 return BCM_E_PARAM; 200 } 201 } 202 203 *port_out = port; 204 *modid_out = modid; 205 206 return BCM_E_NONE; 207 } 208 209 /****************************************************************** Generics */ 210 211 /* 212 * Function: 213 * _bcm_esw_proxy_install 214 * Purpose: 215 * Install proxy client or server 216 * Parameters: 217 * unit - BCM Unit number 218 * bcm_proxy_ifc - local port for which redirection is applied 219 * data - Packet type to classify for redirection 220 * Returns: 221 * BCM_E_XXX 222 */ 223 int 224 _bcm_esw_proxy_install(int unit, 225 _bcm_proxy_ifc_t *ifc, 226 _bcm_proxy_info_t *src) 227 { 228 int rv = BCM_E_INTERNAL; 229 _bcm_proxy_info_t *dst; 230 231 /* Allocate proxy info structure */ 232 dst = sal_alloc(sizeof(_bcm_proxy_info_t), "bcm_esw_proxy"); 233 234 if (dst == NULL) { 235 return BCM_E_MEMORY; 236 } 237 238 sal_memset(dst, 0, sizeof(_bcm_proxy_info_t)); 239 240 if (_BCM_PROXY_LOCK(unit)) { 241 sal_free(dst); 242 return BCM_E_INIT; 243 } 244 245 rv = ifc->install(unit, dst, src); 246 247 if (BCM_SUCCESS(rv)) { 248 /* Put onto list */ 249 dst->next = _bcm_proxy_control[unit].proxy_list; 250 _bcm_proxy_control[unit].proxy_list = dst; 251 } else { 252 sal_free(dst); 253 } 254 255 _BCM_PROXY_UNLOCK(unit); 256 257 return rv; 258 } 259 260 /* 261 * Function: 262 * _bcm_esw_proxy_uninstall 263 * Purpose: 264 * Uninstall proxy client or server 265 * Parameters: 266 * unit - BCM Unit number 267 * ifc - client/server methods 268 * info - info record to uninstall 269 * Returns: 270 * BCM_E_XXX 271 */ 272 int 273 _bcm_esw_proxy_uninstall(int unit, 274 _bcm_proxy_ifc_t *ifc, 275 _bcm_proxy_info_t *src) 276 { 277 int rv = BCM_E_INTERNAL; 278 _bcm_proxy_info_t *dst; 279 280 if (_BCM_PROXY_LOCK(unit)) { 281 return BCM_E_INIT; 282 } 283 284 /* Uninstall the enabled proxy client if the hardware is still 285 capable. */ 286 if (SOC_HW_ACCESS_DISABLE(unit) == 0) { 287 rv = ifc->uninstall(unit, src); 288 } else { 289 rv = BCM_E_NONE; 290 } 291 /* Unlink from list */ 292 if (_bcm_proxy_control[unit].proxy_list == src) { 293 /* Info at beginning of the list */ 294 _bcm_proxy_control[unit].proxy_list = src->next; 295 } else { 296 for (dst = _bcm_proxy_control[unit].proxy_list; 297 dst != NULL; 298 dst = dst->next) { 299 if (dst->next == src) { 300 dst->next = src->next; 301 break; 302 } 303 } 304 } 305 _BCM_PROXY_UNLOCK(unit); 306 307 sal_memset(src, 0, sizeof(_bcm_proxy_info_t)); 308 sal_free(src); 309 310 return rv; 311 } 312 313 /* 314 * Function: 315 * _bcm_esw_proxy_find 316 * Purpose: 317 * Find a previously created proxy client or server 318 * Parameters: 319 * unit - BCM Unit number 320 * ifc - interface methods 321 * src - data to find 322 * dstp - data found, or NULL 323 * Returns: 324 * BCM_E_NONE - found 325 * BCM_E_NOTFOUND - not found 326 * BCM_E_INIT - subsystem not initialized 327 */ 328 329 STATIC int 330 _bcm_esw_proxy_find(int unit, 331 _bcm_proxy_ifc_t *ifc, 332 _bcm_proxy_info_t *src, 333 _bcm_proxy_info_t **dstp) 334 { 335 _bcm_proxy_info_t *dst; 336 int rv = BCM_E_NOT_FOUND; 337 338 if (_BCM_PROXY_LOCK(unit)) { 339 return BCM_E_INIT; 340 } 341 342 for (dst = _bcm_proxy_control[unit].proxy_list; 343 dst != NULL; 344 dst = dst->next) { 345 if (ifc->match(dst, src)) { 346 rv = BCM_E_EXISTS; 347 break; 348 } 349 } 350 _BCM_PROXY_UNLOCK(unit); 351 *dstp = dst; 352 353 return rv; 354 } 355 356 /* 357 * Function: 358 * _bcm_esw_proxy 359 * Purpose: 360 * Generic proxy client or server install or uninstall 361 * Parameters: 362 * unit - BCM Unit number 363 * ifc - interface methods 364 * src - data to find 365 * Returns: 366 * Pointer to _bcm_proxy_info_t if found 367 * NULL if not found 368 */ 369 370 STATIC int 371 _bcm_esw_proxy(int unit, _bcm_proxy_ifc_t *ifc, 372 _bcm_proxy_info_t *src, int enable) 373 { 374 int rv; 375 _bcm_proxy_info_t *dst = NULL; 376 377 rv = _bcm_esw_proxy_find(unit, ifc, src, &dst); 378 379 if (enable) { 380 381 if (rv != BCM_E_NOT_FOUND) { 382 return rv; 383 } 384 385 rv = _bcm_esw_proxy_install(unit, ifc, src); 386 387 } else { 388 /* Disable */ 389 390 if (rv != BCM_E_EXISTS) { 391 return rv; 392 } 393 394 rv = _bcm_esw_proxy_uninstall(unit, ifc, dst); 395 396 } 397 398 return rv; 399 } 400 401 /******************************************************************** Client */ 402 403 /* 404 * Function: 405 * _bcm_proxy_client_enabled 406 * Purpose: 407 * Returns true if the proxy client is enabled on the given unit 408 * Parameters: 409 * unit - BCM Unit number 410 * Returns: 411 * TRUE or FALSE 412 */ 413 414 int 415 _bcm_proxy_client_enabled(int unit) 416 { 417 return (_bcm_proxy_control[unit].num_clients > 0); 418 } 419 420 /* 421 * Function: 422 * bcm_esw_proxy_client_set 423 * Purpose: 424 * Enables redirection for a certain traffic type using either 425 * FFP or FP rule 426 * Parameters: 427 * unit - BCM Unit number 428 * client_port - local port for which redirection is applied 429 * proto_type - Packet type to classify for redirection 430 * server_modid - Module ID of remote device which performs lookups 431 * server_port - Port on remote device where redirected packets are 432 * destined to 433 * enable - toggle to enable or disable redirection 434 * Returns: 435 * BCM_E_XXX 436 */ 437 int 438 bcm_esw_proxy_client_set(int unit, bcm_port_t client_port, 439 bcm_proxy_proto_type_t proto_type, 440 bcm_module_t server_modid, bcm_port_t server_port, 441 int enable) 442 { 443 _bcm_proxy_info_t src; 444 445 if (BCM_GPORT_IS_SET(client_port)) { 446 BCM_IF_ERROR_RETURN( 447 bcm_esw_port_local_get(unit, client_port, &client_port)); 448 } 449 if (BCM_GPORT_IS_SET(server_port)) { 450 BCM_IF_ERROR_RETURN( 451 _bcm_esw_proxy_gport_resolve(unit, server_port, &server_port, 452 &server_modid, 0)); 453 } 454 455 if (!SOC_PORT_VALID(unit, client_port)) { 456 return BCM_E_PORT; 457 } 458 if (server_port < 0 ) { 459 return BCM_E_PORT; 460 } 461 462 sal_memset(&src, 0, sizeof(_bcm_proxy_info_t)); 463 src.client_port = client_port; 464 src.proto_type = proto_type; 465 src.server_modid = server_modid; 466 src.server_port = server_port; 467 468 return _bcm_esw_proxy(unit, &client_methods, &src, enable); 469 } 470 471 /* 472 * Function: 473 * _bcm_esw_proxy_client_match 474 * Purpose: 475 * Return true if src client record matches dst 476 * Parameters: 477 * dst - 478 * src - 479 * Returns: 480 * True if matched 481 */ 482 483 STATIC int 484 _bcm_esw_proxy_client_match(_bcm_proxy_info_t *dst, _bcm_proxy_info_t *src) 485 { 486 return (dst->client_port == src->client_port && 487 dst->proto_type == src->proto_type && 488 dst->server_modid == src->server_modid && 489 dst->server_port == src->server_port && 490 (dst->flags & _BCM_PROXY_INFO_SERVER) == 0); 491 } 492 493 /* 494 * Function: 495 * _bcm_esw_proxy_server_match 496 * Purpose: 497 * Return true if src server record matches dst 498 * Parameters: 499 * dst - 500 * src - 501 * Returns: 502 * True if matched 503 */ 504 505 STATIC int 506 _bcm_esw_proxy_server_match(_bcm_proxy_info_t *dst, 507 _bcm_proxy_info_t *src) 508 { 509 return (dst->mode == src->mode && 510 dst->server_port == src->server_port && 511 (dst->flags & _BCM_PROXY_INFO_SERVER) != 0); 512 } 513 514 /* 515 * Function: 516 * _bcm_esw_proxy_client_create_xgs3 517 * Purpose: 518 * Creates proxy client using FP rules, doesn't clean up on error 519 * Parameters: 520 * unit - BCM Unit number 521 * bcm_proxy_info - proxy data 522 * Returns: 523 * BCM_E_XXX 524 */ 525 526 STATIC int 527 _bcm_esw_proxy_client_create_xgs3(int unit, _bcm_proxy_info_t *bcm_proxy_info) 528 { 529 #ifdef BCM_XGS3_SWITCH_SUPPORT 530 _field_stage_t *stage_fc=NULL; /* Stage Field control structure. */ 531 bcm_port_config_t pc; /* Port Configuration structure. */ 532 bcm_field_group_config_t fg; /* Group configuration structure. */ 533 int instance=0; /* Pipe instance. */ 534 bcm_pbmp_t mask_pbmp; /* IPBM mask. */ 535 bcm_field_entry_t eid; 536 bcm_field_group_t gid; 537 bcm_pbmp_t ingress_pbmp; 538 bcm_port_t client_port = bcm_proxy_info->client_port; 539 bcm_proxy_proto_type_t proto_type = bcm_proxy_info->proto_type; 540 bcm_module_t server_modid = bcm_proxy_info->server_modid; 541 bcm_port_t server_port = bcm_proxy_info->server_port; 542 543 BCM_PBMP_PORT_SET(ingress_pbmp, client_port); 544 545 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, _BCM_FIELD_STAGE_INGRESS, &stage_fc)); 546 547 bcm_port_config_t_init(&pc); 548 BCM_IF_ERROR_RETURN(bcm_esw_port_config_get(unit, &pc)); 549 550 bcm_field_group_config_t_init(&fg); 551 instance = SOC_INFO(unit).port_pipe[client_port]; 552 mask_pbmp = PBMP_ALL(unit); 553 554 /* Replace chip name check with feature check to make it work for TD3 also similar to TH */ 555 if (soc_feature(unit, soc_feature_multi_pipe_mapped_ports) || SOC_IS_TOMAHAWKX(unit)) { 556 switch (stage_fc->oper_mode) { 557 case bcmFieldGroupOperModeGlobal: 558 break; 559 case bcmFieldGroupOperModePipeLocal: 560 fg.ports = pc.per_pipe[instance]; 561 fg.flags |= BCM_FIELD_GROUP_CREATE_WITH_PORT; 562 mask_pbmp = PBMP_PIPE(unit,instance); 563 break; 564 default: 565 return (BCM_E_INTERNAL); 566 } 567 } 568 569 BCM_FIELD_QSET_INIT(fg.qset); 570 if (soc_feature(unit,soc_feature_td3_style_proxy)) { 571 /* TD3 does not support per-port IPBM, instead using 572 device port will suffice in this scenario */ 573 BCM_FIELD_QSET_ADD(fg.qset, bcmFieldQualifyInPort); 574 } else { 575 BCM_FIELD_QSET_ADD(fg.qset, bcmFieldQualifyInPorts); 576 } 577 578 switch(proto_type) { 579 case BCM_PROXY_PROTO_IP4_ALL: 580 BCM_FIELD_QSET_ADD(fg.qset, bcmFieldQualifyEtherType); 581 break; 582 case BCM_PROXY_PROTO_IP6_ALL: 583 BCM_FIELD_QSET_ADD(fg.qset, bcmFieldQualifyEtherType); 584 break; 585 case BCM_PROXY_PROTO_IP4_MCAST: 586 BCM_FIELD_QSET_ADD(fg.qset, bcmFieldQualifyDstIp); 587 break; 588 case BCM_PROXY_PROTO_IP6_MCAST: 589 BCM_FIELD_QSET_ADD(fg.qset, bcmFieldQualifyIpType); 590 BCM_FIELD_QSET_ADD(fg.qset, bcmFieldQualifyDstIp6High); 591 break; 592 case BCM_PROXY_PROTO_MPLS_UCAST: 593 BCM_FIELD_QSET_ADD(fg.qset, bcmFieldQualifyEtherType); 594 break; 595 case BCM_PROXY_PROTO_MPLS_MCAST: 596 BCM_FIELD_QSET_ADD(fg.qset, bcmFieldQualifyEtherType); 597 break; 598 case BCM_PROXY_PROTO_MPLS_ALL: 599 BCM_FIELD_QSET_ADD(fg.qset, bcmFieldQualifyEtherType); 600 break; 601 case BCM_PROXY_PROTO_IP6_IN_IP4: 602 BCM_FIELD_QSET_ADD(fg.qset, bcmFieldQualifyIpProtocol); 603 break; 604 case BCM_PROXY_PROTO_IP_IN_IP: 605 BCM_FIELD_QSET_ADD(fg.qset, bcmFieldQualifyIpProtocol); 606 break; 607 case BCM_PROXY_PROTO_GRE_IN_IP: 608 BCM_FIELD_QSET_ADD(fg.qset, bcmFieldQualifyIpProtocol); 609 break; 610 case BCM_PROXY_PROTO_UNKNOWN_IP4_UCAST: 611 BCM_FIELD_QSET_ADD(fg.qset, bcmFieldQualifyEtherType); 612 BCM_FIELD_QSET_ADD(fg.qset, bcmFieldQualifyPacketRes); 613 break; 614 /* coverity[equality_cond] */ 615 case BCM_PROXY_PROTO_UNKNOWN_IP6_UCAST: 616 BCM_FIELD_QSET_ADD(fg.qset, bcmFieldQualifyEtherType); 617 BCM_FIELD_QSET_ADD(fg.qset, bcmFieldQualifyPacketRes); 618 break; 619 default: 620 return BCM_E_PARAM; 621 } 622 623 if (soc_feature(unit,soc_feature_td3_style_proxy)) { 624 /* For TD3,ensure adding ASET at the group creation phase to avoid 625 un-necessary usage of intraslice mode by default */ 626 BCM_FIELD_ASET_INIT(fg.aset); 627 BCM_FIELD_ASET_ADD(fg.aset, bcmFieldActionRedirect); 628 } 629 BCM_IF_ERROR_RETURN(bcm_esw_field_group_config_create(unit, &fg)); 630 gid = fg.group; 631 632 bcm_proxy_info->flags |= _BCM_PROXY_INFO_GROUP_CREATED; 633 bcm_proxy_info->gid = gid; 634 635 BCM_IF_ERROR_RETURN(bcm_esw_field_entry_create(unit, gid, &eid)); 636 bcm_proxy_info->flags |= _BCM_PROXY_INFO_ENTRY_CREATED; 637 bcm_proxy_info->eid = eid; 638 639 if (soc_feature(unit,soc_feature_td3_style_proxy)) { 640 /* TD3 does not support per-port IPBM, instead using 641 device port will suffice in this scenario */ 642 BCM_IF_ERROR_RETURN 643 (bcm_esw_field_qualify_InPort(unit, eid, client_port, 644 BCM_FIELD_EXACT_MATCH_MASK)); 645 } else { 646 BCM_IF_ERROR_RETURN 647 (bcm_esw_field_qualify_InPorts(unit, eid, ingress_pbmp, 648 mask_pbmp)); 649 } 650 651 switch(proto_type) { 652 case BCM_PROXY_PROTO_IP4_ALL: 653 BCM_IF_ERROR_RETURN 654 (bcm_esw_field_qualify_EtherType(unit, eid, 0x0800, 0xffff)); 655 break; 656 case BCM_PROXY_PROTO_IP6_ALL: 657 BCM_IF_ERROR_RETURN 658 (bcm_esw_field_qualify_EtherType(unit, eid, 0x86dd, 0xffff)); 659 break; 660 case BCM_PROXY_PROTO_IP4_MCAST: 661 BCM_IF_ERROR_RETURN 662 (bcm_esw_field_qualify_DstIp(unit, eid, 0xe0000000, 0xf0000000)); 663 break; 664 case BCM_PROXY_PROTO_IP6_MCAST: 665 { 666 bcm_ip6_t addr, mask; 667 BCM_IF_ERROR_RETURN 668 (bcm_esw_field_qualify_IpType(unit, eid, bcmFieldIpTypeIpv6)); 669 sal_memset(addr, 0, 16); /* BCM_IP6_ADDRLEN */ 670 addr[0] = 0xff; 671 sal_memset(mask, 0, 16); /* BCM_IP6_ADDRLEN */ 672 mask[0] = 0xff; 673 mask[1] = 0xff; 674 BCM_IF_ERROR_RETURN 675 (bcm_esw_field_qualify_DstIp6High(unit, eid, addr, mask)); 676 break; 677 } 678 679 case BCM_PROXY_PROTO_MPLS_UCAST: 680 BCM_IF_ERROR_RETURN 681 (bcm_esw_field_qualify_EtherType(unit, eid, 0x8847, 0xffff)); 682 break; 683 case BCM_PROXY_PROTO_MPLS_MCAST: 684 BCM_IF_ERROR_RETURN 685 (bcm_esw_field_qualify_EtherType(unit, eid, 0x8848, 0xffff)); 686 break; 687 case BCM_PROXY_PROTO_MPLS_ALL: 688 BCM_IF_ERROR_RETURN 689 (bcm_esw_field_qualify_EtherType(unit, eid, 0x8840, 0xfff0)); 690 break; 691 case BCM_PROXY_PROTO_IP6_IN_IP4: 692 BCM_IF_ERROR_RETURN 693 (bcm_esw_field_qualify_IpProtocol(unit, eid, 0x29, 0xff)); 694 break; 695 case BCM_PROXY_PROTO_IP_IN_IP: 696 BCM_IF_ERROR_RETURN 697 (bcm_esw_field_qualify_IpProtocol(unit, eid, 0x4, 0xff)); 698 break; 699 case BCM_PROXY_PROTO_GRE_IN_IP: 700 BCM_IF_ERROR_RETURN 701 (bcm_esw_field_qualify_IpProtocol(unit, eid, 0x2f, 0xff)); 702 break; 703 case BCM_PROXY_PROTO_UNKNOWN_IP4_UCAST: 704 BCM_IF_ERROR_RETURN 705 (bcm_esw_field_qualify_EtherType(unit, eid, 0x0800, 0xffff)); 706 BCM_IF_ERROR_RETURN 707 (bcm_esw_field_qualify_PacketRes(unit, eid, 708 BCM_FIELD_PKT_RES_L3UCUNKNOWN, 709 0xf)); 710 break; 711 case BCM_PROXY_PROTO_UNKNOWN_IP6_UCAST: 712 BCM_IF_ERROR_RETURN 713 (bcm_esw_field_qualify_EtherType(unit, eid, 0x86dd, 0xffff)); 714 BCM_IF_ERROR_RETURN 715 (bcm_esw_field_qualify_PacketRes(unit, eid, 716 BCM_FIELD_PKT_RES_L3UCUNKNOWN, 717 0xf)); 718 break; 719 /* Defensive Default */ 720 /* coverity[dead_error_begin] */ 721 default: 722 return BCM_E_PARAM; 723 } 724 725 BCM_IF_ERROR_RETURN 726 (bcm_esw_field_action_add(unit, eid, bcmFieldActionRedirect, 727 server_modid, server_port)); 728 729 BCM_IF_ERROR_RETURN 730 (bcm_esw_field_entry_install(unit, eid)); 731 732 bcm_proxy_info->flags |= _BCM_PROXY_INFO_INSTALLED; 733 return BCM_E_NONE; 734 #else 735 return BCM_E_UNAVAIL; 736 #endif 737 } 738 739 /* 740 * Function: 741 * _bcm_esw_proxy_client_uninstall_xgs3 742 * Purpose: 743 * Removes and destroys proxy client FP resources 744 * Parameters: 745 * unit - BCM Unit number 746 * bcm_proxy_info - proxy data 747 * Returns: 748 * BCM_E_XXX 749 */ 750 751 STATIC int 752 _bcm_esw_proxy_client_uninstall_xgs3(int unit, 753 _bcm_proxy_info_t *info) 754 { 755 #ifdef BCM_XGS3_SWITCH_SUPPORT 756 bcm_field_entry_t eid = info->eid; 757 bcm_field_group_t gid = info->gid; 758 int flags = info->flags; 759 760 if (flags & _BCM_PROXY_INFO_INSTALLED) { 761 BCM_IF_ERROR_RETURN(bcm_esw_field_entry_remove(unit, eid)); 762 } 763 764 if (flags & _BCM_PROXY_INFO_ENTRY_CREATED) { 765 BCM_IF_ERROR_RETURN(bcm_esw_field_entry_destroy(unit, eid)); 766 } 767 768 if (flags & _BCM_PROXY_INFO_GROUP_CREATED) { 769 BCM_IF_ERROR_RETURN(bcm_esw_field_group_destroy(unit, gid)); 770 } 771 772 return BCM_E_NONE; 773 #else 774 return BCM_E_UNAVAIL; 775 #endif 776 } 777 778 /* 779 * Function: 780 * _bcm_esw_proxy_client_install_xgs3 781 * Purpose: 782 * Creates proxy client using FP rules, clean up on error 783 * Parameters: 784 * unit - BCM Unit number 785 * bcm_proxy_info - proxy data 786 * Returns: 787 * BCM_E_XXX 788 */ 789 790 STATIC int 791 _bcm_esw_proxy_client_install_xgs3(int unit, 792 _bcm_proxy_info_t *info) 793 { 794 int rv = BCM_E_INTERNAL; 795 796 rv = _bcm_esw_proxy_client_create_xgs3(unit, info); 797 798 if (BCM_FAILURE(rv)) { 799 LOG_WARN(BSL_LS_BCM_L3, 800 (BSL_META_U(unit, 801 "Proxy: could not install client: %s\n"), 802 bcm_errmsg(rv))); 803 /* Ignore errors from uninstall */ 804 _bcm_esw_proxy_client_uninstall_xgs3(unit, info); 805 } 806 807 return rv; 808 } 809 810 /* 811 * Function: 812 * _bcm_esw_proxy_client_uninstall 813 * Purpose: 814 * Uninstall proxy client for all device families 815 * Parameters: 816 * unit - BCM Unit number 817 * bcm_proxy_info - proxy data 818 * Returns: 819 * BCM_E_XXX 820 */ 821 822 STATIC int 823 _bcm_esw_proxy_client_uninstall(int unit, _bcm_proxy_info_t *info) 824 { 825 int rv = BCM_E_INTERNAL; 826 827 if (SOC_IS_XGS3_SWITCH(unit)) { 828 rv = _bcm_esw_proxy_client_uninstall_xgs3(unit, info); 829 } 830 831 if (BCM_SUCCESS(rv)) { 832 _bcm_proxy_control[unit].num_clients--; 833 } 834 835 return rv; 836 } 837 838 839 /* 840 * Function: 841 * _bcm_esw_proxy_client_install 842 * Purpose: 843 * Install proxy client for all device families 844 * Parameters: 845 * unit - BCM Unit number 846 * bcm_proxy_info - proxy data 847 * Returns: 848 * BCM_E_XXX 849 */ 850 851 STATIC int 852 _bcm_esw_proxy_client_install(int unit, 853 _bcm_proxy_info_t *dst, 854 _bcm_proxy_info_t *src) 855 { 856 int rv = BCM_E_INTERNAL; 857 858 dst->client_port = src->client_port; 859 dst->proto_type = src->proto_type; 860 dst->server_modid = src->server_modid; 861 dst->server_port = src->server_port; 862 dst->server_port = src->server_port; 863 864 if (SOC_IS_XGS3_SWITCH(unit)) { 865 rv = _bcm_esw_proxy_client_install_xgs3(unit, dst); 866 } 867 868 if (BCM_SUCCESS(rv)) { 869 _bcm_proxy_control[unit].num_clients++; 870 } 871 return rv; 872 } 873 874 /******************************************************************** Server */ 875 /* 876 * Function: 877 * bcmi_td3_proxy_server_config (internal function) 878 * Purpose: 879 * Enables various kinds of lookups for packets coming from remote 880 * (proxy client) devices on the server side for TD3 881 * Parameters: 882 * unit - BCM Unit number 883 * server_port - Local port to which packets from remote devices are 884 * destined to 885 * mode - Indicates lookup type 886 * enable - TRUE to enable lookups 887 * FALSE to disable lookups 888 * Returns: 889 * BCM_E_XXX 890 */ 891 STATIC int 892 bcmi_td3_proxy_server_config(int unit, bcm_port_t server_port, 893 bcm_proxy_mode_t mode, int enable) 894 { 895 int ing_port = 0; 896 uint32 mod = 0; 897 static soc_field_t fields[5] = {VALIDf, DEST_MODULE_IDf, DEST_PORT_IDf, DEST_MODULE_ID_MASKf, DEST_PORT_ID_MASKf}; 898 uint32 values[5] , field_num = 5; 899 bcm_module_t modid_mask; 900 bcm_gport_t server_port_mask; 901 /* Generalize chip specific memory name*/ 902 soc_mem_t port_table = ING_DEVICE_PORTm; 903 soc_reg_t hg_reg = HG_PKT_SIGNATURE_1r; 904 uint32 ptab[SOC_MAX_MEM_WORDS]; 905 sal_memset(ptab, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS); 906 907 BCM_IF_ERROR_RETURN 908 (soc_mem_read(unit, port_table, MEM_BLOCK_ANY, server_port, ptab)); 909 if (BCM_PROXY_MODE_HIGIG == mode) { 910 soc_mem_field32_set(unit, port_table, ptab, 911 HG_LOOKUP_ENABLEf, enable ? 1 : 0); 912 soc_mem_field32_set(unit, port_table, ptab, 913 HYBRID_MODE_ENABLEf, 0); 914 } else { 915 /* BCM_PROXY_MODE_HYBRID */ 916 soc_mem_field32_set(unit, port_table, ptab, 917 HYBRID_MODE_ENABLEf, enable ? 1 : 0); 918 soc_mem_field32_set(unit, port_table, ptab, 919 HG_LOOKUP_ENABLEf, 0); 920 } 921 soc_mem_field32_set(unit, port_table, ptab, 922 USE_MH_VIDf, enable ? 1 : 0); 923 soc_mem_field32_set(unit, port_table, ptab, 924 USE_MH_PKT_PRIf, enable ? 1 : 0); 925 926 BCM_IF_ERROR_RETURN 927 (soc_mem_write(unit, port_table, MEM_BLOCK_ALL, server_port, ptab)); 928 /* 929 * Program LPORT table for the HG port; 930 * HIGIG_PACKET must not be set; MY_MODID must be 931 * set appropriately, and V4/V6 enable bits 932 */ 933 mod = soc_mem_field32_get(unit, port_table, ptab, MY_MODIDf); 934 sal_memset(ptab, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS); 935 soc_LPORT_TABm_field32_set(unit, ptab, V4L3_ENABLEf, 936 enable ? 1 : 0); 937 soc_LPORT_TABm_field32_set(unit, ptab, V6L3_ENABLEf, 938 enable ? 1 : 0); 939 soc_LPORT_TABm_field32_set(unit, ptab, V4IPMC_ENABLEf, 940 enable ? 1 : 0); 941 soc_LPORT_TABm_field32_set(unit, ptab, V6IPMC_ENABLEf, 942 enable ? 1 : 0); 943 soc_LPORT_TABm_field32_set(unit, ptab, IPMC_DO_VLANf, 944 enable ? 1 : 0); 945 soc_LPORT_TABm_field32_set(unit, ptab, FILTER_ENABLEf, 946 enable ? 1 : 0); 947 948 BCM_IF_ERROR_RETURN 949 (soc_mem_write(unit, LPORT_TABm, MEM_BLOCK_ALL, 950 server_port, ptab)); 951 952 /* Set "magic destination" to this server port to 953 match prior devices' behavior */ 954 modid_mask = ((1 << soc_reg_field_length(unit, hg_reg, DEST_MODULE_ID_MASKf)) - 1); 955 server_port_mask = ((1 << soc_reg_field_length(unit, hg_reg, DEST_PORT_ID_MASKf)) - 1); 956 957 values[0] = enable; 958 values[1] = mod; 959 values[2] = server_port; 960 values[3] = modid_mask; 961 values[4] = server_port_mask; 962 PBMP_HG_ITER(unit, ing_port) { 963 SOC_IF_ERROR_RETURN 964 (soc_reg_fields32_modify(unit, hg_reg, ing_port, 965 field_num, fields, values)); 966 } 967 return BCM_E_NONE; 968 } 969 970 /* 971 * Function: 972 * bcmi_td3_proxy_server_retrieve 973 * Purpose: 974 * Retrieves proxy related settings on the server side for TD3 device 975 * Parameters: 976 * unit - BCM Unit number 977 * server_port - Local port to which packets from remote devices are destined to 978 * mode - proxy server mode 979 * enable - (OUT) server status 980 * Returns: 981 * BCM_E_XXX 982 */ 983 STATIC int 984 bcmi_td3_proxy_server_retrieve(int unit, bcm_port_t server_port, 985 bcm_proxy_mode_t mode, int *enable) 986 { 987 uint64 hgld; 988 int hg_enable; 989 /* Generalize chip specific memory and reg name */ 990 soc_mem_t port_table = ING_DEVICE_PORTm; 991 soc_reg_t hg_reg = HG_PKT_SIGNATURE_1r; 992 uint32 ptab[SOC_MAX_MEM_WORDS]; 993 sal_memset(ptab, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS); 994 995 BCM_IF_ERROR_RETURN 996 (soc_reg64_get(unit, hg_reg, server_port, 0, &hgld)); 997 998 if (server_port == soc_reg64_field32_get(unit, hg_reg,hgld, DEST_PORT_IDf)) { 999 BCM_IF_ERROR_RETURN 1000 (soc_mem_read(unit, port_table, MEM_BLOCK_ANY, server_port, ptab)); 1001 if (BCM_PROXY_MODE_HIGIG == mode) { 1002 hg_enable = soc_mem_field32_get(unit, port_table, ptab, HG_LOOKUP_ENABLEf); 1003 } else { 1004 hg_enable = soc_mem_field32_get(unit, port_table, ptab, HYBRID_MODE_ENABLEf); 1005 } 1006 *enable = hg_enable; 1007 } 1008 return BCM_E_NONE; 1009 } 1010 1011 /* 1012 * Function: 1013 * bcmi_td3_proxy_server_signature_match (internal function) 1014 * Purpose: 1015 * Enables programming of the appropiate signature match register 1016 * to enable proxy processing on the server device based on the 1017 * type of application.(Hybrid mode or Bud-node proxy) 1018 * Parameters: 1019 * unit - (IN) Unit number. 1020 * local_ingress_port - (IN) Incoming Higig stack port 1021 * proxy_server - (IN) Proxy server configuration 1022 * hg_reg - (IN) Register used for singature match. 1023 * enable - (IN) Enable proxy server on selected Higig stack port 1024 * Returns: 1025 * BCM_E_xxx 1026 */ 1027 STATIC int 1028 bcmi_td3_proxy_server_signature_match(int unit, bcm_gport_t local_ingress_port, 1029 bcm_proxy_server_t *proxy_server, soc_reg_t hg_reg, int enable) 1030 { 1031 bcm_module_t modid = 0, modid_mask = 0, default_modid_mask; 1032 bcm_port_t server_port = 0, server_port_mask = 0, default_port_mask; 1033 uint32 field_num = 5; 1034 uint32 values[5] = {0}; 1035 static soc_field_t fields[5] = {VALIDf, DEST_MODULE_IDf, DEST_PORT_IDf, 1036 DEST_MODULE_ID_MASKf, DEST_PORT_ID_MASKf}; 1037 1038 default_modid_mask = ((1 << soc_reg_field_length(unit, hg_reg, DEST_MODULE_ID_MASKf)) - 1); 1039 default_port_mask = ((1 << soc_reg_field_length(unit, hg_reg, DEST_PORT_ID_MASKf)) - 1); 1040 BCM_IF_ERROR_RETURN 1041 (_bcm_esw_proxy_gport_resolve(unit, proxy_server->server_gport, 1042 &server_port, &modid, 0)); 1043 1044 /* Only valid flags are allowed */ 1045 if (proxy_server->flags > (BCM_PROXY_SERVER_MASK_PORT | BCM_PROXY_SERVER_KEEP_PRIORITY | 1046 BCM_PROXY_SERVER_KEEP_VID | BCM_PROXY_SERVER_MASK_MODID)) { 1047 return BCM_E_PARAM; 1048 } 1049 /* Logic to flexibly mask the destination port and/or 1050 * destination modid while performing signature match */ 1051 if (proxy_server->server_gport_mask == BCM_PROXY_SERVER_GPORT_ALL_MASK) { 1052 /* Use default full mask for modid and port unless appropriate flags are passed */ 1053 modid_mask = (proxy_server->flags & BCM_PROXY_SERVER_MASK_MODID) ? 0 : default_modid_mask; 1054 server_port_mask = (proxy_server->flags & BCM_PROXY_SERVER_MASK_PORT) ? 0 : default_port_mask; 1055 } else { 1056 modid_mask = BCM_GPORT_PROXY_MODID_GET(proxy_server->server_gport_mask); 1057 server_port_mask = BCM_GPORT_PROXY_PORT_GET(proxy_server->server_gport_mask); 1058 if (proxy_server->flags & BCM_PROXY_SERVER_MASK_MODID) { 1059 if (!(modid_mask == 0)) { 1060 /* When this flag is present, if at all user passes server_gport_mask; 1061 * then modid_mask has to be zero. Otherwise it is PARAM Error*/ 1062 return BCM_E_PARAM; 1063 } 1064 } 1065 if (proxy_server->flags & BCM_PROXY_SERVER_MASK_PORT) { 1066 if (!(server_port_mask == 0)) { 1067 /* When this flag is present, if at all user passes server_gport_mask; 1068 * then server_port_mask has to be zero. Otherwise it is PARAM Error */ 1069 return BCM_E_PARAM; 1070 } 1071 } 1072 } 1073 values[0] = enable; 1074 values[1] = modid; 1075 values[2] = server_port; 1076 values[3] = modid_mask; 1077 values[4] = server_port_mask; 1078 1079 SOC_IF_ERROR_RETURN 1080 (soc_reg_fields32_modify(unit, hg_reg, local_ingress_port, 1081 field_num, fields, values)); 1082 return BCM_E_NONE; 1083 } 1084 1085 /* 1086 * Function: 1087 * bcmi_map_hg_port_to_index(internal function) 1088 * Purpose: 1089 * Creates a mapping of all the HiGig ports to a corresponding index 1090 * in an arrya of HiGig ports. Useful in allocating optimal 1091 * memory while allocating book keeping structures. 1092 * Parameters: 1093 * unit - (IN) Unit number. 1094 * local_ingress_port - (IN) Incoming Higig stack port 1095 * mapped_index - (OUT) Index which points to the location of the 1096 * localingress port in an arry of HG ports 1097 * Returns: 1098 * BCM_E_xxx 1099 */ 1100 STATIC int 1101 bcmi_map_hg_port_to_index(int unit, bcm_gport_t local_ingress_port, int *mapped_index) 1102 { 1103 int index = 0; 1104 int i = 0; 1105 int ing_port = 0; 1106 int hg_size; 1107 int *hg_array = NULL; 1108 1109 BCM_PBMP_COUNT(PBMP_HG_ALL(unit), hg_size); 1110 hg_array = sal_alloc(sizeof(int) * hg_size, "Hg Array"); 1111 if (hg_array == NULL) { 1112 return BCM_E_MEMORY; 1113 } 1114 sal_memset(hg_array, 0, sizeof(int) * hg_size); 1115 1116 PBMP_HG_ITER(unit, ing_port) { 1117 hg_array[index] = ing_port; 1118 index++; 1119 } 1120 for (i = 0; i < hg_size; i++) { 1121 if (hg_array[i] == local_ingress_port) { 1122 *mapped_index = i; 1123 } 1124 } 1125 sal_free(hg_array); 1126 return BCM_E_NONE; 1127 } 1128 1129 /* 1130 * Function: 1131 * bcmi_td3_proxy_server_port_config 1132 * Purpose: 1133 * Enables various kinds of lookups on TD3 device on 1134 * behalf of remote legacy or XGS3 devices on a per ingress port 1135 * basis. The local ingress port is expected to be a Higig stack 1136 * port. The server_gport in the proxy_server structure is the 1137 * target BCM_GPORT_PROXY (modid,port) destination which 1138 * indicates that hybrid proxy lookup is required. 1139 * Parameters: 1140 * unit - (IN) Unit number. 1141 * local_ingress_port - (IN) Incoming Higig stack port 1142 * proxy_server - (IN) Proxy server configuration 1143 * enable - (IN) Enable proxy server on selected Higig stack port 1144 * Returns: 1145 * BCM_E_xxx 1146 */ 1147 STATIC int 1148 bcmi_td3_proxy_server_port_config(int unit, bcm_gport_t local_ingress_port, 1149 bcm_proxy_server_t *proxy_server, 1150 int enable) 1151 { 1152 bcm_gport_t server_gport = 0, server_gport_mask = 0; 1153 int i = 0; 1154 int mapped_index = 0; 1155 int cpu_port = SOC_INFO(unit).cpu_hg_index; 1156 /* Generalize chip specific memory and reg name */ 1157 soc_mem_t port_table = ING_DEVICE_PORTm; 1158 soc_reg_t hg_reg = HG_PKT_SIGNATURE_1r; 1159 static uint32 reg_val_legacy[_BCM_PROXY_RESERVED_DGLP_NUMBER] = {0}; 1160 static uint32 flow_type[_BCM_PROXY_RESERVED_DGLP_NUMBER] = {0}; 1161 static soc_reg_t config_regs[] = { 1162 HG_PKT_SIGNATURE_2r, 1163 HG_PKT_SIGNATURE_3r 1164 }; 1165 /* Use legacy registers for Bud node proxy. Will be handled by CCH 1166 to map into appropriate TD3 programming */ 1167 static soc_reg_t config_regs_legacy[] = { 1168 ING_PACKET_PROCESSING_CONTROL_0r, 1169 ING_PACKET_PROCESSING_CONTROL_1r 1170 }; 1171 static soc_field_t config_reg_fields[] = { 1172 ING_PACKET_PROCESSING_ENABLE_0f, 1173 ING_PACKET_PROCESSING_ENABLE_1f 1174 }; 1175 uint32 ptab[SOC_MAX_MEM_WORDS]; 1176 uint64 const0_64 = COMPILER_64_INIT(0,0); 1177 sal_memset(ptab, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS); 1178 1179 BCM_IF_ERROR_RETURN(soc_mem_read(unit, port_table, MEM_BLOCK_ANY, 1180 local_ingress_port, ptab)); 1181 if (enable) { 1182 server_gport = proxy_server->server_gport; 1183 if (!BCM_GPORT_IS_PROXY(server_gport)) { 1184 /* The server gport is required to be in 1185 * BCM_GPORT_PROXY format */ 1186 return BCM_E_PORT; 1187 } 1188 server_gport_mask = proxy_server->server_gport_mask; 1189 if (!(server_gport_mask == BCM_PROXY_SERVER_GPORT_ALL_MASK) && !BCM_GPORT_IS_PROXY(server_gport_mask)) { 1190 /* The server gport mask; when specified; 1191 * is required to be in BCM_GPORT_PROXY format 1192 */ 1193 return BCM_E_PARAM; 1194 } 1195 1196 BCM_IF_ERROR_RETURN 1197 (bcmi_map_hg_port_to_index(unit, local_ingress_port, &mapped_index)); 1198 if (BCM_PROXY_MODE_HIGIG == proxy_server->mode) { 1199 /* BCM_PROXY_MODE_HIGIG */ 1200 soc_mem_field32_set(unit, port_table, ptab, HG_LOOKUP_ENABLEf, 1); 1201 soc_mem_field32_set(unit, port_table, ptab, HYBRID_MODE_ENABLEf, 0); 1202 } else if (BCM_PROXY_MODE_HYBRID == proxy_server->mode) { 1203 /* BCM_PROXY_MODE_HYBRID */ 1204 soc_mem_field32_set(unit, port_table, ptab, HG_LOOKUP_ENABLEf, 0); 1205 soc_mem_field32_set(unit, port_table, ptab, HYBRID_MODE_ENABLEf, 1); 1206 BCM_IF_ERROR_RETURN 1207 (bcmi_td3_proxy_server_signature_match(unit, local_ingress_port, 1208 proxy_server, hg_reg, enable)); 1209 /* Maintain software state of proxy server in third instance of proxy_bookkeep */ 1210 sal_memcpy(&proxy_bookkeep[unit].proxy_server_copy[_BCM_PROXY_HYBRID][mapped_index], 1211 proxy_server, sizeof(bcm_proxy_server_t)); 1212 } else if (BCM_PROXY_MODE_SECOND_PASS == proxy_server->mode) { 1213 if (!soc_feature(unit, soc_feature_hg_proxy_second_pass)) { 1214 return BCM_E_UNAVAIL; 1215 } 1216 if ((proxy_server->flow_type > bcmProxySecondPassFlowTypeTrillTermination) || 1217 (proxy_server->flow_type < bcmProxySecondPassFlowTypeNone)) { 1218 return BCM_E_PARAM; 1219 } 1220 /* If exist, update the entry*/ 1221 for(i = 0; i < _BCM_PROXY_RESERVED_DGLP_NUMBER; i++) { 1222 /* Flow type is defaulted to "NONE" in CANCUN. CCH is used at SOC layer to overwrite it */ 1223 /* Retaining the legacy register and field names at BCM layer */ 1224 SOC_IF_ERROR_RETURN 1225 (soc_reg32_get(unit, config_regs_legacy[i], REG_PORT_ANY, 1226 0, ®_val_legacy[i])); 1227 flow_type[i] = soc_reg_field_get(unit,config_regs_legacy[i], 1228 reg_val_legacy[i], FLOW_TYPEf); 1229 if (proxy_server->flow_type == flow_type[i]) { 1230 soc_reg_field_set(unit,config_regs_legacy[i], 1231 ®_val_legacy[i], FLOW_TYPEf, proxy_server->flow_type); 1232 BCM_IF_ERROR_RETURN 1233 (bcmi_td3_proxy_server_signature_match(unit, local_ingress_port, 1234 proxy_server, config_regs[i], enable)); 1235 /* Maintain software state of proxy server in first two instances of proxy_bookkeep */ 1236 sal_memcpy(&proxy_bookkeep[unit].proxy_server_copy[i][mapped_index], 1237 proxy_server, sizeof(bcm_proxy_server_t)); 1238 1239 SOC_IF_ERROR_RETURN 1240 (soc_reg32_set(unit, config_regs_legacy[i], REG_PORT_ANY, 1241 0, reg_val_legacy[i])); 1242 1243 soc_mem_field32_set(unit, port_table, ptab, config_reg_fields[i], 1); 1244 soc_mem_field32_set(unit, port_table, ptab, HG_LOOKUP_ENABLEf, 0); 1245 soc_mem_field32_set(unit, port_table, ptab, REMOVE_MH_SRC_PORTf, 1); 1246 1247 BCM_IF_ERROR_RETURN 1248 (soc_mem_write(unit, port_table, MEM_BLOCK_ALL, local_ingress_port, ptab)); 1249 return BCM_E_NONE; 1250 } 1251 } 1252 1253 /* if not exist, create it */ 1254 for(i = 0; i < _BCM_PROXY_RESERVED_DGLP_NUMBER; i++) { 1255 if (bcmProxySecondPassFlowTypeNone == flow_type[i]) { 1256 soc_reg_field_set(unit,config_regs_legacy[i], 1257 ®_val_legacy[i], FLOW_TYPEf, proxy_server->flow_type); 1258 BCM_IF_ERROR_RETURN 1259 (bcmi_td3_proxy_server_signature_match(unit, local_ingress_port, 1260 proxy_server, config_regs[i], enable)); 1261 /* Maintain software state of proxy server in first two instances of proxy_bookkeep */ 1262 sal_memcpy(&proxy_bookkeep[unit].proxy_server_copy[i][mapped_index], 1263 proxy_server, sizeof(bcm_proxy_server_t)); 1264 1265 SOC_IF_ERROR_RETURN 1266 (soc_reg32_set(unit, config_regs_legacy[i], REG_PORT_ANY, 1267 0, reg_val_legacy[i])); 1268 1269 soc_mem_field32_set(unit, port_table, ptab, config_reg_fields[i], 1); 1270 soc_mem_field32_set(unit, port_table, ptab, HG_LOOKUP_ENABLEf, 0); 1271 soc_mem_field32_set(unit, port_table, ptab, REMOVE_MH_SRC_PORTf, 1); 1272 1273 BCM_IF_ERROR_RETURN 1274 (soc_mem_write(unit, port_table, MEM_BLOCK_ALL, local_ingress_port, ptab)); 1275 return BCM_E_NONE; 1276 } 1277 } 1278 return BCM_E_FULL; 1279 } else { 1280 /* We don't support BCM_PROXY_MODE_LOOPBACK in this per-port 1281 * version of the API. 1282 */ 1283 return BCM_E_PARAM; 1284 } 1285 /* Keeping TD3 code consistent with other devices in the 1286 * interpretation of the two flags for using info from module header */ 1287 soc_mem_field32_set(unit, port_table, ptab, USE_MH_VIDf, 1288 proxy_server->flags & BCM_PROXY_SERVER_KEEP_VID ? 0 : 1); 1289 soc_mem_field32_set(unit, port_table, ptab, USE_MH_PKT_PRIf, 1290 proxy_server->flags & BCM_PROXY_SERVER_KEEP_PRIORITY ? 0 : 1); 1291 1292 BCM_IF_ERROR_RETURN 1293 (soc_mem_write(unit, port_table, MEM_BLOCK_ALL, local_ingress_port, ptab)); 1294 1295 if (IS_CPU_PORT(unit, local_ingress_port) && 1296 (BCM_PROXY_MODE_HYBRID == proxy_server->mode)) { 1297 sal_memset(ptab, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS); 1298 1299 BCM_IF_ERROR_RETURN(soc_mem_read( 1300 unit, port_table, MEM_BLOCK_ANY, cpu_port, ptab)); 1301 soc_mem_field32_set(unit, port_table, ptab, HG_LOOKUP_ENABLEf, 0); 1302 soc_mem_field32_set(unit, port_table, ptab, HYBRID_MODE_ENABLEf, 1); 1303 soc_mem_field32_set(unit, port_table, ptab, USE_MH_VIDf, 1304 proxy_server->flags & BCM_PROXY_SERVER_KEEP_VID ? 0 : 1); 1305 soc_mem_field32_set(unit, port_table, ptab, USE_MH_PKT_PRIf, 1306 proxy_server->flags & BCM_PROXY_SERVER_KEEP_PRIORITY ? 0 : 1); 1307 BCM_IF_ERROR_RETURN(soc_mem_write( 1308 unit, port_table, MEM_BLOCK_ALL, cpu_port, ptab)); 1309 } 1310 } else { 1311 /* when enable is 0 */ 1312 if (NULL == proxy_server) { 1313 return BCM_E_PARAM; 1314 } 1315 if (BCM_PROXY_MODE_SECOND_PASS == proxy_server->mode) { 1316 if (soc_feature(unit, soc_feature_hg_proxy_second_pass)) { 1317 1318 if ((proxy_server->flow_type > bcmProxySecondPassFlowTypeTrillTermination) || 1319 (proxy_server->flow_type < bcmProxySecondPassFlowTypeNone)) { 1320 return BCM_E_PARAM; 1321 } 1322 for(i = 0; i < _BCM_PROXY_RESERVED_DGLP_NUMBER; i++) { 1323 /* Use legacy register and field names at BCM layer. 1324 * CCH is used at SOC layer to get the corresponding values */ 1325 SOC_IF_ERROR_RETURN 1326 (soc_reg32_get(unit, config_regs_legacy[i], REG_PORT_ANY, 1327 0, ®_val_legacy[i])); 1328 flow_type[i] = soc_reg_field_get(unit,config_regs_legacy[i], 1329 reg_val_legacy[i], FLOW_TYPEf); 1330 1331 if (proxy_server->flow_type == flow_type[i]) { 1332 int dglp_is_shared = 0; 1333 bcm_gport_t local_port = 0; 1334 uint32 return_val[SOC_MAX_MEM_WORDS]; 1335 sal_memset(return_val, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS); 1336 1337 soc_mem_field32_set(unit, port_table, ptab, config_reg_fields[i], 0); 1338 soc_mem_field32_set(unit, port_table, ptab, USE_MH_VIDf, 0); 1339 soc_mem_field32_set(unit, port_table, ptab, USE_MH_PKT_PRIf, 0); 1340 soc_mem_field32_set(unit, port_table, ptab, REMOVE_MH_SRC_PORTf, 0); 1341 1342 BCM_IF_ERROR_RETURN 1343 (soc_mem_write(unit, port_table, MEM_BLOCK_ALL, local_ingress_port, ptab)); 1344 BCM_PBMP_ITER(PBMP_ALL(unit),local_port) { 1345 BCM_IF_ERROR_RETURN 1346 (soc_mem_read(unit, port_table, MEM_BLOCK_ANY, local_port, return_val)); 1347 if (soc_mem_field32_get(unit, port_table, return_val, config_reg_fields[i])) { 1348 dglp_is_shared = 1; 1349 } 1350 } 1351 if (!dglp_is_shared) { 1352 soc_reg_field_set(unit,config_regs_legacy[i], 1353 ®_val_legacy[i], FLOW_TYPEf,0); 1354 1355 SOC_IF_ERROR_RETURN 1356 (soc_reg32_set(unit, config_regs_legacy[i], REG_PORT_ANY, 0, reg_val_legacy[i])); 1357 SOC_IF_ERROR_RETURN 1358 (soc_reg64_set(unit, config_regs[i], REG_PORT_ANY, 0, const0_64)); 1359 } 1360 return BCM_E_NONE; 1361 } 1362 } 1363 return BCM_E_NOT_FOUND; 1364 } else { 1365 return BCM_E_UNAVAIL; 1366 } 1367 } 1368 /* Clear server configuration, but retain the independent 1369 * source port knockout configuration REMOVE_MH_SRC_PORTf 1370 */ 1371 soc_mem_field32_set(unit, port_table, ptab, HG_LOOKUP_ENABLEf, 0); 1372 soc_mem_field32_set(unit, port_table, ptab, HYBRID_MODE_ENABLEf, 0); 1373 soc_mem_field32_set(unit, port_table, ptab, USE_MH_PKT_PRIf, 0); 1374 soc_mem_field32_set(unit, port_table, ptab, USE_MH_VIDf, 0); 1375 for(i = 0; i < _BCM_PROXY_RESERVED_DGLP_NUMBER; i++) { 1376 soc_mem_field32_set(unit, port_table, ptab, config_reg_fields[i], 0); 1377 } 1378 SOC_IF_ERROR_RETURN 1379 (soc_mem_write(unit, port_table, MEM_BLOCK_ALL, local_ingress_port, ptab)); 1380 1381 if (IS_CPU_PORT(unit, local_ingress_port) && 1382 (BCM_PROXY_MODE_HYBRID == proxy_server->mode)) { 1383 sal_memset(ptab, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS); 1384 1385 BCM_IF_ERROR_RETURN(soc_mem_read( 1386 unit, port_table, MEM_BLOCK_ANY, cpu_port, ptab)); 1387 soc_mem_field32_set(unit, port_table, ptab, HG_LOOKUP_ENABLEf, 0); 1388 soc_mem_field32_set(unit, port_table, ptab, HYBRID_MODE_ENABLEf, 0); 1389 soc_mem_field32_set(unit, port_table, ptab, USE_MH_PKT_PRIf, 0); 1390 soc_mem_field32_set(unit, port_table, ptab, USE_MH_VIDf, 0); 1391 BCM_IF_ERROR_RETURN(soc_mem_write( 1392 unit, port_table, MEM_BLOCK_ALL, cpu_port, ptab)); 1393 } 1394 1395 /* Clear the HG_PKT_SINGATURE_1 config */ 1396 SOC_IF_ERROR_RETURN 1397 (soc_reg64_set(unit, hg_reg, local_ingress_port, 0, const0_64)); 1398 } 1399 /* End of else loop (enable is 0) */ 1400 1401 return BCM_E_NONE; 1402 } 1403 1404 /* 1405 * Function: 1406 * bcmi_td3_proxy_server_port_retrieve 1407 * Purpose: 1408 * Retrieves the current proxy server configuration on a 1409 * given Higig stack port in TD3, if any. 1410 * Parameters: 1411 * unit - (IN) Unit number. 1412 * local_ingress_port - (IN) Incoming Higig stack port 1413 * proxy_server - (OUT) Proxy server configuration 1414 * enable - (OUT) Enable proxy server on selected Higig stack port 1415 * Returns: 1416 * BCM_E_xxx 1417 */ 1418 STATIC int 1419 bcmi_td3_proxy_server_port_retrieve(int unit, bcm_gport_t local_ingress_port, 1420 bcm_proxy_server_t *proxy_server, 1421 int *enable) 1422 { 1423 uint32 hglkup, hybrid; 1424 int i = 0; 1425 int mapped_index = 0; 1426 /* Generalize chip specific memory and reg name */ 1427 soc_mem_t port_table = ING_DEVICE_PORTm; 1428 static uint32 reg_val_legacy[_BCM_PROXY_RESERVED_DGLP_NUMBER] = {0}; 1429 static uint32 flow_type[_BCM_PROXY_RESERVED_DGLP_NUMBER] = {0}; 1430 static soc_reg_t config_regs_legacy[] = { 1431 ING_PACKET_PROCESSING_CONTROL_0r, 1432 ING_PACKET_PROCESSING_CONTROL_1r 1433 }; 1434 static soc_field_t config_reg_fields[] = { 1435 ING_PACKET_PROCESSING_ENABLE_0f, 1436 ING_PACKET_PROCESSING_ENABLE_1f 1437 }; 1438 uint32 ptab[SOC_MAX_MEM_WORDS]; 1439 sal_memset(ptab, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS); 1440 1441 SOC_IF_ERROR_RETURN 1442 (soc_mem_read(unit, port_table, MEM_BLOCK_ANY, local_ingress_port, ptab)); 1443 BCM_IF_ERROR_RETURN 1444 (bcmi_map_hg_port_to_index(unit, local_ingress_port, &mapped_index)); 1445 if (BCM_PROXY_MODE_SECOND_PASS == proxy_server->mode) { 1446 if (!soc_feature(unit, soc_feature_hg_proxy_second_pass)) { 1447 return BCM_E_UNAVAIL; 1448 } 1449 1450 for(i = 0; i < _BCM_PROXY_RESERVED_DGLP_NUMBER; i++) { 1451 SOC_IF_ERROR_RETURN 1452 (soc_reg32_get(unit, config_regs_legacy[i], REG_PORT_ANY, 0, ®_val_legacy[i])); 1453 flow_type[i] = soc_reg_field_get(unit, config_regs_legacy[i], reg_val_legacy[i], FLOW_TYPEf); 1454 1455 if (proxy_server->flow_type == flow_type[i]) { 1456 /* Get proxy server information from software state */ 1457 sal_memcpy(proxy_server, &proxy_bookkeep[unit].proxy_server_copy[i][mapped_index], 1458 sizeof(bcm_proxy_server_t)); 1459 *enable = soc_mem_field32_get(unit, port_table, ptab, config_reg_fields[i]); 1460 return BCM_E_NONE; 1461 } 1462 } 1463 return BCM_E_NOT_FOUND; 1464 } 1465 hglkup = soc_mem_field32_get(unit, port_table, ptab, HG_LOOKUP_ENABLEf); 1466 hybrid = soc_mem_field32_get(unit, port_table, ptab, HYBRID_MODE_ENABLEf); 1467 1468 if (hglkup) { 1469 *enable = TRUE; 1470 proxy_server->mode = BCM_PROXY_MODE_HIGIG; 1471 /* Keeping TD3 code consistent with other devices in the 1472 * interpretation of the two flags for using info from module header */ 1473 if (!soc_mem_field32_get(unit, port_table, ptab, USE_MH_VIDf)) { 1474 proxy_server->flags |= BCM_PROXY_SERVER_KEEP_VID; 1475 } 1476 1477 if (!soc_mem_field32_get(unit, port_table, ptab, USE_MH_PKT_PRIf)) { 1478 proxy_server->flags |= BCM_PROXY_SERVER_KEEP_PRIORITY; 1479 } 1480 } else { 1481 if (hybrid) { 1482 *enable = TRUE; 1483 /*mode = BCM_PROXY_MODE_HYBRID;*/ 1484 /* Get proxy server information from software state */ 1485 sal_memcpy(proxy_server, &proxy_bookkeep[unit].proxy_server_copy[_BCM_PROXY_HYBRID][mapped_index], 1486 sizeof(bcm_proxy_server_t)); 1487 } else { 1488 *enable = FALSE; 1489 /* Nothing else to do */ 1490 return BCM_E_NONE; 1491 } 1492 } 1493 return BCM_E_NONE; 1494 } 1495 1496 #ifdef BCM_WARM_BOOT_SUPPORT 1497 /* 1498 * Function: 1499 * bcmi_proxy_server_wb_alloc 1500 * Purpose: 1501 * Allocates persisitent memory for Warm Boot scache. 1502 * Parameters: 1503 * unit - Device number. 1504 * Returns: 1505 * BCM_E_XXX 1506 */ 1507 STATIC int 1508 bcmi_proxy_server_wb_alloc(int unit) 1509 { 1510 int rv = BCM_E_NONE; 1511 int port_size; 1512 uint8 *proxy_server_scache; 1513 soc_scache_handle_t scache_handle; 1514 1515 BCM_PBMP_COUNT(PBMP_HG_ALL(unit), port_size); 1516 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_PROXY, 0); 1517 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE, 1518 port_size * sizeof(bcm_proxy_server_t), 1519 &proxy_server_scache, 1520 BCM_PROXY_WB_DEFAULT_VERSION, NULL); 1521 if (BCM_E_NOT_FOUND == rv) { 1522 /* Proceed with Level 1 Warm Boot */ 1523 rv = BCM_E_NONE; 1524 } 1525 return rv; 1526 } 1527 1528 /* 1529 * Function: 1530 * bcmi_proxy_server_sync 1531 * Purpose: 1532 * Stores proxy_server_gport and proxy_server_gport_mask information 1533 * in scache so that it can be recovered on warm boot 1534 * Parameters: 1535 * unit - Device number. 1536 * Returns: 1537 * BCM_E_XXX 1538 */ 1539 int 1540 bcmi_proxy_server_sync(int unit) 1541 { 1542 int alloc_size, port_size, idx = 0; 1543 soc_scache_handle_t scache_handle; 1544 uint8 *proxy_server_scache; 1545 1546 if (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) { 1547 return BCM_E_NONE; 1548 } 1549 BCM_PBMP_COUNT(PBMP_HG_ALL(unit), port_size); 1550 alloc_size = port_size * sizeof(bcm_proxy_server_t); 1551 1552 CHECK_PROXY_INIT(unit); 1553 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_PROXY, 0); 1554 BCM_IF_ERROR_RETURN 1555 (_bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 1556 alloc_size * _BCM_PROXY_SERVER_INSTANCES, &proxy_server_scache, 1557 BCM_PROXY_WB_DEFAULT_VERSION, NULL)); 1558 for (idx = 0; idx < _BCM_PROXY_SERVER_INSTANCES; idx++) { 1559 /* copy proxy_server instance into scache and point to the next location */ 1560 sal_memcpy(proxy_server_scache, 1561 proxy_bookkeep[unit].proxy_server_copy[idx], alloc_size); 1562 proxy_server_scache += alloc_size; 1563 } 1564 return BCM_E_NONE; 1565 } 1566 1567 STATIC int 1568 bcmi_proxy_server_recover(int unit) 1569 { 1570 int alloc_size, port_size, idx = 0, rv = BCM_E_NONE; 1571 soc_scache_handle_t scache_handle; 1572 uint8 *proxy_server_scache; 1573 1574 BCM_PBMP_COUNT(PBMP_HG_ALL(unit), port_size); 1575 alloc_size = port_size * sizeof(bcm_proxy_server_t); 1576 1577 /* We can't distinguish boot path for level 1 and level 2 warmboot 1578 * HR3 is the only chip we need to run level 1 warmboot which 1579 * means we don't do "exit clean" and not configuring any scache info 1580 * 1581 * Work around here is for HR3 only - We return from here 1582 * if this is level 1 warmboot by checking whether user configures 1583 * the scache_file 1584 * 1585 * Test case to verify this fix is: AT_IFP_wb_lvl1_005 1586 */ 1587 if (SOC_IS_HURRICANEX(unit)) { 1588 if ((NULL == soc_property_get_str(unit, spn_STABLE_FILENAME)) && 1589 (NULL == soc_property_get_str(unit, "scache_filename"))) { 1590 return BCM_E_NONE; 1591 } 1592 } 1593 1594 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_PROXY, 0); 1595 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 1596 alloc_size * _BCM_PROXY_SERVER_INSTANCES, &proxy_server_scache, 1597 BCM_PROXY_WB_DEFAULT_VERSION, NULL); 1598 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 1599 return rv; 1600 } else if (rv == BCM_E_NOT_FOUND) { 1601 return bcmi_proxy_server_wb_alloc(unit); 1602 } 1603 1604 for (idx = 0; idx < _BCM_PROXY_SERVER_INSTANCES; idx++) { 1605 /* copy scache data into proxy_server instance and point to the next location */ 1606 sal_memcpy(proxy_bookkeep[unit].proxy_server_copy[idx], 1607 proxy_server_scache, alloc_size); 1608 proxy_server_scache += alloc_size; 1609 } 1610 return BCM_E_NONE; 1611 } 1612 #endif /*BCM_WARM_BOOT_SUPPORT*/ 1613 /* 1614 * Function: 1615 * _bcm_esw_proxy_server_set 1616 * Purpose: 1617 * Enables various kinds of lookups for packets coming from remote 1618 * (proxy client) devices (internal function) 1619 * Parameters: 1620 * unit - BCM Unit number 1621 * server_port - Local port to which packets from remote devices are 1622 * destined to 1623 * mode - Indicates lookup type 1624 * enable - TRUE to enable lookups 1625 * FALSE to disable lookups 1626 * Returns: 1627 * BCM_E_XXX 1628 */ 1629 int 1630 _bcm_esw_proxy_server_set(int unit, bcm_port_t server_port, 1631 bcm_proxy_mode_t mode, int enable) 1632 { 1633 1634 if (BCM_GPORT_IS_SET(server_port)) { 1635 bcm_module_t modid; 1636 BCM_IF_ERROR_RETURN( 1637 _bcm_esw_proxy_gport_resolve(unit, server_port, 1638 &server_port, &modid, 1)); 1639 } 1640 1641 if (IS_HG_PORT(unit, server_port) || IS_CPU_PORT(unit, server_port)) { 1642 if ((mode != BCM_PROXY_MODE_HIGIG) && (mode != BCM_PROXY_MODE_HYBRID)) { 1643 return BCM_E_PARAM; 1644 } 1645 1646 #ifdef BCM_XGS3_SWITCH_SUPPORT 1647 if (SOC_IS_FBX(unit)) { 1648 uint32 dst_bmp; 1649 bcm_pbmp_t pbmp; 1650 uint32 val, mod = 0; 1651 int lport_idx; 1652 port_tab_entry_t ptab; 1653 1654 if (!soc_feature(unit, soc_feature_higig_lookup)) { 1655 return BCM_E_UNAVAIL; 1656 } 1657 1658 /* 1659 * Program PORT table V4L3_ENABLE, V6L3_ENABLE; 1660 * required for IP-IP tunneling on XGS3 devices. 1661 * This is not necessary for XGS4 and later. 1662 */ 1663 1664 1665 if (!SOC_IS_TRX(unit)) { 1666 BCM_IF_ERROR_RETURN 1667 (soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ANY, 1668 server_port, &ptab)); 1669 soc_PORT_TABm_field32_set(unit, &ptab, V4L3_ENABLEf, 1670 enable ? 1 : 0); 1671 soc_PORT_TABm_field32_set(unit, &ptab, V6L3_ENABLEf, 1672 enable ? 1 : 0); 1673 BCM_IF_ERROR_RETURN 1674 (soc_mem_write(unit, PORT_TABm, MEM_BLOCK_ALL, 1675 server_port, &ptab)); 1676 } 1677 1678 if (soc_feature(unit,soc_feature_td3_style_proxy)) { 1679 /* Program relevant TD3 tables and registers */ 1680 BCM_IF_ERROR_RETURN(bcmi_td3_proxy_server_config(unit, server_port, mode, enable)); 1681 } else { 1682 /* 1683 * Program LPORT table for the HG port; 1684 * HIGIG_PACKET must not be set; MY_MODID must be 1685 * set appropriately, and V4/V6 enable bits 1686 */ 1687 BCM_IF_ERROR_RETURN 1688 (soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ANY, 1689 server_port, &ptab)); 1690 if (soc_mem_field_valid(unit, PORT_TABm, MY_MODIDf)) { 1691 mod = soc_PORT_TABm_field32_get(unit, &ptab, MY_MODIDf); 1692 } 1693 1694 /* For Triumph, we use entry 0 so all remote ports 1695 * will use this entry. This is the behavior for previous 1696 * devices 1697 */ 1698 lport_idx = SOC_IS_TR_VL(unit) ? 0 : server_port; 1699 1700 sal_memset(&ptab, 0, sizeof(port_tab_entry_t)); 1701 BCM_IF_ERROR_RETURN 1702 (soc_mem_read(unit, LPORT_TABm, MEM_BLOCK_ANY, 1703 lport_idx, &ptab)); 1704 if (soc_mem_field_valid(unit, LPORT_TABm, MY_MODIDf)) { 1705 soc_LPORT_TABm_field32_set(unit, &ptab, MY_MODIDf, mod); 1706 } 1707 soc_LPORT_TABm_field32_set(unit, &ptab, V4L3_ENABLEf, 1708 enable ? 1 : 0); 1709 soc_LPORT_TABm_field32_set(unit, &ptab, V6L3_ENABLEf, 1710 enable ? 1 : 0); 1711 soc_LPORT_TABm_field32_set(unit, &ptab, V4IPMC_ENABLEf, 1712 enable ? 1 : 0); 1713 soc_LPORT_TABm_field32_set(unit, &ptab, V6IPMC_ENABLEf, 1714 enable ? 1 : 0); 1715 soc_LPORT_TABm_field32_set(unit, &ptab, IPMC_DO_VLANf, 1716 enable ? 1 : 0); 1717 soc_LPORT_TABm_field32_set(unit, &ptab, FILTER_ENABLEf, 1718 enable ? 1 : 0); 1719 1720 BCM_IF_ERROR_RETURN 1721 (soc_mem_write(unit, LPORT_TABm, MEM_BLOCK_ALL, 1722 lport_idx, &ptab)); 1723 1724 SOC_IF_ERROR_RETURN(READ_IHG_LOOKUPr 1725 (unit, server_port, &val)); 1726 if (BCM_PROXY_MODE_HIGIG == mode) { 1727 /* BCM_PROXY_MODE_HIGIG */ 1728 soc_reg_field_set(unit, IHG_LOOKUPr, &val, 1729 HG_LOOKUP_ENABLEf, enable ? 1: 0); 1730 soc_reg_field_set(unit, IHG_LOOKUPr, &val, 1731 HYBRID_MODE_ENABLEf, 0); 1732 } else { 1733 /* BCM_PROXY_MODE_HYBRID */ 1734 soc_reg_field_set(unit, IHG_LOOKUPr, &val, 1735 HG_LOOKUP_ENABLEf, 0); 1736 soc_reg_field_set(unit, IHG_LOOKUPr, &val, 1737 HYBRID_MODE_ENABLEf, enable ? 1: 0); 1738 } 1739 if (SOC_IS_TRX(unit)) { 1740 int ing_port; 1741 soc_reg_t reg; 1742 static soc_field_t fields[2] = { DST_MODIDf, DST_PORTf }; 1743 uint32 values[2]; 1744 /* Set "magic destination" to this server port to 1745 match prior devices' behavior */ 1746 reg = HG_LOOKUP_DESTINATIONr; 1747 values[0] = mod; 1748 values[1] = server_port; 1749 if (SOC_REG_INFO(unit, reg).regtype == soc_portreg) { 1750 PBMP_HG_ITER(unit, ing_port) { 1751 SOC_IF_ERROR_RETURN 1752 (soc_reg_fields32_modify(unit, reg, ing_port, 1753 2, fields, values)); 1754 } 1755 } else { 1756 SOC_IF_ERROR_RETURN 1757 (soc_reg_fields32_modify(unit, reg, REG_PORT_ANY, 1758 2, fields, values)); 1759 } 1760 } else { 1761 BCM_PBMP_PORT_SET(pbmp, server_port); 1762 dst_bmp = SOC_PBMP_WORD_GET(pbmp, 0); 1763 dst_bmp >>= SOC_HG_OFFSET(unit); 1764 soc_reg_field_set(unit, IHG_LOOKUPr, &val, 1765 DST_HG_LOOKUP_BITMAPf, dst_bmp); 1766 } 1767 if (SOC_REG_FIELD_VALID(unit, IHG_LOOKUPr, 1768 LOOKUP_WITH_MH_SRC_PORTf)) { 1769 soc_reg_field_set(unit, IHG_LOOKUPr, &val, 1770 LOOKUP_WITH_MH_SRC_PORTf, enable ? 1 :0); 1771 } 1772 if (SOC_REG_FIELD_VALID(unit, IHG_LOOKUPr, 1773 USE_MH_INTERNAL_PRIf)) { 1774 soc_reg_field_set(unit, IHG_LOOKUPr, &val, 1775 USE_MH_INTERNAL_PRIf, enable ? 1: 0); 1776 } 1777 soc_reg_field_set(unit, IHG_LOOKUPr, &val, USE_MH_VIDf, 1778 enable ? 1: 0); 1779 soc_reg_field_set(unit, IHG_LOOKUPr, &val, USE_MH_PKT_PRIf, 1780 enable ? 1: 0); 1781 SOC_IF_ERROR_RETURN(WRITE_IHG_LOOKUPr(unit, server_port, val)); 1782 } 1783 } 1784 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 1785 } else { 1786 1787 if (mode != BCM_PROXY_MODE_LOOPBACK) { 1788 return BCM_E_PARAM; 1789 } 1790 1791 if (enable) { 1792 BCM_IF_ERROR_RETURN 1793 (bcm_esw_port_loopback_set(unit, server_port, 1794 BCM_PORT_LOOPBACK_MAC)); 1795 } else { 1796 BCM_IF_ERROR_RETURN 1797 (bcm_esw_port_loopback_set(unit, server_port, 1798 BCM_PORT_LOOPBACK_NONE)); 1799 } 1800 } 1801 return BCM_E_NONE; 1802 } 1803 1804 /* 1805 * Function: 1806 * bcm_esw_proxy_server_get 1807 * Purpose: 1808 * Get the lookup mode of XGS3 device. 1809 * Parameters: 1810 * unit - BCM Unit number 1811 * server_port - Local port to which packets from remote devices are 1812 * destined to 1813 * mode - proxy server mode 1814 * enable - (OUT) server status 1815 * Returns: 1816 * BCM_E_XXX 1817 */ 1818 int 1819 bcm_esw_proxy_server_get(int unit, bcm_port_t server_port, 1820 bcm_proxy_mode_t mode, int *enable) 1821 { 1822 int rv = BCM_E_NONE; 1823 *enable = FALSE; 1824 1825 if (BCM_GPORT_IS_SET(server_port)) { 1826 BCM_IF_ERROR_RETURN( 1827 bcm_esw_port_local_get(unit, server_port, &server_port)); 1828 } 1829 1830 if (!SOC_PORT_VALID(unit, server_port)) { 1831 return BCM_E_PORT; 1832 } 1833 1834 if (!(IS_HG_PORT(unit, server_port) || IS_CPU_PORT(unit, server_port))) { 1835 int status; 1836 1837 if (mode != BCM_PROXY_MODE_LOOPBACK) { 1838 return BCM_E_PARAM; 1839 } 1840 /* coverity[uninit_use_in_call : FALSE] */ 1841 1842 rv = bcm_esw_port_loopback_get(unit, server_port, &status); 1843 if (BCM_SUCCESS(rv)) { 1844 if (status == BCM_PORT_LOOPBACK_MAC || 1845 status == BCM_PORT_LOOPBACK_PHY) { 1846 *enable = TRUE; 1847 } 1848 } 1849 } else { 1850 1851 if ((mode != BCM_PROXY_MODE_HIGIG) && (mode != BCM_PROXY_MODE_HYBRID)) { 1852 return BCM_E_PARAM; 1853 } 1854 1855 #ifdef BCM_XGS3_SWITCH_SUPPORT 1856 if (soc_feature(unit, soc_feature_higig_lookup)) { 1857 int port, hg_enable; 1858 uint32 val, dst_bmp; 1859 bcm_pbmp_t pbmp, r_pbmp; 1860 soc_reg_t reg; 1861 1862 if (SOC_IS_TRX(unit)) { 1863 uint32 hgld; 1864 if (soc_feature(unit,soc_feature_td3_style_proxy)) { 1865 BCM_IF_ERROR_RETURN(bcmi_td3_proxy_server_retrieve(unit, server_port, mode, enable)); 1866 } else { 1867 /* Set "magic destination" to this server port to 1868 match prior devices' behavior */ 1869 reg = HG_LOOKUP_DESTINATIONr; 1870 if (SOC_REG_INFO(unit, reg).regtype == soc_portreg) { 1871 SOC_IF_ERROR_RETURN 1872 (soc_reg32_get(unit, reg, server_port, 0, &hgld)); 1873 } else { 1874 SOC_IF_ERROR_RETURN 1875 (READ_HG_LOOKUP_DESTINATIONr(unit, &hgld)); 1876 } 1877 if (server_port == soc_reg_field_get(unit, 1878 HG_LOOKUP_DESTINATIONr, 1879 hgld, 1880 DST_PORTf)) { 1881 SOC_IF_ERROR_RETURN 1882 (READ_IHG_LOOKUPr(unit, server_port, &val)); 1883 if (BCM_PROXY_MODE_HIGIG == mode) { 1884 hg_enable = soc_reg_field_get(unit, IHG_LOOKUPr, val, 1885 HG_LOOKUP_ENABLEf); 1886 } else { 1887 hg_enable = soc_reg_field_get(unit, IHG_LOOKUPr, val, 1888 HYBRID_MODE_ENABLEf); 1889 } 1890 *enable = hg_enable; 1891 } 1892 } 1893 } else { 1894 PBMP_HG_ITER(unit, port) { 1895 SOC_PBMP_CLEAR(r_pbmp); 1896 BCM_PBMP_PORT_SET(pbmp, server_port); 1897 1898 SOC_IF_ERROR_RETURN(READ_IHG_LOOKUPr(unit, port, &val)); 1899 hg_enable = soc_reg_field_get(unit, IHG_LOOKUPr, val, 1900 HG_LOOKUP_ENABLEf); 1901 dst_bmp = soc_reg_field_get(unit, IHG_LOOKUPr, val, 1902 DST_HG_LOOKUP_BITMAPf); 1903 dst_bmp <<= SOC_HG_OFFSET(unit); 1904 SOC_PBMP_WORD_SET(r_pbmp, 0, dst_bmp); 1905 BCM_PBMP_AND(pbmp, r_pbmp); 1906 1907 if (hg_enable && BCM_PBMP_EQ(pbmp, r_pbmp)) { 1908 *enable = TRUE; 1909 break; 1910 } 1911 } 1912 } 1913 } 1914 #endif 1915 } 1916 1917 return rv; 1918 } 1919 1920 /* 1921 * Function: 1922 * _bcm_esw_proxy_server 1923 * Purpose: 1924 * Enable/disable proxy server 1925 * Parameters: 1926 * unit - BCM Unit number 1927 * dst - Proxy server data 1928 * enable - server enable/diable flag 1929 * Returns: 1930 * BCM_E_XXX 1931 */ 1932 STATIC int 1933 _bcm_esw_proxy_server(int unit, _bcm_proxy_info_t *src, int enable) 1934 { 1935 int rv = BCM_E_INTERNAL; 1936 1937 1938 rv = _bcm_esw_proxy_server_set(unit, src->server_port, src->mode, enable); 1939 1940 return rv; 1941 } 1942 1943 /* 1944 * Function: 1945 * _bcm_esw_proxy_server_install 1946 * Purpose: 1947 * Install and enable proxy server 1948 * Parameters: 1949 * unit - BCM Unit number 1950 * dst - Proxy server saved data 1951 * src - Proxy server initial data 1952 * Returns: 1953 * BCM_E_XXX 1954 */ 1955 STATIC int 1956 _bcm_esw_proxy_server_install(int unit, 1957 _bcm_proxy_info_t *dst, 1958 _bcm_proxy_info_t *src) 1959 { 1960 dst->server_port = src->server_port; 1961 dst->mode = src->mode; 1962 dst->flags |= (_BCM_PROXY_INFO_INSTALLED|_BCM_PROXY_INFO_SERVER); 1963 1964 return _bcm_esw_proxy_server(unit, dst, 1); 1965 } 1966 1967 /* 1968 * Function: 1969 * _bcm_esw_proxy_server_uninstall 1970 * Purpose: 1971 * Uninstall and disable proxy server 1972 * Parameters: 1973 * unit - BCM Unit number 1974 * dst - Proxy server saved data 1975 * Returns: 1976 * BCM_E_XXX 1977 */ 1978 STATIC int 1979 _bcm_esw_proxy_server_uninstall(int unit, _bcm_proxy_info_t *src) 1980 { 1981 return _bcm_esw_proxy_server(unit, src, 0); 1982 } 1983 1984 /* 1985 * Function: 1986 * bcm_esw_proxy_server_set 1987 * Purpose: 1988 * Enables various kinds of lookups for packets coming from remote 1989 * (proxy client) 1990 * Parameters: 1991 * unit - BCM Unit number 1992 * server_port - Local port to which packets from remote devices are 1993 * destined to 1994 * mode - Indicates lookup type 1995 * enable - TRUE to enable lookups 1996 * FALSE to disable lookups 1997 * Returns: 1998 * BCM_E_XXX 1999 */ 2000 int 2001 bcm_esw_proxy_server_set(int unit, bcm_port_t server_port, 2002 bcm_proxy_mode_t mode, int enable) 2003 { 2004 _bcm_proxy_info_t src; 2005 2006 if (BCM_GPORT_IS_SET(server_port)) { 2007 BCM_IF_ERROR_RETURN( 2008 bcm_esw_port_local_get(unit, server_port, &server_port)); 2009 } 2010 2011 sal_memset(&src, 0, sizeof(_bcm_proxy_info_t)); 2012 src.server_port = server_port; 2013 src.mode = mode; 2014 2015 return _bcm_esw_proxy(unit, &server_methods, &src, enable); 2016 } 2017 2018 /* 2019 * Function: 2020 * bcm_esw_proxy_server_port_set 2021 * Purpose: 2022 * This API enables various kinds of lookups on XGS3 device on 2023 * behalf of remote legacy or XGS3 devices on a per ingress port 2024 * basis. The local ingress port is expected to be a Higig stack 2025 * port. The server_gport in the proxy_server structure is the 2026 * target BCM_GPORT_PROXY (modid,port) destination which 2027 * indicates that hybrid proxy lookup is required. 2028 * Parameters: 2029 * unit - (IN) Unit number. 2030 * local_ingress_port - (IN) Incoming Higig stack port 2031 * proxy_server - (IN) Proxy server configuration 2032 * enable - (IN) Enable proxy server on selected Higig stack port 2033 * Returns: 2034 * BCM_E_xxx 2035 * Notes: 2036 */ 2037 int 2038 bcm_esw_proxy_server_port_set(int unit, bcm_gport_t local_ingress_port, 2039 bcm_proxy_server_t *proxy_server, 2040 int enable) 2041 { 2042 bcm_module_t modid; 2043 bcm_gport_t server_gport, server_port; 2044 uint32 val, field_num, rmsp; 2045 static soc_field_t fields[3] = 2046 { DST_MODIDf, DST_PORTf, DST_PORT_MASKf }; 2047 uint32 values[3]; 2048 int i = 0; 2049 uint32 flow_type[_BCM_PROXY_RESERVED_DGLP_NUMBER] = {0}; 2050 uint32 reg_val[_BCM_PROXY_RESERVED_DGLP_NUMBER] = {0}; 2051 static soc_reg_t config_regs[] = { 2052 ING_PACKET_PROCESSING_CONTROL_0r, 2053 ING_PACKET_PROCESSING_CONTROL_1r 2054 }; 2055 static soc_field_t config_reg_fields[] = { 2056 ING_PACKET_PROCESSING_ENABLE_0f, 2057 ING_PACKET_PROCESSING_ENABLE_1f 2058 }; 2059 2060 if (!soc_feature(unit, soc_feature_proxy_port_property)) { 2061 return BCM_E_UNAVAIL; 2062 } 2063 2064 if ((NULL == proxy_server) && enable) { 2065 /* No configuration to enable */ 2066 return BCM_E_PARAM; 2067 } 2068 2069 if (BCM_GPORT_IS_SET(local_ingress_port)) { 2070 /* Note, modid is a throwaway arg here */ 2071 BCM_IF_ERROR_RETURN 2072 (_bcm_esw_proxy_gport_resolve(unit, local_ingress_port, 2073 &local_ingress_port, &modid, 1)); 2074 } else if (!SOC_PORT_VALID(unit, local_ingress_port)) { 2075 return BCM_E_PORT; 2076 } 2077 2078 if (!(IS_HG_PORT(unit, local_ingress_port) || 2079 IS_CPU_PORT(unit, local_ingress_port))) { 2080 2081 /* Only Higig ports (including the CPU port as 2082 * Higig) are valid. 2083 */ 2084 return BCM_E_PORT; 2085 } 2086 2087 if (soc_feature(unit,soc_feature_td3_style_proxy)) { 2088 /* Program relevant TD3 tables and registers */ 2089 BCM_IF_ERROR_RETURN(bcmi_td3_proxy_server_port_config(unit, local_ingress_port, proxy_server, enable)); 2090 } else { 2091 SOC_IF_ERROR_RETURN(READ_IHG_LOOKUPr(unit, local_ingress_port, &val)); 2092 2093 if (enable) { 2094 server_gport = proxy_server->server_gport; 2095 if (!BCM_GPORT_IS_PROXY(server_gport)) { 2096 /* The server gport is required to be in 2097 * BCM_GPORT_PROXY format */ 2098 return BCM_E_PORT; 2099 } 2100 2101 BCM_IF_ERROR_RETURN 2102 (_bcm_esw_proxy_gport_resolve(unit, server_gport, 2103 &server_port, &modid, 0)); 2104 2105 if (BCM_PROXY_MODE_HIGIG == proxy_server->mode) { 2106 /* BCM_PROXY_MODE_HIGIG */ 2107 soc_reg_field_set(unit, IHG_LOOKUPr, &val, 2108 HG_LOOKUP_ENABLEf, 1); 2109 soc_reg_field_set(unit, IHG_LOOKUPr, &val, 2110 HYBRID_MODE_ENABLEf, 0); 2111 } else if (BCM_PROXY_MODE_HYBRID == proxy_server->mode) { 2112 /* BCM_PROXY_MODE_HYBRID */ 2113 soc_reg_field_set(unit, IHG_LOOKUPr, &val, 2114 HG_LOOKUP_ENABLEf, 0); 2115 soc_reg_field_set(unit, IHG_LOOKUPr, &val, 2116 HYBRID_MODE_ENABLEf, 1); 2117 } else if (BCM_PROXY_MODE_SECOND_PASS == proxy_server->mode) { 2118 if (!soc_feature(unit, soc_feature_hg_proxy_second_pass)) { 2119 return BCM_E_UNAVAIL; 2120 } 2121 2122 if ((proxy_server->flow_type > bcmProxySecondPassFlowTypeTrillTermination) || 2123 (proxy_server->flow_type < bcmProxySecondPassFlowTypeNone)) { 2124 return BCM_E_PARAM; 2125 } 2126 2127 /* if exist, update the entry */ 2128 for(i = 0; i < _BCM_PROXY_RESERVED_DGLP_NUMBER; i++) { 2129 SOC_IF_ERROR_RETURN 2130 (soc_reg32_get(unit, config_regs[i], REG_PORT_ANY, 0, ®_val[i])); 2131 flow_type[i] = soc_reg_field_get(unit,config_regs[i], reg_val[i], FLOW_TYPEf); 2132 2133 if (proxy_server->flow_type == flow_type[i]) { 2134 soc_reg_field_set(unit,config_regs[i], 2135 ®_val[i], FLOW_TYPEf,proxy_server->flow_type); 2136 2137 soc_reg_field_set(unit,config_regs[i], 2138 ®_val[i], DST_MODIDf, modid); 2139 soc_reg_field_set(unit,config_regs[i], 2140 ®_val[i], DST_PORTf, server_port); 2141 2142 SOC_IF_ERROR_RETURN 2143 (soc_reg32_set(unit, config_regs[i], REG_PORT_ANY, 0, reg_val[i])); 2144 2145 soc_reg_field_set(unit, IHG_LOOKUPr, &val, 2146 config_reg_fields[i], 1); 2147 soc_reg_field_set(unit, IHG_LOOKUPr, &val, 2148 HG_LOOKUP_ENABLEf, 0); 2149 soc_reg_field_set(unit, IHG_LOOKUPr, &val, 2150 USE_MH_VIDf, 1); 2151 soc_reg_field_set(unit, IHG_LOOKUPr, &val, 2152 USE_MH_PKT_PRIf, 1); 2153 soc_reg_field_set(unit, IHG_LOOKUPr, &val, 2154 REMOVE_MH_SRC_PORTf, 1); 2155 2156 SOC_IF_ERROR_RETURN 2157 (WRITE_IHG_LOOKUPr(unit, local_ingress_port, val)); 2158 return BCM_E_NONE; 2159 } 2160 } 2161 2162 /* if not exist, create it */ 2163 for(i = 0; i < _BCM_PROXY_RESERVED_DGLP_NUMBER; i++) { 2164 if (bcmProxySecondPassFlowTypeNone == flow_type[i]) { 2165 soc_reg_field_set(unit,config_regs[i], 2166 ®_val[i], FLOW_TYPEf,proxy_server->flow_type); 2167 2168 soc_reg_field_set(unit,config_regs[i], 2169 ®_val[i], DST_MODIDf, modid); 2170 soc_reg_field_set(unit,config_regs[i], 2171 ®_val[i], DST_PORTf, server_port); 2172 2173 SOC_IF_ERROR_RETURN 2174 (soc_reg32_set(unit, config_regs[i], REG_PORT_ANY, 0, reg_val[i])); 2175 2176 soc_reg_field_set(unit, IHG_LOOKUPr, &val, 2177 config_reg_fields[i], 1); 2178 soc_reg_field_set(unit, IHG_LOOKUPr, &val, 2179 HG_LOOKUP_ENABLEf, 0); 2180 soc_reg_field_set(unit, IHG_LOOKUPr, &val, 2181 USE_MH_VIDf, 1); 2182 soc_reg_field_set(unit, IHG_LOOKUPr, &val, 2183 USE_MH_PKT_PRIf, 1); 2184 soc_reg_field_set(unit, IHG_LOOKUPr, &val, 2185 REMOVE_MH_SRC_PORTf, 1); 2186 2187 SOC_IF_ERROR_RETURN 2188 (WRITE_IHG_LOOKUPr(unit, local_ingress_port, val)); 2189 2190 return BCM_E_NONE; 2191 } 2192 } 2193 2194 return BCM_E_FULL; 2195 } else { 2196 /* We don't support BCM_PROXY_MODE_LOOPBACK in this per-port 2197 * version of the API. 2198 */ 2199 return BCM_E_PARAM; 2200 } 2201 2202 /* Invert sense for HW settings */ 2203 soc_reg_field_set(unit, IHG_LOOKUPr, &val, USE_MH_VIDf, 2204 proxy_server->flags & BCM_PROXY_SERVER_KEEP_VID ? 0 : 1); 2205 2206 soc_reg_field_set(unit, IHG_LOOKUPr, &val, USE_MH_PKT_PRIf, 2207 proxy_server->flags & BCM_PROXY_SERVER_KEEP_PRIORITY ? 0 :1); 2208 2209 /* Set "magic destination" server port to trigger proxy lookups */ 2210 values[0] = modid; 2211 values[1] = server_port; 2212 2213 if (SOC_REG_FIELD_VALID(unit, HG_LOOKUP_DESTINATIONr, 2214 DST_PORT_MASKf) && 2215 (proxy_server->flags & BCM_PROXY_SERVER_MASK_PORT)) { 2216 values[2] = 1; 2217 field_num = 3; 2218 } else { 2219 field_num = 2; 2220 } 2221 2222 SOC_IF_ERROR_RETURN 2223 (soc_reg_fields32_modify(unit, HG_LOOKUP_DESTINATIONr, 2224 local_ingress_port, field_num, 2225 fields, values)); 2226 2227 SOC_IF_ERROR_RETURN 2228 (WRITE_IHG_LOOKUPr(unit, local_ingress_port, val)); 2229 } else { 2230 if (NULL == proxy_server) { 2231 return BCM_E_PARAM; 2232 } 2233 if (BCM_PROXY_MODE_SECOND_PASS == proxy_server->mode) { 2234 if (soc_feature(unit, soc_feature_hg_proxy_second_pass)) { 2235 2236 if ((proxy_server->flow_type > bcmProxySecondPassFlowTypeTrillTermination) || 2237 (proxy_server->flow_type < bcmProxySecondPassFlowTypeNone)) { 2238 return BCM_E_PARAM; 2239 } 2240 2241 for(i = 0; i < _BCM_PROXY_RESERVED_DGLP_NUMBER; i++) { 2242 SOC_IF_ERROR_RETURN 2243 (soc_reg32_get(unit, config_regs[i], REG_PORT_ANY, 0, ®_val[i])); 2244 2245 flow_type[i] = soc_reg_field_get(unit,config_regs[i], reg_val[i], FLOW_TYPEf); 2246 2247 if (proxy_server->flow_type == flow_type[i]) { 2248 int dglp_is_shared = 0; 2249 bcm_gport_t local_port = 0; 2250 uint32 return_val = 0; 2251 2252 soc_reg_field_set(unit, IHG_LOOKUPr, &val, 2253 config_reg_fields[i], 0); 2254 soc_reg_field_set(unit, IHG_LOOKUPr, &val, 2255 USE_MH_VIDf, 0); 2256 soc_reg_field_set(unit, IHG_LOOKUPr, &val, 2257 USE_MH_PKT_PRIf, 0); 2258 soc_reg_field_set(unit, IHG_LOOKUPr, &val, 2259 REMOVE_MH_SRC_PORTf, 0); 2260 2261 SOC_IF_ERROR_RETURN 2262 (WRITE_IHG_LOOKUPr(unit, local_ingress_port, val)); 2263 2264 BCM_PBMP_ITER(PBMP_ALL(unit),local_port) { 2265 SOC_IF_ERROR_RETURN 2266 (READ_IHG_LOOKUPr(unit, local_port, &return_val)); 2267 if (soc_reg_field_get(unit, IHG_LOOKUPr, return_val, config_reg_fields[i])) { 2268 dglp_is_shared = 1; 2269 } 2270 } 2271 2272 if(!dglp_is_shared) { 2273 soc_reg_field_set(unit,config_regs[i], 2274 ®_val[i], FLOW_TYPEf,0); 2275 2276 soc_reg_field_set(unit,config_regs[i], 2277 ®_val[i], DST_MODIDf, 0); 2278 soc_reg_field_set(unit,config_regs[i], 2279 ®_val[i], DST_PORTf, 0); 2280 2281 SOC_IF_ERROR_RETURN 2282 (soc_reg32_set(unit, config_regs[i], REG_PORT_ANY, 0, reg_val[i])); 2283 } 2284 2285 return BCM_E_NONE; 2286 } 2287 } 2288 return BCM_E_NOT_FOUND; 2289 } else { 2290 return BCM_E_UNAVAIL; 2291 } 2292 } 2293 /* Clear server configuration, but retain the independent 2294 * source port knockout configuration . 2295 */ 2296 rmsp = soc_reg_field_get(unit, IHG_LOOKUPr, val, 2297 REMOVE_MH_SRC_PORTf); 2298 val = 0; 2299 soc_reg_field_set(unit, IHG_LOOKUPr, &val, 2300 REMOVE_MH_SRC_PORTf, rmsp); 2301 SOC_IF_ERROR_RETURN 2302 (WRITE_IHG_LOOKUPr(unit, local_ingress_port, val)); 2303 2304 /* Clear the HG_LOOKUP_DESTINATION config */ 2305 SOC_IF_ERROR_RETURN 2306 (soc_reg32_set(unit, HG_LOOKUP_DESTINATIONr, 2307 local_ingress_port, 0, 0)); 2308 } 2309 } 2310 return BCM_E_NONE; 2311 } 2312 2313 /* 2314 * Function: 2315 * bcm_esw_proxy_server_port_get 2316 * Purpose: 2317 * This API retrieves the current proxy server configuration on a 2318 * given Higig stack port, if any. 2319 * Parameters: 2320 * unit - (IN) Unit number. 2321 * local_ingress_port - (IN) Incoming Higig stack port 2322 * proxy_server - (OUT) Proxy server configuration 2323 * enable - (OUT) Enable proxy server on selected Higig stack port 2324 * Returns: 2325 * BCM_E_xxx 2326 * Notes: 2327 */ 2328 int 2329 bcm_esw_proxy_server_port_get(int unit, bcm_gport_t local_ingress_port, 2330 bcm_proxy_server_t *proxy_server, 2331 int *enable) 2332 { 2333 bcm_module_t modid; 2334 bcm_gport_t server_port; 2335 uint32 cfg_val, dst_val; 2336 int hglkup, hybrid; 2337 bcm_proxy_mode_t mode; 2338 bcm_module_t reserved_modid = 0; 2339 bcm_gport_t reserved_port = 0; 2340 bcm_gport_t server_gport = 0; 2341 int i = 0; 2342 uint32 flow_type[_BCM_PROXY_RESERVED_DGLP_NUMBER] = {0}; 2343 uint32 reg_val[_BCM_PROXY_RESERVED_DGLP_NUMBER] = {0}; 2344 static soc_reg_t config_regs[] = { 2345 ING_PACKET_PROCESSING_CONTROL_0r, 2346 ING_PACKET_PROCESSING_CONTROL_1r, 2347 }; 2348 static soc_field_t config_reg_fields[] = { 2349 ING_PACKET_PROCESSING_ENABLE_0f, 2350 ING_PACKET_PROCESSING_ENABLE_1f 2351 }; 2352 2353 2354 if (!soc_feature(unit, soc_feature_proxy_port_property)) { 2355 return BCM_E_UNAVAIL; 2356 } 2357 2358 if ((NULL == proxy_server) || (NULL == enable)) { 2359 /* No way to return configuration */ 2360 return BCM_E_PARAM; 2361 } 2362 2363 if (BCM_GPORT_IS_SET(local_ingress_port)) { 2364 /* Note, modid is a throwaway arg here */ 2365 BCM_IF_ERROR_RETURN 2366 (_bcm_esw_proxy_gport_resolve(unit, local_ingress_port, 2367 &local_ingress_port, &modid, 1)); 2368 } else if (!SOC_PORT_VALID(unit, local_ingress_port)) { 2369 return BCM_E_PORT; 2370 } 2371 2372 if (!(IS_HG_PORT(unit, local_ingress_port) || 2373 IS_CPU_PORT(unit, local_ingress_port))) { 2374 2375 /* Only Higig ports (including the CPU port as 2376 * Higig) are valid. 2377 */ 2378 return BCM_E_PORT; 2379 } 2380 if (soc_feature(unit,soc_feature_td3_style_proxy)) { 2381 /* Program relevant TD3 tables and registers */ 2382 BCM_IF_ERROR_RETURN(bcmi_td3_proxy_server_port_retrieve(unit, local_ingress_port, proxy_server, enable)); 2383 } else { 2384 SOC_IF_ERROR_RETURN 2385 (READ_IHG_LOOKUPr(unit, local_ingress_port, &cfg_val)); 2386 2387 if (BCM_PROXY_MODE_SECOND_PASS == proxy_server->mode) { 2388 if (!soc_feature(unit, soc_feature_hg_proxy_second_pass)) { 2389 return BCM_E_UNAVAIL; 2390 } 2391 2392 for(i = 0; i < _BCM_PROXY_RESERVED_DGLP_NUMBER; i++) { 2393 SOC_IF_ERROR_RETURN 2394 (soc_reg32_get(unit, config_regs[i], REG_PORT_ANY, 0, ®_val[i])); 2395 flow_type[i] = soc_reg_field_get(unit,config_regs[i], reg_val[i], FLOW_TYPEf); 2396 2397 if (proxy_server->flow_type == flow_type[i]) { 2398 reserved_modid = soc_reg_field_get(unit, 2399 config_regs[i], reg_val[i], DST_MODIDf); 2400 2401 reserved_port = soc_reg_field_get(unit, 2402 config_regs[i], reg_val[i], DST_PORTf); 2403 2404 BCM_GPORT_PROXY_SET(server_gport, reserved_modid, reserved_port); 2405 2406 proxy_server->server_gport = server_gport; 2407 2408 *enable = soc_reg_field_get(unit, IHG_LOOKUPr, cfg_val, 2409 config_reg_fields[i]); 2410 2411 return BCM_E_NONE; 2412 } 2413 } 2414 return BCM_E_NOT_FOUND; 2415 } 2416 2417 hglkup = soc_reg_field_get(unit, IHG_LOOKUPr, cfg_val, 2418 HG_LOOKUP_ENABLEf); 2419 hybrid = soc_reg_field_get(unit, IHG_LOOKUPr, cfg_val, 2420 HYBRID_MODE_ENABLEf); 2421 2422 if (hglkup) { 2423 if (hybrid) { 2424 /* Illegal configuration */ 2425 return BCM_E_INTERNAL; 2426 } else { 2427 *enable = TRUE; 2428 mode = BCM_PROXY_MODE_HIGIG; 2429 } 2430 } else { 2431 if (hybrid) { 2432 *enable = TRUE; 2433 mode = BCM_PROXY_MODE_HYBRID; 2434 } else { 2435 *enable = FALSE; 2436 /* Nothing else to do */ 2437 return BCM_E_NONE; 2438 } 2439 } 2440 2441 bcm_proxy_server_t_init(proxy_server); 2442 2443 proxy_server->mode = mode; 2444 2445 /* Invert sense from HW settings */ 2446 if (0 == soc_reg_field_get(unit, IHG_LOOKUPr, cfg_val, USE_MH_VIDf)) { 2447 proxy_server->flags |= BCM_PROXY_SERVER_KEEP_VID; 2448 } 2449 2450 if (0 == soc_reg_field_get(unit, IHG_LOOKUPr, cfg_val, USE_MH_PKT_PRIf)) { 2451 proxy_server->flags |= BCM_PROXY_SERVER_KEEP_PRIORITY; 2452 } 2453 2454 2455 SOC_IF_ERROR_RETURN 2456 (soc_reg32_get(unit, HG_LOOKUP_DESTINATIONr, 2457 local_ingress_port, 0, &dst_val)); 2458 2459 if (SOC_REG_FIELD_VALID(unit, HG_LOOKUP_DESTINATIONr, 2460 DST_PORT_MASKf) && 2461 soc_reg_field_get(unit, HG_LOOKUP_DESTINATIONr, 2462 dst_val, DST_PORT_MASKf)) { 2463 proxy_server->flags |= BCM_PROXY_SERVER_MASK_PORT; 2464 } 2465 2466 modid = soc_reg_field_get(unit, HG_LOOKUP_DESTINATIONr, 2467 dst_val, DST_MODIDf); 2468 server_port = soc_reg_field_get(unit, HG_LOOKUP_DESTINATIONr, 2469 dst_val, DST_PORTf); 2470 BCM_GPORT_PROXY_SET(proxy_server->server_gport, modid, server_port); 2471 } 2472 return BCM_E_NONE; 2473 2474 } 2475 2476 /* 2477 * Function: 2478 * _bcm_esw_proxy_cleanup_data 2479 * Purpose: 2480 * Uninstall and release proxy data 2481 * Parameters: 2482 * unit - BCM Unit number 2483 * Returns: 2484 * BCM_E_XXX 2485 */ 2486 STATIC int 2487 _bcm_esw_proxy_cleanup_data(int unit) 2488 { 2489 _bcm_proxy_ifc_t *ifc; 2490 2491 if (_BCM_PROXY_LOCK(unit)) { 2492 return BCM_E_INIT; 2493 } 2494 2495 /* Cleanup clients/servers */ 2496 2497 while (_bcm_proxy_control[unit].proxy_list) { 2498 if (_bcm_proxy_control[unit].proxy_list->flags & 2499 _BCM_PROXY_INFO_SERVER) { 2500 ifc = &server_methods; 2501 } else { 2502 ifc = &client_methods; 2503 } 2504 (void)_bcm_esw_proxy_uninstall 2505 (unit, ifc, _bcm_proxy_control[unit].proxy_list); 2506 } 2507 2508 _BCM_PROXY_UNLOCK(unit); 2509 2510 return BCM_E_NONE; 2511 } 2512 2513 /* 2514 * Function: 2515 * bcm_esw_proxy_init 2516 * Purpose: 2517 * Initialize the Proxy subsystem 2518 * Parameters: 2519 * unit - BCM Unit number 2520 * Returns: 2521 * BCM_E_XXX 2522 */ 2523 int 2524 bcm_esw_proxy_init(int unit) 2525 { 2526 int rv = BCM_E_NONE; 2527 if (soc_feature(unit,soc_feature_td3_style_proxy)) { 2528 int port_size = soc_mem_index_count(unit, ING_DEVICE_PORTm) - 1; 2529 int idx = 0; 2530 2531 if (proxy_internal_initialized[unit]) { 2532 bcm_esw_proxy_cleanup(unit); 2533 } 2534 2535 proxy_bookkeep[unit].proxy_server_copy = 2536 (bcm_proxy_server_t **) 2537 sal_alloc(_BCM_PROXY_SERVER_INSTANCES * 2538 sizeof(bcm_proxy_server_t *), "proxy server sw state entry"); 2539 2540 sal_memset(proxy_bookkeep[unit].proxy_server_copy, 0, 2541 (_BCM_PROXY_SERVER_INSTANCES * sizeof(bcm_proxy_server_t*))); 2542 2543 if (proxy_bookkeep[unit].proxy_server_copy == NULL) { 2544 return BCM_E_MEMORY; 2545 } 2546 2547 for (idx = 0; idx < _BCM_PROXY_SERVER_INSTANCES; idx++) { 2548 proxy_bookkeep[unit].proxy_server_copy[idx] = 2549 (bcm_proxy_server_t *) 2550 sal_alloc(port_size * sizeof(bcm_proxy_server_t), 2551 "per instance proxy server entry"); 2552 2553 sal_memset(proxy_bookkeep[unit].proxy_server_copy[idx], 0, 2554 (port_size * sizeof(bcm_proxy_server_t))); 2555 2556 if (proxy_bookkeep[unit].proxy_server_copy[idx] == NULL) { 2557 bcm_esw_proxy_cleanup(unit); 2558 return BCM_E_MEMORY; 2559 } 2560 } 2561 } 2562 if (_LOCK(unit) == NULL) { 2563 _LOCK(unit) = sal_mutex_create("bcm_proxy_lock"); 2564 rv = (_LOCK(unit) == NULL) ? BCM_E_MEMORY : BCM_E_NONE; 2565 } 2566 2567 if (BCM_SUCCESS(rv)) { 2568 rv = _bcm_esw_proxy_cleanup_data(unit); 2569 } 2570 if (soc_feature(unit,soc_feature_td3_style_proxy)) { 2571 if (BCM_FAILURE(rv)) { 2572 BCM_IF_ERROR_RETURN(bcm_esw_proxy_cleanup(unit)); 2573 return rv; 2574 } 2575 #ifdef BCM_WARM_BOOT_SUPPORT 2576 if (SOC_WARM_BOOT(unit)) { 2577 rv = bcmi_proxy_server_recover(unit); 2578 } else { /* Cold Boot */ 2579 rv = bcmi_proxy_server_wb_alloc(unit); 2580 } 2581 #endif /* BCM_WARM_BOOT_SUPPORT */ 2582 2583 if (BCM_SUCCESS(rv)) { 2584 proxy_internal_initialized[unit] = 1; 2585 } 2586 } 2587 return rv; 2588 } 2589 2590 /* 2591 * Function: 2592 * bcm_esw_proxy_cleanup 2593 * Purpose: 2594 * Deinitialize the Proxy subsystem 2595 * Parameters: 2596 * unit - BCM Unit number 2597 * Returns: 2598 * BCM_E_XXX 2599 */ 2600 int 2601 bcm_esw_proxy_cleanup(int unit) 2602 { 2603 int idx = 0; 2604 if (_LOCK(unit) != NULL) { 2605 (void) _bcm_esw_proxy_cleanup_data(unit); 2606 sal_mutex_destroy(_LOCK(unit)); 2607 _LOCK(unit) = NULL; 2608 } 2609 if (soc_feature(unit,soc_feature_td3_style_proxy)) { 2610 for (idx = 0; idx < _BCM_PROXY_SERVER_INSTANCES; idx++) { 2611 if (NULL != proxy_bookkeep[unit].proxy_server_copy[idx]) { 2612 sal_free(proxy_bookkeep[unit].proxy_server_copy[idx]); 2613 proxy_bookkeep[unit].proxy_server_copy[idx] = NULL; 2614 } 2615 } 2616 if (NULL != proxy_bookkeep[unit].proxy_server_copy) { 2617 sal_free(proxy_bookkeep[unit].proxy_server_copy); 2618 proxy_bookkeep[unit].proxy_server_copy = NULL; 2619 } 2620 2621 proxy_internal_initialized[unit] = 0; 2622 } 2623 return BCM_E_NONE; 2624 } 2625 2626 /* 2627 * Function: 2628 * bcm_esw_proxy_egress_create 2629 * Purpose: 2630 * Create Proxy Egress forwarding object. 2631 * Parameters: 2632 * unit - (IN) bcm device. 2633 * flags - (IN) BCM_PROXY_REPLACE: replace existing. 2634 * BCM_PROXY_WITH_ID: intf argument is given. 2635 * proxy_egress - (IN) Egress forwarding destination. 2636 * proxy_if_id - (OUT) proxy interface id pointing to Egress object. 2637 * This is an IN argument if either BCM_PROXY_REPLACE 2638 * or BCM_PROXY_WITH_ID are given in flags. 2639 * Returns: 2640 * BCM_E_XXX 2641 */ 2642 int 2643 bcm_esw_proxy_egress_create(int unit, uint32 flags, bcm_proxy_egress_t *proxy_egress, 2644 bcm_if_t *proxy_if_id) 2645 { 2646 int rv = BCM_E_UNAVAIL; 2647 2648 #if defined(BCM_TRIDENT2_SUPPORT) 2649 if (SOC_IS_TD2_TT2(unit) && soc_feature(unit, soc_feature_l3)) { 2650 bcm_proxy_egress_t proxy_egress_local; 2651 2652 /* Input parameters check. */ 2653 if ((NULL == proxy_egress) || (NULL == proxy_if_id)) { 2654 return (BCM_E_PARAM); 2655 } 2656 2657 /* Copy provided structure to local so it can be modified. */ 2658 sal_memcpy(&proxy_egress_local, proxy_egress, sizeof(bcm_proxy_egress_t)); 2659 2660 L3_LOCK(unit); 2661 rv = bcm_td2_proxy_egress_create(unit, flags, &proxy_egress_local, proxy_if_id); 2662 L3_UNLOCK(unit); 2663 } 2664 #endif /* BCM_TRIDENT2_SUPPORT*/ 2665 2666 return rv; 2667 } 2668 2669 /* 2670 * Function: 2671 * bcm_esw_proxy_egress_destroy 2672 * Purpose: 2673 * Destroy Proxy Egress forwarding destination. 2674 * Parameters: 2675 * unit - (IN) bcm device. 2676 * proxy_if_id - (IN) proxy interface id pointing to Egress object 2677 * Returns: 2678 * BCM_E_XXX 2679 */ 2680 int 2681 bcm_esw_proxy_egress_destroy(int unit, bcm_if_t proxy_if_id) 2682 { 2683 int rv = BCM_E_UNAVAIL; 2684 2685 #if defined(BCM_TRIDENT2_SUPPORT) 2686 if (SOC_IS_TD2_TT2(unit) && soc_feature(unit, soc_feature_l3)) { 2687 2688 L3_LOCK(unit); 2689 rv = bcm_td2_proxy_egress_destroy(unit, proxy_if_id); 2690 L3_UNLOCK(unit); 2691 } 2692 #endif /* BCM_TRIDENT2_SUPPORT*/ 2693 2694 return rv; 2695 } 2696 2697 /* 2698 * Function: 2699 * bcm_esw_proxy_egress_get 2700 * Purpose: 2701 * Get Proxy Egress forwarding destination. 2702 * Parameters: 2703 * unit - (IN) bcm device. 2704 * proxy_if_id - (IN) Proxy Egress destination 2705 * proxy_egress - (OUT) Egress forwarding destination. 2706 * Returns: 2707 * BCM_E_XXX 2708 */ 2709 int 2710 bcm_esw_proxy_egress_get (int unit, bcm_if_t proxy_if_id, bcm_proxy_egress_t *proxy_egress) 2711 { 2712 int rv = BCM_E_UNAVAIL; 2713 2714 #if defined(BCM_TRIDENT2_SUPPORT) 2715 if (SOC_IS_TD2_TT2(unit) && soc_feature(unit, soc_feature_l3)) { 2716 /* Input parameters check. */ 2717 if (NULL == proxy_egress) { 2718 return (BCM_E_PARAM); 2719 } 2720 2721 L3_LOCK(unit); 2722 rv = bcm_td2_proxy_egress_get (unit, proxy_if_id, proxy_egress); 2723 L3_UNLOCK(unit); 2724 } 2725 #endif /* BCM_TRIDENT2_SUPPORT*/ 2726 2727 return rv; 2728 } 2729 2730 2731 /* 2732 * Function: 2733 * bcm_esw_proxy_egress_traverse 2734 * Purpose: 2735 * Goes through proxy egress objects table and runs the user callback 2736 * function at each valid egress objects entry passing back the 2737 * information for that object. 2738 * Parameters: 2739 * unit - (IN) bcm device. 2740 * trav_fn - (IN) Callback function. 2741 * user_data - (IN) User data to be passed to callback function. 2742 * Returns: 2743 * BCM_E_XXX 2744 */ 2745 int 2746 bcm_esw_proxy_egress_traverse(int unit, 2747 bcm_proxy_egress_traverse_cb trav_fn, void *user_data) 2748 { 2749 int rv = BCM_E_UNAVAIL; 2750 2751 #if defined(BCM_TRIDENT2_SUPPORT) 2752 if (SOC_IS_TD2_TT2(unit) && soc_feature(unit, soc_feature_l3)) { 2753 L3_LOCK(unit); 2754 rv = bcm_td2_proxy_egress_traverse(unit, trav_fn, user_data); 2755 L3_UNLOCK(unit); 2756 2757 } 2758 #endif /* BCM_TRIDENT2_SUPPORT*/ 2759 2760 return rv; 2761 } 2762 2763 #else /* INCLUDE_L3 */ 2764 int _bcm_esw_proxy_not_empty; 2765 #endif /* INCLUDE_L3 */