vxlan.c (336277B)
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 * VXLAN API 8 */ 9 10 #include <shared/bsl.h> 11 #include <soc/defs.h> 12 #include <sal/core/libc.h> 13 #if defined(BCM_GREYHOUND2_SUPPORT) && defined(INCLUDE_L3) 14 #include <soc/drv.h> 15 #include <soc/scache.h> 16 #include <soc/util.h> 17 #include <soc/hash.h> 18 #include <soc/debug.h> 19 #include <soc/greyhound2.h> 20 #include <bcm/types.h> 21 #include <bcm/error.h> 22 #include <bcm/l3.h> 23 #include <bcm_int/esw/mbcm.h> 24 #include <bcm_int/esw_dispatch.h> 25 #include <bcm_int/esw/trx.h> 26 #include <bcm_int/esw/triumph2.h> 27 #include <bcm_int/esw/hurricane3.h> 28 #include <bcm_int/esw/greyhound2.h> 29 #include <bcm_int/esw/vlan.h> 30 #include <bcm_int/esw/vxlan.h> 31 #include <bcm_int/esw/stack.h> 32 #include <bcm_int/esw/switch.h> 33 #include <bcm_int/esw/l3.h> 34 #include <bcm_int/esw/port.h> 35 #include <bcm_int/common/multicast.h> 36 37 /* 38 * GH2 VXLAN VFI info data structure 39 */ 40 typedef struct gh2_vxlan_vpn_info_s { 41 int valid; /* VFI is valid */ 42 uint32 vnid; /* VNID */ 43 } gh2_vxlan_vpn_info_t; 44 45 /* GH2 VXLAN DVP Type definition */ 46 #define GH2_VXLAN_DEST_VP_TYPE_INVALID 0x0 47 #define GH2_VXLAN_DEST_VP_TYPE_ACCESS 0x1 48 #define GH2_VXLAN_DEST_VP_TYPE_TUNNEL 0x2 49 50 /* 51 * GH2 VXLAN VP info data structure 52 */ 53 typedef struct gh2_vxlan_vp_info_s { 54 uint32 vp_type; /* VP type (GH2_VXLAN_DEST_VP_TYPE_XXX) */ 55 int vfi; /* VFI domain */ 56 int ecmp; /* ECMP type */ 57 int nh_ecmp_index; /* Next Hop or ECMP index */ 58 int tpid_valid; /* TPID is valid */ 59 uint16 tpid_value; /* The value of outer TPID */ 60 bcm_if_t ch_encap_id; /* Custom Header encap ID */ 61 int ch_match_id_ipmc; /* Custom Header Match ID for IPMC */ 62 int ch_match_id_non_ipmc; /* Custom Header Match ID for non-IPMC */ 63 } gh2_vxlan_vp_info_t; 64 65 /* 66 * GH2 VXLAN Outer TPID info data structure (per system) 67 */ 68 typedef struct gh2_vxlan_outer_tpid_info_s { 69 uint16 tpid_value; /* The value of outer TPID */ 70 int ref_count; /* Reference count */ 71 } gh2_vxlan_outer_tpid_info_t; 72 73 /* 74 * GH2 VXLAN Ingress VLAN XLATE info data structure 75 */ 76 typedef struct gh2_vxlan_vlan_xlate_info_s { 77 int ref_count; /* Reference count */ 78 } gh2_vxlan_vlan_xlate_info_t; 79 80 typedef struct bcmi_gh2_vxlan_tunnel_endpoint_s { 81 bcm_ip_t dip; /* Tunnel DIP */ 82 bcm_ip_t sip; /* Tunnel SIP */ 83 bcm_ip6_t dip6; /* Tunnel DIP6 */ 84 bcm_ip6_t sip6; /* Tunnel SIP6 */ 85 uint16 tunnel_state; /* Multicast Reference Count */ 86 int activate_flag; /* Tunnel terminator is deactivated or activated */ 87 bcm_vlan_t vlan; /* Out vlan for tunnel termination */ 88 } COMPILER_ATTRIBUTE((packed)) bcmi_gh2_vxlan_tunnel_endpoint_t; 89 90 /* 91 * Software book keeping for GH2's VXLAN-LITE related information 92 */ 93 typedef struct bcmi_gh2_vxlan_bookkeeping_s { 94 int initialized; /* Set to TRUE when VXLAN module initialized */ 95 sal_mutex_t vxlan_mutex; /* Protection mutex. */ 96 SHR_BITDCL *vxlan_ip_tnl_bitmap; /* EGR_IP_TUNNEL index bitmap */ 97 _bcm_vxlan_match_port_info_t *match_key; /* Match Key */ 98 bcmi_gh2_vxlan_tunnel_endpoint_t *vxlan_tunnel_term; 99 bcmi_gh2_vxlan_tunnel_endpoint_t *vxlan_tunnel_init; 100 int num_vxlan_tnl; 101 SHR_BITDCL *vxlan_vfi_bitmap; /* VXLAN VFI bitmap */ 102 gh2_vxlan_vpn_info_t *vxlan_vpn_info; /* VXLAN per VFI info */ 103 int num_vxlan_vfi; 104 SHR_BITDCL *vxlan_vp_bitmap; /* VXLAN Virtual Port bitmap */ 105 SHR_BITDCL *vxlan_network_vp_bitmap; /* VXLAN Network VP bitmap */ 106 gh2_vxlan_outer_tpid_info_t *vxlan_outer_tpid; /* VXLAN Outer TPID info */ 107 int num_vxlan_outer_tpid; /* Number of VXLAN outer TPIDs */ 108 gh2_vxlan_vlan_xlate_info_t *vxlan_vlan_xlate; /* VXLAN VLAN XLATE info */ 109 gh2_vxlan_vp_info_t *vxlan_vp_info; /* VXLAN per VP info */ 110 int num_vxlan_vp; 111 int riot_enable; /* VXLAN RIOT enabled status */ 112 SHR_BITDCL *vxlan_loopback_vp_bitmap; /* VXLAN Loopback VP bitmap */ 113 int riot_custom_header_index0_ref_count; /* Reference count of 114 Custom Header index0 */ 115 } bcmi_gh2_vxlan_bookkeeping_t; 116 117 STATIC bcmi_gh2_vxlan_bookkeeping_t 118 *bcmi_gh2_vxlan_bk_info[BCM_MAX_NUM_UNITS]; 119 120 /* Global initialized parameter for VXLAN bookkeeping info */ 121 STATIC uint8 gh2_vxlan_initialized = FALSE; 122 123 #define GH2_VXLAN_INFO(_unit_) (bcmi_gh2_vxlan_bk_info[_unit_]) 124 #define GH2_L3_INFO(_unit_) (&_bcm_l3_bk_info[_unit_]) 125 126 /* VXLAN-LITE RIOT enable info (only support for GH2-B0) */ 127 #define GH2_VXLAN_RIOT_ENABLE(_unit_) \ 128 (bcmi_gh2_vxlan_bk_info[_unit_]->riot_enable) 129 130 /* 131 * VXLAN-LITE VFI usage bitmap operations 132 */ 133 #define GH2_VXLAN_VFI_USED_GET(_u_, _vfi_) \ 134 ((GH2_VXLAN_INFO(_u_)->vxlan_vfi_bitmap) ? \ 135 SHR_BITGET(GH2_VXLAN_INFO(_u_)->vxlan_vfi_bitmap, (_vfi_)) : 0) 136 #define GH2_VXLAN_VFI_USED_SET(_u_, _vfi_) \ 137 SHR_BITSET(GH2_VXLAN_INFO((_u_))->vxlan_vfi_bitmap, (_vfi_)) 138 #define GH2_VXLAN_VFI_USED_CLR(_u_, _vfi_) \ 139 SHR_BITCLR(GH2_VXLAN_INFO((_u_))->vxlan_vfi_bitmap, (_vfi_)) 140 141 /* 142 * VXLAN-LITE Virtual Port usage bitmap operations 143 */ 144 #define GH2_VXLAN_VP_USED_GET(_u_, _vp_) \ 145 ((GH2_VXLAN_INFO(_u_)->vxlan_vp_bitmap) ? \ 146 SHR_BITGET(GH2_VXLAN_INFO(_u_)->vxlan_vp_bitmap, (_vp_)) : 0) 147 #define GH2_VXLAN_VP_USED_SET(_u_, _vp_) \ 148 SHR_BITSET(GH2_VXLAN_INFO((_u_))->vxlan_vp_bitmap, (_vp_)) 149 #define GH2_VXLAN_VP_USED_CLR(_u_, _vp_) \ 150 SHR_BITCLR(GH2_VXLAN_INFO((_u_))->vxlan_vp_bitmap, (_vp_)) 151 152 /* 153 * Network Port bit-map for VXLAN-LITE usage bitmap operations 154 */ 155 #define GH2_VXLAN_NETWORK_VP_USED_GET(_u_, _vp_) \ 156 ((GH2_VXLAN_INFO(_u_)->vxlan_network_vp_bitmap) ? \ 157 SHR_BITGET(GH2_VXLAN_INFO(_u_)->vxlan_network_vp_bitmap, (_vp_)) : 0) 158 #define GH2_VXLAN_NETWORK_VP_USED_SET(_u_, _vp_) \ 159 SHR_BITSET(GH2_VXLAN_INFO((_u_))->vxlan_network_vp_bitmap, (_vp_)) 160 #define GH2_VXLAN_NETWORK_VP_USED_CLR(_u_, _vp_) \ 161 SHR_BITCLR(GH2_VXLAN_INFO((_u_))->vxlan_network_vp_bitmap, (_vp_)) 162 163 /* 164 * Loopback Port bit-map for VXLAN-LITE RIOT usage bitmap operations 165 */ 166 #define GH2_VXLAN_LOOPBACK_VP_USED_GET(_u_, _vp_) \ 167 ((GH2_VXLAN_INFO(_u_)->vxlan_loopback_vp_bitmap) ? \ 168 SHR_BITGET(GH2_VXLAN_INFO(_u_)->vxlan_loopback_vp_bitmap, (_vp_)) : 0) 169 #define GH2_VXLAN_LOOPBACK_VP_USED_SET(_u_, _vp_) \ 170 SHR_BITSET(GH2_VXLAN_INFO((_u_))->vxlan_loopback_vp_bitmap, (_vp_)) 171 #define GH2_VXLAN_LOOPBACK_VP_USED_CLR(_u_, _vp_) \ 172 SHR_BITCLR(GH2_VXLAN_INFO((_u_))->vxlan_loopback_vp_bitmap, (_vp_)) 173 174 /* VP applications */ 175 #define GH2_VXLAN_VP_INFO_NETWORK_PORT 0x00000001 /* Network side port */ 176 #define GH2_VXLAN_VP_INFO_SHARED_PORT 0x00000002 /* Shared virtual port */ 177 #define GH2_VXLAN_VP_INFO_LOOPBACK_PORT 0x00000004 /* Loopback side port */ 178 179 /* Port Operations */ 180 #define GH2_VXLAN_PORT_OPERATION_NORMAL 0x0 /* Port Operation for normal */ 181 #define GH2_VXLAN_PORT_OPERATION_VFI 0x5 /* Port Operation for VFI */ 182 183 /* 184 * Definitions for VXLAN RIOT port's Custom Header(32 bits) 185 * +-------------------------------+ 186 * | Ethertype (16 bits) | 187 * +--------------+----------------+ 188 * | IPMC Flag | SGPP (15 bits) | 189 * +--------------+----------------+ 190 * 191 * Field location : 192 * - SGPP : b0~b14 193 * - IPMC Flag : b15 194 * - Ethertype : b16~b31 195 * 196 * Note : 197 * - Macros defined below for the term of "CH" means "Custom Header" 198 */ 199 #define GH2_VXLAN_RIOT_CH_HEADER_MASK 0xffffffff 200 #define GH2_VXLAN_RIOT_CH_ETHERTYPE_MASK 0xffff 201 #define GH2_VXLAN_RIOT_CH_ETHERTYPE_OFFSET 16 202 #define GH2_VXLAN_RIOT_CH_IPMC_OFFSET 15 203 #define GH2_VXLAN_RIOT_CH_MODID_MASK 0xff 204 #define GH2_VXLAN_RIOT_CH_MODID_OFFSET 7 205 #define GH2_VXLAN_RIOT_CH_PORT_MASK 0x7f 206 #define GH2_VXLAN_RIOT_CH_PORT_OFFSET 0 207 208 /* SW defined a non-common value for VXLAN RIOT usage */ 209 #define GH2_VXLAN_RIOT_CH_ETHERTYPE 0x21cd 210 211 #define GH2_VXLAN_RIOT_CH_ENCAP_VALUE(_ipmc_, _modid_, _port_) \ 212 ((GH2_VXLAN_RIOT_CH_ETHERTYPE << GH2_VXLAN_RIOT_CH_ETHERTYPE_OFFSET) | \ 213 (((_ipmc_) ? 1 : 0) << GH2_VXLAN_RIOT_CH_IPMC_OFFSET) | \ 214 (((_modid_) & GH2_VXLAN_RIOT_CH_MODID_MASK) << \ 215 GH2_VXLAN_RIOT_CH_MODID_OFFSET) | \ 216 (((_port_) & GH2_VXLAN_RIOT_CH_PORT_MASK) << \ 217 GH2_VXLAN_RIOT_CH_PORT_OFFSET)) 218 219 /* QoS mapping Operations for Custom Header usage */ 220 #define GH2_VXLAN_RIOT_CH_COS_REMAP_NONE 0x0 /* Don't use internal 221 Priority from CH */ 222 #define GH2_VXLAN_RIOT_CH_COS_REMAP_INT_PRI 0x1 /* Use internal Priority 223 from CH */ 224 #define GH2_VXLAN_RIOT_CH_COS_REMAP_INT_PRI_MAP 0x2 /* Use L2 QoS mapping 225 pointer from CH */ 226 #define GH2_VXLAN_RIOT_CH_COS_REMAP_DSCP_QOS_MAP 0x3 /* Use L3 QoS mapping 227 pointer from CH */ 228 229 typedef struct bcmi_vxlan_vp_info_s { 230 uint32 flags; 231 } bcmi_vxlan_vp_info_t; 232 233 #define GH2_VXLAN_TUNNEL_ID_IF_INVALID_RETURN(_unit_, _id_) \ 234 do { \ 235 if (((_id_) < 0) || \ 236 (_id_) >= (GH2_VXLAN_INFO(_unit_)->num_vxlan_tnl)) {\ 237 return BCM_E_BADID; \ 238 } \ 239 } while (0) 240 241 typedef struct bcmi_gh2_vxlan_nh_info_s { 242 int entry_type; 243 int vnid; 244 int intf_num; 245 int tunnel_index; 246 int udp_src_port_range_enable; 247 int apply_evxlt_modify_to_payload; 248 int use_nhi_in_evxlt_key; 249 int payload_otag_delete; 250 int tunnel_otag_delete; 251 int tunnel_itag_delete; 252 int qos_map_id; 253 int tunnel_pkt_pri; 254 int tunnel_pkt_cfi; 255 int custom_header_ipmc; 256 } bcmi_gh2_vxlan_nh_info_t; 257 258 STATIC int 259 bcmi_gh2_vxlan_port_vp_get( 260 int unit, 261 bcm_vpn_t vpn, 262 int vp, 263 bcm_vxlan_port_t *vxlan_port); 264 265 STATIC void 266 bcmi_gh2_vxlan_match_clear(int unit, int vp); 267 268 STATIC int 269 bcmi_gh2_vxlan_riot_custom_header_add( 270 int unit, 271 bcm_vxlan_port_t *vxlan_port, 272 bcm_vxlan_port_t *old_vxlan_port, 273 int vp); 274 STATIC int 275 bcmi_gh2_vxlan_riot_custom_header_delete( 276 int unit, 277 bcm_vxlan_port_t *vxlan_port, 278 int vp); 279 280 /* 281 * Function: 282 * gh2_vxlan_bk_info_instance_get 283 * Description: 284 * Helper function to retrieve VXLAN bookkeeping info pointer 285 * Parameters: 286 * unit - (IN) Device Number 287 * vxlan_bk_info - (OUT) VXLAN bookkeeping info data structure 288 * Returns: 289 * BCM_E_XXX 290 */ 291 STATIC int 292 gh2_vxlan_bk_info_instance_get( 293 int unit, 294 bcmi_gh2_vxlan_bookkeeping_t **vxlan_bk_info) 295 { 296 /* Input parameter check */ 297 if (NULL == vxlan_bk_info) { 298 return BCM_E_PARAM; 299 } 300 if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) { 301 return BCM_E_UNIT; 302 } 303 304 /* Check if VXLAN-LITE supported and initialized */ 305 if (!soc_feature(unit, soc_feature_vxlan_lite)) { 306 return BCM_E_UNAVAIL; 307 } 308 if (NULL == bcmi_gh2_vxlan_bk_info[unit]) { 309 LOG_ERROR(BSL_LS_BCM_VXLAN, 310 (BSL_META_U(unit, 311 "VXLAN bookkeeping info Error: " 312 "not initialized\n"))); 313 return BCM_E_INIT; 314 } 315 if (!bcmi_gh2_vxlan_bk_info[unit]->initialized) { 316 LOG_ERROR(BSL_LS_BCM_VXLAN, 317 (BSL_META_U(unit, 318 "VXLAN module not initialized\n"))); 319 return BCM_E_INIT; 320 } 321 322 /* Fill info structure. */ 323 *vxlan_bk_info = bcmi_gh2_vxlan_bk_info[unit]; 324 325 return BCM_E_NONE; 326 } 327 328 /* 329 * Function: 330 * bcmi_gh2_vxlan_check_init 331 * Purpose: 332 * Check if VXLAN is initialized 333 * Parameters: 334 * unit - (IN) Device Number 335 * Returns: 336 * BCM_E_XXX 337 */ 338 STATIC int 339 bcmi_gh2_vxlan_check_init(int unit) 340 { 341 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 342 343 if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) { 344 return BCM_E_UNIT; 345 } 346 347 vxlan_info = GH2_VXLAN_INFO(unit); 348 349 if ((vxlan_info == NULL) || (vxlan_info->initialized == FALSE)) { 350 return BCM_E_INIT; 351 } else { 352 return BCM_E_NONE; 353 } 354 } 355 356 /* 357 * Function: 358 * bcmi_gh2_vxlan_lock 359 * Purpose: 360 * Take VXLAN Lock Semaphore 361 * Parameters: 362 * unit - (IN) Device Number 363 * Returns: 364 * BCM_E_XXX 365 */ 366 int 367 bcmi_gh2_vxlan_lock(int unit) 368 { 369 int rv = BCM_E_NONE; 370 371 rv = bcmi_gh2_vxlan_check_init(unit); 372 373 if (rv == BCM_E_NONE) { 374 sal_mutex_take(GH2_VXLAN_INFO(unit)->vxlan_mutex, sal_mutex_FOREVER); 375 } 376 377 return rv; 378 } 379 380 /* 381 * Function: 382 * bcmi_gh2_vxlan_unlock 383 * Purpose: 384 * Release VXLAN Lock Semaphore 385 * Parameters: 386 * unit - (IN) Device Number 387 * Returns: 388 * BCM_E_XXX 389 */ 390 void 391 bcmi_gh2_vxlan_unlock(int unit) 392 { 393 int rv = BCM_E_NONE; 394 395 rv = bcmi_gh2_vxlan_check_init(unit); 396 397 if (rv == BCM_E_NONE) { 398 sal_mutex_give(GH2_VXLAN_INFO(unit)->vxlan_mutex); 399 } 400 } 401 402 /* 403 * Function: 404 * bcmi_gh2_vxlan_udp_dest_port_set 405 * Purpose: 406 * Set UDP Dest port for VXLAN 407 * Parameters: 408 * unit - (IN) Device Number 409 * type - (IN) The desired configuration parameter to modify 410 * udp_destport - (IN) UDP Dest port (Non-zero value) 411 * Returns: 412 * BCM_E_XXX. 413 */ 414 int 415 bcmi_gh2_vxlan_udp_dest_port_set( 416 int unit, 417 bcm_switch_control_t type, 418 int udp_destport) 419 { 420 soc_reg_t reg = INVALIDr ; 421 soc_field_t reg_field = INVALIDf; 422 uint64 regval64; 423 uint32 fieldval; 424 425 COMPILER_64_ZERO(regval64); 426 427 /* Given control type select register. */ 428 switch (type) { 429 case bcmSwitchVxlanUdpDestPortSet: 430 reg = ING_VXLAN_CONTROLr; 431 reg_field = UDP_DST_PORT_NUMBER_1f; 432 break; 433 case bcmSwitchVxlanUdpDestPortSet1: 434 reg = ING_VXLAN_CONTROLr; 435 reg_field = UDP_DST_PORT_NUMBER_2f; 436 break; 437 default: 438 return BCM_E_PARAM; 439 } 440 441 if (!SOC_REG_FIELD_VALID(unit, reg, reg_field)) { 442 return BCM_E_UNAVAIL; 443 } 444 445 /* input parameter range check */ 446 if ((udp_destport < 0) || (udp_destport > 0xFFFF)) { 447 return BCM_E_PARAM; 448 } 449 450 BCM_IF_ERROR_RETURN( 451 soc_reg64_get(unit, reg, REG_PORT_ANY, 0, ®val64)); 452 fieldval = soc_reg64_field32_get(unit, reg, regval64, reg_field); 453 if (udp_destport != fieldval) { 454 soc_reg64_field32_set(unit, reg, ®val64, reg_field, udp_destport); 455 BCM_IF_ERROR_RETURN( 456 soc_reg64_set(unit, reg, REG_PORT_ANY, 0, regval64)); 457 } 458 459 return BCM_E_NONE; 460 } 461 462 /* 463 * Function: 464 * bcmi_gh2_vxlan_udp_dest_port_get 465 * Purpose: 466 * Get UDP Dest port for VXLAN 467 * Parameters: 468 * unit - (IN) Device Number 469 * type - (IN) The desired configuration parameter to modify 470 * udp_destport - (OUT) UDP Dest port (Non-zero value) 471 * Returns: 472 * BCM_E_XXX. 473 */ 474 int 475 bcmi_gh2_vxlan_udp_dest_port_get( 476 int unit, 477 bcm_switch_control_t type, 478 int *udp_destport) 479 { 480 soc_reg_t reg = INVALIDr ; 481 soc_field_t reg_field = INVALIDf; 482 uint64 regval64; 483 uint32 fieldval; 484 485 COMPILER_64_ZERO(regval64); 486 487 /* Given control type select register. */ 488 switch (type) { 489 case bcmSwitchVxlanUdpDestPortSet: 490 reg = ING_VXLAN_CONTROLr; 491 reg_field = UDP_DST_PORT_NUMBER_1f; 492 break; 493 case bcmSwitchVxlanUdpDestPortSet1: 494 reg = ING_VXLAN_CONTROLr; 495 reg_field = UDP_DST_PORT_NUMBER_2f; 496 break; 497 default: 498 return BCM_E_PARAM; 499 } 500 501 if (!SOC_REG_FIELD_VALID(unit, reg, reg_field)) { 502 return BCM_E_UNAVAIL; 503 } 504 505 BCM_IF_ERROR_RETURN( 506 soc_reg64_get(unit, reg, REG_PORT_ANY, 0, ®val64)); 507 fieldval = soc_reg64_field32_get(unit, reg, regval64, reg_field); 508 509 *udp_destport = fieldval; 510 511 return BCM_E_NONE; 512 } 513 514 /* 515 * Function: 516 * bcmi_gh2_vxlan_udp_source_port_set 517 * Purpose: 518 * Enable UDP Source port based HASH for VXLAN 519 * Parameters: 520 * unit - (IN) Device Number 521 * type - (IN) The desired configuration parameter to modify 522 * hash_enable - (IN) Enable Hash for UDP SourcePort 523 * Returns: 524 * BCM_E_XXX. 525 */ 526 int 527 bcmi_gh2_vxlan_udp_source_port_set( 528 int unit, 529 bcm_switch_control_t type, 530 int hash_enable) 531 { 532 soc_reg_t reg = INVALIDr ; 533 soc_field_t reg_field = INVALIDf; 534 uint32 regval, fieldval; 535 536 /* Given control type select register. */ 537 switch (type) { 538 case bcmSwitchVxlanEntropyEnable: 539 reg = EGR_VXLAN_CONTROLr; 540 reg_field = UDP_SOURCE_PORT_SELf; 541 break; 542 case bcmSwitchVxlanEntropyEnableIP6: 543 reg = EGR_VXLAN_CONTROLr; 544 reg_field = IPV6_FLOW_LABEL_SELf; 545 break; 546 default: 547 return BCM_E_PARAM; 548 } 549 550 if (!SOC_REG_FIELD_VALID(unit, reg, reg_field)) { 551 return BCM_E_UNAVAIL; 552 } 553 554 if ((hash_enable < 0) || (hash_enable > 1)) { 555 return BCM_E_PARAM; 556 } 557 558 BCM_IF_ERROR_RETURN( 559 soc_reg32_get(unit, reg, REG_PORT_ANY, 0, ®val)); 560 fieldval = soc_reg_field_get(unit, reg, regval, reg_field); 561 if (hash_enable != fieldval) { 562 soc_reg_field_set(unit, reg, ®val, reg_field, hash_enable); 563 BCM_IF_ERROR_RETURN( 564 soc_reg32_set(unit, reg, REG_PORT_ANY, 0, regval)); 565 } 566 567 return BCM_E_NONE; 568 } 569 570 /* 571 * Function: 572 * bcmi_gh2_vxlan_udp_source_port_get 573 * Purpose: 574 * Get UDP Source port based HASH for VXLAN 575 * Parameters: 576 * unit - (IN) Device Number 577 * type - (IN) The desired configuration parameter to modify 578 * hash_enable - (OUT) Enable Hash for UDP SourcePort 579 * Returns: 580 * BCM_E_XXX. 581 */ 582 int 583 bcmi_gh2_vxlan_udp_source_port_get( 584 int unit, 585 bcm_switch_control_t type, 586 int *hash_enable) 587 { 588 soc_reg_t reg = INVALIDr ; 589 soc_field_t reg_field = INVALIDf; 590 uint32 regval, fieldval; 591 592 /* Given control type select register. */ 593 switch (type) { 594 case bcmSwitchVxlanEntropyEnable: 595 reg = EGR_VXLAN_CONTROLr; 596 reg_field = UDP_SOURCE_PORT_SELf; 597 break; 598 case bcmSwitchVxlanEntropyEnableIP6: 599 reg = EGR_VXLAN_CONTROLr; 600 reg_field = IPV6_FLOW_LABEL_SELf; 601 break; 602 default: 603 return BCM_E_PARAM; 604 } 605 606 if (!SOC_REG_FIELD_VALID(unit, reg, reg_field)) { 607 return BCM_E_UNAVAIL; 608 } 609 610 BCM_IF_ERROR_RETURN( 611 soc_reg32_get(unit, reg, REG_PORT_ANY, 0, ®val)); 612 fieldval = soc_reg_field_get(unit, reg, regval, reg_field); 613 614 *hash_enable = fieldval; 615 616 return BCM_E_NONE; 617 } 618 619 /* 620 * Function: 621 * bcmi_gh2_vxlan_free_resource 622 * Purpose: 623 * Free all allocated software resources 624 * Parameters: 625 * unit - (IN) Device Number 626 * Returns: 627 * Nothing 628 */ 629 STATIC void 630 bcmi_gh2_vxlan_free_resource(int unit) 631 { 632 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 633 634 /* If software tables were not allocated we are done. */ 635 if (NULL == GH2_VXLAN_INFO(unit)) { 636 return; 637 } 638 639 vxlan_info = GH2_VXLAN_INFO(unit); 640 641 if (vxlan_info->vxlan_mutex != NULL) { 642 sal_mutex_destroy(vxlan_info->vxlan_mutex); 643 vxlan_info->vxlan_mutex = NULL; 644 } 645 646 /* Destroy EGR_IP_TUNNEL usage bitmap */ 647 if (vxlan_info->vxlan_ip_tnl_bitmap) { 648 sal_free(vxlan_info->vxlan_ip_tnl_bitmap); 649 vxlan_info->vxlan_ip_tnl_bitmap = NULL; 650 } 651 652 if (vxlan_info->match_key) { 653 sal_free(vxlan_info->match_key); 654 vxlan_info->match_key = NULL; 655 } 656 657 if (vxlan_info->vxlan_tunnel_init) { 658 sal_free(vxlan_info->vxlan_tunnel_init); 659 vxlan_info->vxlan_tunnel_init = NULL; 660 } 661 662 if (vxlan_info->vxlan_tunnel_term) { 663 sal_free(vxlan_info->vxlan_tunnel_term); 664 vxlan_info->vxlan_tunnel_term = NULL; 665 } 666 667 /* Destroy VXLAN VFI usage bitmap */ 668 if (vxlan_info->vxlan_vfi_bitmap) { 669 sal_free(vxlan_info->vxlan_vfi_bitmap); 670 vxlan_info->vxlan_vfi_bitmap = NULL; 671 } 672 673 /* Destroy VXLAN VFI info */ 674 if (vxlan_info->vxlan_vpn_info) { 675 sal_free(vxlan_info->vxlan_vpn_info); 676 vxlan_info->vxlan_vpn_info = NULL; 677 } 678 679 /* Destroy VXLAN Virtual Port usage bitmap */ 680 if (vxlan_info->vxlan_vp_bitmap) { 681 sal_free(vxlan_info->vxlan_vp_bitmap); 682 vxlan_info->vxlan_vp_bitmap = NULL; 683 } 684 685 /* Destroy Network VXLAN Virtual Port usage bitmap */ 686 if (vxlan_info->vxlan_network_vp_bitmap) { 687 sal_free(vxlan_info->vxlan_network_vp_bitmap); 688 vxlan_info->vxlan_network_vp_bitmap = NULL; 689 } 690 691 /* Destroy VXLAN Outer TPID info */ 692 if (vxlan_info->vxlan_outer_tpid) { 693 sal_free(vxlan_info->vxlan_outer_tpid); 694 vxlan_info->vxlan_outer_tpid = NULL; 695 } 696 697 /* Destroy VXLAN Ingress VLAN XLATE info */ 698 if (vxlan_info->vxlan_vlan_xlate) { 699 sal_free(vxlan_info->vxlan_vlan_xlate); 700 vxlan_info->vxlan_vlan_xlate = NULL; 701 } 702 703 /* Destroy VXLAN VP info */ 704 if (vxlan_info->vxlan_vp_info) { 705 sal_free(vxlan_info->vxlan_vp_info); 706 vxlan_info->vxlan_vp_info = NULL; 707 } 708 709 /* Destroy Loopback VXLAN Virtual Port usage bitmap (used for RIOT) */ 710 if (vxlan_info->vxlan_loopback_vp_bitmap) { 711 sal_free(vxlan_info->vxlan_loopback_vp_bitmap); 712 vxlan_info->vxlan_loopback_vp_bitmap = NULL; 713 } 714 715 /* Free module data. */ 716 sal_free(GH2_VXLAN_INFO(unit)); 717 GH2_VXLAN_INFO(unit) = NULL; 718 } 719 720 /* 721 * Function: 722 * bcmi_gh2_vxlan_allocate_bk 723 * Purpose: 724 * Initialize VXLAN software book-kepping 725 * Parameters: 726 * unit - (IN) Device Number 727 * Returns: 728 * BCM_E_XXX 729 */ 730 STATIC int 731 bcmi_gh2_vxlan_allocate_bk(int unit) 732 { 733 /* Allocate/Init unit software tables. */ 734 if (NULL == GH2_VXLAN_INFO(unit)) { 735 BCMI_VXLAN_ALLOC(GH2_VXLAN_INFO(unit), 736 sizeof(bcmi_gh2_vxlan_bookkeeping_t), 737 "vxlan_bk_module_data"); 738 if (NULL == GH2_VXLAN_INFO(unit)) { 739 return BCM_E_MEMORY; 740 } else { 741 GH2_VXLAN_INFO(unit)->initialized = FALSE; 742 } 743 } 744 745 return BCM_E_NONE; 746 } 747 748 /* 749 * Function: 750 * bcmi_gh2_vxlan_outer_tpid_ref_inc 751 * Purpose: 752 * Increase reference count for the specified VXLAN outer TPID (per system) 753 * Parameters: 754 * unit - (IN) unit number 755 * tpid_value - (IN) TPID value 756 * Returns: 757 * BCM_E_XXX 758 * Notes: 759 */ 760 STATIC int 761 bcmi_gh2_vxlan_outer_tpid_ref_inc(int unit, uint16 tpid_value) 762 { 763 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 764 gh2_vxlan_outer_tpid_info_t *vxlan_outer_tpid; 765 int num_tpid, i; 766 767 vxlan_info = GH2_VXLAN_INFO(unit); 768 if (NULL == vxlan_info) { 769 LOG_ERROR(BSL_LS_BCM_VXLAN, 770 (BSL_META_U(unit, 771 "VXLAN bookkeeping info Error: " 772 "not initialized\n"))); 773 return BCM_E_INIT; 774 } 775 776 /* Get total number of VXLAN outer TPID */ 777 num_tpid = vxlan_info->num_vxlan_outer_tpid; 778 779 for (i = 0; i < num_tpid; i++) { 780 vxlan_outer_tpid = &(vxlan_info->vxlan_outer_tpid[i]); 781 if (vxlan_outer_tpid->ref_count == 0) { 782 /* Find free index */ 783 vxlan_outer_tpid->tpid_value = tpid_value; 784 /* Update the reference count */ 785 vxlan_outer_tpid->ref_count++; 786 break; 787 } else { 788 if (tpid_value == vxlan_outer_tpid->tpid_value) { 789 /* Update the reference count */ 790 vxlan_outer_tpid->ref_count++; 791 break; 792 } 793 } 794 } 795 796 if (i == num_tpid) { 797 return BCM_E_RESOURCE; 798 } 799 800 return BCM_E_NONE; 801 } 802 803 /* 804 * Function: 805 * bcmi_gh2_vxlan_outer_tpid_ref_dec 806 * Purpose: 807 * Decrease reference count for the specified VXLAN outer TPID (per system) 808 * Parameters: 809 * unit - (IN) unit number 810 * tpid_value - (IN) TPID value 811 * Returns: 812 * BCM_E_XXX 813 * Notes: 814 */ 815 STATIC int 816 bcmi_gh2_vxlan_outer_tpid_ref_dec(int unit, uint16 tpid_value) 817 { 818 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 819 gh2_vxlan_outer_tpid_info_t *vxlan_outer_tpid; 820 int num_tpid, i; 821 bcm_switch_tpid_info_t tpid_info; 822 823 vxlan_info = GH2_VXLAN_INFO(unit); 824 if (NULL == vxlan_info) { 825 LOG_ERROR(BSL_LS_BCM_VXLAN, 826 (BSL_META_U(unit, 827 "VXLAN bookkeeping info Error: " 828 "not initialized\n"))); 829 return BCM_E_INIT; 830 } 831 832 /* Get total number of VXLAN outer TPID */ 833 num_tpid = vxlan_info->num_vxlan_outer_tpid; 834 835 for (i = 0; i < num_tpid; i++) { 836 vxlan_outer_tpid = &(vxlan_info->vxlan_outer_tpid[i]); 837 if (vxlan_outer_tpid->ref_count > 0) { 838 if (tpid_value == vxlan_outer_tpid->tpid_value) { 839 /* Update the reference count */ 840 vxlan_outer_tpid->ref_count--; 841 if (vxlan_outer_tpid->ref_count == 0) { 842 sal_memset(&tpid_info, 0, sizeof(tpid_info)); 843 tpid_info.tpid_type = bcmTpidTypeVxlanPayloadOuter; 844 tpid_info.tpid_value = tpid_value; 845 (void)bcm_esw_switch_tpid_delete(unit, &tpid_info); 846 } 847 break; 848 } 849 } 850 } 851 852 if (i == num_tpid) { 853 return BCM_E_NOT_FOUND; 854 } 855 856 return BCM_E_NONE; 857 } 858 859 /* 860 * Function: 861 * bcmi_gh2_vxlan_vlan_xlate_ref_inc 862 * Purpose: 863 * Increase reference count for the specified VXLAN Vlan XLATE entry. 864 * Parameters: 865 * unit - (IN) unit number 866 * entry_index - (IN) Entry index 867 * Returns: 868 * BCM_E_XXX 869 * Notes: 870 */ 871 STATIC int 872 bcmi_gh2_vxlan_vlan_xlate_ref_inc(int unit, int entry_index) 873 { 874 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 875 gh2_vxlan_vlan_xlate_info_t *vxlan_vlan_xlate; 876 int num_vfi; 877 878 vxlan_info = GH2_VXLAN_INFO(unit); 879 if (NULL == vxlan_info) { 880 LOG_ERROR(BSL_LS_BCM_VXLAN, 881 (BSL_META_U(unit, 882 "VXLAN bookkeeping info Error: " 883 "not initialized\n"))); 884 return BCM_E_INIT; 885 } 886 887 /* Input parameter check */ 888 num_vfi = vxlan_info->num_vxlan_vfi; 889 if (entry_index >= num_vfi) { 890 return BCM_E_RESOURCE; 891 } 892 893 /* Get VXLAN VLAN XLATE entry pointer with specified entry_index */ 894 vxlan_vlan_xlate = &(vxlan_info->vxlan_vlan_xlate[entry_index]); 895 896 /* Update the reference count */ 897 vxlan_vlan_xlate->ref_count++; 898 899 return BCM_E_NONE; 900 } 901 902 /* 903 * Function: 904 * bcmi_gh2_vxlan_vlan_xlate_ref_dec 905 * Purpose: 906 * Decrease reference count for the specified VXLAN Vlan XLATE entry. 907 * Parameters: 908 * unit - (IN) unit number 909 * entry_index - (IN) Entry index 910 * ref_cnt - (OUT) Reference Count 911 * Returns: 912 * BCM_E_XXX 913 * Notes: 914 */ 915 STATIC int 916 bcmi_gh2_vxlan_vlan_xlate_ref_dec(int unit, int entry_index, int *ref_cnt) 917 { 918 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 919 gh2_vxlan_vlan_xlate_info_t *vxlan_vlan_xlate; 920 int num_vfi; 921 922 vxlan_info = GH2_VXLAN_INFO(unit); 923 if (NULL == vxlan_info) { 924 LOG_ERROR(BSL_LS_BCM_VXLAN, 925 (BSL_META_U(unit, 926 "VXLAN bookkeeping info Error: " 927 "not initialized\n"))); 928 return BCM_E_INIT; 929 } 930 931 /* Input parameter check */ 932 num_vfi = vxlan_info->num_vxlan_vfi; 933 if (entry_index >= num_vfi) { 934 return BCM_E_RESOURCE; 935 } 936 937 if (NULL == ref_cnt) { 938 return BCM_E_PARAM; 939 } 940 941 /* Get VXLAN VLAN XLATE entry pointer with specified entry_index */ 942 vxlan_vlan_xlate = &(vxlan_info->vxlan_vlan_xlate[entry_index]); 943 if (vxlan_vlan_xlate->ref_count > 0) { 944 /* Update the reference count */ 945 vxlan_vlan_xlate->ref_count--; 946 } 947 948 *ref_cnt = vxlan_vlan_xlate->ref_count; 949 950 return BCM_E_NONE; 951 } 952 953 #ifdef BCM_WARM_BOOT_SUPPORT 954 955 #define BCM_WB_VERSION_1_0 SOC_SCACHE_VERSION(1, 0) 956 #define BCM_WB_DEFAULT_VERSION BCM_WB_VERSION_1_0 957 958 STATIC int bcmi_gh2_vxlan_wb_alloc(int unit); 959 960 /* 961 * Function: 962 * bcmi_gh2_vxlan_ecmp_nexthop_entry_recover 963 * Purpose: 964 * WB recovery for vxlan ecmp member object's Egress next hop entry 965 * Parameters: 966 * unit - (IN) Device Number 967 * ecmp_nh_index - (IN) ecmp group number 968 * Returns: 969 * BCM_E_XXX 970 */ 971 STATIC int 972 bcmi_gh2_vxlan_egr_mac_da_recover(int unit) 973 { 974 int rv = BCM_E_NONE; 975 int min, max, i; 976 egr_l3_next_hop_entry_t nh_entry; 977 int macda_idx; 978 979 min = soc_mem_index_min(unit, EGR_L3_NEXT_HOPm); 980 max = soc_mem_index_max(unit, EGR_L3_NEXT_HOPm); 981 982 for (i = min; i < max; i++) { 983 984 /* Recover MAC_DA profile count */ 985 SOC_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 986 i, &nh_entry)); 987 if (soc_EGR_L3_NEXT_HOPm_field32_get(unit, &nh_entry, 988 ENTRY_TYPEf) == 0xa) { 989 macda_idx = soc_EGR_L3_NEXT_HOPm_field32_get 990 (unit, &nh_entry, 991 VXLAN__MAC_DA_PROFILE_INDEXf); 992 _bcm_common_profile_mem_ref_cnt_update( 993 unit, EGR_MAC_DA_PROFILEm, macda_idx, 1); 994 } 995 } 996 997 return rv; 998 } 999 1000 /* 1001 * Function: 1002 * bcmi_gh2_vxlan_wb_recover 1003 * Purpose: 1004 * Recover VXLAN module info for Level 2 Warm Boot from persisitent memory 1005 * Warm Boot Version Map: 1006 * see _bcm_esw_vxlan_sync definition 1007 * Parameters: 1008 * unit - (IN) Device Number 1009 * Returns: 1010 * BCM_E_XXX 1011 */ 1012 STATIC int 1013 bcmi_gh2_vxlan_wb_recover(int unit) 1014 { 1015 int rv = BCM_E_NONE; 1016 int i; 1017 int num_tnl = 0, num_vp = 0; 1018 int stable_size; 1019 int add_sz = 0; 1020 bcm_gport_t gport; 1021 uint8 *vxlan_state = NULL; 1022 soc_scache_handle_t scache_handle; 1023 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 1024 int num_vfi = 0; 1025 int intf; 1026 uint32 flag = 0; 1027 int index = -1; 1028 uint16 tpid_value; 1029 1030 vxlan_info = GH2_VXLAN_INFO(unit); 1031 1032 BCM_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 1033 1034 /* Requires extended scache support level-2 warmboot */ 1035 if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) { 1036 return BCM_E_NONE; 1037 } 1038 1039 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_VXLAN, 0); 1040 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 1041 0, &vxlan_state, 1042 BCM_WB_DEFAULT_VERSION, NULL); 1043 if (BCM_FAILURE(rv)) { 1044 return rv; 1045 } 1046 1047 if (vxlan_state != NULL) { 1048 num_vp = vxlan_info->num_vxlan_vp; 1049 num_tnl = vxlan_info->num_vxlan_tnl; 1050 num_vfi = vxlan_info->num_vxlan_vfi; 1051 1052 /* Version_1_0: bcmi_gh2_vxlan_tunnel_endpoint_t in vxlan_bookkeeping_t 1053 * bcm_ip_t dip + bcm_ip_t sip + bcm_ip6_t dip6 + bcm_ip6_t sip6 + 1054 * uin16 tunnel_state + int activate_flag + bcm_vlan_t vlan. 1055 */ 1056 /* size of (bcmi_gh2_vxlan_tunnel_endpoint_t) */ 1057 add_sz = sizeof(bcmi_gh2_vxlan_tunnel_endpoint_t); 1058 1059 /* 1060 * Recover Vxlan Tunnel Terminator 1061 * (DIP, SIP, DIP6, SIP6, Tunnel State(uint16), activate_flag, vlan) 1062 * To correspond with the sync actions in Version_1_0 1063 */ 1064 for (i = 0; i < num_tnl; i++) { 1065 sal_memcpy(&(vxlan_info->vxlan_tunnel_term[i]), 1066 vxlan_state, add_sz); 1067 vxlan_state += add_sz; 1068 } 1069 1070 /* 1071 * Recover Vxlan Tunnel Initiator 1072 * (DIP, SIP, DIP6, SIP6, Tunnel State(uint16), activate_flag, vlan) 1073 * To correspond with the sync actions in Version_1_0 1074 */ 1075 for (i = 0; i < num_tnl; i++) { 1076 sal_memcpy(&(vxlan_info->vxlan_tunnel_init[i]), 1077 vxlan_state, add_sz); 1078 vxlan_state += add_sz; 1079 } 1080 1081 /* Recover the BITMAP of Vxlan Tunnel usage */ 1082 sal_memcpy(vxlan_info->vxlan_ip_tnl_bitmap, vxlan_state, 1083 SHR_BITALLOCSIZE(num_tnl)); 1084 vxlan_state += SHR_BITALLOCSIZE(num_tnl); 1085 1086 /* Recover the flags & match_tunnel_index of each Match Key */ 1087 for (i = 0; i < num_vp; i++) { 1088 sal_memcpy(&(vxlan_info->match_key[i].flags), 1089 vxlan_state, sizeof(uint32)); 1090 vxlan_state += sizeof(uint32); 1091 sal_memcpy(&(vxlan_info->match_key[i].match_tunnel_index), 1092 vxlan_state, sizeof(uint32)); 1093 vxlan_state += sizeof(uint32); 1094 } 1095 1096 /* 1097 * Recover the index && gport(trunk_id, modid, port) && match_vlan && 1098 * match_inner_vlan of each Match Key 1099 */ 1100 for (i = 0; i < num_vp; i++) { 1101 sal_memcpy(&(vxlan_info->match_key[i].index), vxlan_state, 1102 sizeof(uint32)); 1103 vxlan_state += sizeof(uint32); 1104 sal_memcpy(&gport, vxlan_state, sizeof(bcm_gport_t)); 1105 if (BCM_GPORT_IS_TRUNK(gport)) { 1106 vxlan_info->match_key[i].trunk_id = 1107 BCM_GPORT_TRUNK_GET(gport); 1108 } else if (BCM_GPORT_IS_MODPORT(gport)) { 1109 vxlan_info->match_key[i].modid = 1110 BCM_GPORT_MODPORT_MODID_GET(gport); 1111 vxlan_info->match_key[i].port = 1112 BCM_GPORT_MODPORT_PORT_GET(gport); 1113 vxlan_info->match_key[i].trunk_id = -1; 1114 } 1115 vxlan_state += sizeof(bcm_gport_t); 1116 sal_memcpy(&(vxlan_info->match_key[i].match_vlan), vxlan_state, 1117 sizeof(bcm_vlan_t)); 1118 vxlan_state += sizeof(bcm_vlan_t); 1119 sal_memcpy(&(vxlan_info->match_key[i].match_inner_vlan), 1120 vxlan_state, sizeof(bcm_vlan_t)); 1121 vxlan_state += sizeof(bcm_vlan_t); 1122 } 1123 1124 /* Recover the BITMAP of Vxlan VFI usage */ 1125 sal_memcpy(vxlan_info->vxlan_vfi_bitmap, vxlan_state, 1126 SHR_BITALLOCSIZE(num_vfi)); 1127 vxlan_state += SHR_BITALLOCSIZE(num_vfi); 1128 1129 /* Recover the type of each vxlan vpn */ 1130 for (i = 0; i < num_vfi; i++) { 1131 sal_memcpy(&(vxlan_info->vxlan_vpn_info[i].valid), 1132 vxlan_state, sizeof(int)); 1133 vxlan_state += sizeof(int); 1134 sal_memcpy(&(vxlan_info->vxlan_vpn_info[i].vnid), 1135 vxlan_state, sizeof(uint32)); 1136 vxlan_state += sizeof(uint32); 1137 } 1138 1139 /* Recover the vfi index of each vxlan vp */ 1140 for (i = 0; i < num_vp; i++) { 1141 sal_memcpy(&(vxlan_info->match_key[i].vfi), 1142 vxlan_state, sizeof(int)); 1143 vxlan_state += sizeof(int); 1144 } 1145 1146 /* Recover the BITMAP of Vxlan VP usage */ 1147 sal_memcpy(vxlan_info->vxlan_vp_bitmap, vxlan_state, 1148 SHR_BITALLOCSIZE(num_vp)); 1149 vxlan_state += SHR_BITALLOCSIZE(num_vp); 1150 1151 /* Recover the BITMAP of Vxlan VP usage for Network side */ 1152 sal_memcpy(vxlan_info->vxlan_network_vp_bitmap, vxlan_state, 1153 SHR_BITALLOCSIZE(num_vp)); 1154 vxlan_state += SHR_BITALLOCSIZE(num_vp); 1155 1156 /* Recover per VP info */ 1157 for (i = 0; i < num_vp; i++) { 1158 sal_memcpy(&(vxlan_info->vxlan_vp_info[i].vp_type), 1159 vxlan_state, sizeof(uint32)); 1160 vxlan_state += sizeof(uint32); 1161 sal_memcpy(&(vxlan_info->vxlan_vp_info[i].vfi), 1162 vxlan_state, sizeof(int)); 1163 vxlan_state += sizeof(int); 1164 sal_memcpy(&(vxlan_info->vxlan_vp_info[i].ecmp), 1165 vxlan_state, sizeof(int)); 1166 vxlan_state += sizeof(int); 1167 sal_memcpy(&(vxlan_info->vxlan_vp_info[i].nh_ecmp_index), 1168 vxlan_state, sizeof(int)); 1169 vxlan_state += sizeof(int); 1170 /* Recovering EgrObj ref_count (NextHop/ECMP) */ 1171 if (vxlan_info->vxlan_vp_info[i].ecmp) { 1172 intf = vxlan_info->vxlan_vp_info[i].nh_ecmp_index + 1173 BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit); 1174 } else { 1175 intf = vxlan_info->vxlan_vp_info[i].nh_ecmp_index + 1176 BCM_XGS3_EGRESS_IDX_MIN(unit); 1177 } 1178 rv = bcm_xgs3_get_nh_from_egress_object(unit, intf, &flag, 1, 1179 &index); 1180 BCM_IF_ERROR_RETURN(rv); 1181 1182 sal_memcpy(&(vxlan_info->vxlan_vp_info[i].tpid_valid), 1183 vxlan_state, sizeof(int)); 1184 vxlan_state += sizeof(int); 1185 sal_memcpy(&(vxlan_info->vxlan_vp_info[i].tpid_value), 1186 vxlan_state, sizeof(uint16)); 1187 vxlan_state += sizeof(uint16); 1188 1189 /* Recovering VXLAN Outer TPID reference count */ 1190 if (vxlan_info->vxlan_vp_info[i].tpid_valid) { 1191 tpid_value = vxlan_info->vxlan_vp_info[i].tpid_value; 1192 BCM_IF_ERROR_RETURN( 1193 bcmi_gh2_vxlan_outer_tpid_ref_inc(unit, tpid_value)); 1194 } 1195 } 1196 1197 /* Recover the reference count of each vxlan vlan xlate entry */ 1198 for (i = 0; i < num_vfi; i++) { 1199 sal_memcpy(&(vxlan_info->vxlan_vlan_xlate[i].ref_count), 1200 vxlan_state, sizeof(int)); 1201 vxlan_state += sizeof(int); 1202 } 1203 1204 /* Recover Custom Header info per VP info (used for RIOT) */ 1205 for (i = 0; i < num_vp; i++) { 1206 sal_memcpy(&(vxlan_info->vxlan_vp_info[i].ch_encap_id), 1207 vxlan_state, sizeof(bcm_if_t)); 1208 vxlan_state += sizeof(bcm_if_t); 1209 sal_memcpy(&(vxlan_info->vxlan_vp_info[i].ch_match_id_ipmc), 1210 vxlan_state, sizeof(int)); 1211 vxlan_state += sizeof(int); 1212 sal_memcpy(&(vxlan_info->vxlan_vp_info[i].ch_match_id_non_ipmc), 1213 vxlan_state, sizeof(int)); 1214 vxlan_state += sizeof(int); 1215 } 1216 1217 /* 1218 * Recover the BITMAP of Vxlan VP usage for Loopback side 1219 * (used for RIOT) 1220 */ 1221 sal_memcpy(vxlan_info->vxlan_loopback_vp_bitmap, vxlan_state, 1222 SHR_BITALLOCSIZE(num_vp)); 1223 vxlan_state += SHR_BITALLOCSIZE(num_vp); 1224 1225 /* 1226 * Recover Reference count of Custom Header index0 1227 * (used for RIOT) 1228 */ 1229 sal_memcpy(&(vxlan_info->riot_custom_header_index0_ref_count), 1230 vxlan_state, sizeof(int)); 1231 vxlan_state += sizeof(int); 1232 1233 } 1234 1235 return BCM_E_NONE; 1236 } 1237 1238 /* 1239 * Function: 1240 * bcmi_gh2_vxlan_wb_alloc 1241 * Purpose: 1242 * Alloc persisitent memory for Level 2 Warm Boot scache. 1243 * Parameters: 1244 * unit - (IN) Device Number 1245 * Returns: 1246 * BCM_E_XXX 1247 */ 1248 STATIC int 1249 bcmi_gh2_vxlan_wb_alloc(int unit) 1250 { 1251 int rv = BCM_E_NONE; 1252 int alloc_sz = 0; 1253 soc_scache_handle_t scache_handle; 1254 int num_tnl = 0, num_vp = 0; 1255 int num_vfi = 0; 1256 uint8 *vxlan_state; 1257 int stable_size; 1258 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 1259 1260 vxlan_info = GH2_VXLAN_INFO(unit); 1261 1262 BCM_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 1263 1264 if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) { 1265 return BCM_E_NONE; 1266 } 1267 1268 /* Size of Tunnel Terminator & Initiator */ 1269 num_tnl = vxlan_info->num_vxlan_tnl; 1270 alloc_sz += num_tnl * sizeof(bcmi_gh2_vxlan_tunnel_endpoint_t) * 2; 1271 1272 /* Size of EGR_IP_TUNNEL index bitmap */ 1273 alloc_sz += SHR_BITALLOCSIZE(num_tnl); 1274 1275 /* Size of All match_key's flags & match_tunnel_index */ 1276 num_vp = vxlan_info->num_vxlan_vp; 1277 alloc_sz += num_vp * sizeof(uint32) * 2; 1278 1279 /* 1280 * Size of All match_key's index && gport(trunk_id, modid, port) && 1281 * match_vlan && match_inner_vlan 1282 */ 1283 alloc_sz += num_vp * (sizeof(uint32) + sizeof(bcm_gport_t) + 1284 sizeof(bcm_vlan_t) * 2); 1285 1286 /* Size of VXLAN VFI bitmap */ 1287 num_vfi = vxlan_info->num_vxlan_vfi; 1288 alloc_sz += SHR_BITALLOCSIZE(num_vfi); 1289 1290 /* Size of VXLAN VFI info data structure */ 1291 alloc_sz += num_vfi * sizeof(gh2_vxlan_vpn_info_t); 1292 /* Size of match_key's vfi related with vp */ 1293 alloc_sz += num_vp * sizeof(int); 1294 1295 /* Size of VXLAN Virtual Port bitmap & Network Virtual Port bitmap */ 1296 alloc_sz += SHR_BITALLOCSIZE(num_vp); 1297 alloc_sz += SHR_BITALLOCSIZE(num_vp); 1298 1299 /* Size of VXLAN per VLAN XLATE entry info */ 1300 alloc_sz += num_vfi * sizeof(gh2_vxlan_vlan_xlate_info_t); 1301 1302 /* Size of VXLAN per VP info */ 1303 alloc_sz += num_vp * sizeof(gh2_vxlan_vp_info_t); 1304 1305 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_VXLAN, 0); 1306 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE, 1307 alloc_sz, (uint8**)&vxlan_state, 1308 BCM_WB_DEFAULT_VERSION, NULL); 1309 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 1310 return rv; 1311 } 1312 1313 return BCM_E_NONE; 1314 } 1315 1316 /* 1317 * Function: 1318 * bcmi_gh2_vxlan_tunnel_initiator_reinit 1319 * Purpose: 1320 * Tunnel initiator hash and ref-count recovery. 1321 * Parameters: 1322 * unit - (IN) Device Number 1323 * Returns: 1324 * BCM_E_XXX 1325 */ 1326 STATIC int 1327 bcmi_gh2_vxlan_tunnel_initiator_reinit(int unit) 1328 { 1329 bcm_tunnel_initiator_t tnl_init_info; 1330 soc_mem_t mem, mem_ip6; 1331 int i = 0; 1332 int idx_min = 0; 1333 int idx_max = 0; 1334 uint32 tnl_entry[SOC_MAX_MEM_FIELD_WORDS]; /* Buffer to read hw entry */ 1335 int entry_type = 0; /* Entry type (IPv4 or IPv6). */ 1336 int tnl_type = 0; /* Tunnel type. */ 1337 _bcm_l3_tbl_t *tbl_ptr; /* Tunnel init table pointer. */ 1338 1339 mem = BCM_XGS3_L3_MEM(unit, tnl_init_v4); 1340 mem_ip6 = BCM_XGS3_L3_MEM(unit, tnl_init_v6); 1341 idx_min = soc_mem_index_min(unit, mem); 1342 idx_max = soc_mem_index_max(unit, mem); 1343 tbl_ptr = BCM_XGS3_L3_TBL_PTR(unit, tnl_init); 1344 for (i = idx_min; i <= idx_max; i++) { 1345 /* Initialize the buffer */ 1346 sal_memset(tnl_entry, 0, sizeof(tnl_entry)); 1347 BCM_IF_ERROR_RETURN( 1348 soc_mem_read(unit, mem, MEM_BLOCK_ANY, i, tnl_entry)); 1349 1350 tnl_type = soc_mem_field32_get(unit, mem, tnl_entry, TUNNEL_TYPEf); 1351 entry_type = soc_mem_field32_get(unit, mem, tnl_entry, ENTRY_TYPEf); 1352 1353 if (tnl_type == _BCM_VXLAN_TUNNEL_TYPE) { 1354 if (entry_type == BCM_XGS3_TUNNEL_INIT_V6) { 1355 /* Initialize the buffer */ 1356 sal_memset(tnl_entry, 0, sizeof(tnl_entry)); 1357 BCM_IF_ERROR_RETURN( 1358 soc_mem_read(unit, mem_ip6, MEM_BLOCK_ANY, 1359 (i / 2), tnl_entry)); 1360 1361 bcm_tunnel_initiator_t_init(&tnl_init_info); 1362 1363 /* Tunnel for IPv6 */ 1364 tnl_init_info.type = bcmTunnelTypeVxlan6; 1365 1366 /* Extract IPv6 SIP/DIP address */ 1367 soc_mem_ip6_addr_get(unit, mem_ip6, tnl_entry, SIPf, 1368 tnl_init_info.sip6, 1369 SOC_MEM_IP6_FULL_ADDR); 1370 soc_mem_ip6_addr_get(unit, mem_ip6, tnl_entry, DIPf, 1371 tnl_init_info.dip6, 1372 SOC_MEM_IP6_FULL_ADDR); 1373 1374 tnl_init_info.udp_dst_port = 1375 soc_mem_field32_get(unit, mem_ip6, 1376 tnl_entry, L4_DST_PORTf); 1377 BCM_IF_ERROR_RETURN(bcmi_gh2_vxlan_tunnel_initiator_hash_calc 1378 (unit, &tnl_init_info, 1379 &BCM_XGS3_L3_ENT_HASH(tbl_ptr, i))); 1380 BCM_IF_ERROR_RETURN(bcmi_gh2_vxlan_tunnel_initiator_hash_calc 1381 (unit, &tnl_init_info, 1382 &BCM_XGS3_L3_ENT_HASH(tbl_ptr, (i + 1)))); 1383 BCM_XGS3_L3_ENT_REF_CNT_INC( 1384 tbl_ptr, i, 1385 ((_BCM_TUNNEL_OUTER_HEADER_IPV6(tnl_init_info.type)) ? 1386 _BCM_DOUBLE_WIDE : _BCM_SINGLE_WIDE)); 1387 /* Update Maximum used index */ 1388 tbl_ptr->idx_maxused = i; 1389 } else if (entry_type == BCM_XGS3_TUNNEL_INIT_V4) { 1390 bcm_tunnel_initiator_t_init(&tnl_init_info); 1391 1392 /* Tunnel for IPv4 */ 1393 tnl_init_info.type = bcmTunnelTypeVxlan; 1394 1395 /* Get IPv4 SIP/DIP address */ 1396 tnl_init_info.sip = 1397 soc_mem_field32_get(unit, mem, tnl_entry, SIPf); 1398 tnl_init_info.dip = 1399 soc_mem_field32_get(unit, mem, tnl_entry, DIPf); 1400 1401 tnl_init_info.udp_dst_port = 1402 soc_mem_field32_get(unit, mem, tnl_entry, L4_DST_PORTf); 1403 BCM_IF_ERROR_RETURN(bcmi_gh2_vxlan_tunnel_initiator_hash_calc 1404 (unit, &tnl_init_info, 1405 &BCM_XGS3_L3_ENT_HASH(tbl_ptr, i))); 1406 BCM_XGS3_L3_ENT_REF_CNT_INC( 1407 tbl_ptr, i, 1408 ((_BCM_TUNNEL_OUTER_HEADER_IPV6(tnl_init_info.type)) ? 1409 _BCM_DOUBLE_WIDE : _BCM_SINGLE_WIDE)); 1410 /* Update Maximum used index */ 1411 tbl_ptr->idx_maxused = i; 1412 } 1413 } 1414 } 1415 1416 return BCM_E_NONE; 1417 } 1418 1419 /* 1420 * Function: 1421 * bcmi_gh2_vxlan_reinit 1422 * Purpose: 1423 * Warm boot recovery for the VXLAN software module 1424 * Parameters: 1425 * unit - (IN) Device Number 1426 * Returns: 1427 * BCM_E_XXX 1428 */ 1429 STATIC int 1430 bcmi_gh2_vxlan_reinit(int unit) 1431 { 1432 1433 /* Tunnel initiator hash and ref-count recovery */ 1434 BCM_IF_ERROR_RETURN( 1435 bcmi_gh2_vxlan_tunnel_initiator_reinit(unit)); 1436 1437 /* Recover L2 scache */ 1438 BCM_IF_ERROR_RETURN(bcmi_gh2_vxlan_wb_recover(unit)); 1439 1440 /* Recover EGR_MAC_DA reference count */ 1441 BCM_IF_ERROR_RETURN(bcmi_gh2_vxlan_egr_mac_da_recover(unit)); 1442 1443 return BCM_E_NONE; 1444 } 1445 1446 /* 1447 * Function: 1448 * bcmi_gh2_vxlan_sync 1449 * Purpose: 1450 * This routine extracts the state that needs to be stored from the 1451 * book-keeping structs and stores it in the allocated scache location. 1452 * Parameters: 1453 * unit - (IN) Device Number 1454 * Returns: 1455 * BCM_E_XXX 1456 */ 1457 int 1458 bcmi_gh2_vxlan_sync(int unit) 1459 { 1460 int rv = BCM_E_NONE; 1461 int i, num_tnl = 0, num_vp = 0; 1462 int num_vfi = 0; 1463 int size; 1464 int stable_size; 1465 bcm_gport_t gport; 1466 uint8 *vxlan_state; 1467 soc_scache_handle_t scache_handle; 1468 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 1469 1470 if (!soc_feature(unit, soc_feature_vxlan_lite)) { 1471 return BCM_E_UNAVAIL; 1472 } 1473 1474 /* Parameter validation checks */ 1475 if (!SOC_UNIT_VALID(unit)) { 1476 return BCM_E_UNIT; 1477 } 1478 1479 vxlan_info = GH2_VXLAN_INFO(unit); 1480 1481 BCM_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 1482 1483 /* Requires extended scache support level-2 warmboot */ 1484 if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) { 1485 return BCM_E_NONE; 1486 } 1487 1488 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_VXLAN, 0); 1489 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 1490 0, &vxlan_state, 1491 BCM_WB_DEFAULT_VERSION, NULL); 1492 if (BCM_FAILURE(rv) && (rv != BCM_E_INTERNAL)) { 1493 return rv; 1494 } 1495 1496 num_vp = vxlan_info->num_vxlan_vp; 1497 num_tnl = vxlan_info->num_vxlan_tnl; 1498 size = num_tnl * sizeof(bcmi_gh2_vxlan_tunnel_endpoint_t); 1499 1500 /* Store each Vxlan Tunnnel Terminator entry (SIP, DIP, Tunnel State) */ 1501 /* 1502 * vxlan_tunnel_term points to a struct array with a base type of 1503 * bcmi_gh2_vxlan_tunnel_endpoint_t, sized to hold the info of each 1504 * virtual port tunnel. 1505 * 1506 * EGR_IP_TUNNELm hw index equals to array index, related to the IP & state 1507 * info of each VP. 1508 * 1509 * bcmi_gh2_vxlan_tunnel_endpoint_t[size of (EGR_IP_TUNNELm)] * 1510 * vxlan_tunnel_term 1511 */ 1512 sal_memcpy(vxlan_state, vxlan_info->vxlan_tunnel_term, size); 1513 vxlan_state += size; 1514 1515 /* Store each Vxlan Tunnel Initiator entry (SIP, DIP, Tunnel State) */ 1516 /* 1517 * Same as vxlan_tunnel_term. 1518 */ 1519 sal_memcpy(vxlan_state, vxlan_info->vxlan_tunnel_init, size); 1520 vxlan_state += size; 1521 1522 /* Store the BITMAP of Vxlan Tunnel usage */ 1523 /* 1524 * vxlan_ip_tnl_bitmap points to a struct array with a base type of uint32. 1525 * sized to hold the maximum number of Egress IP Tunnel. 1526 * 1527 * EGR_IP_TUNNELm hw index used as offset of this wide bitmap. 1528 * 1529 * uint32[(size of (EGR_IP_TUNNELm) + 31) / 32] * vxlan_ip_tnl_bitmap 1530 */ 1531 sal_memcpy(vxlan_state, vxlan_info->vxlan_ip_tnl_bitmap, 1532 SHR_BITALLOCSIZE(num_tnl)); 1533 vxlan_state += SHR_BITALLOCSIZE(num_tnl); 1534 1535 /* Store the flags & match_tunnel_index of each Match Key */ 1536 /* 1537 * Since we can't recover flags & match_tunnel_index from HW, 1538 * so we need to store it for warmboot recovery. 1539 */ 1540 for (i = 0; i < num_vp; i++) { 1541 sal_memcpy(vxlan_state, &(vxlan_info->match_key[i].flags), 1542 sizeof(uint32)); 1543 vxlan_state += sizeof(uint32); 1544 sal_memcpy(vxlan_state, &(vxlan_info->match_key[i].match_tunnel_index), 1545 sizeof(uint32)); 1546 vxlan_state += sizeof(uint32); 1547 } 1548 1549 /* 1550 * Store the index & gport(trunk_id, modid, port) & match_vlan & 1551 * match_inner_vlan of each Match Key 1552 * 1553 * Since we can't recover index & gport(trunk_id, modid, port) & 1554 * match_vlan & match_inner_vlan from HW, so we need to store it 1555 * for warmboot recovery. 1556 */ 1557 for (i = 0; i < num_vp; i++) { 1558 sal_memcpy(vxlan_state, &(vxlan_info->match_key[i].index), 1559 sizeof(uint32)); 1560 vxlan_state += sizeof(uint32); 1561 if (vxlan_info->match_key[i].trunk_id != -1) { 1562 BCM_GPORT_TRUNK_SET(gport, vxlan_info->match_key[i].trunk_id); 1563 } else if (vxlan_info->match_key[i].modid != -1) { 1564 BCM_GPORT_MODPORT_SET(gport, 1565 vxlan_info->match_key[i].modid, 1566 vxlan_info->match_key[i].port); 1567 } else { 1568 gport = BCM_GPORT_INVALID; 1569 } 1570 sal_memcpy(vxlan_state, &gport, sizeof(bcm_gport_t)); 1571 vxlan_state += sizeof(bcm_gport_t); 1572 sal_memcpy(vxlan_state, &(vxlan_info->match_key[i].match_vlan), 1573 sizeof(bcm_vlan_t)); 1574 vxlan_state += sizeof(bcm_vlan_t); 1575 sal_memcpy(vxlan_state, &(vxlan_info->match_key[i].match_inner_vlan), 1576 sizeof(bcm_vlan_t)); 1577 vxlan_state += sizeof(bcm_vlan_t); 1578 } 1579 1580 num_vfi = vxlan_info->num_vxlan_vfi; 1581 1582 /* Store the BITMAP of Vxlan VFI usage */ 1583 /* 1584 * vxlan_vfi_bitmap points to a struct array with a base type of uint32. 1585 * sized to hold the maximum number of Vxlan VFI. 1586 * 1587 * VFI sw index used as offset of this wide bitmap. 1588 * 1589 * uint32[(size of (VLAN_XLATEm or VFIm) + 31) / 32] * vxlan_vfi_bitmap 1590 * VFIm is support for GH2-B0. VLAN_XLATEm is used for GH2-A0. 1591 */ 1592 sal_memcpy(vxlan_state, vxlan_info->vxlan_vfi_bitmap, 1593 SHR_BITALLOCSIZE(num_vfi)); 1594 vxlan_state += SHR_BITALLOCSIZE(num_vfi); 1595 1596 /* Store the type of each vxlan vpn */ 1597 for (i = 0; i < num_vfi; i++) { 1598 sal_memcpy(vxlan_state, &(vxlan_info->vxlan_vpn_info[i].valid), 1599 sizeof(int)); 1600 vxlan_state += sizeof(int); 1601 sal_memcpy(vxlan_state, &(vxlan_info->vxlan_vpn_info[i].vnid), 1602 sizeof(uint32)); 1603 vxlan_state += sizeof(uint32); 1604 } 1605 1606 /* Store the vfi index for vp */ 1607 for (i = 0; i < num_vp; i++) { 1608 sal_memcpy(vxlan_state, &(vxlan_info->match_key[i].vfi), 1609 sizeof(int)); 1610 vxlan_state += sizeof(int); 1611 } 1612 1613 /* Store the BITMAP of Vxlan VP usage */ 1614 /* 1615 * vxlan_vp_bitmap points to a struct array with a base type of uint32. 1616 * sized to hold the maximum number of Vxlan VP. 1617 * 1618 * VP sw index used as offset of this wide bitmap. 1619 * 1620 * uint32[(size of (VLAN_XLATEm) + 31) / 32] * vxlan_vp_bitmap 1621 */ 1622 sal_memcpy(vxlan_state, vxlan_info->vxlan_vp_bitmap, 1623 SHR_BITALLOCSIZE(num_vp)); 1624 vxlan_state += SHR_BITALLOCSIZE(num_vp); 1625 1626 /* Store the BITMAP of Vxlan VP usage for Network side */ 1627 /* 1628 * Same as vxlan_vp_bitmap. 1629 */ 1630 sal_memcpy(vxlan_state, vxlan_info->vxlan_network_vp_bitmap, 1631 SHR_BITALLOCSIZE(num_vp)); 1632 vxlan_state += SHR_BITALLOCSIZE(num_vp); 1633 1634 /* Store per VP info */ 1635 for (i = 0; i < num_vp; i++) { 1636 sal_memcpy(vxlan_state, &(vxlan_info->vxlan_vp_info[i].vp_type), 1637 sizeof(uint32)); 1638 vxlan_state += sizeof(uint32); 1639 sal_memcpy(vxlan_state, &(vxlan_info->vxlan_vp_info[i].vfi), 1640 sizeof(int)); 1641 vxlan_state += sizeof(int); 1642 sal_memcpy(vxlan_state, &(vxlan_info->vxlan_vp_info[i].ecmp), 1643 sizeof(int)); 1644 vxlan_state += sizeof(int); 1645 sal_memcpy(vxlan_state, &(vxlan_info->vxlan_vp_info[i].nh_ecmp_index), 1646 sizeof(int)); 1647 vxlan_state += sizeof(int); 1648 sal_memcpy(vxlan_state, &(vxlan_info->vxlan_vp_info[i].tpid_valid), 1649 sizeof(int)); 1650 vxlan_state += sizeof(int); 1651 sal_memcpy(vxlan_state, &(vxlan_info->vxlan_vp_info[i].tpid_value), 1652 sizeof(uint16)); 1653 vxlan_state += sizeof(uint16); 1654 } 1655 1656 /* Store the ref_cnt of each vxlan vlan xlate entry */ 1657 for (i = 0; i < num_vfi; i++) { 1658 sal_memcpy(vxlan_state, &(vxlan_info->vxlan_vlan_xlate[i].ref_count), 1659 sizeof(int)); 1660 vxlan_state += sizeof(int); 1661 } 1662 1663 /* Store Cstom Header info per VP info (used for RIOT) */ 1664 for (i = 0; i < num_vp; i++) { 1665 sal_memcpy(vxlan_state, &(vxlan_info->vxlan_vp_info[i].ch_encap_id), 1666 sizeof(bcm_if_t)); 1667 vxlan_state += sizeof(bcm_if_t); 1668 sal_memcpy(vxlan_state, 1669 &(vxlan_info->vxlan_vp_info[i].ch_match_id_ipmc), 1670 sizeof(int)); 1671 vxlan_state += sizeof(int); 1672 sal_memcpy(vxlan_state, 1673 &(vxlan_info->vxlan_vp_info[i].ch_match_id_non_ipmc), 1674 sizeof(int)); 1675 vxlan_state += sizeof(int); 1676 } 1677 1678 /* Store the BITMAP of Vxlan VP usage for Loopback side (used for RIOT) */ 1679 sal_memcpy(vxlan_state, vxlan_info->vxlan_loopback_vp_bitmap, 1680 SHR_BITALLOCSIZE(num_vp)); 1681 vxlan_state += SHR_BITALLOCSIZE(num_vp); 1682 1683 /* Store Reference count of Custom Header index0 (used for RIOT) */ 1684 sal_memcpy(vxlan_state, &(vxlan_info->riot_custom_header_index0_ref_count), 1685 sizeof(int)); 1686 vxlan_state += sizeof(int); 1687 1688 return rv; 1689 1690 } 1691 1692 #endif /* BCM_WARM_BOOT_SUPPORT */ 1693 1694 /* 1695 * Function: 1696 * bcmi_gh2_vxlan_hw_clear 1697 * Purpose: 1698 * Perform hw tables clean up for VXLAN module. 1699 * Parameters: 1700 * unit - (IN) Device Number 1701 * Returns: 1702 * BCM_E_XXX 1703 */ 1704 STATIC int 1705 bcmi_gh2_vxlan_hw_clear(int unit) 1706 { 1707 int rv = BCM_E_NONE, rv_error = BCM_E_NONE; 1708 1709 rv = bcmi_gh2_vxlan_tunnel_terminator_destroy_all(unit); 1710 if (BCM_FAILURE(rv)) { 1711 rv_error = rv; 1712 } 1713 1714 rv = bcmi_gh2_vxlan_tunnel_initiator_destroy_all(unit); 1715 if (BCM_FAILURE(rv) && (rv_error == BCM_E_NONE)) { 1716 rv_error = rv; 1717 } 1718 1719 rv = bcmi_gh2_vxlan_vpn_destroy_all(unit); 1720 if (BCM_FAILURE(rv) && (rv_error == BCM_E_NONE)) { 1721 rv_error = rv; 1722 } 1723 1724 return rv_error; 1725 } 1726 1727 /* 1728 * Function: 1729 * bcmi_gh2_vxlan_vfi_alloc 1730 * Purpose: 1731 * Internal function for allocating a VFI 1732 * Parameters: 1733 * unit - (IN) Device Number 1734 * vfi - (OUT) VFI index 1735 * Returns: 1736 * BCM_X_XXX 1737 */ 1738 STATIC int 1739 bcmi_gh2_vxlan_vfi_alloc(int unit, int *vfi) 1740 { 1741 int i, num_vfi; 1742 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info = GH2_VXLAN_INFO(unit); 1743 1744 if (NULL == vfi) { 1745 return BCM_E_PARAM; 1746 } 1747 1748 num_vfi = vxlan_info->num_vxlan_vfi; 1749 1750 for (i = 0; i < num_vfi; i++) { 1751 if (!GH2_VXLAN_VFI_USED_GET(unit, i)) { 1752 break; 1753 } 1754 } 1755 1756 if (i == num_vfi) { 1757 return BCM_E_RESOURCE; 1758 } 1759 1760 GH2_VXLAN_VFI_USED_SET(unit, i); 1761 *vfi = i; 1762 1763 return BCM_E_NONE; 1764 } 1765 1766 /* 1767 * Function: 1768 * bcmi_gh2_vxlan_vfi_alloc_with_id 1769 * Purpose: 1770 * Internal function for allocating a VFI with a given ID 1771 * Parameters: 1772 * unit - (IN) Device Number 1773 * vfi - (IN) VFI index 1774 * Returns: 1775 * BCM_X_XXX 1776 */ 1777 STATIC int 1778 bcmi_gh2_vxlan_vfi_alloc_with_id(int unit, int vfi) 1779 { 1780 int num_vfi; 1781 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info = GH2_VXLAN_INFO(unit); 1782 1783 num_vfi = vxlan_info->num_vxlan_vfi; 1784 1785 /* Check Valid range of VFI */ 1786 if (vfi < 0 || vfi >= num_vfi) { 1787 return BCM_E_RESOURCE; 1788 } 1789 1790 if (GH2_VXLAN_VFI_USED_GET(unit, vfi)) { 1791 return BCM_E_EXISTS; 1792 } 1793 1794 GH2_VXLAN_VFI_USED_SET(unit, vfi); 1795 1796 return BCM_E_NONE; 1797 } 1798 1799 1800 /* 1801 * Function: 1802 * bcmi_gh2_vxlan_vfi_free 1803 * Purpose: 1804 * Internal function for freeing a VFI 1805 * Parameters: 1806 * unit - (IN) Device Number 1807 * vfi - (IN) VFI index 1808 * Returns: 1809 * None 1810 */ 1811 STATIC int 1812 bcmi_gh2_vxlan_vfi_free(int unit, int vfi) 1813 { 1814 int num_vfi; 1815 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info = GH2_VXLAN_INFO(unit); 1816 vfi_entry_t vfi_entry; 1817 1818 num_vfi = vxlan_info->num_vxlan_vfi; 1819 1820 /* Check Valid range of VFI */ 1821 if (vfi < 0 || vfi >= num_vfi) { 1822 return BCM_E_RESOURCE; 1823 } 1824 1825 GH2_VXLAN_VFI_USED_CLR(unit, vfi); 1826 1827 if (soc_feature(unit, soc_feature_vxlan_lite_riot)) { 1828 /* Only support for GH2-B0 with new VFI table */ 1829 sal_memset(&vfi_entry, 0, sizeof(vfi_entry_t)); 1830 SOC_IF_ERROR_RETURN( 1831 soc_mem_write(unit, VFIm, MEM_BLOCK_ALL, vfi, &vfi_entry)); 1832 } 1833 1834 return BCM_E_NONE; 1835 } 1836 1837 /* 1838 * Function: 1839 * bcmi_gh2_vxlan_vfi_used_get 1840 * Purpose: 1841 * Check whether a VFI is used or not 1842 * Parameters: 1843 * unit - (IN) Device Number 1844 * vfi - (IN) VFI index 1845 * Returns: 1846 * Boolean 1847 */ 1848 int 1849 bcmi_gh2_vxlan_vfi_used_get(int unit, int vfi) 1850 { 1851 int rv; 1852 int num_vfi; 1853 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info = GH2_VXLAN_INFO(unit); 1854 1855 num_vfi = vxlan_info->num_vxlan_vfi; 1856 1857 /* Check Valid range of VFI */ 1858 if (vfi < 0 || vfi >= num_vfi) { 1859 return BCM_E_RESOURCE; 1860 } 1861 1862 rv = GH2_VXLAN_VFI_USED_GET(unit, vfi); 1863 1864 return rv; 1865 } 1866 1867 /* 1868 * Function: 1869 * bcmi_gh2_vxlan_vp_info_init 1870 * Purpose: 1871 * Internal function to initialize bcmi_vxlan_vp_info_t structure 1872 * Parameters: 1873 * vxlan_vp_info - (IN/OUT) variable 1874 * Returns: 1875 * void 1876 */ 1877 STATIC void 1878 bcmi_gh2_vxlan_vp_info_init(bcmi_vxlan_vp_info_t *vxlan_vp_info) 1879 { 1880 if (vxlan_vp_info != NULL) { 1881 sal_memset(vxlan_vp_info, 0, sizeof(*vxlan_vp_info)); 1882 } 1883 1884 return; 1885 } 1886 1887 /* 1888 * Function: 1889 * bcmi_gh2_vxlan_vp_alloc 1890 * Purpose: 1891 * Internal function for allocating a group of VPs 1892 * Parameters: 1893 * unit - (IN) Device Number 1894 * start - (IN) First VP index to allocate from 1895 * end - (IN) Last VP index to allocate from 1896 * count - (IN) How many consecutive VPs to allocate 1897 * vxlan_vp_info - (IN) VXLAN VP information 1898 * base_vp - (OUT) Base VP index 1899 * Returns: 1900 * BCM_X_XXX 1901 */ 1902 STATIC int 1903 bcmi_gh2_vxlan_vp_alloc( 1904 int unit, 1905 int start, 1906 int end, 1907 int count, 1908 bcmi_vxlan_vp_info_t vxlan_vp_info, 1909 int *base_vp) 1910 { 1911 int num_vp; 1912 int i, j; 1913 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info = GH2_VXLAN_INFO(unit); 1914 1915 num_vp = vxlan_info->num_vxlan_vp; 1916 1917 /* Input parameter check */ 1918 if (NULL == base_vp) { 1919 return BCM_E_PARAM; 1920 } 1921 if ((end < 0) || (start < 0) || (end < start) || 1922 (end >= num_vp) || (start >= num_vp)) { 1923 return BCM_E_PARAM; 1924 } 1925 1926 if (vxlan_vp_info.flags) { 1927 /* Loopback VP is only support when VXLAN RIOT is enabled */ 1928 if (GH2_VXLAN_RIOT_ENABLE(unit)) { 1929 if (!(vxlan_vp_info.flags & GH2_VXLAN_VP_INFO_NETWORK_PORT) && 1930 !(vxlan_vp_info.flags & GH2_VXLAN_VP_INFO_LOOPBACK_PORT)) { 1931 return BCM_E_UNAVAIL; 1932 } 1933 } else { 1934 if (!(vxlan_vp_info.flags & GH2_VXLAN_VP_INFO_NETWORK_PORT)) { 1935 return BCM_E_UNAVAIL; 1936 } 1937 } 1938 } 1939 1940 for (i = start; (i + count - 1) <= end; i += (j + 1)) { 1941 for (j = 0; j < count; j++) { 1942 if (GH2_VXLAN_VP_USED_GET(unit, (i + j))) { 1943 break; 1944 } 1945 } 1946 if (j == count) { 1947 break; 1948 } 1949 } 1950 1951 if ((i + count - 1) <= end) { 1952 *base_vp = i; 1953 for (j = 0; j < count; j++) { 1954 GH2_VXLAN_VP_USED_SET(unit, i + j); 1955 if (vxlan_vp_info.flags & GH2_VXLAN_VP_INFO_NETWORK_PORT) { 1956 GH2_VXLAN_NETWORK_VP_USED_SET(unit, (i + j)); 1957 } else if (vxlan_vp_info.flags & GH2_VXLAN_VP_INFO_LOOPBACK_PORT) { 1958 GH2_VXLAN_LOOPBACK_VP_USED_SET(unit, (i + j)); 1959 } 1960 } 1961 return BCM_E_NONE; 1962 } 1963 1964 return BCM_E_RESOURCE; 1965 } 1966 1967 /* 1968 * Function: 1969 * bcmi_gh2_vxlan_vp_free 1970 * Purpose: 1971 * Internal function for freeing a group of VPs 1972 * Parameters: 1973 * unit - (IN) Device Number 1974 * count - (IN) How many consecutive VPs to free 1975 * base_vp - (IN) Base VP index 1976 * Returns: 1977 * BCM_X_XXX 1978 */ 1979 STATIC int 1980 bcmi_gh2_vxlan_vp_free(int unit, int count, int base_vp) 1981 { 1982 int i; 1983 1984 for (i = 0; i < count; i++) { 1985 GH2_VXLAN_VP_USED_CLR(unit, (base_vp + i)); 1986 GH2_VXLAN_NETWORK_VP_USED_CLR(unit, (base_vp + i)); 1987 /* Loopback VP is only support when VXLAN RIOT is enabled */ 1988 if (GH2_VXLAN_RIOT_ENABLE(unit)) { 1989 GH2_VXLAN_LOOPBACK_VP_USED_CLR(unit, (base_vp + i)); 1990 } 1991 } 1992 1993 return BCM_E_NONE; 1994 } 1995 1996 /* 1997 * Function: 1998 * bcmi_gh2_vxlan_vp_used_set 1999 * Purpose: 2000 * Mark the VP as used 2001 * Parameters: 2002 * unit - (IN) Device Number 2003 * vp - (IN) VP 2004 * vxlan_vp_info - (IN) VXLAN VP info 2005 * Returns: 2006 * Boolean 2007 */ 2008 STATIC int 2009 bcmi_gh2_vxlan_vp_used_set( 2010 int unit, 2011 int vp, 2012 bcmi_vxlan_vp_info_t vxlan_vp_info) 2013 { 2014 if (vxlan_vp_info.flags & GH2_VXLAN_VP_INFO_SHARED_PORT) { 2015 return BCM_E_UNAVAIL; 2016 } 2017 2018 GH2_VXLAN_VP_USED_SET(unit, vp); 2019 2020 if (vxlan_vp_info.flags & GH2_VXLAN_VP_INFO_NETWORK_PORT) { 2021 GH2_VXLAN_NETWORK_VP_USED_SET(unit, vp); 2022 } else { 2023 GH2_VXLAN_NETWORK_VP_USED_CLR(unit, vp); 2024 } 2025 2026 /* Loopback VP is only support when VXLAN RIOT is enabled */ 2027 if (GH2_VXLAN_RIOT_ENABLE(unit)) { 2028 if (vxlan_vp_info.flags & GH2_VXLAN_VP_INFO_LOOPBACK_PORT) { 2029 GH2_VXLAN_LOOPBACK_VP_USED_SET(unit, vp); 2030 } else { 2031 GH2_VXLAN_LOOPBACK_VP_USED_CLR(unit, vp); 2032 } 2033 } 2034 2035 return BCM_E_NONE; 2036 } 2037 2038 /* 2039 * Function: 2040 * bcmi_gh2_vxlan_vp_used_get 2041 * Purpose: 2042 * Check whether a VP is used or not 2043 * Parameters: 2044 * unit - (IN) Device Number 2045 * vp - (IN) VP 2046 * Returns: 2047 * Boolean 2048 */ 2049 int 2050 bcmi_gh2_vxlan_vp_used_get(int unit, int vp) 2051 { 2052 int rv = BCM_E_NONE; 2053 int num_vp; 2054 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info = GH2_VXLAN_INFO(unit); 2055 2056 num_vp = vxlan_info->num_vxlan_vp; 2057 2058 /* Check Valid range of VFI */ 2059 if ((vp < 0) || (vp >= num_vp)) { 2060 return rv; 2061 } 2062 2063 rv = GH2_VXLAN_VP_USED_GET(unit, vp); 2064 2065 return rv; 2066 } 2067 2068 /* 2069 * Function: 2070 * bcmi_gh2_vxlan_vp_info_get 2071 * Purpose: 2072 * Get the VP Type of a VP, given its Id 2073 * Parameters: 2074 * unit - (IN) Device Number 2075 * vp - (IN) VP 2076 * vp_info - (OUT) VP info structure 2077 * Returns: 2078 * BCM_E_XXX 2079 */ 2080 int 2081 bcmi_gh2_vxlan_vp_info_get(int unit, int vp, bcmi_vxlan_vp_info_t *vp_info) 2082 { 2083 if (NULL == vp_info) { 2084 return BCM_E_PARAM; 2085 } 2086 2087 bcmi_gh2_vxlan_vp_info_init(vp_info); 2088 2089 if (bcmi_gh2_vxlan_vp_used_get(unit, vp)) { 2090 if (GH2_VXLAN_NETWORK_VP_USED_GET(unit, vp)) { 2091 vp_info->flags |= GH2_VXLAN_VP_INFO_NETWORK_PORT; 2092 } else { 2093 /* Loopback VP is only support when VXLAN RIOT is enabled */ 2094 if (GH2_VXLAN_RIOT_ENABLE(unit)) { 2095 if (GH2_VXLAN_LOOPBACK_VP_USED_GET(unit, vp)) { 2096 vp_info->flags |= GH2_VXLAN_VP_INFO_LOOPBACK_PORT; 2097 } 2098 } 2099 } 2100 2101 return BCM_E_NONE; 2102 } 2103 2104 return BCM_E_NOT_FOUND; 2105 } 2106 2107 /* 2108 * Function: 2109 * bcmi_gh2_vxlan_port_match_count_adjust 2110 * Purpose: 2111 * Obtain ref-count for a VXLAN port 2112 * Parameters: 2113 * unit - (IN) Device Number 2114 * vp - (IN) VP 2115 * step - (IN) number for rer-count increment 2116 * Returns: 2117 * None 2118 */ 2119 2120 STATIC void 2121 bcmi_gh2_vxlan_port_match_count_adjust(int unit, int vp, int step) 2122 { 2123 int num_vp; 2124 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info = GH2_VXLAN_INFO(unit); 2125 2126 num_vp = vxlan_info->num_vxlan_vp; 2127 2128 /* Check Valid range of VFI */ 2129 if ((vp < 0) || (vp >= num_vp)) { 2130 return; 2131 } 2132 2133 vxlan_info->match_key[vp].match_count += step; 2134 } 2135 2136 /* 2137 * Function: 2138 * bcmi_gh2_vxlan_cleanup 2139 * Purpose: 2140 * DeInit VXLAN software module 2141 * Parameters: 2142 * unit - (IN) Device Number 2143 * Returns: 2144 * BCM_E_XXX 2145 */ 2146 int 2147 bcmi_gh2_vxlan_cleanup(int unit) 2148 { 2149 int rv = BCM_E_UNAVAIL; 2150 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 2151 2152 if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) { 2153 return BCM_E_UNIT; 2154 } 2155 2156 vxlan_info = GH2_VXLAN_INFO(unit); 2157 2158 if (vxlan_info->initialized == FALSE) { 2159 return BCM_E_NONE; 2160 } 2161 2162 rv = bcmi_gh2_vxlan_lock(unit); 2163 if (BCM_FAILURE(rv)) { 2164 return rv; 2165 } 2166 2167 if (0 == SOC_HW_ACCESS_DISABLE(unit)) { 2168 rv = bcmi_gh2_vxlan_hw_clear(unit); 2169 } 2170 2171 bcmi_gh2_vxlan_unlock(unit); 2172 2173 /* Mark the state as uninitialized */ 2174 vxlan_info->initialized = FALSE; 2175 2176 /* Free software resources */ 2177 (void)bcmi_gh2_vxlan_free_resource(unit); 2178 2179 return rv; 2180 } 2181 2182 /* 2183 * Function: 2184 * bcmi_gh2_vxlan_header_init 2185 * Purpose: 2186 * Initialize the VXLAN header info 2187 * Parameters: 2188 * unit - (IN) Device Number 2189 * Returns: 2190 * BCM_E_XXX 2191 */ 2192 STATIC int 2193 bcmi_gh2_vxlan_header_init(int unit) 2194 { 2195 uint32 mem_entry[SOC_MAX_MEM_WORDS]; 2196 soc_mem_t mem; 2197 2198 if (soc_feature(unit, soc_feature_vxlan_lite)) { 2199 sal_memset(mem_entry, 0, (sizeof(uint32) * SOC_MAX_MEM_WORDS)); 2200 2201 /* 2202 * Ingress VXLAN class selection: 2203 * only support one class (VXLAN_FLAGS = 0x08, others are all zero) 2204 * the VXLAN_CLASS_ID hit will be one condition of VXLAN-LITE decap 2205 */ 2206 /* ING_VXLAN_CLASS_ID_TCAMm */ 2207 mem = ING_VXLAN_CLASS_ID_TCAMm; 2208 sal_memset(mem_entry, 0, (sizeof(uint32) * SOC_MAX_MEM_WORDS)); 2209 BCM_IF_ERROR_RETURN( 2210 soc_mem_read(unit, mem, MEM_BLOCK_ANY, 0, mem_entry)); 2211 soc_mem_field32_set(unit, mem, mem_entry, VALIDf, 0x1); 2212 soc_mem_field32_set(unit, mem, mem_entry, VXLAN_FLAGSf, 0x8); 2213 soc_mem_field32_set(unit, mem, mem_entry, VXLAN_FLAGS_MASKf, 0xff); 2214 /* Write buffer to hw. */ 2215 BCM_IF_ERROR_RETURN( 2216 soc_mem_write(unit, mem, MEM_BLOCK_ALL, 0, mem_entry)); 2217 2218 /* ING_VXLAN_CLASS_ID_POLICY_TABLE */ 2219 mem = ING_VXLAN_CLASS_ID_POLICY_TABLEm; 2220 sal_memset(mem_entry, 0, (sizeof(uint32) * SOC_MAX_MEM_WORDS)); 2221 BCM_IF_ERROR_RETURN( 2222 soc_mem_read(unit, mem, MEM_BLOCK_ANY, 0, mem_entry)); 2223 soc_mem_field32_set(unit, mem, mem_entry, VALIDf, 0x1); 2224 soc_mem_field32_set(unit, mem, mem_entry, CLASS_IDf, 0x0); 2225 /* Write buffer to hw. */ 2226 BCM_IF_ERROR_RETURN( 2227 soc_mem_write(unit, mem, MEM_BLOCK_ALL, 0, mem_entry)); 2228 2229 /* Egress VXLAN header */ 2230 mem = EGR_VXLAN_HEADERm; 2231 sal_memset(mem_entry, 0, (sizeof(uint32) * SOC_MAX_MEM_WORDS)); 2232 BCM_IF_ERROR_RETURN( 2233 soc_mem_read(unit, mem, MEM_BLOCK_ANY, 0, mem_entry)); 2234 soc_mem_field32_set(unit, mem, mem_entry, VXLAN_FLAGSf, 0x8); 2235 /* Write buffer to hw. */ 2236 BCM_IF_ERROR_RETURN( 2237 soc_mem_write(unit, mem, MEM_BLOCK_ALL, 0, mem_entry)); 2238 } 2239 2240 return BCM_E_NONE; 2241 } 2242 2243 /* 2244 * Function: 2245 * bcmi_gh2_vxlan_init 2246 * Purpose: 2247 * Initialize the VXLAN software module 2248 * Parameters: 2249 * unit - (IN) Device Number 2250 * Returns: 2251 * BCM_E_XXX 2252 */ 2253 int 2254 bcmi_gh2_vxlan_init(int unit) 2255 { 2256 int rv = BCM_E_NONE; 2257 int i, num_tnl = 0, num_vp = 0, num_vfi = 0, num_tpid = 0; 2258 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 2259 int riot_enable = 0; 2260 2261 if (!GH2_L3_INFO(unit)->l3_initialized) { 2262 LOG_ERROR(BSL_LS_BCM_VXLAN, 2263 (BSL_META_U(unit, 2264 "L3 module must be initialized" \ 2265 "prior to VXLAN Init\n"))); 2266 return BCM_E_CONFIG; 2267 } 2268 2269 /* VXLAN-Lite RIOT is only support for GH2-B0 */ 2270 riot_enable = soc_property_get(unit, spn_RIOT_ENABLE, 0); 2271 if (riot_enable && !soc_feature(unit, soc_feature_vxlan_lite_riot)) { 2272 LOG_ERROR(BSL_LS_BCM_VXLAN, 2273 (BSL_META_U(unit, 2274 "VXLAN RIOT is not supported\n"))); 2275 return BCM_E_CONFIG; 2276 } 2277 2278 /* Global initialization flag setup */ 2279 if (gh2_vxlan_initialized == FALSE) { 2280 for (i = 0; i < BCM_MAX_NUM_UNITS; i++) { 2281 bcmi_gh2_vxlan_bk_info[i] = NULL; 2282 } 2283 gh2_vxlan_initialized = TRUE; 2284 } 2285 2286 /* Allocate BK Info */ 2287 BCM_IF_ERROR_RETURN( 2288 bcmi_gh2_vxlan_allocate_bk(unit)); 2289 vxlan_info = GH2_VXLAN_INFO(unit); 2290 2291 /* 2292 * Allocate Resources 2293 */ 2294 if (vxlan_info->initialized) { 2295 BCM_IF_ERROR_RETURN( 2296 bcmi_gh2_vxlan_cleanup(unit)); 2297 BCM_IF_ERROR_RETURN( 2298 bcmi_gh2_vxlan_allocate_bk(unit)); 2299 vxlan_info = GH2_VXLAN_INFO(unit); 2300 } 2301 2302 num_vp = soc_mem_index_count(unit, VLAN_XLATEm); 2303 2304 /* VXLAN Virtual Port store */ 2305 BCMI_VXLAN_ALLOC(vxlan_info->match_key, 2306 sizeof(_bcm_vxlan_match_port_info_t) * num_vp, 2307 "match_key"); 2308 if (vxlan_info->match_key == NULL) { 2309 bcmi_gh2_vxlan_free_resource(unit); 2310 return BCM_E_MEMORY; 2311 } 2312 2313 /* Stay same after recover */ 2314 for (i = 0; i < num_vp; i++) { 2315 bcmi_gh2_vxlan_match_clear(unit, i); 2316 } 2317 2318 num_tnl = soc_mem_index_count(unit, BCM_XGS3_L3_MEM(unit, tnl_init_v4)); 2319 2320 /* Create EGR_IP_TUNNEL usage bitmap */ 2321 BCMI_VXLAN_ALLOC(vxlan_info->vxlan_ip_tnl_bitmap, 2322 SHR_BITALLOCSIZE(num_tnl), "vxlan_ip_tnl_bitmap"); 2323 if (vxlan_info->vxlan_ip_tnl_bitmap == NULL) { 2324 bcmi_gh2_vxlan_free_resource(unit); 2325 return BCM_E_MEMORY; 2326 } 2327 2328 /* Create VXLAN protection mutex. */ 2329 vxlan_info->vxlan_mutex = sal_mutex_create("vxlan_mutex"); 2330 if (!vxlan_info->vxlan_mutex) { 2331 bcmi_gh2_vxlan_free_resource(unit); 2332 return BCM_E_MEMORY; 2333 } 2334 2335 /* VXLAN tunnel termination store */ 2336 BCMI_VXLAN_ALLOC(vxlan_info->vxlan_tunnel_term, 2337 sizeof(bcmi_gh2_vxlan_tunnel_endpoint_t) * num_tnl, 2338 "vxlan tunnel term store"); 2339 if (vxlan_info->vxlan_tunnel_term == NULL) { 2340 bcmi_gh2_vxlan_free_resource(unit); 2341 return BCM_E_MEMORY; 2342 } 2343 2344 /* VXLAN tunnel initialization store */ 2345 BCMI_VXLAN_ALLOC(vxlan_info->vxlan_tunnel_init, 2346 sizeof(bcmi_gh2_vxlan_tunnel_endpoint_t) * num_tnl, 2347 "vxlan tunnel init store"); 2348 if (vxlan_info->vxlan_tunnel_init == NULL) { 2349 bcmi_gh2_vxlan_free_resource(unit); 2350 return BCM_E_MEMORY; 2351 } 2352 2353 vxlan_info->num_vxlan_tnl = num_tnl; 2354 2355 if (soc_feature(unit, soc_feature_vxlan_lite_riot)) { 2356 /* GH2-B0 support hardware VFI table */ 2357 num_vfi = soc_mem_index_count(unit, VFIm); 2358 } else { 2359 /* GH2-A0 support software VFI table (depends on VLAN_XLATEm) */ 2360 num_vfi = soc_mem_index_count(unit, VLAN_XLATEm); 2361 } 2362 2363 /* VXLAN VFI bitmap initialization store */ 2364 BCMI_VXLAN_ALLOC(vxlan_info->vxlan_vfi_bitmap, 2365 SHR_BITALLOCSIZE(num_vfi), "vxlan_vfi_bitmap"); 2366 if (vxlan_info->vxlan_vfi_bitmap == NULL) { 2367 bcmi_gh2_vxlan_free_resource(unit); 2368 return BCM_E_MEMORY; 2369 } 2370 2371 /* VXLAN VFI info initialization store */ 2372 BCMI_VXLAN_ALLOC(vxlan_info->vxlan_vpn_info, 2373 sizeof(gh2_vxlan_vpn_info_t) * num_vfi, "vxlan_vpn_info"); 2374 if (vxlan_info->vxlan_vpn_info == NULL) { 2375 bcmi_gh2_vxlan_free_resource(unit); 2376 return BCM_E_MEMORY; 2377 } 2378 vxlan_info->num_vxlan_vfi = num_vfi; 2379 2380 /* VXLAN Virtual Port bitmap initialization store */ 2381 BCMI_VXLAN_ALLOC(vxlan_info->vxlan_vp_bitmap, 2382 SHR_BITALLOCSIZE(num_vp), "vxlan_vp_bitmap"); 2383 if (vxlan_info->vxlan_vp_bitmap == NULL) { 2384 bcmi_gh2_vxlan_free_resource(unit); 2385 return BCM_E_MEMORY; 2386 } 2387 2388 /* Network VXLAN Virtual Port bitmap initialization store */ 2389 BCMI_VXLAN_ALLOC(vxlan_info->vxlan_network_vp_bitmap, 2390 SHR_BITALLOCSIZE(num_vp), "vxlan_network_vp_bitmap"); 2391 if (vxlan_info->vxlan_network_vp_bitmap == NULL) { 2392 bcmi_gh2_vxlan_free_resource(unit); 2393 return BCM_E_MEMORY; 2394 } 2395 2396 /* VXLAN Outer TPID info initialization store */ 2397 num_tpid = soc_reg_field_length(unit, ING_VXLAN_CONTROLr, 2398 PAYLOAD_OUTER_TPID_ENABLEf); 2399 BCMI_VXLAN_ALLOC(vxlan_info->vxlan_outer_tpid, 2400 sizeof(gh2_vxlan_outer_tpid_info_t) * num_tpid, 2401 "vxlan_outer_tpid"); 2402 if (vxlan_info->vxlan_outer_tpid == NULL) { 2403 bcmi_gh2_vxlan_free_resource(unit); 2404 return BCM_E_MEMORY; 2405 } 2406 vxlan_info->num_vxlan_outer_tpid = num_tpid; 2407 2408 /* VXLAN Ingress VLAN XLATE info initialization store */ 2409 BCMI_VXLAN_ALLOC(vxlan_info->vxlan_vlan_xlate, 2410 sizeof(gh2_vxlan_vlan_xlate_info_t) * num_vfi, 2411 "vxlan_vlan_xlate"); 2412 if (vxlan_info->vxlan_vlan_xlate == NULL) { 2413 bcmi_gh2_vxlan_free_resource(unit); 2414 return BCM_E_MEMORY; 2415 } 2416 2417 /* VXLAN VP info initialization store */ 2418 BCMI_VXLAN_ALLOC(vxlan_info->vxlan_vp_info, 2419 sizeof(gh2_vxlan_vp_info_t) * num_vp, "vxlan_vp_info"); 2420 if (vxlan_info->vxlan_vp_info == NULL) { 2421 bcmi_gh2_vxlan_free_resource(unit); 2422 return BCM_E_MEMORY; 2423 } 2424 vxlan_info->num_vxlan_vp = num_vp; 2425 2426 /* RIOT is Enabled/Disabled on this device (for GH2-B0 only) */ 2427 vxlan_info->riot_enable = riot_enable; 2428 2429 /* 2430 * Loopback VXLAN Virtual Port bitmap initialization store 2431 * (used for RIOT) 2432 */ 2433 BCMI_VXLAN_ALLOC(vxlan_info->vxlan_loopback_vp_bitmap, 2434 SHR_BITALLOCSIZE(num_vp), "vxlan_loopback_vp_bitmap"); 2435 if (vxlan_info->vxlan_loopback_vp_bitmap == NULL) { 2436 bcmi_gh2_vxlan_free_resource(unit); 2437 return BCM_E_MEMORY; 2438 } 2439 2440 /* Reference count of Custom Header index0 initialization store */ 2441 vxlan_info->riot_custom_header_index0_ref_count = 0; 2442 2443 /* Initialize the VXLAN header info */ 2444 rv = bcmi_gh2_vxlan_header_init(unit); 2445 if (BCM_FAILURE(rv)) { 2446 bcmi_gh2_vxlan_free_resource(unit); 2447 return rv; 2448 } 2449 2450 #ifdef BCM_WARM_BOOT_SUPPORT 2451 if (SOC_WARM_BOOT(unit)) { 2452 rv = bcmi_gh2_vxlan_reinit(unit); 2453 } else { 2454 rv = bcmi_gh2_vxlan_wb_alloc(unit); 2455 } 2456 /* clean up the bookkeeping resource if any errors */ 2457 if (BCM_FAILURE(rv)) { 2458 bcmi_gh2_vxlan_free_resource(unit); 2459 return rv; 2460 } 2461 #endif /* BCM_WARM_BOOT_SUPPORT */ 2462 2463 /* Mark the state as initialized */ 2464 vxlan_info->initialized = TRUE; 2465 2466 return rv; 2467 } 2468 2469 /* 2470 * Function: 2471 * bcmi_gh2_vxlan_vpn_is_valid 2472 * Purpose: 2473 * Find if given VXLAN VPN is Valid 2474 * Parameters: 2475 * unit - (IN) Device Number 2476 * l2vpn - (IN) VXLAN VPN 2477 * Returns: 2478 * BCM_E_XXXX 2479 */ 2480 STATIC int 2481 bcmi_gh2_vxlan_vpn_is_valid(int unit, bcm_vpn_t l2vpn) 2482 { 2483 bcm_vpn_t vxlan_vpn_min = 0; 2484 int vfi_index = -1, num_vfi = 0; 2485 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 2486 2487 /* Get VXLAN bookkeeping info instance */ 2488 BCM_IF_ERROR_RETURN( 2489 gh2_vxlan_bk_info_instance_get(unit, &vxlan_info)); 2490 2491 num_vfi = vxlan_info->num_vxlan_vfi; 2492 2493 /* Check for Valid vpn */ 2494 _BCM_VXLAN_VPN_SET(vxlan_vpn_min, _BCM_VPN_TYPE_VFI, 0); 2495 if (l2vpn < vxlan_vpn_min || l2vpn > (vxlan_vpn_min + num_vfi - 1)) { 2496 return BCM_E_PARAM; 2497 } 2498 2499 _BCM_VXLAN_VPN_GET(vfi_index, _BCM_VPN_TYPE_VFI, l2vpn); 2500 2501 if (!bcmi_gh2_vxlan_vfi_used_get(unit, vfi_index)) { 2502 return BCM_E_NOT_FOUND; 2503 } 2504 2505 return BCM_E_NONE; 2506 } 2507 2508 /* 2509 * Function: 2510 * bcmi_gh2_vxlan_vpn_is_eline 2511 * Purpose: 2512 * Find if given VXLAN VPN is ELINE 2513 * Parameters: 2514 * unit - (IN) Device Number 2515 * l2vpn - VXLAN VPN 2516 * is_eline - Flag 2517 * Returns: 2518 * BCM_E_XXXX 2519 */ 2520 STATIC int 2521 bcmi_gh2_vxlan_vpn_is_eline(int unit, bcm_vpn_t l2vpn, uint8 *is_eline) 2522 { 2523 /* Input parameter check */ 2524 if (NULL == is_eline) { 2525 return BCM_E_PARAM; 2526 } 2527 2528 BCM_IF_ERROR_RETURN( 2529 bcmi_gh2_vxlan_vpn_is_valid(unit, l2vpn)); 2530 2531 /* Currently, VXLAN-LITE only support ELAN */ 2532 *is_eline = 0; 2533 2534 return BCM_E_NONE; 2535 } 2536 2537 /* 2538 * Function: 2539 * bcmi_gh2_vxlan_vp_is_eline 2540 * Purpose: 2541 * Find if given VXLAN VP is ELINE 2542 * Parameters: 2543 * unit - (IN) Device Number 2544 * vp - (IN) VXLAN VP 2545 * is_eline - (IN) Flag 2546 * Returns: 2547 * BCM_E_XXXX 2548 * Assumes: 2549 * l2vpn is valid 2550 */ 2551 STATIC int 2552 bcmi_gh2_vxlan_vp_is_eline( int unit, int vp, uint8 *is_eline) 2553 { 2554 /* Input parameter check */ 2555 if (NULL == is_eline) { 2556 return BCM_E_PARAM; 2557 } 2558 if (vp == -1) { 2559 return BCM_E_PARAM; 2560 } 2561 2562 if (!bcmi_gh2_vxlan_vp_used_get(unit, vp)) { 2563 return BCM_E_NOT_FOUND; 2564 } 2565 2566 *is_eline = 0x0; 2567 2568 return BCM_E_NONE; 2569 } 2570 2571 /* 2572 * Function: 2573 * bcmi_gh2_vxlan_match_vnid_entry_reset 2574 * Purpose: 2575 * Reset VXLAN Match VNID Entry 2576 * Parameters: 2577 * unit - (IN) Device Number 2578 * IN : Vnid 2579 * Returns: 2580 * BCM_E_XXX 2581 */ 2582 STATIC int 2583 bcmi_gh2_vxlan_match_vnid_entry_reset(int unit, uint32 vnid) 2584 { 2585 soc_mem_t mem; 2586 uint32 vxlate_entry[SOC_MAX_MEM_WORDS]; 2587 2588 sal_memset(vxlate_entry, 0, (sizeof(uint32) * SOC_MAX_MEM_WORDS)); 2589 2590 mem = VLAN_XLATEm; 2591 2592 soc_mem_field32_set(unit, mem, vxlate_entry, VALIDf, 0x1); 2593 soc_mem_field32_set(unit, mem, vxlate_entry, XLATE__VNIDf, vnid); 2594 /* incoming port not used in lookup key, set field to all 1's */ 2595 soc_mem_field32_set(unit, mem, vxlate_entry, XLATE__GLPf, 2596 SOC_VLAN_XLATE_GLP_WILDCARD(unit)); 2597 soc_mem_field32_set(unit, mem, vxlate_entry, KEY_TYPEf, 2598 GH2_VLXLT_HASH_KEY_TYPE_VNID); 2599 2600 BCM_IF_ERROR_RETURN( 2601 soc_mem_delete(unit, mem, MEM_BLOCK_ALL, vxlate_entry)); 2602 2603 return BCM_E_NONE; 2604 } 2605 2606 /* 2607 * Function: 2608 * bcmi_gh2_vxlan_vfi_to_vpn_get 2609 * Purpose: 2610 * Get L2-VPN instance for VXLAN 2611 * Parameters: 2612 * unit - (IN) Device Number 2613 * vfi_index - (IN) vfi_index 2614 * vid - (OUT) VLAN Id (l2vpn id) 2615 * Returns: 2616 * BCM_E_XXXX 2617 */ 2618 int 2619 bcmi_gh2_vxlan_vfi_to_vpn_get(int unit, int vfi_index, bcm_vlan_t *vid) 2620 { 2621 /* Input parameter check */ 2622 if (NULL == vid) { 2623 return BCM_E_PARAM; 2624 } 2625 2626 if (!bcmi_gh2_vxlan_vfi_used_get(unit, vfi_index)) { 2627 return BCM_E_NOT_FOUND; 2628 } 2629 2630 _BCM_VXLAN_VPN_SET(*vid, _BCM_VXLAN_VPN_TYPE_ELAN, vfi_index); 2631 2632 return BCM_E_NONE; 2633 } 2634 2635 /* 2636 * Function: 2637 * bcmi_gh2_vxlan_vpn_create 2638 * Purpose: 2639 * Create a VPN instance 2640 * Parameters: 2641 * unit - (IN) Device Number 2642 * info - (IN/OUT) VPN configuration info 2643 * Returns: 2644 * BCM_E_XXX 2645 */ 2646 int 2647 bcmi_gh2_vxlan_vpn_create(int unit, bcm_vxlan_vpn_config_t *info) 2648 { 2649 int rv, rv2; 2650 int vfi_index = -1; 2651 uint32 vnid = 0; 2652 uint8 vpn_alloc_flag = 0; 2653 bcm_vlan_protocol_packet_ctrl_t protocol_pkt; 2654 soc_mem_t mem; 2655 uint32 vxlate_entry[SOC_MAX_MEM_WORDS]; 2656 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 2657 gh2_vxlan_vpn_info_t *vfi_info; 2658 vfi_entry_t vfi_entry; 2659 int uuc_umc_bc_group = 0; 2660 int uuc_umc_bc_group_type = 0; 2661 2662 /* Input parameter check */ 2663 if (NULL == info) { 2664 return BCM_E_PARAM; 2665 } 2666 2667 /* Get VXLAN bookkeeping info instance */ 2668 BCM_IF_ERROR_RETURN( 2669 gh2_vxlan_bk_info_instance_get(unit, &vxlan_info)); 2670 2671 sal_memset(vxlate_entry, 0, (sizeof(uint32) * SOC_MAX_MEM_WORDS)); 2672 2673 /* Allocate VFI */ 2674 if (info->flags & BCM_VXLAN_VPN_REPLACE) { 2675 BCM_IF_ERROR_RETURN( 2676 bcmi_gh2_vxlan_vpn_is_valid(unit, info->vpn)); 2677 _BCM_VXLAN_VPN_GET(vfi_index, _BCM_VPN_TYPE_VFI, info->vpn); 2678 } else if (info->flags & BCM_VXLAN_VPN_WITH_ID) { 2679 rv = bcmi_gh2_vxlan_vpn_is_valid(unit, info->vpn); 2680 if (rv == BCM_E_NONE) { 2681 return BCM_E_EXISTS; 2682 } else if (rv != BCM_E_NOT_FOUND) { 2683 return rv; 2684 } 2685 _BCM_VXLAN_VPN_GET(vfi_index, _BCM_VPN_TYPE_VFI, info->vpn); 2686 BCM_IF_ERROR_RETURN( 2687 bcmi_gh2_vxlan_vfi_alloc_with_id(unit, vfi_index)); 2688 vpn_alloc_flag = 1; 2689 } else { 2690 BCM_IF_ERROR_RETURN( 2691 bcmi_gh2_vxlan_vfi_alloc(unit, &vfi_index)); 2692 _BCM_VXLAN_VPN_SET(info->vpn, _BCM_VPN_TYPE_VFI, vfi_index); 2693 vpn_alloc_flag = 1; 2694 } 2695 2696 /* Initial and configure VFI */ 2697 if (info->flags & BCM_VXLAN_VPN_ELINE) { 2698 /* Currently, VXLAN-LITE doesn't support ELINE on VPN */ 2699 return BCM_E_UNAVAIL; 2700 } else if (info->flags & BCM_VXLAN_VPN_ELAN) { 2701 /* Configure unknown UC/MC/BC packets forwarding on the VFI */ 2702 if (soc_feature(unit, soc_feature_vxlan_lite_riot)) { 2703 /* Only support for GH2-B0 with new VFI table */ 2704 2705 /* Check that the groups are valid */ 2706 /* Unknown UC/MC/BC group share the same field for GH2-B0 */ 2707 if ((info->unknown_unicast_group != 2708 info->unknown_multicast_group) || 2709 (info->unknown_multicast_group != 2710 info->broadcast_group)) { 2711 if (vpn_alloc_flag) { 2712 rv = bcmi_gh2_vxlan_vfi_free(unit, vfi_index); 2713 if (BCM_FAILURE(rv)) { 2714 return rv; 2715 } 2716 } 2717 return BCM_E_PARAM; 2718 } 2719 2720 /* Select one of groups (suppose they should be the same) */ 2721 if (info->unknown_unicast_group != 0) { 2722 uuc_umc_bc_group_type = 2723 _BCM_MULTICAST_TYPE_GET(info->unknown_unicast_group); 2724 uuc_umc_bc_group = 2725 _BCM_MULTICAST_ID_GET(info->unknown_unicast_group); 2726 2727 if ((uuc_umc_bc_group_type != _BCM_MULTICAST_TYPE_VXLAN) || 2728 (uuc_umc_bc_group >= soc_mem_index_count(unit, 2729 L3_IPMCm))) { 2730 if (vpn_alloc_flag) { 2731 rv = bcmi_gh2_vxlan_vfi_free(unit, vfi_index); 2732 if (BCM_FAILURE(rv)) { 2733 return rv; 2734 } 2735 } 2736 return BCM_E_PARAM; 2737 } 2738 2739 /* Commit the entry to HW */ 2740 rv = soc_mem_read(unit, VFIm, MEM_BLOCK_ANY, 2741 vfi_index, &vfi_entry); 2742 if (SOC_FAILURE(rv)) { 2743 if (vpn_alloc_flag) { 2744 rv = bcmi_gh2_vxlan_vfi_free(unit, vfi_index); 2745 if (BCM_FAILURE(rv)) { 2746 return rv; 2747 } 2748 } 2749 return rv; 2750 } 2751 soc_mem_field32_set(unit, VFIm, &vfi_entry, 2752 UUC_UMC_BC_INDEXf, uuc_umc_bc_group); 2753 rv = soc_mem_write(unit, VFIm, MEM_BLOCK_ALL, 2754 vfi_index, &vfi_entry); 2755 if (SOC_FAILURE(rv)) { 2756 if (vpn_alloc_flag) { 2757 rv = bcmi_gh2_vxlan_vfi_free(unit, vfi_index); 2758 if (BCM_FAILURE(rv)) { 2759 return rv; 2760 } 2761 } 2762 return rv; 2763 } 2764 } 2765 } else { 2766 /* Not support for GH2-A0 (no VFI table) */ 2767 if ((info->broadcast_group != 0) || 2768 (info->unknown_multicast_group != 0) || 2769 (info->unknown_unicast_group != 0)) { 2770 if (vpn_alloc_flag) { 2771 rv = bcmi_gh2_vxlan_vfi_free(unit, vfi_index); 2772 if (BCM_FAILURE(rv)) { 2773 return rv; 2774 } 2775 } 2776 return BCM_E_PARAM; 2777 } 2778 } 2779 } 2780 2781 /* Configure protocol packet control (not support for VXLAN-LITE) */ 2782 sal_memset(&protocol_pkt, 0, sizeof(protocol_pkt)); 2783 if (0 != sal_memcmp(&(info->protocol_pkt), &protocol_pkt, 2784 sizeof(bcm_vlan_protocol_packet_ctrl_t))) { 2785 if (vpn_alloc_flag) { 2786 rv = bcmi_gh2_vxlan_vfi_free(unit, vfi_index); 2787 if (BCM_FAILURE(rv)) { 2788 return rv; 2789 } 2790 } 2791 return BCM_E_UNAVAIL; 2792 } 2793 2794 if (info->flags & BCM_VXLAN_VPN_WITH_VPNID) { 2795 /* VXLAN-LITE doesn't support BCM_VXLAN_VPN_SERVICE_XXX */ 2796 if ((info->flags & BCM_VXLAN_VPN_SERVICE_TAGGED) || 2797 (info->flags & BCM_VXLAN_VPN_SERVICE_VLAN_ADD) || 2798 (info->flags & BCM_VXLAN_VPN_SERVICE_VLAN_REPLACE) || 2799 (info->flags & BCM_VXLAN_VPN_SERVICE_VLAN_DELETE) || 2800 (info->flags & BCM_VXLAN_VPN_SERVICE_VLAN_TPID_REPLACE) || 2801 (info->flags & BCM_VXLAN_VPN_SERVICE_VLAN_PRI_TPID_REPLACE) || 2802 (info->flags & BCM_VXLAN_VPN_SERVICE_VLAN_PRI_REPLACE) || 2803 (info->flags & BCM_VXLAN_VPN_SERVICE_PRI_REPLACE) || 2804 (info->flags & BCM_VXLAN_VPN_SERVICE_TPID_REPLACE)) { 2805 if (vpn_alloc_flag) { 2806 rv = bcmi_gh2_vxlan_vfi_free(unit, vfi_index); 2807 if (BCM_FAILURE(rv)) { 2808 return rv; 2809 } 2810 } 2811 return BCM_E_UNAVAIL; 2812 } 2813 2814 /* Valid check for VNID value */ 2815 if ((info->vnid > 0xFFFFFF) || 2816 (info->flags & BCM_VXLAN_VPN_TUNNEL_BASED_VNID)) { 2817 if (vpn_alloc_flag) { 2818 rv = bcmi_gh2_vxlan_vfi_free(unit, vfi_index); 2819 if (BCM_FAILURE(rv)) { 2820 return rv; 2821 } 2822 } 2823 return BCM_E_PARAM; 2824 } 2825 2826 /* Configure Ingress VNID (use VLAN_XLATE) */ 2827 mem = VLAN_XLATEm; 2828 2829 soc_mem_field32_set(unit, mem, vxlate_entry, VALIDf, 0x1); 2830 soc_mem_field32_set(unit, mem, vxlate_entry, XLATE__MPLS_ACTIONf, 0x5); 2831 soc_mem_field32_set(unit, mem, vxlate_entry, 2832 XLATE__DISABLE_VLAN_CHECKSf, 0x1); 2833 soc_mem_field32_set(unit, mem, vxlate_entry, XLATE__VFI_VALIDf, 0x1); 2834 soc_mem_field32_set(unit, mem, vxlate_entry, XLATE__VFIf, vfi_index); 2835 2836 soc_mem_field32_set(unit, mem, vxlate_entry, KEY_TYPEf, 2837 GH2_VLXLT_HASH_KEY_TYPE_VNID); 2838 /* incoming port not used in lookup key, set field to all 1's */ 2839 soc_mem_field32_set(unit, mem, vxlate_entry, XLATE__GLPf, 2840 SOC_VLAN_XLATE_GLP_WILDCARD(unit)); 2841 2842 vfi_info = &(vxlan_info->vxlan_vpn_info[vfi_index]); 2843 if (info->flags & BCM_VXLAN_VPN_REPLACE) { 2844 /* Delete old match vnid entry */ 2845 vnid = vfi_info->vnid; 2846 if (vfi_info->valid) { 2847 if (info->vnid == vnid) { 2848 /* Return when the vnid is not changed */ 2849 return BCM_E_NONE; 2850 } 2851 2852 soc_mem_field32_set(unit, mem, vxlate_entry, 2853 XLATE__VNIDf, vnid); 2854 rv = soc_mem_delete(unit, mem, MEM_BLOCK_ALL, vxlate_entry); 2855 if (BCM_FAILURE(rv)) { 2856 if (vpn_alloc_flag) { 2857 rv2 = bcmi_gh2_vxlan_vfi_free(unit, vfi_index); 2858 if (BCM_FAILURE(rv2)) { 2859 return rv2; 2860 } 2861 } 2862 return rv; 2863 } 2864 } 2865 } 2866 soc_mem_field32_set(unit, mem, vxlate_entry, 2867 XLATE__VNIDf, info->vnid); 2868 rv = soc_mem_insert(unit, mem, MEM_BLOCK_ALL, vxlate_entry); 2869 if (BCM_FAILURE(rv)) { 2870 if (vpn_alloc_flag) { 2871 rv2 = bcmi_gh2_vxlan_vfi_free(unit, vfi_index); 2872 if (BCM_FAILURE(rv2)) { 2873 return rv2; 2874 } 2875 } 2876 return rv; 2877 } 2878 2879 /* Update vnid for VXLAN VFI */ 2880 vfi_info->valid = 1; 2881 vfi_info->vnid = info->vnid; 2882 2883 /* Configure Egress VNID (use EGR_L3_NEXT_HOPm) */ 2884 /* Will be programmed with bcm_vxlan_port_add */ 2885 } else { 2886 if (info->flags & BCM_VXLAN_VPN_TUNNEL_BASED_VNID) { 2887 if (vpn_alloc_flag) { 2888 rv = bcmi_gh2_vxlan_vfi_free(unit, vfi_index); 2889 if (BCM_FAILURE(rv)) { 2890 return rv; 2891 } 2892 } 2893 return BCM_E_PARAM; 2894 } 2895 2896 /* Reset match vnid table */ 2897 vfi_info = &(vxlan_info->vxlan_vpn_info[vfi_index]); 2898 if (vfi_info->valid) { 2899 vnid = vfi_info->vnid; 2900 /* Delete vxlate_entry */ 2901 rv = bcmi_gh2_vxlan_match_vnid_entry_reset(unit, vnid); 2902 if ((rv != BCM_E_NONE) && (rv != BCM_E_NOT_FOUND)) { 2903 return rv; 2904 } 2905 2906 /* Update vnid for VXLAN VFI */ 2907 vfi_info->valid = 0; 2908 vfi_info->vnid = 0; 2909 } 2910 } 2911 2912 return BCM_E_NONE; 2913 } 2914 2915 /* 2916 * Function: 2917 * bcmi_gh2_vxlan_vpn_destroy 2918 * Purpose: 2919 * Delete a VPN instance 2920 * Parameters: 2921 * unit - (IN) Device Number 2922 * l2vpn - (IN) VPN instance ID 2923 * Returns: 2924 * BCM_E_XXX 2925 */ 2926 int 2927 bcmi_gh2_vxlan_vpn_destroy(int unit, bcm_vpn_t l2vpn) 2928 { 2929 int rv = 0; 2930 int vfi_index = 0; 2931 uint8 is_eline = 0; 2932 uint32 vnid = 0; 2933 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 2934 gh2_vxlan_vpn_info_t *vfi_info; 2935 2936 /* Get VXLAN bookkeeping info instance */ 2937 BCM_IF_ERROR_RETURN( 2938 gh2_vxlan_bk_info_instance_get(unit, &vxlan_info)); 2939 2940 /* Get vfi index */ 2941 BCM_IF_ERROR_RETURN( 2942 bcmi_gh2_vxlan_vpn_is_eline(unit, l2vpn, &is_eline)); 2943 if (is_eline != 0x0) { 2944 /* VXLAN-LITE doesn't support ELINE */ 2945 return BCM_E_INTERNAL; 2946 } else { 2947 _BCM_VXLAN_VPN_GET(vfi_index, _BCM_VPN_TYPE_VFI, l2vpn); 2948 } 2949 2950 /* Reset match vnid table */ 2951 vfi_info = &(vxlan_info->vxlan_vpn_info[vfi_index]); 2952 if (vfi_info->valid) { 2953 vnid = vfi_info->vnid; 2954 /* Delete vxlate_entry */ 2955 rv = bcmi_gh2_vxlan_match_vnid_entry_reset(unit, vnid); 2956 if ((rv != BCM_E_NONE) && (rv != BCM_E_NOT_FOUND)) { 2957 return rv; 2958 } 2959 2960 /* Update vnid for VXLAN VFI */ 2961 vfi_info->valid = 0; 2962 vfi_info->vnid = 0; 2963 } 2964 2965 /* Delete all VXLAN ports on this VPN */ 2966 BCM_IF_ERROR_RETURN( 2967 bcmi_gh2_vxlan_port_delete_all(unit, l2vpn)); 2968 2969 /* Reset VFI table */ 2970 rv = bcmi_gh2_vxlan_vfi_free(unit, vfi_index); 2971 2972 return rv; 2973 } 2974 2975 /* 2976 * Function: 2977 * bcmi_gh2_vxlan_vpn_id_destroy_all 2978 * Purpose: 2979 * Delete all L2-VPN instances 2980 * Parameters: 2981 * unit - (IN) Device Number 2982 * Returns: 2983 * BCM_E_XXXX 2984 */ 2985 int 2986 bcmi_gh2_vxlan_vpn_destroy_all(int unit) 2987 { 2988 int num_vfi = 0, idx = 0; 2989 bcm_vpn_t l2vpn = 0; 2990 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 2991 2992 /* Get VXLAN bookkeeping info instance */ 2993 BCM_IF_ERROR_RETURN( 2994 gh2_vxlan_bk_info_instance_get(unit, &vxlan_info)); 2995 2996 /* Destroy all VXLAN VPNs */ 2997 num_vfi = vxlan_info->num_vxlan_vfi; 2998 for (idx = 0; idx < num_vfi; idx++) { 2999 if (bcmi_gh2_vxlan_vfi_used_get(unit, idx)) { 3000 _BCM_VXLAN_VPN_SET(l2vpn, _BCM_VPN_TYPE_VFI, idx); 3001 BCM_IF_ERROR_RETURN( 3002 bcmi_gh2_vxlan_vpn_destroy(unit, l2vpn)); 3003 } 3004 } 3005 3006 return BCM_E_NONE; 3007 } 3008 3009 /* 3010 * Function: 3011 * bcmi_gh2_vxlan_vpn_get 3012 * Purpose: 3013 * Get L2-VPN instance 3014 * Parameters: 3015 * unit - (IN) Device Number 3016 * l2vpn - (IN) VXLAN VPN 3017 * info - (OUT) VXLAN VPN Config 3018 * Returns: 3019 * BCM_E_XXXX 3020 */ 3021 int 3022 bcmi_gh2_vxlan_vpn_get( 3023 int unit, 3024 bcm_vpn_t l2vpn, 3025 bcm_vxlan_vpn_config_t *info) 3026 { 3027 int vfi_index = -1; 3028 uint8 is_eline = 0; 3029 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 3030 gh2_vxlan_vpn_info_t *vfi_info; 3031 vfi_entry_t vfi_entry; 3032 int uuc_umc_bc_group = 0; 3033 3034 /* Input parameter check */ 3035 if (NULL == info) { 3036 return BCM_E_PARAM; 3037 } 3038 3039 /* Get VXLAN bookkeeping info instance */ 3040 BCM_IF_ERROR_RETURN( 3041 gh2_vxlan_bk_info_instance_get(unit, &vxlan_info)); 3042 3043 /* Get vfi table */ 3044 BCM_IF_ERROR_RETURN( 3045 bcmi_gh2_vxlan_vpn_is_eline(unit, l2vpn, &is_eline)); 3046 if (is_eline != 0x0) { 3047 /* VXLAN-LITE doesn't support ELINE */ 3048 return BCM_E_INTERNAL; 3049 } else { 3050 _BCM_VXLAN_VPN_GET(vfi_index, _BCM_VXLAN_VPN_TYPE_ELAN, l2vpn); 3051 /* Get info associated with vfi table */ 3052 info->flags = BCM_VXLAN_VPN_ELAN; 3053 3054 if (soc_feature(unit, soc_feature_vxlan_lite_riot)) { 3055 /* Only support for GH2-B0 with new VFI table */ 3056 SOC_IF_ERROR_RETURN( 3057 soc_mem_read(unit, VFIm, MEM_BLOCK_ANY, 3058 vfi_index, &vfi_entry)); 3059 3060 /* Unknown UC/MC/BC group share the same field for GH2-B0 */ 3061 uuc_umc_bc_group = 3062 soc_mem_field32_get(unit, VFIm, &vfi_entry, UUC_UMC_BC_INDEXf); 3063 if (uuc_umc_bc_group != 0) { 3064 _BCM_MULTICAST_GROUP_SET(info->broadcast_group, 3065 _BCM_MULTICAST_TYPE_VXLAN, 3066 uuc_umc_bc_group); 3067 _BCM_MULTICAST_GROUP_SET(info->unknown_unicast_group, 3068 _BCM_MULTICAST_TYPE_VXLAN, 3069 uuc_umc_bc_group); 3070 _BCM_MULTICAST_GROUP_SET(info->unknown_multicast_group, 3071 _BCM_MULTICAST_TYPE_VXLAN, 3072 uuc_umc_bc_group); 3073 } 3074 } 3075 } 3076 3077 _BCM_VXLAN_VPN_SET(info->vpn, _BCM_VPN_TYPE_VFI, vfi_index); 3078 3079 /* Get VNID */ 3080 vfi_info = &(vxlan_info->vxlan_vpn_info[vfi_index]); 3081 if (vfi_info->valid) { 3082 info->flags |= BCM_VXLAN_VPN_WITH_VPNID; 3083 info->vnid = vfi_info->vnid; 3084 } 3085 3086 return BCM_E_NONE; 3087 } 3088 3089 /* 3090 * Function: 3091 * bcmi_gh2_vxlan_vpn_traverse 3092 * Purpose: 3093 * Get information about a VPN instance 3094 * Parameters: 3095 * unit - (IN) Device Number 3096 * cb - (IN) User-provided callback 3097 * user_data - (IN/OUT) callback user data 3098 * Returns: 3099 * BCM_E_XXX 3100 */ 3101 int 3102 bcmi_gh2_vxlan_vpn_traverse( 3103 int unit, 3104 bcm_vxlan_vpn_traverse_cb cb, 3105 void *user_data) 3106 { 3107 int rv = BCM_E_NONE; 3108 int idx, num_vfi; 3109 int vpn; 3110 bcm_vxlan_vpn_config_t info; 3111 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 3112 3113 /* Input parameter check */ 3114 if (NULL == cb) { 3115 return BCM_E_PARAM; 3116 } 3117 3118 /* Get VXLAN bookkeeping info instance */ 3119 BCM_IF_ERROR_RETURN( 3120 gh2_vxlan_bk_info_instance_get(unit, &vxlan_info)); 3121 3122 num_vfi = vxlan_info->num_vxlan_vfi; 3123 for (idx = 0; idx < num_vfi; idx++) { 3124 if (bcmi_gh2_vxlan_vfi_used_get(unit, idx)) { 3125 _BCM_VXLAN_VPN_SET(vpn, _BCM_VPN_TYPE_VFI, idx); 3126 bcm_vxlan_vpn_config_t_init(&info); 3127 rv = bcmi_gh2_vxlan_vpn_get(unit, vpn, &info); 3128 if (BCM_SUCCESS(rv)) { 3129 BCM_IF_ERROR_RETURN( 3130 cb(unit, &info, user_data)); 3131 } 3132 } 3133 } 3134 3135 return rv; 3136 } 3137 3138 /* 3139 * Function: 3140 * bcmi_gh2_vxlan_tunnel_ip6_is_zero 3141 * Purpose: 3142 * Helper function to check input IPv6 address is zero or not 3143 * Parameters: 3144 * ip6 - (IN) IPv6 address 3145 * Returns: 3146 * TRUE: IPv6 address is all zero, FALSE: IPv6 address is not zero 3147 */ 3148 STATIC int 3149 bcmi_gh2_vxlan_tunnel_ip6_is_zero(bcm_ip6_t ip6) 3150 { 3151 bcm_ip6_t ip6_zero; 3152 int is_zero = FALSE; 3153 3154 sal_memset(ip6_zero, 0, BCM_IP6_ADDRLEN); 3155 3156 if (sal_memcmp(ip6, ip6_zero, BCM_IP6_ADDRLEN) == 0) { 3157 is_zero = TRUE; 3158 } 3159 3160 return is_zero; 3161 } 3162 3163 /* 3164 * Function: 3165 * bcmi_gh2_vxlan_tunnel_terminator_create 3166 * Purpose: 3167 * Set VXLAN Tunnel terminator 3168 * Parameters: 3169 * unit - (IN) Device Number 3170 * tnl_info - (IN) Tunnel terminator info data structure 3171 * Returns: 3172 * BCM_E_XXX 3173 */ 3174 int 3175 bcmi_gh2_vxlan_tunnel_terminator_create( 3176 int unit, 3177 bcm_tunnel_terminator_t *tnl_info) 3178 { 3179 int tunnel_idx = -1; 3180 bcm_ip6_t tnl_ip6; 3181 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 3182 3183 /* Input parameter check */ 3184 if (NULL == tnl_info) { 3185 return BCM_E_PARAM; 3186 } 3187 3188 /* Get VXLAN bookkeeping info instance */ 3189 BCM_IF_ERROR_RETURN( 3190 gh2_vxlan_bk_info_instance_get(unit, &vxlan_info)); 3191 3192 /* Input Tunnel Type check */ 3193 if (tnl_info->type == bcmTunnelTypeVxlan6) { 3194 /* Tunnel for IPv6 */ 3195 if (bcmi_gh2_vxlan_tunnel_ip6_is_zero(tnl_info->dip6) || 3196 bcmi_gh2_vxlan_tunnel_ip6_is_zero(tnl_info->sip6)) { 3197 return BCM_E_PARAM; 3198 } 3199 } else if (tnl_info->type == bcmTunnelTypeVxlan) { 3200 /* Tunnel for IPv4 */ 3201 if ((tnl_info->dip == 0) || (tnl_info->sip == 0)) { 3202 return BCM_E_PARAM; 3203 } 3204 } else { 3205 /* Others are not supported */ 3206 return BCM_E_PARAM; 3207 } 3208 3209 /* GH2 doesn't support below tunnel flags */ 3210 if (tnl_info->flags & BCM_TUNNEL_TERM_UDP_CHECKSUM_ENABLE || 3211 tnl_info->flags & BCM_TUNNEL_TERM_USE_OUTER_DSCP || 3212 tnl_info->flags & BCM_TUNNEL_TERM_USE_OUTER_PCP) { 3213 return BCM_E_PARAM; 3214 } 3215 3216 /* Program tunnel id */ 3217 if (tnl_info->flags & BCM_TUNNEL_TERM_TUNNEL_WITH_ID) { 3218 if (!BCM_GPORT_IS_TUNNEL(tnl_info->tunnel_id)) { 3219 return BCM_E_PARAM; 3220 } 3221 3222 tunnel_idx = BCM_GPORT_TUNNEL_ID_GET(tnl_info->tunnel_id); 3223 GH2_VXLAN_TUNNEL_ID_IF_INVALID_RETURN(unit, tunnel_idx); 3224 } else { 3225 /* Only BCM_TUNNEL_TERM_TUNNEL_WITH_ID supported */ 3226 /* Use tunnel_id which is got by _create */ 3227 return BCM_E_PARAM; 3228 } 3229 3230 if (tnl_info->type == bcmTunnelTypeVxlan6) { 3231 /* Tunnel for IPv6 */ 3232 sal_memcpy(tnl_ip6, 3233 vxlan_info->vxlan_tunnel_term[tunnel_idx].dip6, 3234 BCM_IP6_ADDRLEN); 3235 if (!bcmi_gh2_vxlan_tunnel_ip6_is_zero(tnl_ip6)) { 3236 /* 3237 * Entry exists with the same idx no matter the dip6 3238 * is the same or not 3239 */ 3240 return BCM_E_EXISTS; 3241 } 3242 } else { 3243 /* Tunnel for IPv4 */ 3244 if (vxlan_info->vxlan_tunnel_term[tunnel_idx].dip != 0) { 3245 /* 3246 * Entry exists with the same idx no matter the dip 3247 * is the same or not 3248 */ 3249 return BCM_E_EXISTS; 3250 } 3251 } 3252 3253 sal_memset(&(vxlan_info->vxlan_tunnel_term[tunnel_idx]), 3254 0, sizeof(bcmi_gh2_vxlan_tunnel_endpoint_t)); 3255 if (tunnel_idx != -1) { 3256 if (tnl_info->type == bcmTunnelTypeVxlan6) { 3257 /* Tunnel for IPv6 */ 3258 sal_memcpy(vxlan_info->vxlan_tunnel_term[tunnel_idx].sip6, 3259 tnl_info->sip6, BCM_IP6_ADDRLEN); 3260 sal_memcpy(vxlan_info->vxlan_tunnel_term[tunnel_idx].dip6, 3261 tnl_info->dip6, BCM_IP6_ADDRLEN); 3262 } else { 3263 /* Tunnel for IPv4 */ 3264 vxlan_info->vxlan_tunnel_term[tunnel_idx].sip = tnl_info->sip; 3265 vxlan_info->vxlan_tunnel_term[tunnel_idx].dip = tnl_info->dip; 3266 } 3267 vxlan_info->vxlan_tunnel_term[tunnel_idx].vlan = tnl_info->vlan; 3268 vxlan_info->vxlan_tunnel_term[tunnel_idx].tunnel_state = 3269 _BCM_VXLAN_TUNNEL_TERM_MULTICAST_LEAF; 3270 vxlan_info->vxlan_tunnel_term[tunnel_idx].activate_flag |= 3271 _BCM_VXLAN_TUNNEL_TERM_ENABLE; 3272 } 3273 3274 return BCM_E_NONE; 3275 } 3276 3277 /* 3278 * Function: 3279 * bcmi_gh2_vxlan_tunnel_terminator_update 3280 * Purpose: 3281 * Update VXLAN Tunnel terminator multicast state 3282 * Parameters: 3283 * unit - (IN) Device Number 3284 * tnl_info - (IN) Tunnel terminator info data structure 3285 * Returns: 3286 * BCM_E_XXX 3287 */ 3288 int 3289 bcmi_gh2_vxlan_tunnel_terminator_update( 3290 int unit, 3291 bcm_tunnel_terminator_t *tnl_info) 3292 { 3293 int tunnel_idx = -1; 3294 bcm_ip_t tunnel_dip = 0; 3295 bcm_ip6_t tunnel_dip6; 3296 uint16 tunnel_multicast_state = 0; 3297 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 3298 3299 /* Input parameter check */ 3300 if (NULL == tnl_info) { 3301 return BCM_E_PARAM; 3302 } 3303 3304 /* Get VXLAN bookkeeping info instance */ 3305 BCM_IF_ERROR_RETURN( 3306 gh2_vxlan_bk_info_instance_get(unit, &vxlan_info)); 3307 3308 /* Program tunnel id */ 3309 if (tnl_info->flags & BCM_TUNNEL_TERM_TUNNEL_WITH_ID) { 3310 if (!BCM_GPORT_IS_TUNNEL(tnl_info->tunnel_id)) { 3311 return BCM_E_PARAM; 3312 } 3313 tunnel_idx = BCM_GPORT_TUNNEL_ID_GET(tnl_info->tunnel_id); 3314 GH2_VXLAN_TUNNEL_ID_IF_INVALID_RETURN(unit, tunnel_idx); 3315 } else { 3316 /* Only BCM_TUNNEL_TERM_TUNNEL_WITH_ID supported */ 3317 /* Use tunnel_id which is got by _create */ 3318 return BCM_E_PARAM; 3319 } 3320 3321 tunnel_dip = vxlan_info->vxlan_tunnel_term[tunnel_idx].dip; 3322 sal_memcpy(tunnel_dip6, 3323 vxlan_info->vxlan_tunnel_term[tunnel_idx].dip6, 3324 BCM_IP6_ADDRLEN); 3325 3326 if (tnl_info->flags & BCM_TUNNEL_TERM_TUNNEL_DEACTIVATE) { 3327 vxlan_info->vxlan_tunnel_term[tunnel_idx].activate_flag &= 3328 (~_BCM_VXLAN_TUNNEL_TERM_ENABLE); 3329 return BCM_E_NONE; 3330 } else if (!(vxlan_info->vxlan_tunnel_term[tunnel_idx].activate_flag & 3331 _BCM_VXLAN_TUNNEL_TERM_ENABLE)) { 3332 if ((tunnel_dip != 0) || 3333 (!bcmi_gh2_vxlan_tunnel_ip6_is_zero(tunnel_dip6))) { 3334 /* 3335 * Below tunnel flags are not supported for GH2: 3336 * - _BCM_VXLAN_TUNNEL_TERM_UDP_CHECKSUM_ENABLE 3337 * - _BCM_VXLAN_TUNNEL_TERM_USE_OUTER_DSCP 3338 * - _BCM_VXLAN_TUNNEL_TERM_USE_OUTER_PCP 3339 */ 3340 vxlan_info->vxlan_tunnel_term[tunnel_idx].activate_flag |= 3341 _BCM_VXLAN_TUNNEL_TERM_ENABLE; 3342 } 3343 } 3344 3345 /* Set (SIP, DIP) based Software State */ 3346 tunnel_multicast_state = 3347 vxlan_info->vxlan_tunnel_term[tunnel_idx].tunnel_state; 3348 3349 if (tnl_info->multicast_flag == 3350 BCM_VXLAN_MULTICAST_TUNNEL_STATE_BUD_DISABLE) { 3351 if (tunnel_multicast_state != _BCM_VXLAN_TUNNEL_TERM_MULTICAST_LEAF) { 3352 vxlan_info->vxlan_tunnel_term[tunnel_idx].tunnel_state = 3353 _BCM_VXLAN_TUNNEL_TERM_MULTICAST_LEAF; 3354 } 3355 } else { 3356 /* GH2 doesn't support BUD node */ 3357 return BCM_E_PARAM; 3358 } 3359 3360 return BCM_E_NONE; 3361 } 3362 3363 /* 3364 * Function: 3365 * bcmi_gh2_vxlan_tunnel_terminate_destroy 3366 * Purpose: 3367 * Destroy VXLAN tunnel_terminate Entry 3368 * Parameters: 3369 * unit - (IN) Device Number 3370 * vxlan_tunnel_id - (IN) vxlan_tunnel_id 3371 * Returns: 3372 * BCM_E_XXX 3373 */ 3374 int 3375 bcmi_gh2_vxlan_tunnel_terminator_destroy( 3376 int unit, 3377 bcm_gport_t vxlan_tunnel_id) 3378 { 3379 int tunnel_idx = -1; 3380 bcm_ip_t tunnel_dip = 0; 3381 bcm_ip6_t tunnel_dip6; 3382 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 3383 3384 /* Get VXLAN bookkeeping info instance */ 3385 BCM_IF_ERROR_RETURN( 3386 gh2_vxlan_bk_info_instance_get(unit, &vxlan_info)); 3387 3388 /* Input parameter check */ 3389 if (!BCM_GPORT_IS_TUNNEL(vxlan_tunnel_id)) { 3390 return BCM_E_PARAM; 3391 } 3392 3393 tunnel_idx = BCM_GPORT_TUNNEL_ID_GET(vxlan_tunnel_id); 3394 GH2_VXLAN_TUNNEL_ID_IF_INVALID_RETURN(unit, tunnel_idx); 3395 3396 tunnel_dip = vxlan_info->vxlan_tunnel_term[tunnel_idx].dip; 3397 sal_memcpy(tunnel_dip6, 3398 vxlan_info->vxlan_tunnel_term[tunnel_idx].dip6, 3399 BCM_IP6_ADDRLEN); 3400 3401 if ((tunnel_dip == 0) && 3402 (bcmi_gh2_vxlan_tunnel_ip6_is_zero(tunnel_dip6))) { 3403 return BCM_E_NOT_FOUND; 3404 } 3405 3406 if (!(_BCM_VXLAN_TUNNEL_TERM_ENABLE & 3407 vxlan_info->vxlan_tunnel_term[tunnel_idx].activate_flag)) { 3408 /* Deactivated tunnel terminator can not be destroyed */ 3409 return BCM_E_DISABLED; 3410 } 3411 3412 /* Remove Tunnel term-entry for given DIP from Software based */ 3413 if (tunnel_idx != -1) { 3414 vxlan_info->vxlan_tunnel_term[tunnel_idx].dip = 0; 3415 sal_memset(vxlan_info->vxlan_tunnel_term[tunnel_idx].dip6, 3416 0, BCM_IP6_ADDRLEN); 3417 vxlan_info->vxlan_tunnel_term[tunnel_idx].vlan = 0; 3418 vxlan_info->vxlan_tunnel_term[tunnel_idx].tunnel_state = 0; 3419 vxlan_info->vxlan_tunnel_term[tunnel_idx].activate_flag = 0; 3420 } 3421 3422 return BCM_E_NONE; 3423 } 3424 3425 /* 3426 * Function: 3427 * bcmi_gh2_vxlan_tunnel_terminator_destroy_all 3428 * Purpose: 3429 * Destroy all incoming VXLAN tunnel 3430 * Parameters: 3431 * unit - (IN) Device Number 3432 * Returns: 3433 * BCM_E_XXX 3434 */ 3435 int 3436 bcmi_gh2_vxlan_tunnel_terminator_destroy_all(int unit) 3437 { 3438 int rv = BCM_E_NONE; 3439 int tnl_idx = 0, num_tnl = 0; 3440 bcm_gport_t vxlan_tunnel_id; 3441 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 3442 3443 /* Get VXLAN bookkeeping info instance */ 3444 BCM_IF_ERROR_RETURN( 3445 gh2_vxlan_bk_info_instance_get(unit, &vxlan_info)); 3446 3447 /* Remove all Tunnel term-entry from Software based */ 3448 num_tnl = vxlan_info->num_vxlan_tnl; 3449 for (tnl_idx = 0; tnl_idx < num_tnl; tnl_idx++) { 3450 BCM_GPORT_TUNNEL_ID_SET(vxlan_tunnel_id, tnl_idx); 3451 rv = bcmi_gh2_vxlan_tunnel_terminator_destroy(unit, vxlan_tunnel_id); 3452 if (BCM_FAILURE(rv)) { 3453 if ((rv != BCM_E_NOT_FOUND) && (rv != BCM_E_DISABLED)) { 3454 return rv; 3455 } 3456 } 3457 } 3458 3459 return BCM_E_NONE; 3460 } 3461 3462 /* 3463 * Function: 3464 * bcmi_gh2_vxlan_tunnel_terminator_get 3465 * Purpose: 3466 * Get VXLAN tunnel_terminate Entry 3467 * Parameters: 3468 * unit - (IN) Device Number 3469 * info - (IN/OUT) Tunnel terminator structure 3470 * Returns: 3471 * BCM_E_XXX 3472 */ 3473 int 3474 bcmi_gh2_vxlan_tunnel_terminator_get( 3475 int unit, 3476 bcm_tunnel_terminator_t *tnl_info) 3477 { 3478 int tunnel_idx = -1; 3479 bcm_ip_t tunnel_dip = 0; 3480 bcm_ip6_t tunnel_dip6; 3481 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 3482 3483 /* Input parameter check */ 3484 if (NULL == tnl_info) { 3485 return BCM_E_PARAM; 3486 } 3487 3488 /* Get VXLAN bookkeeping info instance */ 3489 BCM_IF_ERROR_RETURN( 3490 gh2_vxlan_bk_info_instance_get(unit, &vxlan_info)); 3491 3492 /* Program tunnel id */ 3493 if (!BCM_GPORT_IS_TUNNEL(tnl_info->tunnel_id)) { 3494 return BCM_E_PARAM; 3495 } 3496 3497 tunnel_idx = BCM_GPORT_TUNNEL_ID_GET(tnl_info->tunnel_id); 3498 GH2_VXLAN_TUNNEL_ID_IF_INVALID_RETURN(unit, tunnel_idx); 3499 3500 tunnel_dip = vxlan_info->vxlan_tunnel_term[tunnel_idx].dip; 3501 sal_memcpy(tunnel_dip6, 3502 vxlan_info->vxlan_tunnel_term[tunnel_idx].dip6, 3503 BCM_IP6_ADDRLEN); 3504 3505 if (tunnel_dip != 0) { 3506 /* Tunnel for IPv4 */ 3507 tnl_info->sip = vxlan_info->vxlan_tunnel_term[tunnel_idx].sip; 3508 tnl_info->dip = vxlan_info->vxlan_tunnel_term[tunnel_idx].dip; 3509 tnl_info->type = bcmTunnelTypeVxlan; 3510 } else if (!bcmi_gh2_vxlan_tunnel_ip6_is_zero(tunnel_dip6)) { 3511 /* Tunnel for IPv6 */ 3512 sal_memcpy(tnl_info->sip6, 3513 vxlan_info->vxlan_tunnel_term[tunnel_idx].sip6, 3514 BCM_IP6_ADDRLEN); 3515 sal_memcpy(tnl_info->dip6, 3516 vxlan_info->vxlan_tunnel_term[tunnel_idx].dip6, 3517 BCM_IP6_ADDRLEN); 3518 tnl_info->type = bcmTunnelTypeVxlan6; 3519 } else { 3520 /* not exist */ 3521 return BCM_E_NOT_FOUND; 3522 } 3523 3524 /* De-activated */ 3525 if (!(vxlan_info->vxlan_tunnel_term[tunnel_idx].activate_flag & 3526 _BCM_VXLAN_TUNNEL_TERM_ENABLE)) { 3527 tnl_info->flags |= BCM_TUNNEL_TERM_TUNNEL_DEACTIVATE; 3528 } 3529 3530 tnl_info->vlan = vxlan_info->vxlan_tunnel_term[tunnel_idx].vlan; 3531 if (vxlan_info->vxlan_tunnel_term[tunnel_idx].tunnel_state == 3532 _BCM_VXLAN_TUNNEL_TERM_MULTICAST_LEAF) { 3533 tnl_info->multicast_flag = 3534 BCM_VXLAN_MULTICAST_TUNNEL_STATE_BUD_DISABLE; 3535 } else { 3536 tnl_info->multicast_flag = 0; 3537 } 3538 3539 /* 3540 * Below tunnel flags are not supported for GH2: 3541 * - BCM_TUNNEL_TERM_UDP_CHECKSUM_ENABLE 3542 * - BCM_TUNNEL_TERM_USE_OUTER_DSCP 3543 * - BCM_TUNNEL_TERM_USE_OUTER_PCP 3544 */ 3545 3546 return BCM_E_NONE; 3547 } 3548 3549 /* 3550 * Function: 3551 * bcmi_gh2_vxlan_tunnel_terminator_traverse 3552 * Purpose: 3553 * Traverse VXLAN tunnel terminator entries 3554 * Parameters: 3555 * unit - (IN) Device Number 3556 * cb - (IN) User callback function, called once per entry 3557 * user_data - (IN) User supplied cookie used in callback function 3558 * Returns: 3559 * BCM_E_XXX 3560 */ 3561 int 3562 bcmi_gh2_vxlan_tunnel_terminator_traverse( 3563 int unit, 3564 bcm_tunnel_terminator_traverse_cb cb, 3565 void *user_data) 3566 { 3567 int rv = BCM_E_NONE; 3568 int num_tnl = 0, idx = 0; 3569 bcm_tunnel_terminator_t info; 3570 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 3571 3572 /* Input parameter check */ 3573 if (NULL == cb) { 3574 return BCM_E_PARAM; 3575 } 3576 3577 /* Get VXLAN bookkeeping info instance */ 3578 BCM_IF_ERROR_RETURN( 3579 gh2_vxlan_bk_info_instance_get(unit, &vxlan_info)); 3580 3581 num_tnl = vxlan_info->num_vxlan_tnl; 3582 3583 /* Iterate over all the entries - search valid ones */ 3584 for (idx = 0; idx < num_tnl; idx++) { 3585 /* Check a valid entry */ 3586 if ((vxlan_info->vxlan_tunnel_term[idx].dip) || 3587 (vxlan_info->vxlan_tunnel_term[idx].sip) || 3588 (!bcmi_gh2_vxlan_tunnel_ip6_is_zero( 3589 vxlan_info->vxlan_tunnel_term[idx].dip6)) || 3590 (!bcmi_gh2_vxlan_tunnel_ip6_is_zero( 3591 vxlan_info->vxlan_tunnel_term[idx].sip6))) { 3592 /* Reset buffer before read */ 3593 bcm_tunnel_terminator_t_init(&info); 3594 3595 BCM_GPORT_TUNNEL_ID_SET(info.tunnel_id, idx); 3596 rv = bcmi_gh2_vxlan_tunnel_terminator_get(unit, &info); 3597 3598 /* search failure */ 3599 if (BCM_FAILURE(rv)) { 3600 if (rv != BCM_E_NOT_FOUND) { 3601 break; 3602 } 3603 continue; 3604 } 3605 3606 rv = (*cb)(unit, &info, user_data); 3607 #ifdef BCM_CB_ABORT_ON_ERR 3608 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 3609 break; 3610 } 3611 #endif 3612 } 3613 } 3614 3615 /* Reset last read status */ 3616 if (rv == BCM_E_NOT_FOUND) { 3617 rv = BCM_E_NONE; 3618 } 3619 3620 return rv; 3621 } 3622 3623 /* 3624 * Function: 3625 * bcmi_gh2_vxlan_tunnel_initiator_add 3626 * Purpose: 3627 * Add tunnel initiator entry to hw. 3628 * Parameters: 3629 * unit - (IN) Device Number 3630 * idx - (IN) Index to insert tunnel initiator. 3631 * info - (IN) Tunnel initiator entry info. 3632 * Returns: 3633 * BCM_E_XXX 3634 */ 3635 STATIC int 3636 bcmi_gh2_vxlan_tunnel_initiator_add( 3637 int unit, 3638 int idx, 3639 bcm_tunnel_initiator_t *info) 3640 { 3641 int rv = BCM_E_NONE; 3642 uint32 tnl_entry[SOC_MAX_MEM_FIELD_WORDS]; /* Buffer to write hw entry */ 3643 soc_mem_t mem; /* Tunnel initiator table memory */ 3644 int ipv6; /* IPv6 tunnel initiator */ 3645 int df_val = 0; /* Don't fragment encoding */ 3646 int hw_map_idx = 0; 3647 int entry_type = 0; 3648 int val; 3649 uint16 random; 3650 egr_fragment_id_table_entry_t entry; 3651 3652 /* Input parameters check */ 3653 if (NULL == info) { 3654 return BCM_E_PARAM; 3655 } 3656 3657 ipv6 = _BCM_TUNNEL_OUTER_HEADER_IPV6(info->type); 3658 3659 /* Get table memory. */ 3660 if (ipv6) { 3661 /* Tunnel for IPv6 */ 3662 idx >>= 1; 3663 mem = BCM_XGS3_L3_MEM(unit, tnl_init_v6); 3664 entry_type = BCM_XGS3_TUNNEL_INIT_V6; 3665 } else { 3666 /* Tunnel for IPv4 */ 3667 mem = BCM_XGS3_L3_MEM(unit, tnl_init_v4); 3668 entry_type = BCM_XGS3_TUNNEL_INIT_V4; 3669 } 3670 3671 /* Zero write buffer. */ 3672 sal_memset(tnl_entry, 0, sizeof(tnl_entry)); 3673 3674 /* 3675 * If replacing existing entry, first read the entry to get old 3676 * profile pointer and TPID 3677 */ 3678 if (info->flags & BCM_TUNNEL_REPLACE) { 3679 BCM_IF_ERROR_RETURN( 3680 soc_mem_read(unit, mem, MEM_BLOCK_ANY, idx, tnl_entry)); 3681 } 3682 3683 if (info->type == bcmTunnelTypeVxlan6) { 3684 /* Tunnel for IPv6 */ 3685 /* Set source address within Tunnel Table */ 3686 soc_mem_ip6_addr_set(unit, mem, tnl_entry, SIPf, info->sip6, 3687 SOC_MEM_IP6_FULL_ADDR); 3688 3689 /* Set destination address within Tunnel Table */ 3690 soc_mem_ip6_addr_set(unit, mem, tnl_entry, DIPf, info->dip6, 3691 SOC_MEM_IP6_FULL_ADDR); 3692 3693 /* Set FLOW_LABEL. */ 3694 soc_mem_field32_set(unit, mem, tnl_entry, 3695 FLOW_LABELf, info->flow_label); 3696 3697 /* Set HOP_LIMIT. */ 3698 soc_mem_field32_set(unit, mem, tnl_entry, HOP_LIMITf, info->ttl); 3699 } else { 3700 /* Tunnel for IPv4 */ 3701 /* Set source address within Tunnel Table */ 3702 soc_mem_field_set(unit, mem, tnl_entry, SIPf, (uint32 *)&info->sip); 3703 3704 /* Set destination address within Tunnel Table */ 3705 soc_mem_field_set(unit, mem, tnl_entry, DIPf, (uint32 *)&info->dip); 3706 3707 /* IP tunnel hdr DF bit for IPv4. */ 3708 df_val = 0; 3709 if (info->flags & BCM_TUNNEL_INIT_USE_INNER_DF) { 3710 df_val |= 0x2; 3711 } else if (info->flags & BCM_TUNNEL_INIT_IPV4_SET_DF) { 3712 df_val |= 0x1; 3713 } 3714 soc_mem_field32_set(unit, mem, tnl_entry, IPV4_DF_SELf, df_val); 3715 3716 /* IP tunnel hdr DF bit for IPv6. */ 3717 if (info->flags & BCM_TUNNEL_INIT_IPV6_SET_DF) { 3718 soc_mem_field32_set(unit, mem, tnl_entry, IPV6_DF_SELf, 1); 3719 } 3720 3721 /* Set TTL. */ 3722 soc_mem_field32_set(unit, mem, tnl_entry, TTLf, info->ttl); 3723 } 3724 3725 /* Tunnel header DSCP select. */ 3726 soc_mem_field32_set(unit, mem, tnl_entry, DSCP_SELf, info->dscp_sel); 3727 3728 if (info->dscp_sel == bcmTunnelDscpMap) { 3729 /* Set DSCP_MAP value. */ 3730 if (SOC_MEM_FIELD_VALID(unit, mem, DSCP_MAPPING_PTRf)) { 3731 BCM_IF_ERROR_RETURN( 3732 _bcm_tr2_qos_id2idx(unit, info->dscp_map, &hw_map_idx)); 3733 soc_mem_field32_set(unit, mem, tnl_entry, 3734 DSCP_MAPPING_PTRf, hw_map_idx); 3735 } else { 3736 return BCM_E_PARAM; 3737 } 3738 } else if (info->dscp_sel == bcmTunnelDscpAssign) { 3739 /* Set DSCP value. */ 3740 if (SOC_MEM_FIELD_VALID(unit, mem, DSCPf)) { 3741 soc_mem_field32_set(unit, mem, tnl_entry, 3742 DSCPf, info->dscp); 3743 } else { 3744 return BCM_E_PARAM; 3745 } 3746 } 3747 3748 /* Set UDP Dest Port */ 3749 soc_mem_field32_set(unit, mem, tnl_entry, 3750 L4_DST_PORTf, info->udp_dst_port); 3751 3752 /* Set UDP Src Port */ 3753 soc_mem_field32_set(unit, mem, tnl_entry, 3754 L4_SRC_PORTf, info->udp_src_port); 3755 3756 /* Set Tunnel type = VXLAN */ 3757 soc_mem_field32_set(unit, mem, tnl_entry, 3758 TUNNEL_TYPEf, _BCM_VXLAN_TUNNEL_TYPE); 3759 3760 /* 3761 * Set entry type: 3762 * IPv4: BCM_XGS3_TUNNEL_INIT_V4 = 0x1 3763 * IPv6: BCM_XGS3_TUNNEL_INIT_V6 = 0x2 3764 */ 3765 soc_mem_field32_set(unit, mem, tnl_entry, ENTRY_TYPEf, entry_type); 3766 3767 if ((info->flags & BCM_TUNNEL_INIT_IP4_ID_SET_FIXED) || 3768 (info->flags & BCM_TUNNEL_INIT_IP4_ID_SET_RANDOM)) { 3769 if (info->type != bcmTunnelTypeVxlan) { 3770 return BCM_E_PARAM; 3771 } 3772 BCM_IF_ERROR_RETURN( 3773 bcm_esw_switch_control_get(unit, 3774 bcmSwitchTunnelIp4IdShared, &val)); 3775 if (val == 0) { 3776 sal_memset(&entry, 0, sizeof(egr_fragment_id_table_entry_t)); 3777 3778 if (info->flags & BCM_TUNNEL_INIT_IP4_ID_SET_FIXED) { 3779 soc_EGR_FRAGMENT_ID_TABLEm_field32_set(unit, &entry, 3780 FRAGMENT_IDf, 3781 info->ip4_id); 3782 } else if (info->flags & BCM_TUNNEL_INIT_IP4_ID_SET_RANDOM) { 3783 random = (uint16)(sal_time_usecs() & 0xFFFF); 3784 soc_EGR_FRAGMENT_ID_TABLEm_field32_set(unit, &entry, 3785 FRAGMENT_IDf, random); 3786 } 3787 BCM_IF_ERROR_RETURN( 3788 soc_mem_write(unit, EGR_FRAGMENT_ID_TABLEm, 3789 SOC_BLOCK_ALL, idx, &entry)); 3790 } 3791 } 3792 3793 /* Write buffer to hw */ 3794 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, idx, tnl_entry); 3795 3796 return rv; 3797 } 3798 3799 /* 3800 * Function: 3801 * bcmi_gh2_vxlan_tnl_init_del 3802 * Purpose: 3803 * Delete tunnels initiator entry. Entry kept if reference count 3804 * not equals to 1 (Other tunnels reference the same entry). 3805 * Parameters: 3806 * unit - (IN) Device Number 3807 * flags - (IN) Table shared flags 3808 * info - (IN) The informaton of tunnel initiator 3809 * ent_index - (IN) Entry index 3810 * Returns: 3811 * BCM_E_XXX 3812 */ 3813 STATIC int 3814 bcmi_gh2_vxlan_tnl_init_del( 3815 int unit, 3816 uint32 flags, 3817 bcm_tunnel_initiator_t *info, 3818 int ent_index) 3819 { 3820 _bcm_l3_tbl_op_t data; /* Delete operation info. */ 3821 3822 /* Initialization */ 3823 sal_memset(&data, 0, sizeof(_bcm_l3_tbl_op_t)); 3824 3825 /* Check hw call is defined. */ 3826 if (!BCM_XGS3_L3_HWCALL_CHECK(unit, tnl_init_del)) { 3827 return BCM_E_UNAVAIL; 3828 } 3829 3830 if(_BCM_EGR_IP_TUNNEL_DOUBLE_WIDE_ENTRY(unit, info->type)) { 3831 /* IPv6 tunnel is double table entry operation (occupy 2 slots). */ 3832 data.width = _BCM_DOUBLE_WIDE; 3833 } else { 3834 /* IPv4 tunnel is single table entry operation.*/ 3835 data.width = _BCM_SINGLE_WIDE; 3836 } 3837 3838 data.tbl_ptr = BCM_XGS3_L3_TBL_PTR(unit, tnl_init); 3839 data.entry_index = ent_index; 3840 data.oper_flags = flags; 3841 data.delete_func = BCM_XGS3_L3_HWCALL(unit, tnl_init_del); 3842 3843 /* Delete tunnel initiator table entry. */ 3844 return _bcm_xgs3_tbl_del(unit, &data); 3845 } 3846 3847 /* 3848 * Function: 3849 * bcmi_gh2_vxlan_tunnel_initiator_entry_add 3850 * Purpose: 3851 * Configure VXLAN Tunnel initiator hardware Entry 3852 * Parameters: 3853 * unit - (IN) Device Number 3854 * flags - (IN) the flags of tunnel initiator 3855 * info - (IN) the informaton of tunnel initiator 3856 * tnl_idx - (OUT) Tunnel id for tunnel initiator 3857 * Returns: 3858 * BCM_E_XXX 3859 */ 3860 STATIC int 3861 bcmi_gh2_vxlan_tunnel_initiator_entry_add( 3862 int unit, 3863 uint32 flags, 3864 bcm_tunnel_initiator_t *info, 3865 int *tnl_idx) 3866 { 3867 int rv = BCM_E_NONE; 3868 3869 /* Input parameters check */ 3870 if ((NULL == info) || (NULL == tnl_idx)) { 3871 return BCM_E_PARAM; 3872 } 3873 3874 rv = bcm_xgs3_tnl_init_add(unit, flags, info, tnl_idx); 3875 if (BCM_FAILURE(rv)) { 3876 return rv; 3877 } 3878 3879 /* Write the entry to HW */ 3880 rv = bcmi_gh2_vxlan_tunnel_initiator_add(unit, *tnl_idx, info); 3881 if (BCM_FAILURE(rv)) { 3882 flags = _BCM_L3_SHR_WRITE_DISABLE; 3883 (void)bcmi_gh2_vxlan_tnl_init_del(unit, flags, info, *tnl_idx); 3884 } 3885 3886 return rv; 3887 } 3888 3889 /* 3890 * Function: 3891 * bcmi_gh2_vxlan_tunnel_initiator_get_tunnel_id 3892 * Purpose: 3893 * Get an available tunnel id for vxlan tunnel initiator 3894 * Parameters: 3895 * unit - (IN) Device Number 3896 * info - (IN) the informaton of tunnel initiator 3897 * hw_match_flag - (IN) Indicate if an existing EGR_IP_TUNNEL entry 3898 * soft_tnl_idx - (OUT) Tunnel id for tunnel initiator 3899 * new_id_flag - (OUT) Indicate if a new free tunnel id 3900 * Returns: 3901 * BCM_E_XXX 3902 */ 3903 STATIC int 3904 bcmi_gh2_vxlan_tunnel_initiator_get_tunnel_id( 3905 int unit, 3906 bcm_tunnel_initiator_t *info, 3907 int hw_match_flag, 3908 int *soft_tnl_idx, 3909 int *new_id_flag) 3910 { 3911 int rv = BCM_E_NONE; 3912 int idx = 0, num_tnl = 0; 3913 int free_index = -1, free_entry_found = 0; 3914 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 3915 3916 if ((NULL == info) || (NULL == soft_tnl_idx) || (NULL == new_id_flag)) { 3917 return BCM_E_PARAM; 3918 } 3919 3920 /* Get VXLAN bookkeeping info instance */ 3921 BCM_IF_ERROR_RETURN( 3922 gh2_vxlan_bk_info_instance_get(unit, &vxlan_info)); 3923 3924 num_tnl = vxlan_info->num_vxlan_tnl; 3925 *new_id_flag = FALSE; 3926 3927 for (idx = 0; idx < num_tnl; idx++) { 3928 if (info->type == bcmTunnelTypeVxlan6) { 3929 /* Tunnel for IPv6 */ 3930 if (((sal_memcmp(vxlan_info->vxlan_tunnel_init[idx].sip6, 3931 info->sip6, BCM_IP6_ADDRLEN) == 0)) && 3932 ((sal_memcmp(vxlan_info->vxlan_tunnel_init[idx].dip6, 3933 info->dip6, BCM_IP6_ADDRLEN) == 0)) && 3934 (vxlan_info->vxlan_tunnel_init[idx].tunnel_state == 3935 info->udp_dst_port)) { 3936 /* Obtain existed index */ 3937 *soft_tnl_idx = idx; 3938 return BCM_E_NONE; 3939 } 3940 } else { 3941 /* Tunnel for IPv4 */ 3942 if ((vxlan_info->vxlan_tunnel_init[idx].sip == info->sip) && 3943 (vxlan_info->vxlan_tunnel_init[idx].dip == info->dip) && 3944 (vxlan_info->vxlan_tunnel_init[idx].tunnel_state == 3945 info->udp_dst_port)) { 3946 /* Obtain existed index */ 3947 *soft_tnl_idx = idx; 3948 return BCM_E_NONE; 3949 } 3950 } 3951 3952 if ((vxlan_info->vxlan_tunnel_init[idx].sip == 0) && 3953 (bcmi_gh2_vxlan_tunnel_ip6_is_zero( 3954 vxlan_info->vxlan_tunnel_init[idx].sip6)) && 3955 !free_entry_found) { 3956 /* Obtain Free index */ 3957 free_index = idx; 3958 free_entry_found = 1; 3959 if (!hw_match_flag) { 3960 break; 3961 } 3962 } 3963 } 3964 3965 if (free_entry_found) { 3966 *new_id_flag = TRUE; 3967 *soft_tnl_idx = free_index; 3968 } else { 3969 /* No free resource */ 3970 return BCM_E_RESOURCE; 3971 } 3972 3973 return rv; 3974 } 3975 3976 /* 3977 * Function: 3978 * bcmi_gh2_vxlan_tunnel_initiator_idx_translate 3979 * Purpose: 3980 * Translate the index of software object to the index 3981 * of hw entry for tunnel initiator 3982 * Parameters: 3983 * unit - (IN) Device Number 3984 * soft_idx - (IN) The index of software object 3985 * hw_idx - (OUT) The index of hw entry 3986 * Returns: 3987 * BCM_E_XXX 3988 */ 3989 STATIC int 3990 bcmi_gh2_vxlan_tunnel_initiator_idx_translate( 3991 int unit, 3992 int soft_idx, 3993 int *hw_idx) 3994 { 3995 int rv = BCM_E_NONE; 3996 bcm_tunnel_initiator_t init_tnl_info; 3997 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 3998 3999 /* Input parameter check */ 4000 if (NULL == hw_idx) { 4001 return BCM_E_PARAM; 4002 } 4003 4004 /* Get VXLAN bookkeeping info instance */ 4005 BCM_IF_ERROR_RETURN( 4006 gh2_vxlan_bk_info_instance_get(unit, &vxlan_info)); 4007 4008 bcm_tunnel_initiator_t_init(&init_tnl_info); 4009 4010 if (vxlan_info->vxlan_tunnel_init[soft_idx].sip != 0) { 4011 /* Tunnel for IPv4 */ 4012 init_tnl_info.type = bcmTunnelTypeVxlan; 4013 init_tnl_info.sip = vxlan_info->vxlan_tunnel_init[soft_idx].sip; 4014 } else { 4015 /* Tunnel for IPv6 */ 4016 init_tnl_info.type = bcmTunnelTypeVxlan6; 4017 sal_memcpy(init_tnl_info.sip6, 4018 vxlan_info->vxlan_tunnel_init[soft_idx].sip6, 4019 BCM_IP6_ADDRLEN); 4020 } 4021 4022 init_tnl_info.udp_dst_port = 4023 vxlan_info->vxlan_tunnel_init[soft_idx].tunnel_state; 4024 4025 rv = _bcm_xgs3_l3_tnl_init_find(unit, &init_tnl_info, hw_idx); 4026 4027 return rv; 4028 } 4029 4030 /* 4031 * Function: 4032 * bcmi_gh2_vxlan_tunnel_initiator_cmp 4033 * Purpose: 4034 * Routine compares vxlan tunnel initiator entry with entry in the chip 4035 * with specified index. 4036 * Parameters: 4037 * unit - (IN) Device Number 4038 * buf - (IN) Tunnel initiator entry to compare. 4039 * index- (IN) Entry index in the chip to compare. 4040 * cmp_result - (OUT) Compare result. 4041 * Returns: 4042 * BCM_E_XXX 4043 */ 4044 int 4045 bcmi_gh2_vxlan_tunnel_initiator_cmp( 4046 int unit, 4047 void *buf, 4048 int index, 4049 int *cmp_result) 4050 { 4051 int rv = BCM_E_NONE; 4052 bcm_tunnel_initiator_t hw_entry; /* Entry read from hw */ 4053 bcm_tunnel_initiator_t *tnl_entry; /* Api passed buffer */ 4054 4055 if ((NULL == buf) || (NULL == cmp_result)) { 4056 return BCM_E_PARAM; 4057 } 4058 4059 *cmp_result = BCM_L3_CMP_NOT_EQUAL; 4060 4061 /* Copy buffer to structure */ 4062 tnl_entry = (bcm_tunnel_initiator_t *)buf; 4063 4064 /* Initialization */ 4065 bcm_tunnel_initiator_t_init(&hw_entry); 4066 4067 /* Get tunnel initiator entry from hw */ 4068 if (BCM_XGS3_L3_HWCALL_CHECK(unit, tnl_init_get)) { 4069 BCM_XGS3_L3_MODULE_LOCK(unit); 4070 rv = (BCM_XGS3_L3_HWCALL_EXEC 4071 (unit, tnl_init_get)(unit, index, &hw_entry)); 4072 BCM_XGS3_L3_MODULE_UNLOCK(unit); 4073 BCM_IF_ERROR_RETURN(rv); 4074 } else { 4075 return BCM_E_UNAVAIL; 4076 } 4077 4078 /* Compare source ip */ 4079 if ((tnl_entry->sip != hw_entry.sip) || 4080 (sal_memcmp(tnl_entry->sip6, hw_entry.sip6, 4081 BCM_IP6_ADDRLEN) != 0)) { 4082 return BCM_E_NONE; 4083 } 4084 4085 /* Compare udp dst port */ 4086 if (tnl_entry->udp_dst_port != hw_entry.udp_dst_port) { 4087 return BCM_E_NONE; 4088 } 4089 4090 *cmp_result = BCM_L3_CMP_EQUAL; 4091 4092 return BCM_E_NONE; 4093 } 4094 4095 /* 4096 * Function: 4097 * bcmi_gh2_vxlan_tunnel_initiator_hash_calc 4098 * Purpose: 4099 * Calculate tunnel initiator entry hash (signature). 4100 * Parameters: 4101 * unit - (IN) Device Number 4102 * buf - (IN) Tunnel initiator entry information. 4103 * hash - (OUT) Hash (signature) calculated value. 4104 * Returns: 4105 * BCM_X_XXX 4106 */ 4107 int 4108 bcmi_gh2_vxlan_tunnel_initiator_hash_calc(int unit, void *buf, uint16 *hash) 4109 { 4110 bcm_tunnel_initiator_t tnl_entry; 4111 4112 if ((NULL == buf) || (NULL == hash)) { 4113 return (BCM_E_PARAM); 4114 } 4115 4116 bcm_tunnel_initiator_t_init(&tnl_entry); 4117 tnl_entry.type = ((bcm_tunnel_initiator_t *)buf)->type; 4118 4119 /* Set source ip */ 4120 if (tnl_entry.type == bcmTunnelTypeVxlan6) { 4121 /* Tunnel for IPv6 */ 4122 sal_memcpy(tnl_entry.sip6, 4123 ((bcm_tunnel_initiator_t *)buf)->sip6, BCM_IP6_ADDRLEN); 4124 } else { 4125 /* Tunnel for IPv4 */ 4126 tnl_entry.sip = ((bcm_tunnel_initiator_t *)buf)->sip; 4127 } 4128 4129 tnl_entry.udp_dst_port = ((bcm_tunnel_initiator_t *)buf)->udp_dst_port; 4130 4131 /* Calculate hash */ 4132 *hash = _shr_crc16(0, (uint8 *)&tnl_entry, sizeof(bcm_tunnel_initiator_t)); 4133 4134 return BCM_E_NONE; 4135 } 4136 4137 /* 4138 * Function: 4139 * bcmi_gh2_vxlan_tunnel_initiator_create 4140 * Purpose: 4141 * Set VXLAN Tunnel initiator 4142 * Parameters: 4143 * unit - (IN) Device Number 4144 * Returns: 4145 * BCM_E_XXX 4146 */ 4147 int 4148 bcmi_gh2_vxlan_tunnel_initiator_create(int unit, bcm_tunnel_initiator_t *info) 4149 { 4150 int tnl_idx = -1, ref_count = 0; 4151 uint32 flags = 0; 4152 int idx = 0, num_tnl = 0; 4153 uint8 match_entry_present = 0; 4154 int soft_tnl_idx = -1, tunnel_idx = -1; 4155 int new_idx_flag = FALSE; 4156 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 4157 4158 /* Input parameter check */ 4159 if (NULL == info) { 4160 return BCM_E_PARAM; 4161 } 4162 4163 /* Input Tunnel Type check */ 4164 if (info->type == bcmTunnelTypeVxlan6) { 4165 /* Tunnel for IPv6 */ 4166 if (bcmi_gh2_vxlan_tunnel_ip6_is_zero(info->dip6) || 4167 bcmi_gh2_vxlan_tunnel_ip6_is_zero(info->sip6)) { 4168 return BCM_E_PARAM; 4169 } 4170 4171 /* IPv6 doesn't support DSCP value. */ 4172 if (info->dscp_sel == bcmTunnelDscpAssign) { 4173 return BCM_E_PARAM; 4174 } 4175 } else if (info->type == bcmTunnelTypeVxlan) { 4176 /* Tunnel for IPv4 */ 4177 if ((info->dip == 0) || (info->sip == 0)) { 4178 return BCM_E_PARAM; 4179 } 4180 } else { 4181 return BCM_E_PARAM; 4182 } 4183 4184 /* Input TTL valid range check */ 4185 if (!BCM_TTL_VALID(info->ttl)) { 4186 return BCM_E_PARAM; 4187 } 4188 /* Input DSCP selection valid range check */ 4189 if (info->dscp_sel > bcmTunnelDscpMap || info->dscp_sel < 0) { 4190 return BCM_E_PARAM; 4191 } 4192 /* Validate IP tunnel DSCP value. */ 4193 if (info->dscp > 63 || info->dscp < 0) { 4194 return BCM_E_PARAM; 4195 } 4196 /* Validate flow label value. */ 4197 if (_BCM_TUNNEL_OUTER_HEADER_IPV6(info->type)) { 4198 if (info->flow_label >= (1 << 20)) { 4199 return BCM_E_PARAM; 4200 } 4201 } 4202 4203 /* Get VXLAN bookkeeping info instance */ 4204 BCM_IF_ERROR_RETURN( 4205 gh2_vxlan_bk_info_instance_get(unit, &vxlan_info)); 4206 4207 num_tnl = vxlan_info->num_vxlan_tnl; 4208 if (info->flags & BCM_TUNNEL_REPLACE) { 4209 tunnel_idx = BCM_GPORT_TUNNEL_ID_GET(info->tunnel_id); 4210 GH2_VXLAN_TUNNEL_ID_IF_INVALID_RETURN(unit, tunnel_idx); 4211 if (info->type == bcmTunnelTypeVxlan6) { 4212 /* Tunnel for IPv6 */ 4213 if ((sal_memcmp(info->sip6, 4214 vxlan_info->vxlan_tunnel_init[tunnel_idx].sip6, 4215 BCM_IP6_ADDRLEN) != 0) || 4216 (sal_memcmp(info->dip6, 4217 vxlan_info->vxlan_tunnel_init[tunnel_idx].dip6, 4218 BCM_IP6_ADDRLEN) != 0) || 4219 (info->udp_dst_port != 4220 vxlan_info->vxlan_tunnel_init[tunnel_idx].tunnel_state)) { 4221 return BCM_E_UNAVAIL; 4222 } 4223 } else { 4224 /* Tunnel for IPv4 */ 4225 if ((info->sip != 4226 vxlan_info->vxlan_tunnel_init[tunnel_idx].sip) || 4227 (info->udp_dst_port != 4228 vxlan_info->vxlan_tunnel_init[tunnel_idx].tunnel_state) || 4229 (info->dip != 4230 vxlan_info->vxlan_tunnel_init[tunnel_idx].dip)) { 4231 return BCM_E_UNAVAIL; 4232 } 4233 } 4234 } 4235 4236 /* Allocate either existing or new tunnel initiator entry */ 4237 flags = _BCM_L3_SHR_MATCH_DISABLE | 4238 _BCM_L3_SHR_WRITE_DISABLE | 4239 _BCM_L3_SHR_SKIP_INDEX_ZERO; 4240 4241 if (_bcm_xgs3_l3_tnl_init_find(unit, info, &tnl_idx) == BCM_E_NONE) { 4242 match_entry_present = 1; 4243 } 4244 4245 /* Get an available tunnel id */ 4246 BCM_IF_ERROR_RETURN( 4247 bcmi_gh2_vxlan_tunnel_initiator_get_tunnel_id( 4248 unit, info, match_entry_present, &soft_tnl_idx, &new_idx_flag)); 4249 4250 if (match_entry_present) { 4251 if (info->flags & BCM_TUNNEL_REPLACE) { 4252 if (new_idx_flag) { 4253 return BCM_E_UNAVAIL; 4254 } 4255 4256 /* Check for Ref-count in (SIP, multi-DIP) situation */ 4257 for (idx = 0; idx < num_tnl; idx++) { 4258 if (info->type == bcmTunnelTypeVxlan6) { 4259 /* Tunnel for IPv6 */ 4260 if ((sal_memcmp(info->sip6, 4261 vxlan_info->vxlan_tunnel_init[idx].sip6, 4262 BCM_IP6_ADDRLEN) == 0) && 4263 (info->udp_dst_port == 4264 vxlan_info->vxlan_tunnel_init[idx].tunnel_state)) { 4265 if (++ref_count > 1) { 4266 return BCM_E_RESOURCE; 4267 } 4268 } 4269 } else { 4270 /* Tunnel for IPv4 */ 4271 if ((info->sip == 4272 vxlan_info->vxlan_tunnel_init[idx].sip) && 4273 (info->udp_dst_port == 4274 vxlan_info->vxlan_tunnel_init[idx].tunnel_state)) { 4275 if (++ref_count > 1) { 4276 return BCM_E_RESOURCE; 4277 } 4278 } 4279 } 4280 } 4281 4282 flags |= _BCM_L3_SHR_UPDATE | _BCM_L3_SHR_WITH_ID; 4283 BCM_IF_ERROR_RETURN( 4284 bcmi_gh2_vxlan_tunnel_initiator_entry_add(unit, flags, 4285 info, &tnl_idx)); 4286 } 4287 } else { 4288 /* Parse tunnel replace flag */ 4289 if (info->flags & BCM_TUNNEL_REPLACE) { 4290 /* replace an inexistent tunnel initiator */ 4291 return BCM_E_NOT_FOUND; 4292 } 4293 BCM_IF_ERROR_RETURN( 4294 bcmi_gh2_vxlan_tunnel_initiator_entry_add(unit, flags, 4295 info, &tnl_idx)); 4296 } 4297 4298 if (soft_tnl_idx != -1) { 4299 if (info->type == bcmTunnelTypeVxlan6) { 4300 /* Tunnel for IPv6 */ 4301 sal_memcpy(vxlan_info->vxlan_tunnel_init[soft_tnl_idx].sip6, 4302 info->sip6, BCM_IP6_ADDRLEN); 4303 sal_memcpy(vxlan_info->vxlan_tunnel_init[soft_tnl_idx].dip6, 4304 info->dip6, BCM_IP6_ADDRLEN); 4305 } else { 4306 /* Tunnel for IPv4 */ 4307 vxlan_info->vxlan_tunnel_init[soft_tnl_idx].sip = info->sip; 4308 vxlan_info->vxlan_tunnel_init[soft_tnl_idx].dip = info->dip; 4309 } 4310 vxlan_info->vxlan_tunnel_init[soft_tnl_idx].tunnel_state = 4311 info->udp_dst_port; 4312 BCM_GPORT_TUNNEL_ID_SET(info->tunnel_id, soft_tnl_idx); 4313 } else { 4314 return BCM_E_NOT_FOUND; 4315 } 4316 4317 return BCM_E_NONE; 4318 } 4319 4320 /* 4321 * Function: 4322 * bcmi_gh2_vxlan_tunnel_initiator_destroy 4323 * Purpose: 4324 * Destroy outgoing VXLAN tunnel 4325 * Parameters: 4326 * unit - (IN) Device Number 4327 * vxlan_tunnel_id - (IN) Tunnel ID (Gport) 4328 * Returns: 4329 * BCM_E_XXX 4330 */ 4331 int 4332 bcmi_gh2_vxlan_tunnel_initiator_destroy( 4333 int unit, 4334 bcm_gport_t vxlan_tunnel_id) 4335 { 4336 int rv = BCM_E_NONE; 4337 int tnl_idx = -1, temp_tnl_idx = -1, ref_count = 0, idx = 0; 4338 uint32 flags = 0; 4339 int num_tnl = 0; 4340 bcm_ip_t sip = 0; /* Tunnel header SIP (IPv4). */ 4341 bcm_ip6_t sip6; /* Tunnel header SIP (IPv6). */ 4342 uint16 udp_dst_port; /* Destination UDP port */ 4343 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 4344 4345 /* Input parameters check */ 4346 if (!BCM_GPORT_IS_TUNNEL(vxlan_tunnel_id)) { 4347 return BCM_E_PARAM; 4348 } 4349 4350 /* Get VXLAN bookkeeping info instance */ 4351 BCM_IF_ERROR_RETURN( 4352 gh2_vxlan_bk_info_instance_get(unit, &vxlan_info)); 4353 4354 tnl_idx = BCM_GPORT_TUNNEL_ID_GET(vxlan_tunnel_id); 4355 GH2_VXLAN_TUNNEL_ID_IF_INVALID_RETURN(unit, tnl_idx); 4356 4357 /* Tunnel for IPv4/IPv6 */ 4358 sip = vxlan_info->vxlan_tunnel_init[tnl_idx].sip; 4359 sal_memcpy(sip6, vxlan_info->vxlan_tunnel_init[tnl_idx].sip6, 4360 BCM_IP6_ADDRLEN); 4361 udp_dst_port = vxlan_info->vxlan_tunnel_init[tnl_idx].tunnel_state; 4362 4363 if ((sip == 0) && (bcmi_gh2_vxlan_tunnel_ip6_is_zero(sip6))) { 4364 return BCM_E_NOT_FOUND; 4365 } 4366 4367 /* 4368 * Remove HW TNL entry only if all matching SIP, UDP_DEST_PORT 4369 * gets removed 4370 */ 4371 num_tnl = vxlan_info->num_vxlan_tnl; 4372 for (idx = 0; idx < num_tnl; idx++) { 4373 if (sip != 0) { 4374 /* Tunnel for IPv4 */ 4375 if ((vxlan_info->vxlan_tunnel_init[idx].sip == sip) && 4376 (vxlan_info->vxlan_tunnel_init[idx].tunnel_state == 4377 udp_dst_port)) { 4378 ref_count++; 4379 } 4380 } else { 4381 /* Tunnel for IPv6 */ 4382 if ((sal_memcmp(vxlan_info->vxlan_tunnel_init[idx].sip6, 4383 sip6, BCM_IP6_ADDRLEN) == 0) && 4384 (vxlan_info->vxlan_tunnel_init[idx].tunnel_state == 4385 udp_dst_port)) { 4386 ref_count++; 4387 } 4388 } 4389 } 4390 4391 if (ref_count == 1) { 4392 /* Get the entry first */ 4393 temp_tnl_idx = tnl_idx; 4394 BCM_IF_ERROR_RETURN( 4395 bcmi_gh2_vxlan_tunnel_initiator_idx_translate(unit, temp_tnl_idx, 4396 &tnl_idx)); 4397 /* Destroy the tunnel entry */ 4398 (void)bcm_xgs3_tnl_init_del(unit, flags, tnl_idx); 4399 vxlan_info->vxlan_tunnel_init[temp_tnl_idx].sip = 0; 4400 vxlan_info->vxlan_tunnel_init[temp_tnl_idx].dip = 0; 4401 sal_memset(vxlan_info->vxlan_tunnel_init[temp_tnl_idx].sip6, 4402 0, BCM_IP6_ADDRLEN); 4403 sal_memset(vxlan_info->vxlan_tunnel_init[temp_tnl_idx].dip6, 4404 0, BCM_IP6_ADDRLEN); 4405 vxlan_info->vxlan_tunnel_init[temp_tnl_idx].tunnel_state = 0; 4406 } else if (ref_count > 1) { 4407 vxlan_info->vxlan_tunnel_init[tnl_idx].sip = 0; 4408 vxlan_info->vxlan_tunnel_init[tnl_idx].dip = 0; 4409 sal_memset(vxlan_info->vxlan_tunnel_init[tnl_idx].sip6, 4410 0, BCM_IP6_ADDRLEN); 4411 sal_memset(vxlan_info->vxlan_tunnel_init[tnl_idx].dip6, 4412 0, BCM_IP6_ADDRLEN); 4413 vxlan_info->vxlan_tunnel_init[tnl_idx].tunnel_state = 0; 4414 } 4415 4416 return rv; 4417 } 4418 4419 /* 4420 * Function: 4421 * bcmi_gh2_vxlan_tunnel_initiator_destroy_all 4422 * Purpose: 4423 * Destroy all outgoing VXLAN tunnel 4424 * Parameters: 4425 * unit - (IN) Device Number 4426 * Returns: 4427 * BCM_E_XXX 4428 */ 4429 int 4430 bcmi_gh2_vxlan_tunnel_initiator_destroy_all(int unit) 4431 { 4432 int rv = BCM_E_NONE; 4433 soc_mem_t mem; /* Tunnel initiator table memory */ 4434 egr_ip_tunnel_entry_t *tnl_entry, *tnl_entries; 4435 int tnl_idx, num_entries, num_tnl; 4436 int tnl_type = 0; /* Tunnel type. */ 4437 uint32 entry_type; /* Entry type (IPv4/IPv6) */ 4438 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 4439 4440 /* Get VXLAN bookkeeping info instance */ 4441 BCM_IF_ERROR_RETURN( 4442 gh2_vxlan_bk_info_instance_get(unit, &vxlan_info)); 4443 4444 num_tnl = vxlan_info->num_vxlan_tnl; 4445 4446 /* Destroy VXLAN IPv4/IPv6 Tunnel from hardware */ 4447 mem = BCM_XGS3_L3_MEM(unit, tnl_init_v4); 4448 num_entries = soc_mem_index_count(unit, mem); 4449 tnl_entries = soc_cm_salloc(unit, num_entries * sizeof(*tnl_entries), 4450 "egr_ip_tunnel"); 4451 if (tnl_entries == NULL) { 4452 return BCM_E_MEMORY; 4453 } 4454 sal_memset(tnl_entries, 0, num_entries * sizeof(*tnl_entries)); 4455 4456 soc_mem_lock(unit, mem); 4457 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, 4458 0, (num_entries - 1), tnl_entries); 4459 if (BCM_FAILURE(rv)) { 4460 soc_mem_unlock(unit, mem); 4461 soc_cm_sfree(unit, tnl_entries); 4462 return rv; 4463 } 4464 4465 for (tnl_idx = 0; tnl_idx < num_entries; tnl_idx++) { 4466 tnl_entry = 4467 soc_mem_table_idx_to_pointer(unit, mem, 4468 egr_ip_tunnel_entry_t *, 4469 tnl_entries, tnl_idx); 4470 tnl_type = soc_mem_field32_get(unit, mem, tnl_entry, TUNNEL_TYPEf); 4471 entry_type = soc_mem_field32_get(unit, mem, tnl_entry, ENTRY_TYPEf); 4472 if (tnl_type == _BCM_VXLAN_TUNNEL_TYPE) { 4473 if ((entry_type == BCM_XGS3_TUNNEL_INIT_V4) || 4474 (entry_type == BCM_XGS3_TUNNEL_INIT_V6)) { 4475 /* Delete the entry from HW */ 4476 /* Destroy the tunnel entry */ 4477 (void)bcm_xgs3_tnl_init_del(unit, 0, tnl_idx); 4478 } 4479 } 4480 } 4481 soc_mem_unlock(unit, mem); 4482 soc_cm_sfree(unit, tnl_entries); 4483 4484 /* Clear all VXLAN IPv4/IPv6 Tunnel from software */ 4485 for (tnl_idx = 0; tnl_idx < num_tnl; tnl_idx++) { 4486 vxlan_info->vxlan_tunnel_init[tnl_idx].sip = 0; 4487 vxlan_info->vxlan_tunnel_init[tnl_idx].dip = 0; 4488 sal_memset(vxlan_info->vxlan_tunnel_init[tnl_idx].sip6, 4489 0, BCM_IP6_ADDRLEN); 4490 sal_memset(vxlan_info->vxlan_tunnel_init[tnl_idx].dip6, 4491 0, BCM_IP6_ADDRLEN); 4492 vxlan_info->vxlan_tunnel_init[tnl_idx].tunnel_state = 0; 4493 } 4494 4495 return BCM_E_NONE; 4496 } 4497 4498 /* 4499 * Function: 4500 * bcmi_gh2_vxlan_tunnel_initiator_get 4501 * Purpose: 4502 * Get an outgong VXLAN tunnel info 4503 * Parameters: 4504 * unit - (IN) Device Number 4505 * info - (IN/OUT) Tunnel initiator structure 4506 * Returns: 4507 * BCM_E_XXX 4508 */ 4509 int 4510 bcmi_gh2_vxlan_tunnel_initiator_get(int unit, bcm_tunnel_initiator_t *info) 4511 { 4512 int rv = BCM_E_NONE; 4513 int soft_idx = -1, hw_idx = -1; 4514 egr_fragment_id_table_entry_t entry; 4515 uint32 tnl_entry[SOC_MAX_MEM_FIELD_WORDS]; /* Buffer to read hw entry */ 4516 soc_mem_t mem; /* Tunnel initiator table memory.*/ 4517 int df_val = 0; /* Don't fragment encoded value. */ 4518 int tnl_type = 0; /* Tunnel type. */ 4519 uint32 entry_type; /* Entry type (IPv4/IPv6) */ 4520 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 4521 4522 /* Input parameters check */ 4523 if (NULL == info) { 4524 return BCM_E_PARAM; 4525 } 4526 4527 /* Get VXLAN bookkeeping info instance */ 4528 BCM_IF_ERROR_RETURN( 4529 gh2_vxlan_bk_info_instance_get(unit, &vxlan_info)); 4530 4531 if (!BCM_GPORT_IS_TUNNEL(info->tunnel_id)) { 4532 return BCM_E_PARAM; 4533 } 4534 4535 soft_idx = BCM_GPORT_TUNNEL_ID_GET(info->tunnel_id); 4536 GH2_VXLAN_TUNNEL_ID_IF_INVALID_RETURN(unit, soft_idx); 4537 4538 /* Get SIP/DIP info from hardware */ 4539 BCM_IF_ERROR_RETURN( 4540 bcmi_gh2_vxlan_tunnel_initiator_idx_translate(unit, soft_idx, 4541 &hw_idx)); 4542 4543 /* Get table memory for IPv4 */ 4544 mem = BCM_XGS3_L3_MEM(unit, tnl_init_v4); 4545 /* Initialize the buffer */ 4546 sal_memset(tnl_entry, 0, sizeof(tnl_entry)); 4547 BCM_IF_ERROR_RETURN( 4548 soc_mem_read(unit, mem, MEM_BLOCK_ANY, hw_idx, tnl_entry)); 4549 4550 /* Get entry_type. */ 4551 entry_type = soc_mem_field32_get(unit, mem, tnl_entry, ENTRY_TYPEf); 4552 if (entry_type == BCM_XGS3_TUNNEL_INIT_V6) { 4553 /* Tunnel for IPv6 */ 4554 mem = BCM_XGS3_L3_MEM(unit, tnl_init_v6); 4555 hw_idx >>= 1; /* Each record takes two slots. */ 4556 4557 /* Initialize the buffer */ 4558 sal_memset(tnl_entry, 0, sizeof(tnl_entry)); 4559 BCM_IF_ERROR_RETURN( 4560 soc_mem_read(unit, mem, MEM_BLOCK_ANY, hw_idx, tnl_entry)); 4561 } 4562 4563 /* Get tunnel type. */ 4564 tnl_type = soc_mem_field32_get(unit, mem, tnl_entry, TUNNEL_TYPEf); 4565 if (tnl_type != _BCM_VXLAN_TUNNEL_TYPE) { 4566 return BCM_E_NOT_FOUND; 4567 } 4568 4569 if (entry_type == BCM_XGS3_TUNNEL_INIT_V6) { 4570 /* Tunnel for IPv6 */ 4571 4572 /* Extract IPv6 SIP/DIP address */ 4573 soc_mem_ip6_addr_get(unit, mem, tnl_entry, SIPf, info->sip6, 4574 SOC_MEM_IP6_FULL_ADDR); 4575 sal_memcpy(info->dip6, vxlan_info->vxlan_tunnel_init[soft_idx].dip6, 4576 BCM_IP6_ADDRLEN); 4577 4578 /* Get FLOW_LABEL. */ 4579 info->flow_label = soc_mem_field32_get(unit, mem, 4580 tnl_entry, FLOW_LABELf); 4581 4582 /* Get HOP_LIMIT. */ 4583 info->ttl = soc_mem_field32_get(unit, mem, tnl_entry, HOP_LIMITf); 4584 } else if (entry_type == BCM_XGS3_TUNNEL_INIT_V4) { 4585 /* Tunnel for IPv4 */ 4586 4587 /* Extract IPv4 SIP/DIP address */ 4588 info->sip = soc_mem_field32_get(unit, mem, tnl_entry, SIPf); 4589 info->dip = vxlan_info->vxlan_tunnel_init[soft_idx].dip; 4590 4591 /* IP tunnel hdr DF bit for IPv4 */ 4592 df_val = soc_mem_field32_get(unit, mem, tnl_entry, IPV4_DF_SELf); 4593 if (0x2 <= df_val) { 4594 info->flags |= BCM_TUNNEL_INIT_USE_INNER_DF; 4595 } else if (0x1 == df_val) { 4596 info->flags |= BCM_TUNNEL_INIT_IPV4_SET_DF; 4597 } 4598 4599 df_val = soc_mem_field32_get(unit, mem, tnl_entry, IPV6_DF_SELf); 4600 if (0x1 == df_val) { 4601 info->flags |= BCM_TUNNEL_INIT_IPV6_SET_DF; 4602 } 4603 4604 /* Get TTL. */ 4605 info->ttl = soc_mem_field32_get(unit, mem, tnl_entry, TTLf); 4606 } else { 4607 return BCM_E_NOT_FOUND; 4608 } 4609 4610 /* Tunnel header DSCP select. */ 4611 info->dscp_sel = soc_mem_field32_get(unit, mem, tnl_entry, DSCP_SELf); 4612 if (info->dscp_sel == bcmTunnelDscpMap) { 4613 /* Tunnel header DSCP_MAP value. */ 4614 if (SOC_MEM_FIELD_VALID(unit, mem, DSCP_MAPPING_PTRf)) { 4615 BCM_IF_ERROR_RETURN( 4616 _bcm_tr2_qos_idx2id 4617 (unit, soc_mem_field32_get(unit, mem, tnl_entry, 4618 DSCP_MAPPING_PTRf), 4619 _BCM_QOS_MAP_TYPE_EGR_DSCP_TABLE, 4620 &info->dscp_map)); 4621 } else { 4622 return BCM_E_INTERNAL; 4623 } 4624 } else if (info->dscp_sel == bcmTunnelDscpAssign) { 4625 /* Tunnel header DSCP value. */ 4626 if (SOC_MEM_FIELD_VALID(unit, mem, DSCPf)) { 4627 info->dscp = soc_mem_field32_get(unit, mem, tnl_entry, DSCPf); 4628 } else { 4629 return BCM_E_INTERNAL; 4630 } 4631 } 4632 4633 /* Get UDP Dest Port */ 4634 info->udp_dst_port = 4635 soc_mem_field32_get(unit, mem, tnl_entry, L4_DST_PORTf); 4636 4637 /* Get UDP Src Port */ 4638 info->udp_src_port = 4639 soc_mem_field32_get(unit, mem, tnl_entry, L4_SRC_PORTf); 4640 4641 /* 4642 * Translate hw tunnel type into API encoding: 4643 * - bcmTunnelTypeVxlan (IPv4) or bcmTunnelTypeVxlan6 (IPv6) 4644 */ 4645 BCM_IF_ERROR_RETURN( 4646 _bcm_trx_tnl_hw_code_to_type(unit, 4647 tnl_type, entry_type, &info->type)); 4648 4649 BCM_IF_ERROR_RETURN( 4650 soc_mem_read(unit, EGR_FRAGMENT_ID_TABLEm, 4651 MEM_BLOCK_ANY, hw_idx, &entry)); 4652 info->ip4_id = soc_mem_field32_get( 4653 unit, EGR_FRAGMENT_ID_TABLEm, &entry, FRAGMENT_IDf); 4654 4655 return rv; 4656 } 4657 4658 /* 4659 * Function: 4660 * bcmi_gh2_vxlan_tunnel_initiator_traverse 4661 * Purpose: 4662 * Traverse VXLAN tunnel initiator entries 4663 * Parameters: 4664 * unit - (IN) Device Number 4665 * cb - (IN) User callback function, called once per entry 4666 * user_data - (IN) User supplied cookie used in parameter 4667 * in callback function 4668 * Returns: 4669 * BCM_E_XXX 4670 */ 4671 int 4672 bcmi_gh2_vxlan_tunnel_initiator_traverse( 4673 int unit, 4674 bcm_tunnel_initiator_traverse_cb cb, 4675 void *user_data) 4676 { 4677 int rv = BCM_E_NONE; 4678 int num_tnl = 0, idx = 0; 4679 bcm_tunnel_initiator_t info; 4680 bcm_ip6_t sip6; 4681 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 4682 4683 /* Input parameter check */ 4684 if (NULL == cb) { 4685 return BCM_E_PARAM; 4686 } 4687 4688 /* Get VXLAN bookkeeping info instance */ 4689 BCM_IF_ERROR_RETURN( 4690 gh2_vxlan_bk_info_instance_get(unit, &vxlan_info)); 4691 4692 num_tnl = vxlan_info->num_vxlan_tnl; 4693 4694 sal_memset(sip6, 0, BCM_IP6_ADDRLEN); 4695 4696 /* Iterate over all the entries - search valid ones */ 4697 for (idx = 0; idx < num_tnl; idx++) { 4698 /* Check a valid entry */ 4699 sal_memcpy(sip6, vxlan_info->vxlan_tunnel_init[idx].sip6, 4700 BCM_IP6_ADDRLEN); 4701 if ((vxlan_info->vxlan_tunnel_init[idx].sip != 0) || 4702 (!bcmi_gh2_vxlan_tunnel_ip6_is_zero(sip6))) { 4703 /* Reset buffer before read */ 4704 bcm_tunnel_initiator_t_init(&info); 4705 4706 BCM_GPORT_TUNNEL_ID_SET(info.tunnel_id, idx); 4707 rv = bcmi_gh2_vxlan_tunnel_initiator_get(unit, &info); 4708 4709 /* search failure */ 4710 if (BCM_FAILURE(rv)) { 4711 if (rv != BCM_E_NOT_FOUND) { 4712 break; 4713 } 4714 continue; 4715 } 4716 4717 rv = (*cb)(unit, &info, user_data); 4718 #ifdef BCM_CB_ABORT_ON_ERR 4719 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 4720 break; 4721 } 4722 #endif 4723 } 4724 } 4725 4726 /* Reset last read status */ 4727 if (rv == BCM_E_NOT_FOUND) { 4728 rv = BCM_E_NONE; 4729 } 4730 4731 return rv; 4732 } 4733 4734 /* 4735 * Function: 4736 * bcmi_gh2_vxlan_port_resolve 4737 * Purpose: 4738 * Get the modid, port, trunk values for a VXLAN port 4739 * Parameters: 4740 * unit - (IN) Device Number 4741 * Returns: 4742 * BCM_E_XXX 4743 */ 4744 int 4745 bcmi_gh2_vxlan_port_resolve( 4746 int unit, 4747 bcm_gport_t vxlan_port_id, 4748 bcm_if_t encap_id, 4749 bcm_module_t *modid, 4750 bcm_port_t *port, 4751 bcm_trunk_t *trunk_id, 4752 int *id) 4753 4754 { 4755 int rv = BCM_E_NONE; 4756 ing_l3_next_hop_entry_t ing_nh; 4757 egr_l3_next_hop_entry_t egr_nh; 4758 int ecmp = 0, nh_index = -1, nh_ecmp_index = -1, vp = -1; 4759 uint32 hw_buf[SOC_MAX_MEM_FIELD_WORDS]; /* Buffer to read hw entry */ 4760 int idx, max_ent_count, base_idx; 4761 4762 /* Input parameter check */ 4763 if ((NULL == modid) || (NULL == port) || 4764 (NULL == trunk_id) || (NULL == id)) { 4765 return BCM_E_PARAM; 4766 } 4767 if (!BCM_GPORT_IS_VXLAN_PORT(vxlan_port_id)) { 4768 return BCM_E_BADID; 4769 } 4770 4771 vp = BCM_GPORT_VXLAN_PORT_ID_GET(vxlan_port_id); 4772 if (vp == -1) { 4773 return BCM_E_PARAM; 4774 } 4775 4776 if (!bcmi_gh2_vxlan_vp_used_get(unit, vp)) { 4777 return BCM_E_NOT_FOUND; 4778 } 4779 4780 /* GH2 requires to retrieve vp to ecmp or nhi from software database */ 4781 BCM_IF_ERROR_RETURN( 4782 bcmi_gh2_vxlan_port_to_nh_ecmp_index(unit, vp, 4783 &ecmp, &nh_ecmp_index)); 4784 4785 if (!ecmp) { 4786 nh_index = nh_ecmp_index; 4787 BCM_IF_ERROR_RETURN( 4788 soc_mem_read(unit, ING_L3_NEXT_HOPm, MEM_BLOCK_ANY, 4789 nh_index, &ing_nh)); 4790 4791 if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, Tf)) { 4792 *trunk_id = soc_ING_L3_NEXT_HOPm_field32_get(unit, 4793 &ing_nh, TGIDf); 4794 } else { 4795 /* Only add this to replication set if destination is local */ 4796 *modid = soc_ING_L3_NEXT_HOPm_field32_get(unit, 4797 &ing_nh, MODULE_IDf); 4798 *port = soc_ING_L3_NEXT_HOPm_field32_get(unit, 4799 &ing_nh, PORT_NUMf); 4800 } 4801 } else { 4802 /* Select the desired next hop from ECMP group - pointed by encap_id */ 4803 BCM_IF_ERROR_RETURN( 4804 soc_mem_read(unit, L3_ECMP_COUNTm, MEM_BLOCK_ANY, 4805 nh_ecmp_index, hw_buf)); 4806 4807 max_ent_count = soc_mem_field32_get(unit, L3_ECMP_COUNTm, 4808 hw_buf, COUNTf); 4809 base_idx = soc_mem_field32_get(unit, L3_ECMP_COUNTm, 4810 hw_buf, BASE_PTRf); 4811 max_ent_count++; /* Count is zero based */ 4812 4813 if (encap_id == -1) { 4814 BCM_IF_ERROR_RETURN( 4815 soc_mem_read(unit, L3_ECMPm, MEM_BLOCK_ANY, 4816 base_idx, hw_buf)); 4817 4818 nh_index = soc_mem_field32_get(unit, L3_ECMPm, 4819 hw_buf, NEXT_HOP_INDEXf); 4820 4821 BCM_IF_ERROR_RETURN ( 4822 soc_mem_read(unit, ING_L3_NEXT_HOPm, MEM_BLOCK_ANY, 4823 nh_index, &ing_nh)); 4824 4825 if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, Tf)) { 4826 *trunk_id = soc_ING_L3_NEXT_HOPm_field32_get(unit, 4827 &ing_nh, TGIDf); 4828 } else { 4829 /* Only add this to replication set if destination is local */ 4830 *modid = soc_ING_L3_NEXT_HOPm_field32_get(unit, 4831 &ing_nh, MODULE_IDf); 4832 *port = soc_ING_L3_NEXT_HOPm_field32_get(unit, 4833 &ing_nh, PORT_NUMf); 4834 } 4835 } else { 4836 for (idx = 0; idx < max_ent_count; idx++) { 4837 BCM_IF_ERROR_RETURN( 4838 soc_mem_read(unit, L3_ECMPm, MEM_BLOCK_ANY, 4839 (base_idx + idx), hw_buf)); 4840 nh_index = soc_mem_field32_get(unit, L3_ECMPm, 4841 hw_buf, NEXT_HOP_INDEXf); 4842 BCM_IF_ERROR_RETURN( 4843 soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 4844 nh_index, &egr_nh)); 4845 if (encap_id == soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, 4846 &egr_nh, INTF_NUMf)) { 4847 BCM_IF_ERROR_RETURN( 4848 soc_mem_read(unit, ING_L3_NEXT_HOPm, MEM_BLOCK_ANY, 4849 nh_index, &ing_nh)); 4850 if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, Tf)) { 4851 *trunk_id = soc_ING_L3_NEXT_HOPm_field32_get(unit, 4852 &ing_nh, 4853 TGIDf); 4854 } else { 4855 /* 4856 * Only add this to replication set 4857 * if destination is local 4858 */ 4859 *modid = soc_ING_L3_NEXT_HOPm_field32_get(unit, 4860 &ing_nh, 4861 MODULE_IDf); 4862 *port = soc_ING_L3_NEXT_HOPm_field32_get(unit, 4863 &ing_nh, 4864 PORT_NUMf); 4865 } 4866 break; 4867 } 4868 } 4869 } 4870 } 4871 4872 *id = vp; 4873 4874 return rv; 4875 } 4876 4877 /* 4878 * Function: 4879 * bcmi_gh2_vxlan_port_cnt_update 4880 * Purpose: 4881 * Update port's VP count. 4882 * Parameters: 4883 * unit - (IN) Device Number 4884 * gport- (IN) GPORT ID 4885 * vp - (IN) Virtual port number 4886 * incr - (IN) If TRUE, increment VP count, else decrease VP count 4887 * Returns: 4888 * BCM_X_XXX 4889 */ 4890 STATIC int 4891 bcmi_gh2_vxlan_port_cnt_update( 4892 int unit, 4893 bcm_gport_t gport, 4894 int vp, 4895 int incr_decr_flag) 4896 { 4897 int mod_out = -1, port_out = -1, tgid_out = -1, vp_out = -1; 4898 bcm_port_t local_member_array[SOC_MAX_NUM_PORTS]; 4899 int local_member_count = 0; 4900 int idx = -1; 4901 int mod_local = -1; 4902 _bcm_port_info_t *port_info; 4903 uint32 port_flags; 4904 4905 BCM_IF_ERROR_RETURN( 4906 bcmi_gh2_vxlan_port_resolve(unit, gport, -1, &mod_out, 4907 &port_out, &tgid_out, &vp_out)); 4908 4909 if (vp_out == -1) { 4910 return BCM_E_PARAM; 4911 } 4912 4913 /* 4914 * Update the physical port's SW state. If associated with a trunk, 4915 * update each local physical port's SW state. 4916 */ 4917 if (BCM_TRUNK_INVALID != tgid_out) { 4918 BCM_IF_ERROR_RETURN( 4919 _bcm_esw_trunk_local_members_get(unit, tgid_out, 4920 SOC_MAX_NUM_PORTS, 4921 local_member_array, 4922 &local_member_count)); 4923 4924 for (idx = 0; idx < local_member_count; idx++) { 4925 _bcm_port_info_access(unit, local_member_array[idx], &port_info); 4926 if (incr_decr_flag) { 4927 port_info->vp_count++; 4928 } else { 4929 if (port_info->vp_count > 0) { 4930 port_info->vp_count--; 4931 } 4932 } 4933 BCM_IF_ERROR_RETURN( 4934 bcm_esw_port_vlan_member_get(unit, 4935 local_member_array[idx], 4936 &port_flags)); 4937 BCM_IF_ERROR_RETURN( 4938 bcm_esw_port_vlan_member_set(unit, 4939 local_member_array[idx], 4940 port_flags)); 4941 } 4942 } else { 4943 BCM_IF_ERROR_RETURN( 4944 _bcm_esw_modid_is_local(unit, mod_out, &mod_local)); 4945 4946 if (mod_local) { 4947 _bcm_port_info_access(unit, port_out, &port_info); 4948 4949 if (incr_decr_flag) { 4950 port_info->vp_count++; 4951 } else { 4952 port_info->vp_count--; 4953 } 4954 4955 BCM_IF_ERROR_RETURN( 4956 bcm_esw_port_vlan_member_get(unit, port_out, &port_flags)); 4957 BCM_IF_ERROR_RETURN( 4958 bcm_esw_port_vlan_member_set(unit, port_out, port_flags)); 4959 } 4960 } 4961 4962 return BCM_E_NONE; 4963 } 4964 4965 /* 4966 * Function: 4967 * bcmi_gh2_vxlan_ingress_dvp_set 4968 * Purpose: 4969 * Set Ingress DVP to Next Hop info 4970 * Parameters: 4971 * unit - (IN) Device Number 4972 * vp - (IN) Virtual port number 4973 * mpath_flag - (IN) Multiple Path flag 4974 * vp_nh_ecmp_index - (IN) nhi or ecmp index 4975 * vxlan_port - (IN) vxlan_port information 4976 * Returns: 4977 * BCM_E_XXX 4978 */ 4979 STATIC int 4980 bcmi_gh2_vxlan_ingress_dvp_set( 4981 int unit, 4982 int vp, 4983 uint32 mpath_flag, 4984 int vp_nh_ecmp_index, 4985 bcm_vxlan_port_t *vxlan_port) 4986 { 4987 int rv = BCM_E_NONE; 4988 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 4989 gh2_vxlan_vp_info_t *vp_info; 4990 4991 /* Input parameter check */ 4992 if (NULL == vxlan_port) { 4993 return BCM_E_PARAM; 4994 } 4995 4996 /* Get VXLAN bookkeeping info instance */ 4997 BCM_IF_ERROR_RETURN( 4998 gh2_vxlan_bk_info_instance_get(unit, &vxlan_info)); 4999 5000 vp_info = &(vxlan_info->vxlan_vp_info[vp]); 5001 5002 if (!(vxlan_port->flags & BCM_VXLAN_PORT_SHARE)) { 5003 if (mpath_flag) { 5004 vp_info->ecmp = 1; /* ECMP */ 5005 } else { 5006 vp_info->ecmp = 0; /* Next Hop */ 5007 } 5008 vp_info->nh_ecmp_index = vp_nh_ecmp_index; 5009 } 5010 5011 if (vxlan_port->flags & BCM_VXLAN_PORT_EGRESS_TUNNEL) { 5012 vp_info->vp_type = GH2_VXLAN_DEST_VP_TYPE_TUNNEL; 5013 } else { 5014 vp_info->vp_type = GH2_VXLAN_DEST_VP_TYPE_ACCESS; 5015 } 5016 5017 return rv; 5018 } 5019 5020 /* 5021 * Function: 5022 * bcmi_gh2_vxlan_egress_tunnel_set 5023 * Purpose: 5024 * Set Egress Tunnel index for Egress Next Hop Info 5025 * Parameters: 5026 * unit - (IN) Device Number 5027 * vxlan_port - (IN) vxlan_port information 5028 * egr_nh_info - (OUT) Egress Next Hop Info 5029 * Returns: 5030 * BCM_E_XXX 5031 */ 5032 STATIC int 5033 bcmi_gh2_vxlan_egress_tunnel_set( 5034 int unit, 5035 bcm_vxlan_port_t *vxlan_port, 5036 bcmi_gh2_vxlan_nh_info_t *egr_nh_info) 5037 { 5038 int rv = BCM_E_NONE; 5039 int tunnel_index = -1, hw_idx = -1; 5040 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 5041 5042 /* Input parameter check */ 5043 if ((NULL == vxlan_port) || (NULL == egr_nh_info)) { 5044 return BCM_E_PARAM; 5045 } 5046 5047 /* Get VXLAN bookkeeping info instance */ 5048 BCM_IF_ERROR_RETURN( 5049 gh2_vxlan_bk_info_instance_get(unit, &vxlan_info)); 5050 5051 tunnel_index = BCM_GPORT_TUNNEL_ID_GET(vxlan_port->egress_tunnel_id); 5052 GH2_VXLAN_TUNNEL_ID_IF_INVALID_RETURN(unit, tunnel_index); 5053 5054 /* Got HW tunnel index */ 5055 BCM_IF_ERROR_RETURN( 5056 bcmi_gh2_vxlan_tunnel_initiator_idx_translate(unit, tunnel_index, 5057 &hw_idx)); 5058 egr_nh_info->tunnel_index = hw_idx; 5059 5060 if (vxlan_port->flags & BCM_VXLAN_PORT_UDP_SRC_PORT_RANGE_ENABLE) { 5061 egr_nh_info->udp_src_port_range_enable = 1; 5062 } 5063 5064 return rv; 5065 } 5066 5067 /* 5068 * Function: 5069 * bcmi_gh2_vxlan_egress_tunnel_get 5070 * Purpose: 5071 * Get Egress Tunnel index Info 5072 * Parameters: 5073 * unit - (IN) Device Number 5074 * vxlan_port - (IN/OUT) vxlan_port information 5075 * tunnel_index - (IN) Tunnel index 5076 * Returns: 5077 * BCM_E_XXX 5078 */ 5079 STATIC int 5080 bcmi_gh2_vxlan_egress_tunnel_get( 5081 int unit, 5082 bcm_vxlan_port_t *vxlan_port, 5083 int tunnel_index) 5084 { 5085 int idx = 0, num_tnl = 0; 5086 soc_mem_t mem; /* Tunnel initiator table memory */ 5087 uint32 tnl_entry[SOC_MAX_MEM_FIELD_WORDS]; /* Buffer to read hw entry */ 5088 uint32 entry_type; /* Entry type (IPv4/IPv6) */ 5089 bcm_ip_t dip = 0; /* Tunnel header DIP (IPv4). */ 5090 bcm_ip6_t dip6; /* Tunnel header DIP (IPv6). */ 5091 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 5092 5093 /* Input parameter check */ 5094 if (NULL == vxlan_port) { 5095 return BCM_E_PARAM; 5096 } 5097 5098 /* Get VXLAN bookkeeping info instance */ 5099 BCM_IF_ERROR_RETURN( 5100 gh2_vxlan_bk_info_instance_get(unit, &vxlan_info)); 5101 5102 num_tnl = vxlan_info->num_vxlan_tnl; 5103 5104 /* First to read for IPv4 */ 5105 mem = BCM_XGS3_L3_MEM(unit, tnl_init_v4); 5106 BCM_IF_ERROR_RETURN( 5107 soc_mem_read(unit, mem, MEM_BLOCK_ANY, tunnel_index, tnl_entry)); 5108 entry_type = soc_mem_field32_get(unit, mem, tnl_entry, ENTRY_TYPEf); 5109 if (entry_type != BCM_XGS3_TUNNEL_INIT_V4) { 5110 mem = BCM_XGS3_L3_MEM(unit, tnl_init_v6); 5111 BCM_IF_ERROR_RETURN( 5112 soc_mem_read(unit, mem, MEM_BLOCK_ANY, tunnel_index, tnl_entry)); 5113 entry_type = soc_mem_field32_get(unit, mem, tnl_entry, ENTRY_TYPEf); 5114 } 5115 5116 if (entry_type == BCM_XGS3_TUNNEL_INIT_V6) { 5117 /* Extract IPv6 address. */ 5118 soc_mem_ip6_addr_get(unit, mem, tnl_entry, DIPf, dip6, 5119 SOC_MEM_IP6_FULL_ADDR); 5120 5121 /* Find DIP within Softare State */ 5122 for (idx = 0; idx < num_tnl; idx++) { 5123 if (sal_memcmp(dip6, vxlan_info->vxlan_tunnel_init[idx].dip6, 5124 BCM_IP6_ADDRLEN) == 0) { 5125 break; 5126 } 5127 } 5128 } else if (entry_type == BCM_XGS3_TUNNEL_INIT_V4) { 5129 /* Extract IPv4 address. */ 5130 dip = soc_mem_field32_get(unit, mem, tnl_entry, DIPf); 5131 5132 /* Find DIP within Softare State */ 5133 for (idx = 0; idx < num_tnl; idx++) { 5134 if (vxlan_info->vxlan_tunnel_init[idx].dip == dip) { 5135 break; 5136 } 5137 } 5138 } 5139 5140 if (idx == num_tnl) { 5141 return BCM_E_NOT_FOUND; 5142 } 5143 5144 BCM_GPORT_TUNNEL_ID_SET(vxlan_port->egress_tunnel_id, idx); 5145 5146 return BCM_E_NONE; 5147 } 5148 5149 /* 5150 * Function: 5151 * bcmi_gh2_vxlan_vlan_tag_set 5152 * Purpose: 5153 * Program inner payload/outer tunnel VLAN TAG settings 5154 * Parameters: 5155 * unit - (IN) Device Number 5156 * vxlan_port - (IN) VXLAN port info 5157 * egr_nh_info - (IN/OUT) Egress Next Hop Info 5158 * nh_index - (IN) Egress Next Hop Index 5159 * Returns: 5160 * BCM_E_XXX 5161 */ 5162 STATIC int 5163 bcmi_gh2_vxlan_vlan_tag_set( 5164 int unit, 5165 bcm_vxlan_port_t *vxlan_port, 5166 bcmi_gh2_vxlan_nh_info_t *egr_nh_info, 5167 int nh_index) 5168 { 5169 int rv = BCM_E_NONE; 5170 bcm_vlan_action_set_t action; 5171 egr_vlan_xlate_entry_t egr_vent, return_vent; 5172 int index = -1; 5173 uint32 egr_profile_idx; 5174 soc_mem_t hw_mem = EGR_VLAN_XLATEm; 5175 5176 /* Input parameter check */ 5177 if ((NULL == vxlan_port) || (NULL == egr_nh_info)) { 5178 return BCM_E_PARAM; 5179 } 5180 5181 /* VXLAN-LITE doesn't support replace TPID related actions */ 5182 if (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_TPID_REPLACE || 5183 vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_PRI_TPID_REPLACE || 5184 vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_TPID_REPLACE) { 5185 return BCM_E_UNAVAIL; 5186 } 5187 5188 /* Common setting for below flags */ 5189 if (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_ADD || 5190 vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_REPLACE || 5191 vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_PRI_REPLACE || 5192 vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_PRI_REPLACE || 5193 (!(vxlan_port->flags & BCM_VXLAN_PORT_EGRESS_TUNNEL) && 5194 vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_DELETE)) { 5195 bcm_vlan_action_set_t_init(&action); 5196 sal_memset(&egr_vent, 0, sizeof(egr_vent)); 5197 /* Valid Entry */ 5198 soc_mem_field32_set(unit, hw_mem, &egr_vent, VALIDf, 1); 5199 /* Entry type = NHI */ 5200 soc_mem_field32_set(unit, hw_mem, &egr_vent, ENTRY_TYPEf, 0x07); 5201 /* Key type = nh_index */ 5202 soc_mem_field32_set(unit, hw_mem, &egr_vent, NHI__NHIf, nh_index); 5203 5204 /* Old Outer VID = match_vlan */ 5205 if (!BCM_VLAN_VALID(vxlan_port->match_vlan)) { 5206 return BCM_E_PARAM; 5207 } 5208 soc_mem_field32_set(unit, hw_mem, &egr_vent, 5209 NHI__OLD_VLAN_IDf, vxlan_port->match_vlan); 5210 } 5211 5212 if (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_ADD) { 5213 if (!BCM_VLAN_VALID(vxlan_port->egress_service_vlan)) { 5214 return BCM_E_PARAM; 5215 } 5216 5217 if (vxlan_port->pkt_pri > BCM_PRIO_MAX) { 5218 return BCM_E_PARAM; 5219 } 5220 if (vxlan_port->pkt_cfi != 0) { 5221 return BCM_E_PARAM; 5222 } 5223 5224 action.ut_outer = bcmVlanActionAdd; 5225 action.it_outer = bcmVlanActionAdd; 5226 BCM_IF_ERROR_RETURN( 5227 _bcm_trx_egr_vlan_action_profile_entry_add(unit, &action, 5228 &egr_profile_idx)); 5229 5230 /* Data */ 5231 soc_mem_field32_set(unit, hw_mem, &egr_vent, 5232 NHI__TAG_ACTION_PROFILE_PTRf, egr_profile_idx); 5233 soc_mem_field32_set(unit, hw_mem, &egr_vent, 5234 NHI__NEW_OVIDf, vxlan_port->egress_service_vlan); 5235 soc_mem_field32_set(unit, hw_mem, &egr_vent, 5236 NHI__NEW_OPRIf, vxlan_port->pkt_pri); 5237 soc_mem_field32_set(unit, hw_mem, &egr_vent, 5238 NHI__NEW_ORPEf, 0x1); 5239 } 5240 5241 if (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_REPLACE) { 5242 if (!BCM_VLAN_VALID(vxlan_port->egress_service_vlan)) { 5243 return BCM_E_PARAM; 5244 } 5245 5246 action.ot_outer = bcmVlanActionReplace; 5247 action.dt_outer = bcmVlanActionReplace; 5248 BCM_IF_ERROR_RETURN( 5249 _bcm_trx_egr_vlan_action_profile_entry_add(unit, &action, 5250 &egr_profile_idx)); 5251 5252 /* Data */ 5253 soc_mem_field32_set(unit, hw_mem, &egr_vent, 5254 NHI__TAG_ACTION_PROFILE_PTRf, egr_profile_idx); 5255 soc_mem_field32_set(unit, hw_mem, &egr_vent, 5256 NHI__NEW_OVIDf, vxlan_port->egress_service_vlan); 5257 } else if (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_PRI_REPLACE) { 5258 if (!BCM_VLAN_VALID(vxlan_port->egress_service_vlan)) { 5259 return BCM_E_PARAM; 5260 } 5261 5262 if (vxlan_port->pkt_pri > BCM_PRIO_MAX) { 5263 return BCM_E_PARAM; 5264 } 5265 if (vxlan_port->pkt_cfi != 0) { 5266 return BCM_E_PARAM; 5267 } 5268 5269 action.ot_outer = bcmVlanActionReplace; 5270 action.ot_outer_prio = bcmVlanActionReplace; 5271 action.dt_outer = bcmVlanActionReplace; 5272 action.dt_outer_prio = bcmVlanActionReplace; 5273 BCM_IF_ERROR_RETURN( 5274 _bcm_trx_egr_vlan_action_profile_entry_add(unit, &action, 5275 &egr_profile_idx)); 5276 5277 /* Data */ 5278 soc_mem_field32_set(unit, hw_mem, &egr_vent, 5279 NHI__TAG_ACTION_PROFILE_PTRf, egr_profile_idx); 5280 soc_mem_field32_set(unit, hw_mem, &egr_vent, 5281 NHI__NEW_OVIDf, vxlan_port->egress_service_vlan); 5282 soc_mem_field32_set(unit, hw_mem, &egr_vent, 5283 NHI__NEW_OPRIf, vxlan_port->pkt_pri); 5284 soc_mem_field32_set(unit, hw_mem, &egr_vent, 5285 NHI__NEW_ORPEf, 0x1); 5286 } else if (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_PRI_REPLACE) { 5287 if (vxlan_port->pkt_pri > BCM_PRIO_MAX) { 5288 return BCM_E_PARAM; 5289 } 5290 if (vxlan_port->pkt_cfi != 0) { 5291 return BCM_E_PARAM; 5292 } 5293 5294 action.ot_outer_prio = bcmVlanActionReplace; 5295 action.dt_outer_prio = bcmVlanActionReplace; 5296 BCM_IF_ERROR_RETURN( 5297 _bcm_trx_egr_vlan_action_profile_entry_add(unit, &action, 5298 &egr_profile_idx)); 5299 5300 /* Data */ 5301 soc_mem_field32_set(unit, hw_mem, &egr_vent, 5302 NHI__TAG_ACTION_PROFILE_PTRf, egr_profile_idx); 5303 soc_mem_field32_set(unit, hw_mem, &egr_vent, 5304 NHI__NEW_OPRIf, vxlan_port->pkt_pri); 5305 soc_mem_field32_set(unit, hw_mem, &egr_vent, 5306 NHI__NEW_ORPEf, 0x1); 5307 } else if (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_DELETE) { 5308 if (vxlan_port->flags & BCM_VXLAN_PORT_EGRESS_TUNNEL) { 5309 egr_nh_info->payload_otag_delete = 1; 5310 } else { 5311 action.ot_outer = bcmVlanActionDelete; 5312 action.dt_outer = bcmVlanActionDelete; 5313 BCM_IF_ERROR_RETURN( 5314 _bcm_trx_egr_vlan_action_profile_entry_add(unit, &action, 5315 &egr_profile_idx)); 5316 5317 /* Data */ 5318 soc_mem_field32_set(unit, hw_mem, &egr_vent, 5319 NHI__TAG_ACTION_PROFILE_PTRf, egr_profile_idx); 5320 } 5321 } 5322 5323 /* Common memory write for below flags */ 5324 if (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_ADD || 5325 vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_REPLACE || 5326 vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_PRI_REPLACE || 5327 vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_PRI_REPLACE || 5328 (!(vxlan_port->flags & BCM_VXLAN_PORT_EGRESS_TUNNEL) && 5329 vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_DELETE)) { 5330 rv = soc_mem_search(unit, hw_mem, 5331 MEM_BLOCK_ANY, &index, &egr_vent, &return_vent, 0); 5332 if (BCM_SUCCESS(rv)) { 5333 /* Replace the new egress vlan translate entry */ 5334 BCM_IF_ERROR_RETURN( 5335 soc_mem_write(unit, hw_mem, MEM_BLOCK_ALL, index, &egr_vent)); 5336 /* Delete the old vlan translate profile entry */ 5337 egr_profile_idx = 5338 soc_mem_field32_get(unit, hw_mem, &return_vent, 5339 NHI__TAG_ACTION_PROFILE_PTRf); 5340 BCM_IF_ERROR_RETURN( 5341 _bcm_trx_egr_vlan_action_profile_entry_delete 5342 (unit, egr_profile_idx)); 5343 } else if (rv == BCM_E_NOT_FOUND) { 5344 BCM_IF_ERROR_RETURN( 5345 soc_mem_insert(unit, hw_mem, MEM_BLOCK_ALL, &egr_vent)); 5346 } else { 5347 return rv; 5348 } 5349 5350 egr_nh_info->use_nhi_in_evxlt_key = 1; 5351 /* Apply EVXLT modification to inner payload VLAN tag */ 5352 egr_nh_info->apply_evxlt_modify_to_payload = 1; 5353 } 5354 5355 if (vxlan_port->flags & BCM_VXLAN_PORT_EGRESS_TUNNEL) { 5356 /* Use NHI as key for Egress VLAN Translation on Egress Tunnel */ 5357 egr_nh_info->use_nhi_in_evxlt_key = 1; 5358 5359 /* Delete Tunnel Outer Tag */ 5360 if (vxlan_port->flags & BCM_VXLAN_PORT_TUNNEL_OUTER_VLAN_DELETE) { 5361 egr_nh_info->tunnel_otag_delete = 1; 5362 } 5363 /* Delete Tunnel Inner Tag */ 5364 if (vxlan_port->flags & BCM_VXLAN_PORT_TUNNEL_INNER_VLAN_DELETE) { 5365 egr_nh_info->tunnel_itag_delete = 1; 5366 } 5367 5368 /* DOT1P priority selection for Tunnel outer header */ 5369 if (vxlan_port->flags & BCM_VXLAN_PORT_TUNNEL_QOS_MAP) { 5370 /* Apply qos_map_id to outer VXLAN header directly */ 5371 egr_nh_info->apply_evxlt_modify_to_payload = 1; 5372 /* USE_MAPPING */ 5373 egr_nh_info->qos_map_id = vxlan_port->qos_map_id; 5374 } else { 5375 if ((vxlan_port->tunnel_pkt_pri) || (vxlan_port->tunnel_pkt_cfi)) { 5376 /* Apply NEW_PCP/NEW_CFI to outer VXLAN header directly */ 5377 egr_nh_info->apply_evxlt_modify_to_payload = 1; 5378 /* USE_FIXED */ 5379 egr_nh_info->tunnel_pkt_pri = vxlan_port->tunnel_pkt_pri; 5380 egr_nh_info->tunnel_pkt_cfi = vxlan_port->tunnel_pkt_cfi; 5381 } 5382 } 5383 } 5384 5385 /* Only support for GH2-B0 when VXLAN RIOT is enabled */ 5386 if (GH2_VXLAN_RIOT_ENABLE(unit)) { 5387 if (vxlan_port->flags & BCM_VXLAN_PORT_LOOPBACK) { 5388 /* Copied to Custom Header IPMC bit for encap */ 5389 if (vxlan_port->flags & BCM_VXLAN_PORT_MULTICAST) { 5390 egr_nh_info->custom_header_ipmc = 1; 5391 } else { 5392 egr_nh_info->custom_header_ipmc = 0; 5393 } 5394 } 5395 } 5396 5397 return BCM_E_NONE; 5398 } 5399 5400 /* 5401 * Function: 5402 * bcmi_gh2_vxlan_vlan_tag_get 5403 * Purpose: 5404 * Program inner payload/outer tunnel VLAN TAG settings 5405 * Parameters: 5406 * unit - (IN) Device Number 5407 * vxlan_port - (IN/OUT) VXLAN port info 5408 * egr_nh_entry - (IN) Egress L3 Next Hop entry 5409 * nh_index - (IN) Egress Next Hop Index 5410 * Returns: 5411 * BCM_E_XXX 5412 */ 5413 STATIC int 5414 bcmi_gh2_vxlan_vlan_tag_get( 5415 int unit, 5416 bcm_vxlan_port_t *vxlan_port, 5417 egr_l3_next_hop_entry_t *egr_nh_entry, 5418 int nh_index) 5419 { 5420 int rv = BCM_E_NONE; 5421 bcm_vlan_action_set_t action; 5422 egr_vlan_xlate_entry_t egr_vent; 5423 egr_vlan_xlate_entry_t ret_egr_vent; 5424 int index = -1, use_nhi_in_evxlt_key = 0; 5425 uint32 entry_type, egr_profile_idx; 5426 soc_mem_t hw_mem = EGR_VLAN_XLATEm; 5427 uint32 value = 0, dot1p_pri_select = 0; 5428 int custom_header_ipmc = 0; 5429 5430 /* Input parameter check */ 5431 if ((NULL == vxlan_port) || (NULL == egr_nh_entry)) { 5432 return BCM_E_PARAM; 5433 } 5434 5435 entry_type = 5436 soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry, ENTRY_TYPEf); 5437 5438 if (entry_type == _BCM_VXLAN_EGR_NEXT_HOP_VXLAN_VIEW) { 5439 use_nhi_in_evxlt_key = 5440 soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry, 5441 VXLAN__USE_NHI_IN_EVXLT_KEYf); 5442 } else if (entry_type == _BCM_VXLAN_EGR_NEXT_HOP_L3_VIEW) { 5443 use_nhi_in_evxlt_key = 5444 soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry, 5445 L3__USE_NHI_IN_EVXLT_KEYf); 5446 5447 /* Only support for GH2-B0 when VXLAN RIOT is enabled */ 5448 if (GH2_VXLAN_RIOT_ENABLE(unit)) { 5449 custom_header_ipmc = 5450 soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry, 5451 L3__CUSTOM_HEADER_IPMCf); 5452 } 5453 } else if (entry_type == _BCM_VXLAN_EGR_NEXT_HOP_L3MC_VIEW) { 5454 use_nhi_in_evxlt_key = 5455 soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry, 5456 L3MC__USE_NHI_IN_EVXLT_KEYf); 5457 5458 /* Only support for GH2-B0 when VXLAN RIOT is enabled */ 5459 if (GH2_VXLAN_RIOT_ENABLE(unit)) { 5460 custom_header_ipmc = 5461 soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry, 5462 L3MC__CUSTOM_HEADER_IPMCf); 5463 } 5464 } else if (entry_type == _BCM_VXLAN_EGR_NEXT_HOP_IFP_ACTION_VIEW) { 5465 /* Only support for GH2-B0 when VXLAN RIOT is enabled */ 5466 if (GH2_VXLAN_RIOT_ENABLE(unit)) { 5467 custom_header_ipmc = 5468 soc_EGR_L3_NEXT_HOPm_field32_get 5469 (unit, egr_nh_entry, IFP_ACTIONS__CUSTOM_HEADER_IPMCf); 5470 } 5471 } 5472 5473 if (use_nhi_in_evxlt_key) { 5474 /* Initialize */ 5475 sal_memset(&egr_vent, 0, sizeof(egr_vlan_xlate_entry_t)); 5476 sal_memset(&ret_egr_vent, 0, sizeof(egr_vlan_xlate_entry_t)); 5477 bcm_vlan_action_set_t_init(&action); 5478 5479 /* Valid Entry */ 5480 soc_mem_field32_set(unit, hw_mem, &egr_vent, VALIDf, 1); 5481 /* Entry type = NHI */ 5482 soc_mem_field32_set(unit, hw_mem, &egr_vent, ENTRY_TYPEf, 0x07); 5483 /* Key type = nh_index */ 5484 soc_mem_field32_set(unit, hw_mem, &egr_vent, NHI__NHIf, nh_index); 5485 /* Old Outer VID = match_vlan */ 5486 VLAN_CHK_ID(unit, vxlan_port->match_vlan); 5487 soc_mem_field32_set(unit, hw_mem, &egr_vent, 5488 NHI__OLD_VLAN_IDf, vxlan_port->match_vlan); 5489 rv = soc_mem_search(unit, hw_mem, MEM_BLOCK_ANY, &index, 5490 &egr_vent, &ret_egr_vent, 0); 5491 if (BCM_SUCCESS(rv)) { 5492 egr_profile_idx = soc_mem_field32_get(unit, hw_mem, &ret_egr_vent, 5493 NHI__TAG_ACTION_PROFILE_PTRf); 5494 5495 _bcm_trx_egr_vlan_action_profile_entry_get(unit, &action, 5496 egr_profile_idx); 5497 5498 if (action.ut_outer == bcmVlanActionAdd && 5499 action.it_outer == bcmVlanActionAdd) { 5500 vxlan_port->flags |= BCM_VXLAN_PORT_SERVICE_VLAN_ADD; 5501 vxlan_port->egress_service_vlan = 5502 soc_mem_field32_get(unit, hw_mem, &ret_egr_vent, 5503 NHI__NEW_OVIDf); 5504 vxlan_port->pkt_pri = 5505 soc_mem_field32_get(unit, hw_mem, &ret_egr_vent, 5506 NHI__NEW_OPRIf); 5507 } 5508 5509 if (action.ot_outer == bcmVlanActionReplace && 5510 action.ot_outer_prio == bcmVlanActionReplace && 5511 action.dt_outer == bcmVlanActionReplace && 5512 action.dt_outer_prio == bcmVlanActionReplace) { 5513 vxlan_port->flags |= BCM_VXLAN_PORT_SERVICE_VLAN_PRI_REPLACE; 5514 vxlan_port->egress_service_vlan = 5515 soc_mem_field32_get(unit, hw_mem, &ret_egr_vent, 5516 NHI__NEW_OVIDf); 5517 vxlan_port->pkt_pri = 5518 soc_mem_field32_get(unit, hw_mem, &ret_egr_vent, 5519 NHI__NEW_OPRIf); 5520 } else if (action.ot_outer == bcmVlanActionReplace && 5521 action.dt_outer == bcmVlanActionReplace) { 5522 vxlan_port->flags |= BCM_VXLAN_PORT_SERVICE_VLAN_REPLACE; 5523 vxlan_port->egress_service_vlan = 5524 soc_mem_field32_get(unit, hw_mem, &ret_egr_vent, 5525 NHI__NEW_OVIDf); 5526 } else if (action.ot_outer_prio == bcmVlanActionReplace && 5527 action.dt_outer_prio == bcmVlanActionReplace) { 5528 vxlan_port->flags |= BCM_VXLAN_PORT_SERVICE_PRI_REPLACE; 5529 vxlan_port->pkt_pri = 5530 soc_mem_field32_get(unit, hw_mem, &ret_egr_vent, 5531 NHI__NEW_OPRIf); 5532 } else if (action.ot_outer == bcmVlanActionDelete && 5533 action.dt_outer == bcmVlanActionDelete) { 5534 vxlan_port->flags |= BCM_VXLAN_PORT_SERVICE_VLAN_DELETE; 5535 vxlan_port->egress_service_vlan = BCM_VLAN_INVALID; 5536 } 5537 5538 vxlan_port->match_vlan = 5539 soc_mem_field32_get(unit, hw_mem, &ret_egr_vent, 5540 NHI__OLD_VLAN_IDf); 5541 } 5542 } 5543 5544 if (entry_type == _BCM_VXLAN_EGR_NEXT_HOP_VXLAN_VIEW) { 5545 /* Delete Payload Outer Tag */ 5546 value = soc_EGR_L3_NEXT_HOPm_field32_get(unit, 5547 egr_nh_entry, 5548 VXLAN__DELETE_PAYLOAD_OTAGf); 5549 if (value) { 5550 vxlan_port->flags |= BCM_VXLAN_PORT_SERVICE_VLAN_DELETE; 5551 } 5552 5553 /* Delete Tunnel Outer Tag */ 5554 value = soc_EGR_L3_NEXT_HOPm_field32_get(unit, 5555 egr_nh_entry, 5556 VXLAN__DELETE_TUNNEL_OTAGf); 5557 if (value) { 5558 vxlan_port->flags |= BCM_VXLAN_PORT_TUNNEL_OUTER_VLAN_DELETE; 5559 } 5560 5561 /* Delete Tunnel Inner Tag */ 5562 value = soc_EGR_L3_NEXT_HOPm_field32_get(unit, 5563 egr_nh_entry, 5564 VXLAN__DELETE_TUNNEL_ITAGf); 5565 if (value) { 5566 vxlan_port->flags |= BCM_VXLAN_PORT_TUNNEL_INNER_VLAN_DELETE; 5567 } 5568 5569 /* DOT1P priority selection for Tunnel outer header */ 5570 dot1p_pri_select = 5571 soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry, 5572 VXLAN__DOT1P_PRI_SELECTf); 5573 if (dot1p_pri_select == 0x1) { 5574 /* USE_MAPPING */ 5575 value = soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry, 5576 VXLAN__DOT1P_MAPPING_PTRf); 5577 BCM_IF_ERROR_RETURN( 5578 _bcm_tr2_qos_idx2id(unit, value, 5579 _BCM_QOS_MAP_TYPE_EGR_MPLS_MAPS, &vxlan_port->qos_map_id)); 5580 vxlan_port->flags |= BCM_VXLAN_PORT_TUNNEL_QOS_MAP; 5581 } else { 5582 /* USE_FIXED */ 5583 vxlan_port->tunnel_pkt_pri = 5584 soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry, 5585 VXLAN__NEW_PCPf); 5586 vxlan_port->tunnel_pkt_cfi = 5587 soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry, 5588 VXLAN__NEW_CFIf); 5589 } 5590 } 5591 5592 /* Only support for GH2-B0 when VXLAN RIOT is enabled */ 5593 if (GH2_VXLAN_RIOT_ENABLE(unit)) { 5594 if (custom_header_ipmc) { 5595 vxlan_port->flags |= BCM_VXLAN_PORT_MULTICAST; 5596 } 5597 } 5598 5599 return rv; 5600 } 5601 5602 /* 5603 * Function: 5604 * bcmi_gh2_vxlan_nexthop_entry_modify 5605 * Purpose: 5606 * Modify Egress entry 5607 * Parameters: 5608 * unit - (IN) Device Number 5609 * nh_index - (IN) Next Hop Index 5610 * egr_nh_info - (IN) Egress Next Hop info 5611 * new_entry_type - (IN) New Entry type 5612 * Returns: 5613 * BCM_E_XXX 5614 */ 5615 STATIC int 5616 bcmi_gh2_vxlan_nexthop_entry_modify( 5617 int unit, 5618 int nh_index, 5619 bcmi_gh2_vxlan_nh_info_t *egr_nh_info, 5620 int new_entry_type) 5621 { 5622 int rv = BCM_E_NONE; 5623 soc_mem_t mem; 5624 egr_l3_next_hop_entry_t egr_nh_entry; 5625 uint32 old_entry_type = 0, intf_num = 0; 5626 bcm_mac_t mac_addr; /* Next hop forwarding destination mac. */ 5627 uint32 macda_index; 5628 void *entries[1]; 5629 egr_mac_da_profile_entry_t macda_entry; 5630 int pri_field_len = 0; 5631 int max_pri = 0; 5632 int hw_idx = 0; 5633 uint32 value; 5634 5635 /* Input parameter check */ 5636 if (NULL == egr_nh_info) { 5637 return BCM_E_PARAM; 5638 } 5639 5640 mem = EGR_L3_NEXT_HOPm; 5641 5642 sal_memset(&mac_addr, 0, sizeof(mac_addr)); 5643 BCM_IF_ERROR_RETURN( 5644 soc_mem_read(unit, mem, MEM_BLOCK_ANY, nh_index, &egr_nh_entry)); 5645 5646 old_entry_type = soc_mem_field32_get(unit, mem, &egr_nh_entry, 5647 ENTRY_TYPEf); 5648 5649 if ((new_entry_type == _BCM_VXLAN_EGR_NEXT_HOP_VXLAN_VIEW) && 5650 ((old_entry_type == _BCM_VXLAN_EGR_NEXT_HOP_L3_VIEW) || 5651 (old_entry_type == _BCM_VXLAN_EGR_NEXT_HOP_VXLAN_VIEW))) { 5652 5653 if (old_entry_type == _BCM_VXLAN_EGR_NEXT_HOP_L3_VIEW) { 5654 /* Get mac address for L3 (Normal view) */ 5655 soc_mem_mac_addr_get(unit, mem, &egr_nh_entry, 5656 L3__MAC_ADDRESSf, mac_addr); 5657 5658 /* Get int_num for L3 (Normal view) */ 5659 intf_num = soc_mem_field32_get(unit, mem, &egr_nh_entry, 5660 L3__INTF_NUMf); 5661 5662 /* Zero buffers for new Entry Type (VXLAN) */ 5663 sal_memset(&egr_nh_entry, 0, sizeof(egr_nh_entry)); 5664 5665 /* Add mac_addr (MAC_DA) into EGR_MAC_DA_PROFILEm */ 5666 sal_memset(&macda_entry, 0, sizeof(macda_entry)); 5667 soc_mem_mac_addr_set(unit, EGR_MAC_DA_PROFILEm, &macda_entry, 5668 MAC_ADDRESSf, mac_addr); 5669 entries[0] = &macda_entry; 5670 BCM_IF_ERROR_RETURN( 5671 _bcm_mac_da_profile_entry_add(unit, entries, 1, &macda_index)); 5672 5673 /* Set MAC_DA_PROFILE_INDEX */ 5674 soc_mem_field32_set(unit, mem, &egr_nh_entry, 5675 VXLAN__MAC_DA_PROFILE_INDEXf, macda_index); 5676 5677 /* Set INTF_NUM */ 5678 soc_mem_field32_set(unit, mem, &egr_nh_entry, 5679 VXLAN__INTF_NUMf, intf_num); 5680 } 5681 5682 /* Set Tunnel Index */ 5683 if (egr_nh_info->tunnel_index != -1) { 5684 soc_mem_field32_set(unit, mem, &egr_nh_entry, 5685 VXLAN__TUNNEL_INDEXf, 5686 egr_nh_info->tunnel_index); 5687 } 5688 5689 /* Set UDP source port range checking for Entropy */ 5690 value = 0; 5691 if (egr_nh_info->udp_src_port_range_enable != -1) { 5692 value = egr_nh_info->udp_src_port_range_enable; 5693 } 5694 soc_mem_field32_set(unit, mem, &egr_nh_entry, 5695 VXLAN__UDP_SRC_PORT_RANGE_ENf, value); 5696 5697 /* Set VXLAN_CLASS_ID (currently use index = 0 for GH2) */ 5698 value = 0; 5699 soc_mem_field32_set(unit, mem, &egr_nh_entry, 5700 VXLAN__VXLAN_CLASS_IDf, value); 5701 5702 /* Set UDP source port range checking for Entropy */ 5703 value = 0; 5704 if (egr_nh_info->vnid != -1) { 5705 value = egr_nh_info->vnid; 5706 } 5707 soc_mem_field32_set(unit, mem, &egr_nh_entry, 5708 VXLAN__VN_IDf, value); 5709 5710 /* Use NHI as key in EGR_VLAN_XLATE */ 5711 value = 0; 5712 if (egr_nh_info->use_nhi_in_evxlt_key != -1) { 5713 value = egr_nh_info->use_nhi_in_evxlt_key; 5714 } 5715 soc_mem_field32_set(unit, mem, &egr_nh_entry, 5716 VXLAN__USE_NHI_IN_EVXLT_KEYf, value); 5717 5718 /* Set for Egress VLAN XLATE modify to Payload/Tunnel */ 5719 value = 0; 5720 if (egr_nh_info->apply_evxlt_modify_to_payload != -1) { 5721 value = egr_nh_info->apply_evxlt_modify_to_payload; 5722 } 5723 soc_mem_field32_set(unit, mem, &egr_nh_entry, 5724 VXLAN__DO_EVXLT_BEFORE_TUNNEL_ENCAPf, value); 5725 5726 /* Delete payload OTAG */ 5727 value = 0; 5728 if (egr_nh_info->payload_otag_delete != -1) { 5729 value = egr_nh_info->payload_otag_delete; 5730 } 5731 soc_mem_field32_set(unit, mem, &egr_nh_entry, 5732 VXLAN__DELETE_PAYLOAD_OTAGf, value); 5733 5734 /* Delete Tunnel OTAG */ 5735 value = 0; 5736 if (egr_nh_info->tunnel_otag_delete != -1) { 5737 value = egr_nh_info->tunnel_otag_delete; 5738 } 5739 soc_mem_field32_set(unit, mem, &egr_nh_entry, 5740 VXLAN__DELETE_TUNNEL_OTAGf, value); 5741 5742 /* Delete Tunnel ITAG */ 5743 value = 0; 5744 if (egr_nh_info->tunnel_itag_delete != -1) { 5745 value = egr_nh_info->tunnel_itag_delete; 5746 } 5747 soc_mem_field32_set(unit, mem, &egr_nh_entry, 5748 VXLAN__DELETE_TUNNEL_ITAGf, value); 5749 5750 /* DOT1P priority selection for Tunnel outer header */ 5751 if (egr_nh_info->qos_map_id != -1) { 5752 /* USE_MAPPING */ 5753 BCM_IF_ERROR_RETURN( 5754 _bcm_tr2_qos_id2idx(unit, egr_nh_info->qos_map_id, &hw_idx)); 5755 soc_mem_field32_set(unit, mem, &egr_nh_entry, 5756 VXLAN__DOT1P_PRI_SELECTf, 0x1); 5757 soc_mem_field32_set(unit, mem, &egr_nh_entry, 5758 VXLAN__DOT1P_MAPPING_PTRf, hw_idx); 5759 } else if ((egr_nh_info->tunnel_pkt_pri != -1) && 5760 (egr_nh_info->tunnel_pkt_cfi != -1)) { 5761 /* USE_FIXED */ 5762 pri_field_len = soc_mem_field_length(unit, mem, VXLAN__NEW_PCPf); 5763 max_pri = (1 << pri_field_len) - 1; 5764 5765 if ((egr_nh_info->tunnel_pkt_pri > max_pri) || 5766 (egr_nh_info->tunnel_pkt_cfi > 1)) { 5767 return BCM_E_PARAM; 5768 } 5769 soc_mem_field32_set(unit, mem, &egr_nh_entry, 5770 VXLAN__DOT1P_PRI_SELECTf, 0x0); 5771 soc_mem_field32_set(unit, mem, &egr_nh_entry, 5772 VXLAN__NEW_PCPf, egr_nh_info->tunnel_pkt_pri); 5773 soc_mem_field32_set(unit, mem, &egr_nh_entry, 5774 VXLAN__NEW_CFIf, egr_nh_info->tunnel_pkt_cfi); 5775 } 5776 5777 /* Set Entry Type */ 5778 soc_mem_field32_set(unit, mem, &egr_nh_entry, ENTRY_TYPEf, 5779 new_entry_type); 5780 } else if ((new_entry_type == _BCM_VXLAN_EGR_NEXT_HOP_L3MC_VIEW) && 5781 (old_entry_type == _BCM_VXLAN_EGR_NEXT_HOP_L3MC_VIEW)) { 5782 /* Use NHI as key in EGR_VLAN_XLATE */ 5783 value = 0; 5784 if (egr_nh_info->use_nhi_in_evxlt_key != -1) { 5785 value = egr_nh_info->use_nhi_in_evxlt_key; 5786 } 5787 soc_mem_field32_set(unit, mem, &egr_nh_entry, 5788 L3MC__USE_NHI_IN_EVXLT_KEYf, value); 5789 5790 /* Only support for GH2-B0 when VXLAN RIOT is enabled */ 5791 if (GH2_VXLAN_RIOT_ENABLE(unit)) { 5792 /* Set to copied to Custom Header IPMC bit */ 5793 value = 0; 5794 if (egr_nh_info->custom_header_ipmc != -1) { 5795 value = egr_nh_info->custom_header_ipmc; 5796 } 5797 soc_mem_field32_set(unit, mem, &egr_nh_entry, 5798 L3MC__CUSTOM_HEADER_IPMCf, value); 5799 } 5800 } else if ((new_entry_type == _BCM_VXLAN_EGR_NEXT_HOP_L3_VIEW) && 5801 (old_entry_type == _BCM_VXLAN_EGR_NEXT_HOP_L3_VIEW)) { 5802 /* Use NHI as key in EGR_VLAN_XLATE */ 5803 value = 0; 5804 if (egr_nh_info->use_nhi_in_evxlt_key != -1) { 5805 value = egr_nh_info->use_nhi_in_evxlt_key; 5806 } 5807 soc_mem_field32_set(unit, mem, &egr_nh_entry, 5808 L3__USE_NHI_IN_EVXLT_KEYf, value); 5809 5810 /* Only support for GH2-B0 when VXLAN RIOT is enabled */ 5811 if (GH2_VXLAN_RIOT_ENABLE(unit)) { 5812 /* Set to copied to Custom Header IPMC bit */ 5813 value = 0; 5814 if (egr_nh_info->custom_header_ipmc != -1) { 5815 value = egr_nh_info->custom_header_ipmc; 5816 } 5817 soc_mem_field32_set(unit, mem, &egr_nh_entry, 5818 L3__CUSTOM_HEADER_IPMCf, value); 5819 } 5820 } else if ((new_entry_type == _BCM_VXLAN_EGR_NEXT_HOP_IFP_ACTION_VIEW) && 5821 ((old_entry_type == _BCM_VXLAN_EGR_NEXT_HOP_L3_VIEW) || 5822 (old_entry_type == _BCM_VXLAN_EGR_NEXT_HOP_IFP_ACTION_VIEW))) { 5823 /* Only support for GH2-B0 when VXLAN RIOT is enabled */ 5824 5825 /* Set to copied to Custom Header IPMC bit */ 5826 value = 0; 5827 if (egr_nh_info->custom_header_ipmc != -1) { 5828 value = egr_nh_info->custom_header_ipmc; 5829 } 5830 soc_mem_field32_set(unit, mem, &egr_nh_entry, 5831 IFP_ACTIONS__CUSTOM_HEADER_IPMCf, value); 5832 5833 /* Disable the DA/SA replacement when unicast decap flow */ 5834 value = 1; 5835 soc_mem_field32_set(unit, mem, &egr_nh_entry, 5836 IFP_ACTIONS__L3_UC_DA_DISABLEf, value); 5837 soc_mem_field32_set(unit, mem, &egr_nh_entry, 5838 IFP_ACTIONS__L3_UC_SA_DISABLEf, value); 5839 5840 /* Set Entry Type */ 5841 soc_mem_field32_set(unit, mem, &egr_nh_entry, ENTRY_TYPEf, 5842 new_entry_type); 5843 } else if (new_entry_type == _BCM_VXLAN_EGR_NEXT_HOP_L3_VIEW) { 5844 if (old_entry_type == _BCM_VXLAN_EGR_NEXT_HOP_VXLAN_VIEW) { 5845 /* Get MAC_DA_PROFILE_INDEX for VXLAN view */ 5846 macda_index = 5847 soc_mem_field32_get(unit, mem, &egr_nh_entry, 5848 VXLAN__MAC_DA_PROFILE_INDEXf); 5849 /* Write MAC_DA from profile into NH table in L3 view */ 5850 sal_memset(&macda_entry, 0, sizeof(macda_entry)); 5851 BCM_IF_ERROR_RETURN( 5852 soc_mem_read(unit, EGR_MAC_DA_PROFILEm, MEM_BLOCK_ANY, 5853 macda_index, &macda_entry)); 5854 soc_mem_mac_addr_get(unit, EGR_MAC_DA_PROFILEm, &macda_entry, 5855 MAC_ADDRESSf, mac_addr); 5856 soc_mem_mac_addr_set(unit, mem, &egr_nh_entry, L3__MAC_ADDRESSf, 5857 mac_addr); 5858 /* Delete mac_addr (MAC_DA) from EGR_MAC_DA_PROFILEm */ 5859 BCM_IF_ERROR_RETURN( 5860 _bcm_mac_da_profile_entry_delete(unit, macda_index)); 5861 } 5862 5863 /* Use NHI as key in EGR_VLAN_XLATE */ 5864 value = 0; 5865 if (egr_nh_info->use_nhi_in_evxlt_key != -1) { 5866 value = egr_nh_info->use_nhi_in_evxlt_key; 5867 } 5868 soc_mem_field32_set(unit, mem, &egr_nh_entry, 5869 L3__USE_NHI_IN_EVXLT_KEYf, value); 5870 5871 /* Only support for GH2-B0 when VXLAN RIOT is enabled */ 5872 if (GH2_VXLAN_RIOT_ENABLE(unit)) { 5873 /* Set to copied to Custom Header IPMC bit */ 5874 value = 0; 5875 if (egr_nh_info->custom_header_ipmc != -1) { 5876 value = egr_nh_info->custom_header_ipmc; 5877 } 5878 soc_mem_field32_set(unit, mem, &egr_nh_entry, 5879 L3__CUSTOM_HEADER_IPMCf, value); 5880 } 5881 5882 /* Set Entry Type */ 5883 soc_mem_field32_set(unit, mem, &egr_nh_entry, ENTRY_TYPEf, 5884 new_entry_type); 5885 } else if ((new_entry_type == _BCM_VXLAN_EGR_NEXT_HOP_VXLAN_VIEW) && 5886 (old_entry_type == _BCM_VXLAN_EGR_NEXT_HOP_L3MC_VIEW)) { 5887 return BCM_E_PARAM; 5888 } 5889 5890 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, nh_index, &egr_nh_entry); 5891 5892 return rv; 5893 } 5894 5895 /* 5896 * Function: 5897 * bcmi_gh2_vxlan_ecmp_nexthop_entry_modify 5898 * Purpose: 5899 * Modify vxlan ecmp member object's Egress next hop entry 5900 * Parameters: 5901 * unit - (IN) Device Number 5902 * vxlan_port - (IN) vxlan_port information 5903 * egr_nh_info - (IN) Egress Next Hop info 5904 * new_entry_type - (IN) New Entry type 5905 * Returns: 5906 * BCM_E_XXX 5907 */ 5908 STATIC int 5909 bcmi_gh2_vxlan_ecmp_nexthop_entry_modify( 5910 int unit, 5911 bcm_vxlan_port_t *vxlan_port, 5912 bcmi_gh2_vxlan_nh_info_t *egr_nh_info, 5913 int new_entry_type) 5914 { 5915 int rv = BCM_E_NONE; 5916 int i = 0, ecmp_member_count = 0; 5917 int ecmp_index; 5918 int alloc_size, index; 5919 bcm_l3_egress_ecmp_t ecmp_info; 5920 bcm_if_t *ecmp_member_array = NULL; 5921 5922 if ((NULL == vxlan_port) || (NULL == egr_nh_info) ) { 5923 return BCM_E_PARAM; 5924 } 5925 5926 ecmp_index = vxlan_port->egress_if; 5927 if (!BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, ecmp_index)) { 5928 return BCM_E_PARAM; 5929 } 5930 5931 ecmp_info.ecmp_intf = ecmp_index; 5932 alloc_size = sizeof(bcm_if_t) * BCM_XGS3_L3_ECMP_MAX(unit); 5933 ecmp_member_array = sal_alloc(alloc_size, "ecmp member array"); 5934 if (NULL == ecmp_member_array) { 5935 return BCM_E_MEMORY; 5936 } 5937 sal_memset(ecmp_member_array, 0, alloc_size); 5938 5939 rv = bcm_esw_l3_egress_ecmp_get(unit, &ecmp_info, 5940 BCM_XGS3_L3_ECMP_MAX(unit), 5941 ecmp_member_array, &ecmp_member_count); 5942 if (BCM_FAILURE(rv)) { 5943 sal_free(ecmp_member_array); 5944 ecmp_member_array = NULL; 5945 return rv; 5946 } 5947 5948 while (i < ecmp_member_count) { 5949 if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, ecmp_member_array[i])) { 5950 index = (ecmp_member_array[i] - BCM_XGS3_EGRESS_IDX_MIN(unit)); 5951 } else { 5952 sal_free(ecmp_member_array); 5953 ecmp_member_array = NULL; 5954 return BCM_E_PARAM; 5955 } 5956 5957 /* Configure inner payload/outer tunnel VLAN TAG setting */ 5958 rv = bcmi_gh2_vxlan_vlan_tag_set(unit, vxlan_port, 5959 egr_nh_info, index); 5960 if (BCM_FAILURE(rv)) { 5961 sal_free(ecmp_member_array); 5962 ecmp_member_array = NULL; 5963 return rv; 5964 } 5965 5966 rv = bcmi_gh2_vxlan_nexthop_entry_modify(unit, index, 5967 egr_nh_info, new_entry_type); 5968 if (BCM_FAILURE(rv)) { 5969 sal_free(ecmp_member_array); 5970 ecmp_member_array = NULL; 5971 return rv; 5972 } 5973 5974 i++; 5975 } 5976 5977 if (ecmp_member_array) { 5978 sal_free(ecmp_member_array); 5979 ecmp_member_array = NULL; 5980 } 5981 5982 return rv; 5983 } 5984 5985 /* 5986 * Function: 5987 * bcmi_gh2_vxlan_ecmp_member_egress_get_first 5988 * Purpose: 5989 * Get ECMP first member nexthop index 5990 * Parameters: 5991 * unit - (IN) Device Number 5992 * ecmp_index - (IN) ECMP index 5993 * index - (OUT) poiter to first next hop index 5994 * Returns: 5995 * BCM_E_XXX 5996 */ 5997 STATIC int 5998 bcmi_gh2_vxlan_ecmp_member_egress_get_first( 5999 int unit, 6000 int ecmp_index, 6001 int *index) 6002 { 6003 int rv = BCM_E_NONE; 6004 int alloc_size; 6005 int ecmp_member_count = 0; 6006 bcm_l3_egress_ecmp_t ecmp_info; 6007 bcm_if_t *ecmp_member_array = NULL; 6008 6009 /* Input parameter check */ 6010 if (NULL == index) { 6011 return BCM_E_PARAM; 6012 } 6013 6014 if (!BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, ecmp_index)) { 6015 return BCM_E_PARAM; 6016 } 6017 6018 bcm_l3_egress_ecmp_t_init(&ecmp_info); 6019 ecmp_info.ecmp_intf = ecmp_index; 6020 alloc_size = sizeof(bcm_if_t) * BCM_XGS3_L3_ECMP_MAX(unit); 6021 ecmp_member_array = sal_alloc(alloc_size, "ecmp member array"); 6022 if (NULL == ecmp_member_array) { 6023 return BCM_E_MEMORY; 6024 } 6025 sal_memset(ecmp_member_array, 0, alloc_size); 6026 6027 rv = bcm_esw_l3_egress_ecmp_get(unit, &ecmp_info, 6028 BCM_XGS3_L3_ECMP_MAX(unit), 6029 ecmp_member_array, &ecmp_member_count); 6030 if (BCM_FAILURE(rv)) { 6031 sal_free(ecmp_member_array); 6032 ecmp_member_array = NULL; 6033 return rv; 6034 } 6035 6036 if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, ecmp_member_array[0])) { 6037 *index = (ecmp_member_array[0] - BCM_XGS3_EGRESS_IDX_MIN(unit)); 6038 } else { 6039 rv = BCM_E_PARAM; 6040 } 6041 6042 if (ecmp_member_array) { 6043 sal_free(ecmp_member_array); 6044 ecmp_member_array = NULL; 6045 } 6046 6047 return rv; 6048 } 6049 6050 /* 6051 * Function: 6052 * bcmi_gh2_vxlan_port_egress_nexthop_reset 6053 * Purpose: 6054 * Reset VXLAN Egress NextHop 6055 * Parameters: 6056 * unit - (IN) Device Number 6057 * nh_index - (IN) Next Hop index 6058 * vp_type - (IN) VP type 6059 * vp - (IN) vxlan virtual port 6060 * vpn - (IN) VPN instance ID 6061 * Returns: 6062 * BCM_E_XXX 6063 */ 6064 STATIC int 6065 bcmi_gh2_vxlan_port_egress_nexthop_reset( 6066 int unit, 6067 int nh_index, 6068 int vp_type, 6069 int vp, 6070 bcm_vpn_t vpn) 6071 { 6072 int rv = BCM_E_NONE; 6073 egr_l3_next_hop_entry_t egr_nh_entry; 6074 uint32 entry_type = 0; 6075 bcmi_gh2_vxlan_nh_info_t egr_nh_info; 6076 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 6077 int index = -1, use_nhi_in_evxlt_key = 0; 6078 egr_vlan_xlate_entry_t egr_vent; 6079 egr_vlan_xlate_entry_t ret_egr_vent; 6080 soc_mem_t hw_mem = EGR_VLAN_XLATEm; 6081 uint32 egr_profile_idx; 6082 6083 /* Get VXLAN bookkeeping info instance */ 6084 BCM_IF_ERROR_RETURN( 6085 gh2_vxlan_bk_info_instance_get(unit, &vxlan_info)); 6086 6087 BCM_IF_ERROR_RETURN( 6088 soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 6089 nh_index, &egr_nh_entry)); 6090 6091 /* Egressing into a regular port */ 6092 entry_type = soc_EGR_L3_NEXT_HOPm_field32_get(unit, 6093 &egr_nh_entry, ENTRY_TYPEf); 6094 if (entry_type == _BCM_VXLAN_EGR_NEXT_HOP_VXLAN_VIEW) { 6095 use_nhi_in_evxlt_key = 6096 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh_entry, 6097 VXLAN__USE_NHI_IN_EVXLT_KEYf); 6098 } else if (entry_type == _BCM_VXLAN_EGR_NEXT_HOP_L3_VIEW) { 6099 use_nhi_in_evxlt_key = 6100 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh_entry, 6101 L3__USE_NHI_IN_EVXLT_KEYf); 6102 } else if (entry_type == _BCM_VXLAN_EGR_NEXT_HOP_L3MC_VIEW) { 6103 use_nhi_in_evxlt_key = 6104 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh_entry, 6105 L3MC__USE_NHI_IN_EVXLT_KEYf); 6106 } 6107 6108 if (use_nhi_in_evxlt_key) { 6109 /* Initialize */ 6110 sal_memset(&egr_vent, 0, sizeof(egr_vlan_xlate_entry_t)); 6111 sal_memset(&ret_egr_vent, 0, sizeof(egr_vlan_xlate_entry_t)); 6112 6113 /* Valid Entry */ 6114 soc_mem_field32_set(unit, hw_mem, &egr_vent, VALIDf, 1); 6115 /* Entry type = NHI */ 6116 soc_mem_field32_set(unit, hw_mem, &egr_vent, ENTRY_TYPEf, 0x07); 6117 /* Key type = nh_index */ 6118 soc_mem_field32_set(unit, hw_mem, &egr_vent, NHI__NHIf, nh_index); 6119 /* Old Outer VID = match_vlan */ 6120 soc_mem_field32_set(unit, hw_mem, &egr_vent, 6121 NHI__OLD_VLAN_IDf, 6122 vxlan_info->match_key[vp].match_vlan); 6123 rv = soc_mem_search(unit, hw_mem, MEM_BLOCK_ANY, &index, 6124 &egr_vent, &ret_egr_vent, 0); 6125 if (BCM_SUCCESS(rv)) { 6126 /* Existing EGR_VLAN_XLATE entry is found */ 6127 6128 /* Delete the old vlan translate profile entry */ 6129 egr_profile_idx = 6130 soc_mem_field32_get(unit, hw_mem, &ret_egr_vent, 6131 NHI__TAG_ACTION_PROFILE_PTRf); 6132 BCM_IF_ERROR_RETURN( 6133 _bcm_trx_egr_vlan_action_profile_entry_delete 6134 (unit, egr_profile_idx)); 6135 6136 /* Delete the related EGR_VLAN_XLATE entry with nh_index */ 6137 BCM_IF_ERROR_RETURN( 6138 soc_mem_delete(unit, hw_mem, MEM_BLOCK_ALL, &egr_vent)); 6139 } else { 6140 if (rv == BCM_E_NOT_FOUND) { 6141 rv = BCM_E_NONE; 6142 } else { 6143 return rv; 6144 } 6145 } 6146 } 6147 6148 sal_memset(&egr_nh_info, 0, sizeof(egr_nh_info)); 6149 if (vp_type == GH2_VXLAN_DEST_VP_TYPE_ACCESS) { 6150 /* Normalize Next-hop Entry - L3 View */ 6151 rv = bcmi_gh2_vxlan_nexthop_entry_modify 6152 (unit, nh_index, &egr_nh_info, 6153 _BCM_VXLAN_EGR_NEXT_HOP_L3_VIEW); 6154 6155 } else if (vp_type == GH2_VXLAN_DEST_VP_TYPE_TUNNEL) { 6156 /* 6157 * Egressing into a tunnel, vp type should be 6158 * GH2_VXLAN_DEST_VP_TYPE_TUNNEL 6159 */ 6160 /* Normalize Next-hop Entry - L3 View */ 6161 if (entry_type == _BCM_VXLAN_EGR_NEXT_HOP_VXLAN_VIEW) { 6162 rv = bcmi_gh2_vxlan_nexthop_entry_modify 6163 (unit, nh_index, &egr_nh_info, 6164 _BCM_VXLAN_EGR_NEXT_HOP_L3_VIEW); 6165 } 6166 } 6167 6168 return rv; 6169 } 6170 6171 /* 6172 * Function: 6173 * bcmi_gh2_vxlan_ecmp_port_egress_nexthop_reset 6174 * Purpose: 6175 * Reset VXLAN ecmp Egress NextHop 6176 * Parameters: 6177 * unit - (IN) Device Number 6178 * ecmp_index - (IN) ECMP index 6179 * vp_type - (IN) VP type 6180 * vp - (IN) vxlan virtual port 6181 * vpn - (IN) VPN instance ID 6182 * Returns: 6183 * BCM_E_XXX 6184 */ 6185 STATIC int 6186 bcmi_gh2_vxlan_ecmp_port_egress_nexthop_reset( 6187 int unit, 6188 int ecmp_index, 6189 int vp_type, 6190 int vp, 6191 bcm_vpn_t vpn) 6192 { 6193 int rv = BCM_E_NONE; 6194 int i = 0, ecmp_member_count = 0; 6195 int alloc_size, index; 6196 bcm_l3_egress_ecmp_t ecmp_info; 6197 bcm_if_t *ecmp_member_array = NULL; 6198 uint32 ref_count; 6199 6200 if (!BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, ecmp_index)) { 6201 return BCM_E_PARAM; 6202 } 6203 6204 /* Initialize ecmp_info data structure */ 6205 bcm_l3_egress_ecmp_t_init(&ecmp_info); 6206 ecmp_info.ecmp_intf = ecmp_index; 6207 alloc_size = sizeof(bcm_if_t) * BCM_XGS3_L3_ECMP_MAX(unit); 6208 ecmp_member_array = sal_alloc(alloc_size, "ecmp member array"); 6209 if (NULL == ecmp_member_array) { 6210 return BCM_E_MEMORY; 6211 } 6212 sal_memset(ecmp_member_array, 0, alloc_size); 6213 6214 rv = bcm_esw_l3_egress_ecmp_get(unit, &ecmp_info, 6215 BCM_XGS3_L3_ECMP_MAX(unit), 6216 ecmp_member_array, &ecmp_member_count); 6217 if (BCM_FAILURE(rv)) { 6218 sal_free(ecmp_member_array); 6219 ecmp_member_array = NULL; 6220 return rv; 6221 } 6222 6223 while (i < ecmp_member_count) { 6224 if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, ecmp_member_array[i])) { 6225 index = (ecmp_member_array[i] - BCM_XGS3_EGRESS_IDX_MIN(unit)); 6226 } else { 6227 sal_free(ecmp_member_array); 6228 ecmp_member_array = NULL; 6229 return BCM_E_PARAM; 6230 } 6231 6232 /* Get current reference count */ 6233 _bcm_esw_l3_egress_reference_get(unit, index, 0, &ref_count); 6234 6235 /* 6236 * If (ref_count == 1), it means the NHI is used for 6237 * ECMP group only, then we must reset VXLAN Egress NextHop. 6238 */ 6239 if (ref_count == 1) { 6240 if (index) { 6241 rv = bcmi_gh2_vxlan_port_egress_nexthop_reset 6242 (unit, index, vp_type, vp, vpn); 6243 } 6244 } 6245 6246 if (BCM_FAILURE(rv)) { 6247 sal_free(ecmp_member_array); 6248 ecmp_member_array = NULL; 6249 return rv; 6250 } 6251 i++; 6252 } 6253 6254 if (ecmp_member_array) { 6255 sal_free(ecmp_member_array); 6256 ecmp_member_array = NULL; 6257 } 6258 6259 return rv; 6260 } 6261 6262 /* 6263 * Function: 6264 * bcmi_gh2_vxlan_nexthop_ecmp_find 6265 * Purpose: 6266 * Find ECMP group with specified egress forwarding object and 6267 * reset VXLAN Egress NextHop when found 6268 * Parameters: 6269 * unit - (IN) Device Number 6270 * ecmp - (IN) ECMP group info. 6271 * intf_count - (IN) Number of elements in intf_array. 6272 * intf_array - (IN) Array of Egress forwarding objects. 6273 * user_data - (IN) User data to be passed to callback function. 6274 * Returns: 6275 * BCM_E_XXX 6276 */ 6277 STATIC int 6278 bcmi_gh2_vxlan_nexthop_ecmp_find( 6279 int unit, 6280 bcm_l3_egress_ecmp_t *ecmp, 6281 int intf_count, 6282 bcm_if_t *intf_array, 6283 void *user_data) 6284 { 6285 int rv = BCM_E_NONE; 6286 int *nh_ecmp_index; 6287 int idx, nh_ecmp_intf, found, nhi; 6288 egr_l3_next_hop_entry_t egr_nh_entry; 6289 bcmi_gh2_vxlan_nh_info_t egr_nh_info; 6290 uint32 entry_type = 0; 6291 6292 /* Input parameters check */ 6293 if ((NULL == ecmp) || (NULL == intf_array) || (NULL == user_data)) { 6294 return BCM_E_PARAM; 6295 } 6296 6297 nh_ecmp_index = (int *)user_data; 6298 nh_ecmp_intf = (*nh_ecmp_index + BCM_XGS3_EGRESS_IDX_MIN(unit)); 6299 found = 0; 6300 for (idx = 0; idx < intf_count; idx++) { 6301 if (*intf_array == nh_ecmp_intf) { 6302 found = 1; 6303 break; 6304 } 6305 intf_array++; 6306 } 6307 6308 if (found != 0) { 6309 sal_memset(&egr_nh_info, 0, sizeof(egr_nh_info)); 6310 6311 nhi = (nh_ecmp_intf - BCM_XGS3_EGRESS_IDX_MIN(unit)); 6312 BCM_IF_ERROR_RETURN( 6313 soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 6314 nhi, &egr_nh_entry)); 6315 6316 /* Egressing into a regular port */ 6317 entry_type = 6318 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh_entry, 6319 ENTRY_TYPEf); 6320 6321 /* Normalize Next-hop Entry - L3 View */ 6322 if (entry_type == _BCM_VXLAN_EGR_NEXT_HOP_VXLAN_VIEW) { 6323 rv = bcmi_gh2_vxlan_nexthop_entry_modify 6324 (unit, nhi, &egr_nh_info, 6325 _BCM_VXLAN_EGR_NEXT_HOP_L3_VIEW); 6326 } 6327 } 6328 6329 return rv; 6330 } 6331 6332 /* 6333 * Function: 6334 * bcmi_gh2_vxlan_port_nh_add 6335 * Purpose: 6336 * Add VXLAN Next Hop entry 6337 * Parameters: 6338 * unit - (IN) Device Number 6339 * vxlan_port - (IN/OUT) vxlan_port information (OUT : vxlan_port_id) 6340 * vp - (IN) vxlan virtual port 6341 * vpn - (IN) VPN instance ID 6342 * Returns: 6343 * BCM_E_XXX 6344 */ 6345 STATIC int 6346 bcmi_gh2_vxlan_port_nh_add( 6347 int unit, 6348 bcm_vxlan_port_t *vxlan_port, 6349 int vp, 6350 bcm_vpn_t vpn) 6351 { 6352 int rv = BCM_E_NONE; 6353 int vfi_index = -1; 6354 int new_entry_type; 6355 egr_l3_next_hop_entry_t egr_nh_entry; 6356 bcmi_gh2_vxlan_nh_info_t egr_nh_info; 6357 uint32 mpath_flag = 0; 6358 int vp_nh_ecmp_index = -1; 6359 int ref_count = 0; 6360 int l3_flag = 0; 6361 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 6362 gh2_vxlan_vpn_info_t *vfi_info; 6363 gh2_vxlan_vp_info_t *vp_info; 6364 6365 /* Input parameter check */ 6366 if (NULL == vxlan_port) { 6367 return BCM_E_PARAM; 6368 } 6369 6370 /* Get VXLAN bookkeeping info instance */ 6371 BCM_IF_ERROR_RETURN( 6372 gh2_vxlan_bk_info_instance_get(unit, &vxlan_info)); 6373 6374 _BCM_VXLAN_VPN_GET(vfi_index, _BCM_VPN_TYPE_VFI, vpn); 6375 /* Get VFI info for VN_ID */ 6376 vfi_info = &(vxlan_info->vxlan_vpn_info[vfi_index]); 6377 6378 /* Get VP info for vfi_index */ 6379 vp_info = &(vxlan_info->vxlan_vp_info[vp]); 6380 vp_info->vfi = vfi_index; 6381 6382 sal_memset(&egr_nh_info, 0, sizeof(egr_nh_info)); 6383 egr_nh_info.vnid = vfi_info->vnid; 6384 egr_nh_info.entry_type = -1; 6385 egr_nh_info.intf_num = -1; 6386 egr_nh_info.tunnel_index = -1; 6387 egr_nh_info.udp_src_port_range_enable = -1; 6388 egr_nh_info.payload_otag_delete = -1; 6389 egr_nh_info.use_nhi_in_evxlt_key = -1; 6390 egr_nh_info.apply_evxlt_modify_to_payload = -1; 6391 egr_nh_info.tunnel_otag_delete = -1; 6392 egr_nh_info.tunnel_itag_delete = -1; 6393 egr_nh_info.qos_map_id = -1; 6394 egr_nh_info.tunnel_pkt_pri = -1; 6395 egr_nh_info.tunnel_pkt_cfi = -1; 6396 egr_nh_info.custom_header_ipmc = -1; 6397 6398 /* 6399 * Get egress next-hop index from egress object and 6400 * increase egress object reference count. 6401 */ 6402 if (!(vxlan_port->flags & BCM_VXLAN_PORT_SHARE)) { 6403 rv = bcm_xgs3_get_nh_from_egress_object(unit, vxlan_port->egress_if, 6404 &mpath_flag, 1, 6405 &vp_nh_ecmp_index); 6406 BCM_IF_ERROR_RETURN(rv); 6407 6408 /* Read the existing egress next_hop entry */ 6409 if (mpath_flag == 0) { 6410 if (vxlan_port->flags & BCM_VXLAN_PORT_NETWORK) { 6411 l3_flag = BCM_XGS3_L3_ENT_FLAG( 6412 BCM_XGS3_L3_TBL_PTR(unit, next_hop), vp_nh_ecmp_index); 6413 if (l3_flag != _BCM_L3_VXLAN_ONLY) { 6414 if (vp_nh_ecmp_index != -1) { 6415 /* Decrement reference count */ 6416 (void)bcm_xgs3_get_ref_count_from_nhi 6417 (unit, mpath_flag, &ref_count, 6418 vp_nh_ecmp_index); 6419 } 6420 return BCM_E_CONFIG; 6421 } 6422 } 6423 } 6424 6425 sal_memset(&egr_nh_entry, 0, sizeof(egr_l3_next_hop_entry_t)); 6426 rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 6427 vp_nh_ecmp_index, &egr_nh_entry); 6428 if (BCM_FAILURE(rv)) { 6429 if (vp_nh_ecmp_index != -1) { 6430 /* Decrement reference count */ 6431 (void)bcm_xgs3_get_ref_count_from_nhi 6432 (unit, mpath_flag, &ref_count, 6433 vp_nh_ecmp_index); 6434 } 6435 return rv; 6436 } 6437 } 6438 6439 if (vxlan_port->flags & BCM_VXLAN_PORT_EGRESS_TUNNEL) { 6440 /* Egress into Network - Tunnel */ 6441 6442 if (!(vxlan_port->flags & BCM_VXLAN_PORT_SHARE)) { 6443 if (vxlan_port->flags & BCM_VXLAN_PORT_MULTICAST) { 6444 /* GH2 doesn't support multicast VXLAN tunnel */ 6445 rv = BCM_E_UNAVAIL; 6446 } 6447 6448 /* 6449 * Select PPD type for Higig header: 6450 * - Must be BCM_VXLAN_PORT_ENCAP_LOCAL for GH2 6451 */ 6452 if (!(vxlan_port->flags & BCM_VXLAN_PORT_ENCAP_LOCAL)) { 6453 rv = BCM_E_PARAM; 6454 } 6455 6456 if (BCM_FAILURE(rv)) { 6457 if (vp_nh_ecmp_index != -1) { 6458 /* Decrement reference count */ 6459 (void)bcm_xgs3_get_ref_count_from_nhi 6460 (unit, mpath_flag, &ref_count, 6461 vp_nh_ecmp_index); 6462 } 6463 return rv; 6464 } 6465 } 6466 6467 /* Program software Egress Tunnel info */ 6468 rv = bcmi_gh2_vxlan_egress_tunnel_set(unit, vxlan_port, &egr_nh_info); 6469 if (BCM_FAILURE(rv)) { 6470 if (vp_nh_ecmp_index != -1) { 6471 /* Decrement reference count */ 6472 (void)bcm_xgs3_get_ref_count_from_nhi 6473 (unit, mpath_flag, &ref_count, 6474 vp_nh_ecmp_index); 6475 } 6476 return rv; 6477 } 6478 6479 /* Program software DVP to NHI/ECMP */ 6480 rv = bcmi_gh2_vxlan_ingress_dvp_set(unit, vp, mpath_flag, 6481 vp_nh_ecmp_index, vxlan_port); 6482 if (BCM_FAILURE(rv)) { 6483 if (vp_nh_ecmp_index != -1) { 6484 /* Decrement reference count */ 6485 (void)bcm_xgs3_get_ref_count_from_nhi 6486 (unit, mpath_flag, &ref_count, 6487 vp_nh_ecmp_index); 6488 } 6489 return rv; 6490 } 6491 6492 new_entry_type = _BCM_VXLAN_EGR_NEXT_HOP_VXLAN_VIEW; 6493 if (mpath_flag == 0) { 6494 /* Configure inner payload/outer tunnel VLAN TAG setting */ 6495 rv = bcmi_gh2_vxlan_vlan_tag_set(unit, vxlan_port, 6496 &egr_nh_info, vp_nh_ecmp_index); 6497 if (BCM_FAILURE(rv)) { 6498 if (vp_nh_ecmp_index != -1) { 6499 /* Decrement reference count */ 6500 (void)bcm_xgs3_get_ref_count_from_nhi 6501 (unit, mpath_flag, &ref_count, 6502 vp_nh_ecmp_index); 6503 } 6504 return rv; 6505 } 6506 6507 rv = bcmi_gh2_vxlan_nexthop_entry_modify 6508 (unit, vp_nh_ecmp_index, &egr_nh_info, new_entry_type); 6509 if (BCM_FAILURE(rv)) { 6510 if (vp_nh_ecmp_index != -1) { 6511 /* Decrement reference count */ 6512 (void)bcm_xgs3_get_ref_count_from_nhi 6513 (unit, mpath_flag, &ref_count, 6514 vp_nh_ecmp_index); 6515 } 6516 return rv; 6517 } 6518 } else { 6519 /* ECMP */ 6520 rv = bcmi_gh2_vxlan_ecmp_nexthop_entry_modify 6521 (unit, vxlan_port, &egr_nh_info, new_entry_type); 6522 if (BCM_FAILURE(rv)) { 6523 if (vp_nh_ecmp_index != -1) { 6524 /* Decrement reference count */ 6525 (void)bcm_xgs3_get_ref_count_from_nhi 6526 (unit, mpath_flag, &ref_count, 6527 vp_nh_ecmp_index); 6528 } 6529 return rv; 6530 } 6531 } 6532 } else { 6533 /* Egress into Access - Non Tunnel */ 6534 6535 /* Configure inner payload VLAN TAG setting */ 6536 rv = bcmi_gh2_vxlan_vlan_tag_set(unit, vxlan_port, 6537 &egr_nh_info, vp_nh_ecmp_index); 6538 if (BCM_FAILURE(rv)) { 6539 if (vp_nh_ecmp_index != -1) { 6540 /* Decrement reference count */ 6541 (void)bcm_xgs3_get_ref_count_from_nhi 6542 (unit, mpath_flag, &ref_count, 6543 vp_nh_ecmp_index); 6544 } 6545 return rv; 6546 } 6547 6548 egr_nh_info.entry_type = 6549 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh_entry, ENTRY_TYPEf); 6550 if (vxlan_port->flags & BCM_VXLAN_PORT_LOOPBACK) { 6551 /* Loopback VP is only support when VXLAN RIOT is enabled */ 6552 if ((egr_nh_info.entry_type != 6553 _BCM_VXLAN_EGR_NEXT_HOP_L3_VIEW) && 6554 (egr_nh_info.entry_type != 6555 _BCM_VXLAN_EGR_NEXT_HOP_L3MC_VIEW) && 6556 (egr_nh_info.entry_type != 6557 _BCM_VXLAN_EGR_NEXT_HOP_IFP_ACTION_VIEW)) { 6558 if (vp_nh_ecmp_index != -1) { 6559 /* Decrement reference count */ 6560 (void)bcm_xgs3_get_ref_count_from_nhi 6561 (unit, mpath_flag, &ref_count, 6562 vp_nh_ecmp_index); 6563 } 6564 return BCM_E_PARAM; 6565 } 6566 6567 new_entry_type = _BCM_VXLAN_EGR_NEXT_HOP_IFP_ACTION_VIEW; 6568 } else { 6569 if ((egr_nh_info.entry_type != 6570 _BCM_VXLAN_EGR_NEXT_HOP_L3_VIEW) && 6571 (egr_nh_info.entry_type != 6572 _BCM_VXLAN_EGR_NEXT_HOP_L3MC_VIEW)) { 6573 if (vp_nh_ecmp_index != -1) { 6574 /* Decrement reference count */ 6575 (void)bcm_xgs3_get_ref_count_from_nhi 6576 (unit, mpath_flag, &ref_count, 6577 vp_nh_ecmp_index); 6578 } 6579 return BCM_E_PARAM; 6580 } 6581 6582 new_entry_type = egr_nh_info.entry_type; 6583 } 6584 6585 /* Program software DVP to NHI/ECMP */ 6586 rv = bcmi_gh2_vxlan_ingress_dvp_set(unit, vp, mpath_flag, 6587 vp_nh_ecmp_index, vxlan_port); 6588 if (BCM_FAILURE(rv)) { 6589 if (vp_nh_ecmp_index != -1) { 6590 /* Decrement reference count */ 6591 (void)bcm_xgs3_get_ref_count_from_nhi 6592 (unit, mpath_flag, &ref_count, 6593 vp_nh_ecmp_index); 6594 } 6595 return rv; 6596 } 6597 6598 /* Configure EGR Next Hop entry - Normal or L3MC view */ 6599 rv = bcmi_gh2_vxlan_nexthop_entry_modify(unit, vp_nh_ecmp_index, 6600 &egr_nh_info, new_entry_type); 6601 if (BCM_FAILURE(rv)) { 6602 if (vp_nh_ecmp_index != -1) { 6603 /* Decrement reference count */ 6604 (void)bcm_xgs3_get_ref_count_from_nhi 6605 (unit, mpath_flag, &ref_count, 6606 vp_nh_ecmp_index); 6607 } 6608 return rv; 6609 } 6610 } 6611 6612 return rv; 6613 } 6614 6615 /* 6616 * Function: 6617 * bcmi_gh2_vxlan_port_nh_delete 6618 * Purpose: 6619 * Delete VXLAN Next Hop entry 6620 * Parameters: 6621 * unit - (IN) Device Number 6622 * vpn - (IN) VPN instance ID 6623 * vp - (IN) vxlan virtual port 6624 * Returns: 6625 * BCM_E_XXX 6626 */ 6627 STATIC int 6628 bcmi_gh2_vxlan_port_nh_delete(int unit, bcm_vpn_t vpn, int vp) 6629 { 6630 uint32 flags = 0; 6631 int ref_count = 0; 6632 uint32 vp_type = 0; 6633 int ecmp = -1; 6634 int nh_ecmp_index = -1; 6635 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 6636 gh2_vxlan_vp_info_t *vp_info; 6637 6638 /* Get VXLAN bookkeeping info instance */ 6639 BCM_IF_ERROR_RETURN( 6640 gh2_vxlan_bk_info_instance_get(unit, &vxlan_info)); 6641 6642 /* GH2 requires to retrieve vp to ecmp or nhi from software database */ 6643 vp_info = &(vxlan_info->vxlan_vp_info[vp]); 6644 vp_type = vp_info->vp_type; 6645 ecmp = vp_info->ecmp; 6646 nh_ecmp_index = vp_info->nh_ecmp_index; 6647 6648 if (ecmp) { 6649 flags = BCM_L3_MULTIPATH; 6650 /* Decrease reference count */ 6651 BCM_IF_ERROR_RETURN( 6652 bcm_xgs3_get_ref_count_from_nhi(unit, flags, 6653 &ref_count, nh_ecmp_index)); 6654 if (ref_count == 1) { 6655 if (vp_type == GH2_VXLAN_DEST_VP_TYPE_TUNNEL) { 6656 /* support ecmp on network port only */ 6657 BCM_IF_ERROR_RETURN( 6658 bcmi_gh2_vxlan_ecmp_port_egress_nexthop_reset 6659 (unit, (nh_ecmp_index + BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit)), 6660 vp_type, vp, vpn)); 6661 } 6662 } 6663 } else { 6664 if (nh_ecmp_index != 0) { 6665 /* Decrease reference count */ 6666 BCM_IF_ERROR_RETURN( 6667 bcm_xgs3_get_ref_count_from_nhi(unit, flags, 6668 &ref_count, nh_ecmp_index)); 6669 } 6670 6671 if (ref_count == 1) { 6672 if (nh_ecmp_index) { 6673 BCM_IF_ERROR_RETURN( 6674 bcmi_gh2_vxlan_port_egress_nexthop_reset 6675 (unit, nh_ecmp_index, vp_type, vp, vpn)); 6676 } 6677 } else if (ref_count == 2) { 6678 /* 6679 * Need to check if the NHI is used for ECMP group only when 6680 * (ref_count == 2), if TRUE, we must reset VXLAN Egress NextHop. 6681 */ 6682 if (nh_ecmp_index) { 6683 BCM_IF_ERROR_RETURN( 6684 bcm_esw_l3_egress_ecmp_traverse 6685 (unit, bcmi_gh2_vxlan_nexthop_ecmp_find, 6686 (void *)&nh_ecmp_index)); 6687 } 6688 } 6689 } 6690 6691 /* Decrement VXLAN outer TPID ref count */ 6692 if (vp_info->tpid_valid) { 6693 BCM_IF_ERROR_RETURN( 6694 bcmi_gh2_vxlan_outer_tpid_ref_dec(unit, vp_info->tpid_value)); 6695 } 6696 6697 /* Clear software database for vp_info */ 6698 vp_info->vp_type = GH2_VXLAN_DEST_VP_TYPE_INVALID; 6699 vp_info->vfi = -1; 6700 vp_info->ecmp = 0; 6701 vp_info->nh_ecmp_index = 0; 6702 vp_info->tpid_valid= 0; 6703 vp_info->tpid_value = 0x0; 6704 6705 return BCM_E_NONE; 6706 } 6707 6708 /* 6709 * Function: 6710 * bcmi_gh2_vxlan_port_nh_get 6711 * Purpose: 6712 * Get VXLAN Next Hop entry 6713 * Parameters: 6714 * unit - (IN) Device Number 6715 * vpn - (IN) VPN instance ID 6716 * vp - (IN) vxlan virtual port 6717 * vxlan_port - (IN/OUT) vxlan_port information 6718 * Returns: 6719 * BCM_E_XXX 6720 */ 6721 STATIC int 6722 bcmi_gh2_vxlan_port_nh_get( 6723 int unit, 6724 bcm_vpn_t vpn, 6725 int vp, 6726 bcm_vxlan_port_t *vxlan_port) 6727 { 6728 int nh_ecmp_index = 0, tunnel_index = 0, udp_src_port_range_enable = 0; 6729 uint32 ecmp = 0; 6730 uint32 entry_type; 6731 egr_l3_next_hop_entry_t egr_nh_entry; 6732 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 6733 gh2_vxlan_vp_info_t *vp_info; 6734 6735 /* Input parameter check */ 6736 if (NULL == vxlan_port) { 6737 return BCM_E_PARAM; 6738 } 6739 6740 /* Get VXLAN bookkeeping info instance */ 6741 BCM_IF_ERROR_RETURN( 6742 gh2_vxlan_bk_info_instance_get(unit, &vxlan_info)); 6743 6744 /* Clear egr_nh_entry */ 6745 sal_memset(&egr_nh_entry, 0, sizeof(egr_nh_entry)); 6746 6747 /* Get SW VP info */ 6748 vp_info = &(vxlan_info->vxlan_vp_info[vp]); 6749 6750 if (vp_info->vp_type == GH2_VXLAN_DEST_VP_TYPE_TUNNEL) { 6751 /* Egress into VXLAN tunnel, find the tunnel_if */ 6752 vxlan_port->flags |= BCM_VXLAN_PORT_EGRESS_TUNNEL; 6753 6754 ecmp = vp_info->ecmp; 6755 nh_ecmp_index = vp_info->nh_ecmp_index; 6756 if (ecmp) { 6757 /* Extract next hop index from multipath egress object */ 6758 vxlan_port->egress_if = 6759 (nh_ecmp_index + BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit)); 6760 6761 /* Get ecmp's first member nexthop index */ 6762 BCM_IF_ERROR_RETURN( 6763 bcmi_gh2_vxlan_ecmp_member_egress_get_first 6764 (unit, vxlan_port->egress_if, &nh_ecmp_index)); 6765 } else { 6766 /* Extract next hop index from unipath egress object */ 6767 vxlan_port->egress_if = 6768 (nh_ecmp_index + BCM_XGS3_EGRESS_IDX_MIN(unit)); 6769 } 6770 6771 BCM_IF_ERROR_RETURN( 6772 soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 6773 nh_ecmp_index, &egr_nh_entry)); 6774 6775 } else if (vp_info->vp_type == GH2_VXLAN_DEST_VP_TYPE_ACCESS) { 6776 /* Egress into Access-side, find the tunnel_if */ 6777 nh_ecmp_index = vp_info->nh_ecmp_index; 6778 6779 /* Extract next hop index from unipath egress object. */ 6780 vxlan_port->egress_if = 6781 (nh_ecmp_index + BCM_XGS3_EGRESS_IDX_MIN(unit)); 6782 6783 BCM_IF_ERROR_RETURN( 6784 soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 6785 nh_ecmp_index, &egr_nh_entry)); 6786 } else { 6787 return BCM_E_NOT_FOUND; 6788 } 6789 6790 entry_type = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh_entry, 6791 ENTRY_TYPEf); 6792 if (entry_type == _BCM_VXLAN_EGR_NEXT_HOP_VXLAN_VIEW) { 6793 /* Get Tunnel index */ 6794 tunnel_index = 6795 soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, 6796 &egr_nh_entry, VXLAN__TUNNEL_INDEXf); 6797 6798 BCM_IF_ERROR_RETURN( 6799 bcmi_gh2_vxlan_egress_tunnel_get(unit, vxlan_port, tunnel_index)); 6800 6801 /* Get UDP source port range checking for Entropy */ 6802 udp_src_port_range_enable = 6803 soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, 6804 &egr_nh_entry, VXLAN__UDP_SRC_PORT_RANGE_ENf); 6805 if (udp_src_port_range_enable) { 6806 vxlan_port->flags |= BCM_VXLAN_PORT_UDP_SRC_PORT_RANGE_ENABLE; 6807 } 6808 } 6809 6810 if (vp_info->vp_type == GH2_VXLAN_DEST_VP_TYPE_TUNNEL) { 6811 /* Must be BCM_VXLAN_PORT_ENCAP_LOCAL for GH2 */ 6812 vxlan_port->flags |= BCM_VXLAN_PORT_ENCAP_LOCAL; 6813 } 6814 6815 /* Get VXLAN vlan tag info */ 6816 (void)bcmi_gh2_vxlan_vlan_tag_get(unit, vxlan_port, 6817 &egr_nh_entry, nh_ecmp_index); 6818 6819 return BCM_E_NONE; 6820 } 6821 6822 /* 6823 * Function: 6824 * bcmi_gh2_vxlan_port_untagged_profile_set 6825 * Purpose: 6826 * Set VLan profile per Physical port entry 6827 * Parameters: 6828 * unit - (IN) Device Number 6829 * port - (IN) Physical port 6830 * Returns: 6831 * BCM_E_XXX 6832 */ 6833 STATIC int 6834 bcmi_gh2_vxlan_port_untagged_profile_set(int unit, bcm_port_t port) 6835 { 6836 int rv = BCM_E_NONE; 6837 bcm_vlan_action_set_t action; 6838 uint32 ing_profile_idx = 0xffffffff; 6839 6840 bcm_vlan_action_set_t_init(&action); 6841 action.ut_outer = 0x0; /* No Op */ 6842 action.ut_inner = 0x0; /* No Op */ 6843 6844 rv = _bcm_trx_vlan_action_profile_entry_add(unit, &action, 6845 &ing_profile_idx); 6846 if (BCM_FAILURE(rv)) { 6847 return rv; 6848 } 6849 6850 rv = _bcm_esw_port_tab_set(unit, port, _BCM_CPU_TABS_NONE, 6851 TAG_ACTION_PROFILE_PTRf, ing_profile_idx); 6852 6853 return rv; 6854 } 6855 6856 /* 6857 * Function: 6858 * bcmi_gh2_vxlan_port_untagged_profile_reset 6859 * Purpose: 6860 * Reset VLan profile per Physical port entry 6861 * Parameters: 6862 * unit - (IN) Device Number 6863 * port - (IN) Physical port 6864 * Returns: 6865 * BCM_E_XXX 6866 */ 6867 STATIC int 6868 bcmi_gh2_vxlan_port_untagged_profile_reset(int unit, bcm_port_t port) 6869 { 6870 int rv = BCM_E_NONE; 6871 int ing_profile_idx = -1; 6872 6873 BCM_IF_ERROR_RETURN( 6874 _bcm_esw_port_tab_get(unit, port, TAG_ACTION_PROFILE_PTRf, 6875 &ing_profile_idx)); 6876 6877 rv = _bcm_trx_vlan_action_profile_entry_delete(unit, ing_profile_idx); 6878 if (BCM_FAILURE(rv)) { 6879 return rv; 6880 } 6881 6882 rv = _bcm_esw_port_tab_set(unit, port, _BCM_CPU_TABS_NONE, 6883 TAG_ACTION_PROFILE_PTRf, 0); 6884 6885 return rv; 6886 } 6887 6888 /* 6889 * Function: 6890 * bcmi_gh2_vxlan_match_vxlate_entry_set 6891 * Purpose: 6892 * Set VXLAN Match Vxlate Entry 6893 * Parameters: 6894 * unit - (IN) Device Number 6895 * vpn - (IN) VPN instance ID 6896 * vxlan_port - (IN/OUT) vxlan_port information (OUT : vxlan_port_id) 6897 * vent - (IN) vlan xlate entry pointer 6898 * Returns: 6899 * BCM_E_XXX 6900 */ 6901 STATIC int 6902 bcmi_gh2_vxlan_match_vxlate_entry_set( 6903 int unit, 6904 bcm_vpn_t vpn, 6905 bcm_vxlan_port_t *vxlan_port, 6906 uint32 *vent) 6907 { 6908 int rv = BCM_E_NONE; 6909 int index = -1, added_index = -1; 6910 soc_mem_t mem; 6911 uint32 return_vent[SOC_MAX_MEM_WORDS]; 6912 int vfi = 0; 6913 6914 mem = VLAN_XLATEm; 6915 6916 soc_mem_field32_set(unit, mem, vent, VALIDf, 0x1); 6917 soc_mem_field32_set(unit, mem, vent, XLATE__MPLS_ACTIONf, 0x5); /* VFI */ 6918 soc_mem_field32_set(unit, mem, vent, XLATE__VFI_VALIDf, 0x1); 6919 if (!(vxlan_port->flags & BCM_VXLAN_PORT_ENABLE_VLAN_CHECKS)) { 6920 soc_mem_field32_set(unit, mem, vent, XLATE__DISABLE_VLAN_CHECKSf, 0x1); 6921 } 6922 6923 _BCM_VXLAN_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, vpn); 6924 soc_mem_field32_set(unit, mem, vent, XLATE__VFIf, vfi); 6925 6926 rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, 6927 &index, vent, return_vent, 0); 6928 if (BCM_SUCCESS(rv)) { 6929 /* Existing VLAN_XLATE entry is found */ 6930 BCM_IF_ERROR_RETURN( 6931 soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, vent)); 6932 6933 if (!(vxlan_port->flags & BCM_VXLAN_PORT_REPLACE)) { 6934 added_index = index; 6935 } 6936 } else if (rv == BCM_E_NOT_FOUND) { 6937 /* New VLAN_XLATE entry to be inserted */ 6938 if (vxlan_port->flags & BCM_VXLAN_PORT_REPLACE) { 6939 return BCM_E_NOT_FOUND; 6940 } 6941 BCM_IF_ERROR_RETURN( 6942 soc_mem_insert(unit, mem, MEM_BLOCK_ALL, vent)); 6943 6944 /* Search inserted VLAN_XLATE entry index */ 6945 rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, 6946 &index, vent, return_vent, 0); 6947 added_index = index; 6948 } else { 6949 return rv; 6950 } 6951 6952 /* Increase ref_cnt for the specified VXLAN Vlan XLATE entry */ 6953 if (added_index != -1) { 6954 BCM_IF_ERROR_RETURN( 6955 bcmi_gh2_vxlan_vlan_xlate_ref_inc(unit, added_index)); 6956 } 6957 6958 return BCM_E_NONE; 6959 } 6960 6961 /* 6962 * Function: 6963 * bcmi_gh2_vxlan_match_vxlate_entry_reset 6964 * Purpose: 6965 * Reset VXLAN Match Vxlate Entry 6966 * Parameters: 6967 * unit - (IN) Device Number 6968 * vpn - (IN) VPN instance ID 6969 * vxlan_port - (IN/OUT) vxlan_port information (OUT : vxlan_port_id) 6970 * vent - (IN) vlan xlate entry pointer 6971 * Returns: 6972 * BCM_E_XXX 6973 */ 6974 STATIC int 6975 bcmi_gh2_vxlan_match_vxlate_entry_reset( 6976 int unit, 6977 uint32 *vent) 6978 { 6979 int rv = BCM_E_NONE; 6980 int index = -1, deleted_index = -1; 6981 soc_mem_t mem; 6982 uint32 return_vent[SOC_MAX_MEM_WORDS]; 6983 int ref_cnt = 0; 6984 6985 mem = VLAN_XLATEm; 6986 6987 soc_mem_field32_set(unit, mem, vent, VALIDf, 0x1); 6988 rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, 6989 &index, vent, return_vent, 0); 6990 if (BCM_SUCCESS(rv)) { 6991 /* Existing VLAN_XLATE entry is found */ 6992 deleted_index = index; 6993 } else { 6994 return rv; 6995 } 6996 6997 /* Decrease ref_cnt for the specified VXLAN Vlan XLATE entry */ 6998 if (deleted_index != -1) { 6999 BCM_IF_ERROR_RETURN( 7000 bcmi_gh2_vxlan_vlan_xlate_ref_dec(unit, deleted_index, &ref_cnt)); 7001 7002 if (ref_cnt == 0) { 7003 BCM_IF_ERROR_RETURN( 7004 soc_mem_delete(unit, mem, MEM_BLOCK_ALL, vent)); 7005 } 7006 } 7007 7008 return rv; 7009 } 7010 7011 /* 7012 * Function: 7013 * bcmi_gh2_vxlan_trunk_table_set 7014 * Purpose: 7015 * Configure VXLAN Trunk port entry 7016 * Parameters: 7017 * unit - (IN) Device Number 7018 * port - (IN) Trunk member port 7019 * tgid - (IN) Trunk group Id 7020 * vpn - (IN) VPN instance ID 7021 * Returns: 7022 * BCM_E_XXX 7023 */ 7024 STATIC int 7025 bcmi_gh2_vxlan_trunk_table_set( 7026 int unit, 7027 bcm_port_t port, 7028 bcm_trunk_t tgid, 7029 bcm_vpn_t vpn) 7030 { 7031 int rv = BCM_E_NONE; 7032 source_trunk_map_table_entry_t trunk_map_entry; 7033 bcm_module_t my_modid; 7034 int src_trk_idx = -1; 7035 int port_type; 7036 int vfi = 0; 7037 7038 if (tgid != BCM_TRUNK_INVALID) { 7039 port_type = 1; /* TRUNK_PORT_TYPE */ 7040 } else { 7041 return BCM_E_PARAM; 7042 } 7043 7044 if (vpn != BCM_VXLAN_VPN_INVALID) { 7045 _BCM_VXLAN_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, vpn); 7046 if (!bcmi_gh2_vxlan_vfi_used_get(unit, vfi)) { 7047 return BCM_E_NOT_FOUND; 7048 } 7049 } else { 7050 return BCM_E_PARAM; 7051 } 7052 7053 /* Get module id for unit */ 7054 BCM_IF_ERROR_RETURN( 7055 bcm_esw_stk_my_modid_get(unit, &my_modid)); 7056 7057 /* Get index to source trunk map table */ 7058 BCM_IF_ERROR_RETURN( 7059 _bcm_esw_src_mod_port_table_index_get(unit, my_modid, 7060 port, &src_trk_idx)); 7061 7062 soc_mem_lock(unit, SOURCE_TRUNK_MAP_TABLEm); 7063 7064 /* Read source trunk map table */ 7065 rv = soc_mem_read(unit, SOURCE_TRUNK_MAP_TABLEm, MEM_BLOCK_ANY, 7066 src_trk_idx, &trunk_map_entry); 7067 if (BCM_FAILURE(rv)) { 7068 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 7069 return rv; 7070 } 7071 7072 /* Set trunk group id */ 7073 soc_mem_field32_set(unit, SOURCE_TRUNK_MAP_TABLEm, &trunk_map_entry, 7074 TGIDf, tgid); 7075 7076 /* Set port is part of Trunk group */ 7077 soc_mem_field32_set(unit, SOURCE_TRUNK_MAP_TABLEm, &trunk_map_entry, 7078 PORT_TYPEf, port_type); 7079 7080 /* Set vfi to provide default VFI (for untag & ptag packets) */ 7081 soc_mem_field32_set(unit, SOURCE_TRUNK_MAP_TABLEm, &trunk_map_entry, 7082 VFIf, vfi); 7083 7084 /* Disable VLAN check for SOURCE_TRUNK_MAP_TABLEm */ 7085 soc_mem_field32_set(unit, SOURCE_TRUNK_MAP_TABLEm, &trunk_map_entry, 7086 DISABLE_VLAN_CHECKSf, 1); 7087 7088 /* Write entry to hw. */ 7089 rv = soc_mem_write(unit, SOURCE_TRUNK_MAP_TABLEm, MEM_BLOCK_ALL, 7090 src_trk_idx, &trunk_map_entry); 7091 7092 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 7093 7094 return rv; 7095 } 7096 7097 7098 /* 7099 * Function: 7100 * bcmi_gh2_vxlan_trunk_table_reset 7101 * Purpose: 7102 * Reset VXLAN Trunk port entry 7103 * Parameters: 7104 * unit - (IN) Device Number 7105 * port - (IN) Trunk member port 7106 * Returns: 7107 * BCM_E_XXX 7108 */ 7109 7110 STATIC int 7111 bcmi_gh2_vxlan_trunk_table_reset(int unit, bcm_port_t port) 7112 { 7113 int rv = BCM_E_NONE; 7114 source_trunk_map_table_entry_t trunk_map_entry; 7115 bcm_module_t my_modid; 7116 int src_trk_idx = -1; 7117 7118 /* Get module id for unit. */ 7119 BCM_IF_ERROR_RETURN( 7120 bcm_esw_stk_my_modid_get(unit, &my_modid)); 7121 7122 /* Get index to source trunk map table */ 7123 BCM_IF_ERROR_RETURN( 7124 _bcm_esw_src_mod_port_table_index_get(unit, my_modid, 7125 port, &src_trk_idx)); 7126 7127 soc_mem_lock(unit, SOURCE_TRUNK_MAP_TABLEm); 7128 7129 /* Read source trunk map table */ 7130 rv = soc_mem_read(unit, SOURCE_TRUNK_MAP_TABLEm, MEM_BLOCK_ANY, 7131 src_trk_idx, &trunk_map_entry); 7132 if (BCM_FAILURE(rv)) { 7133 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 7134 return rv; 7135 } 7136 7137 /* Set vfi */ 7138 soc_mem_field32_set(unit, SOURCE_TRUNK_MAP_TABLEm, &trunk_map_entry, 7139 VFIf, 0); 7140 7141 soc_mem_field32_set(unit, SOURCE_TRUNK_MAP_TABLEm, &trunk_map_entry, 7142 DISABLE_VLAN_CHECKSf, 0); 7143 7144 /* Write entry to hw */ 7145 rv = soc_mem_write(unit, SOURCE_TRUNK_MAP_TABLEm, MEM_BLOCK_ALL, 7146 src_trk_idx, &trunk_map_entry); 7147 7148 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 7149 7150 return rv; 7151 } 7152 7153 /* 7154 * Function: 7155 * bcmi_gh2_vxlan_trunk_member_delete 7156 * Purpose: 7157 * Clear Trunk Port-membership when the members to be deleted. 7158 * Parameters: 7159 * unit - (IN) Device Number 7160 * tgid - (IN) Trunk Group ID 7161 * trunk_member_count - (IN) Count of Trunk members to be deleted 7162 * trunk_member_array - (IN) Trunk member gports to be deleted 7163 */ 7164 int 7165 bcmi_gh2_vxlan_trunk_member_delete( 7166 int unit, 7167 bcm_trunk_t trunk_id, 7168 int trunk_member_count, 7169 bcm_port_t *trunk_member_array) 7170 { 7171 int rv = BCM_E_NONE, rv2 = BCM_E_NONE; 7172 int idx = 0; 7173 int value; 7174 bcm_port_t local_member; 7175 7176 if (NULL == trunk_member_array) { 7177 return BCM_E_PARAM; 7178 } 7179 7180 rv = _bcm_trunk_id_validate(unit, trunk_id); 7181 if (BCM_FAILURE(rv)) { 7182 return BCM_E_PORT; 7183 } 7184 7185 for (idx = 0; idx < trunk_member_count; idx++) { 7186 rv2 = bcm_esw_port_local_get(unit, trunk_member_array[idx], 7187 &local_member); 7188 /* Only support trunk local ports for trunk match */ 7189 if (BCM_FAILURE(rv2)) { 7190 continue; 7191 } 7192 (void)_bcm_esw_port_tab_get(unit, local_member, 7193 PORT_OPERATIONf, &value); 7194 if (value == GH2_VXLAN_PORT_OPERATION_VFI) { 7195 (void)_bcm_esw_port_tab_set(unit, local_member, 7196 _BCM_CPU_TABS_NONE, PORT_OPERATIONf, 7197 GH2_VXLAN_PORT_OPERATION_NORMAL); 7198 BCM_IF_ERROR_RETURN( 7199 bcmi_gh2_vxlan_trunk_table_reset(unit, local_member)); 7200 } 7201 } 7202 7203 return rv; 7204 } 7205 7206 /* 7207 * Function: 7208 * bcmi_gh2_vxlan_riot_custom_header_add 7209 * Purpose: 7210 * Add Custom Header entry for 2-Pass VXLAN RIOT support. 7211 * Parameters: 7212 * unit - (IN) Device Number 7213 * vxlan_port - (IN) vxlan_port information 7214 * old_vxlan_port - (IN) old vxlan_port information (for replace) 7215 * vp - (IN) Source Virtual Port 7216 * Returns: 7217 * BCM_X_XXX 7218 */ 7219 STATIC int 7220 bcmi_gh2_vxlan_riot_custom_header_add( 7221 int unit, 7222 bcm_vxlan_port_t *vxlan_port, 7223 bcm_vxlan_port_t *old_vxlan_port, 7224 int vp) 7225 { 7226 int rv = BCM_E_NONE; 7227 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 7228 gh2_vxlan_vp_info_t *vp_info; 7229 bcm_switch_match_control_info_t match_control_info; 7230 bcm_switch_encap_info_t encap_info; 7231 bcm_module_t mod_out = -1; 7232 bcm_port_t port_out = -1; 7233 bcm_trunk_t trunk_id = -1; 7234 int gport_id = -1; 7235 int local_port_out[SOC_MAX_NUM_PORTS]; 7236 int local_member_count = 0; 7237 int port_idx = 0; 7238 bcm_if_t encap_id; 7239 int index_array[2]; 7240 bcm_module_t lmodid; 7241 int egr_gpp_index = 0; 7242 egr_gpp_attributes_entry_t egr_gpp_entry; 7243 int i; 7244 int is_ipmc; 7245 int match_id_ipmc, match_id_non_ipmc; 7246 int *match_id_ptr; 7247 bcm_switch_match_config_info_t match_info; 7248 bcm_switch_match_service_t match_service; 7249 uint32 match_id_hw; 7250 custom_header_policy_table_entry_t policy_entry; 7251 int mode = 0; 7252 int qos_map_ptr = 0; 7253 7254 /* Input parameter check */ 7255 if ((NULL == vxlan_port) || (NULL == old_vxlan_port)) { 7256 return BCM_E_PARAM; 7257 } 7258 7259 /* Get VXLAN bookkeeping info instance */ 7260 BCM_IF_ERROR_RETURN( 7261 gh2_vxlan_bk_info_instance_get(unit, &vxlan_info)); 7262 7263 if (vxlan_port->flags & BCM_VXLAN_PORT_REPLACE) { 7264 /* Delete old VP related Custom Header configurations */ 7265 BCM_IF_ERROR_RETURN( 7266 bcmi_gh2_vxlan_riot_custom_header_delete(unit, 7267 old_vxlan_port, vp)); 7268 } 7269 7270 /* 7271 * Set Custom Header match mask value (global) when 7272 * VXLAN RIOT enabled (for GH2-B0 only) 7273 */ 7274 if (vxlan_port->flags & BCM_VXLAN_PORT_LOOPBACK) { 7275 /* Get current Custom Header match mask value (global) */ 7276 bcm_switch_match_control_info_t_init(&match_control_info); 7277 7278 BCM_IF_ERROR_RETURN( 7279 bcm_esw_switch_match_control_get( 7280 unit, bcmSwitchMatchServiceCustomHeader, 7281 bcmSwitchMatchControlMatchMask, 7282 0, &match_control_info)); 7283 7284 if (match_control_info.mask32 != GH2_VXLAN_RIOT_CH_HEADER_MASK) { 7285 bcm_switch_match_control_info_t_init(&match_control_info); 7286 match_control_info.mask32 = GH2_VXLAN_RIOT_CH_HEADER_MASK; 7287 7288 BCM_IF_ERROR_RETURN( 7289 bcm_esw_switch_match_control_set( 7290 unit, bcmSwitchMatchServiceCustomHeader, 7291 bcmSwitchMatchControlMatchMask, 7292 0, &match_control_info)); 7293 } 7294 } else { 7295 /* 7296 * Create one dummy Custom Header encap entry with index = 0 : 7297 * - the Custom Header index could not be 0 when using 7298 * the EGR_GPP_ATTRIBUTES 7299 */ 7300 index_array[0] = 0; /* hw index = 0 */ 7301 BCM_IF_ERROR_RETURN( 7302 _bcm_hr3_switch_encap_idx2id(unit, 7303 _BCM_SWITCH_ENCAP_TYPE_CUSTOM_HEADER, 7304 1, index_array, &encap_id)); 7305 7306 bcm_switch_encap_info_t_init(&encap_info); 7307 BCM_IF_ERROR_RETURN( 7308 bcm_esw_switch_encap_get(unit, encap_id, &encap_info)); 7309 7310 if (encap_info.value32 == 0) { 7311 bcm_switch_encap_info_t_init(&encap_info); 7312 encap_info.encap_service = BCM_SWITCH_ENCAP_SERVICE_CUSTOM_HEADER; 7313 encap_info.value32 = GH2_VXLAN_RIOT_CH_HEADER_MASK; 7314 BCM_IF_ERROR_RETURN( 7315 bcm_esw_switch_encap_create(unit, &encap_info, &encap_id)); 7316 7317 vxlan_info->riot_custom_header_index0_ref_count++; 7318 } else if (encap_info.value32 == GH2_VXLAN_RIOT_CH_HEADER_MASK) { 7319 vxlan_info->riot_custom_header_index0_ref_count++; 7320 } 7321 } 7322 7323 /* 7324 * For all VXLAN RIOT flow support (loopback, access or network ports), 7325 * we must use vxlan_port->match_port for Custom Header related 7326 * configurations 7327 */ 7328 BCM_IF_ERROR_RETURN( 7329 _bcm_esw_gport_resolve(unit, vxlan_port->match_port, &mod_out, 7330 &port_out, &trunk_id, &gport_id)); 7331 7332 sal_memset(local_port_out, 0, sizeof(local_port_out)); 7333 if (BCM_GPORT_IS_TRUNK(vxlan_port->match_port)) { 7334 /* Trunk port */ 7335 BCM_IF_ERROR_RETURN( 7336 _bcm_esw_trunk_local_members_get(unit, trunk_id, 7337 SOC_MAX_NUM_PORTS, 7338 local_port_out, 7339 &local_member_count)); 7340 7341 if ((vxlan_port->criteria == BCM_VXLAN_PORT_MATCH_NONE) || 7342 (vxlan_port->criteria == BCM_VXLAN_PORT_MATCH_VN_ID)) { 7343 vxlan_info->match_key[vp].trunk_id = trunk_id; 7344 vxlan_info->match_key[vp].modid = -1; 7345 } 7346 } else { 7347 /* Local port */ 7348 local_port_out[0] = port_out; 7349 local_member_count++; 7350 7351 if ((vxlan_port->criteria == BCM_VXLAN_PORT_MATCH_NONE) || 7352 (vxlan_port->criteria == BCM_VXLAN_PORT_MATCH_VN_ID)) { 7353 vxlan_info->match_key[vp].port = port_out; 7354 vxlan_info->match_key[vp].modid = mod_out; 7355 vxlan_info->match_key[vp].trunk_id = -1; 7356 } 7357 } 7358 7359 /* Get current MY_MODID */ 7360 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &lmodid)); 7361 7362 vp_info = &(vxlan_info->vxlan_vp_info[vp]); 7363 for (port_idx = 0; port_idx < local_member_count; port_idx++) { 7364 if (vxlan_port->flags & BCM_VXLAN_PORT_LOOPBACK) { 7365 /* 7366 * For Loopback Ports: 7367 * - Enable Custom Header match/encap on loopbcak port 7368 */ 7369 7370 /* Enable the capability of Custom Header match detection */ 7371 bcm_switch_match_control_info_t_init(&match_control_info); 7372 match_control_info.port_enable = TRUE; 7373 BCM_IF_ERROR_RETURN( 7374 bcm_esw_switch_match_control_set( 7375 unit, bcmSwitchMatchServiceCustomHeader, 7376 bcmSwitchMatchControlPortEnable, 7377 local_port_out[port_idx], &match_control_info)); 7378 7379 /* Enable the capability of Custom Header encapsulation */ 7380 BCM_IF_ERROR_RETURN( 7381 bcm_esw_port_control_set( 7382 unit, local_port_out[port_idx], 7383 bcmPortControlCustomHeaderEncapEnable, TRUE)); 7384 } else { 7385 /* 7386 * For Access or Network Ports: 7387 * - Prepare Custom Header encap, match and policy entries: 7388 * Encap - 1 entry per access/network port 7389 * Match and Policy - 2 entries for each table 7390 */ 7391 7392 /* Encap: Create one Custom Header encap */ 7393 bcm_switch_encap_info_t_init(&encap_info); 7394 encap_info.encap_service = BCM_SWITCH_ENCAP_SERVICE_CUSTOM_HEADER; 7395 encap_info.value32 = 7396 GH2_VXLAN_RIOT_CH_ENCAP_VALUE(0, lmodid, 7397 local_port_out[port_idx]); 7398 rv = bcm_esw_switch_encap_create(unit, &encap_info, &encap_id); 7399 if (BCM_SUCCESS(rv) || rv == BCM_E_EXISTS) { 7400 if ((encap_id >> _BCM_SWITCH_ENCAP_SHIFT) == 7401 _BCM_SWITCH_ENCAP_TYPE_CUSTOM_HEADER) { 7402 BCM_IF_ERROR_RETURN( 7403 _bcm_hr3_switch_encap_id2idx(unit, encap_id, 1, 7404 index_array)); 7405 } else { 7406 return BCM_E_INTERNAL; 7407 } 7408 7409 if (rv == BCM_E_EXISTS) { 7410 /* Increase ref_cnt */ 7411 _bcm_common_profile_mem_ref_cnt_update 7412 (unit, EGR_HEADER_ENCAP_DATAm, index_array[0], 1); 7413 } 7414 } else { 7415 return rv; 7416 } 7417 7418 /* Encap: Program EGR_GPP_ATTRIBUTES table with created encap_id */ 7419 /* 7420 * Assign Custom Header index using the EGR_GPP_ATTRIBUTES: 7421 * - egr_gpp_index = EGR_GPP_ATTRIBUTES_MODBASE[my_modid].BASE + 7422 * source tgid or egress port 7423 * - EGR_GPP_ATTRIBUTES[egr_gpp_index].CUSTOM_HEADER_INDEXf = 7424 * index_array[0] (Custom Header index) 7425 */ 7426 BCM_IF_ERROR_RETURN( 7427 _bcm_esw_src_mod_port_table_index_get(unit, lmodid, 7428 local_port_out[port_idx], 7429 &egr_gpp_index)); 7430 BCM_IF_ERROR_RETURN( 7431 READ_EGR_GPP_ATTRIBUTESm(unit, MEM_BLOCK_ANY, 7432 egr_gpp_index, &egr_gpp_entry)); 7433 soc_mem_field32_set(unit, EGR_GPP_ATTRIBUTESm, &egr_gpp_entry, 7434 CUSTOM_HEADER_INDEXf, (uint32)index_array[0]); 7435 BCM_IF_ERROR_RETURN( 7436 WRITE_EGR_GPP_ATTRIBUTESm(unit, MEM_BLOCK_ALL, 7437 egr_gpp_index, &egr_gpp_entry)); 7438 7439 vp_info->ch_encap_id = encap_id; 7440 7441 7442 /* QoS mapping: get current DSCP map mode on this port */ 7443 BCM_IF_ERROR_RETURN( 7444 bcm_esw_port_dscp_map_mode_get(unit, 7445 local_port_out[port_idx], 7446 &mode)); 7447 if (mode == BCM_PORT_DSCP_MAP_NONE) { 7448 BCM_IF_ERROR_RETURN(_bcm_esw_port_tab_set 7449 (unit, local_port_out[port_idx], _BCM_CPU_TABS_NONE, 7450 USE_CUSTOM_HEADER_FOR_PRIf, 7451 GH2_VXLAN_RIOT_CH_COS_REMAP_INT_PRI_MAP)); 7452 7453 BCM_IF_ERROR_RETURN( 7454 _bcm_esw_port_tab_get(unit, local_port_out[port_idx], 7455 TRUST_DOT1P_PTRf, &qos_map_ptr)); 7456 } else { 7457 /* trust incoming IPv4/IPv6 DSCP */ 7458 BCM_IF_ERROR_RETURN(_bcm_esw_port_tab_set 7459 (unit, local_port_out[port_idx], _BCM_CPU_TABS_NONE, 7460 USE_CUSTOM_HEADER_FOR_PRIf, 7461 GH2_VXLAN_RIOT_CH_COS_REMAP_DSCP_QOS_MAP)); 7462 7463 qos_map_ptr = local_port_out[port_idx]; 7464 } 7465 7466 /* Match and Policy: Setup two Custom Header match and policy */ 7467 for (i = 0; i < 2; i++) { 7468 is_ipmc = i; /* i = 0: non-IPMC, i = 1: IPMC */ 7469 7470 /* Setup Custom Header match */ 7471 match_id_ptr = (is_ipmc) ? &match_id_ipmc : &match_id_non_ipmc; 7472 7473 bcm_switch_match_config_info_t_init(&match_info); 7474 match_info.value32 = 7475 GH2_VXLAN_RIOT_CH_ENCAP_VALUE((is_ipmc) ? 1 : 0, lmodid, 7476 local_port_out[port_idx]); 7477 rv = bcm_esw_switch_match_config_add 7478 (unit, bcmSwitchMatchServiceCustomHeader, 7479 &match_info, match_id_ptr); 7480 if (BCM_SUCCESS(rv) || rv == BCM_E_EXISTS) { 7481 BCM_IF_ERROR_RETURN( 7482 bcmi_switch_match_hw_id_get( 7483 unit, *match_id_ptr, &match_service, 7484 &match_id_hw)); 7485 if (match_service != bcmSwitchMatchServiceCustomHeader) { 7486 return BCM_E_INTERNAL; 7487 } 7488 7489 if (rv == BCM_E_EXISTS) { 7490 /* Increase ref_cnt */ 7491 _bcm_common_profile_mem_ref_cnt_update 7492 (unit, CUSTOM_HEADER_MATCHm, (int)match_id_hw, 1); 7493 } 7494 } else { 7495 return rv; 7496 } 7497 7498 /* Setup Custom Header policy table */ 7499 sal_memset(&policy_entry, 0, sizeof(policy_entry)); 7500 7501 SOC_IF_ERROR_RETURN( 7502 soc_mem_read(unit, CUSTOM_HEADER_POLICY_TABLEm, 7503 MEM_BLOCK_ANY, match_id_hw, &policy_entry)); 7504 7505 soc_mem_field32_set(unit, CUSTOM_HEADER_POLICY_TABLEm, 7506 &policy_entry, VALIDf, 1); 7507 soc_mem_field32_set(unit, CUSTOM_HEADER_POLICY_TABLEm, 7508 &policy_entry, REPLACE_SGPPf, 1); 7509 soc_mem_field32_set(unit, CUSTOM_HEADER_POLICY_TABLEm, 7510 &policy_entry, VFI_INVALIDf, 7511 (is_ipmc) ? 1 : 0); 7512 7513 /* Setup Custom Header QoS mapping */ 7514 soc_mem_field32_set(unit, CUSTOM_HEADER_POLICY_TABLEm, 7515 &policy_entry, QOS_MAPPING_PTRf, 7516 qos_map_ptr); 7517 7518 SOC_IF_ERROR_RETURN( 7519 soc_mem_write(unit, CUSTOM_HEADER_POLICY_TABLEm, 7520 MEM_BLOCK_ALL, match_id_hw, &policy_entry)); 7521 } 7522 7523 vp_info->ch_match_id_ipmc = match_id_ipmc; 7524 vp_info->ch_match_id_non_ipmc = match_id_non_ipmc; 7525 } 7526 7527 } 7528 7529 return BCM_E_NONE; 7530 } 7531 7532 /* 7533 * Function: 7534 * bcmi_gh2_vxlan_riot_custom_header_delete 7535 * Purpose: 7536 * Delete Custom Header entry for 2-Pass VXLAN RIOT support. 7537 * Parameters: 7538 * unit - (IN) Device Number 7539 * vxlan_port - (IN) vxlan_port information 7540 * vp - (IN) Source Virtual Port 7541 * Returns: 7542 * BCM_X_XXX 7543 */ 7544 STATIC int 7545 bcmi_gh2_vxlan_riot_custom_header_delete( 7546 int unit, 7547 bcm_vxlan_port_t *vxlan_port, 7548 int vp) 7549 { 7550 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 7551 gh2_vxlan_vp_info_t *vp_info; 7552 _bcm_port_info_t *port_info; 7553 bcm_switch_match_control_info_t match_control_info; 7554 bcm_switch_encap_info_t encap_info; 7555 int index_array[2]; 7556 bcm_if_t encap_id; 7557 bcm_module_t mod_out = -1; 7558 bcm_port_t port_out = -1; 7559 bcm_trunk_t trunk_id = -1; 7560 int gport_id = -1; 7561 int local_port_out[SOC_MAX_NUM_PORTS]; 7562 int local_member_count = 0; 7563 int port_idx = 0; 7564 int i; 7565 int is_ipmc; 7566 int match_id_ptr; 7567 bcm_switch_match_service_t match_service; 7568 uint32 match_id_hw; 7569 custom_header_policy_table_entry_t policy_entry; 7570 bcm_module_t lmodid; 7571 int egr_gpp_index = 0; 7572 egr_gpp_attributes_entry_t egr_gpp_entry; 7573 int ref_count = 0; 7574 7575 /* Input parameter check */ 7576 if (NULL == vxlan_port) { 7577 return BCM_E_PARAM; 7578 } 7579 7580 /* Get VXLAN bookkeeping info instance */ 7581 BCM_IF_ERROR_RETURN( 7582 gh2_vxlan_bk_info_instance_get(unit, &vxlan_info)); 7583 7584 /* 7585 * Delete dummy Custom Header encap entry with index = 0 : 7586 * - the Custom Header index could not be 0 when using 7587 * the EGR_GPP_ATTRIBUTES 7588 */ 7589 if (!(vxlan_port->flags & BCM_VXLAN_PORT_LOOPBACK)) { 7590 index_array[0] = 0; /* hw index = 0 */ 7591 BCM_IF_ERROR_RETURN( 7592 _bcm_hr3_switch_encap_idx2id(unit, 7593 _BCM_SWITCH_ENCAP_TYPE_CUSTOM_HEADER, 7594 1, index_array, &encap_id)); 7595 7596 bcm_switch_encap_info_t_init(&encap_info); 7597 BCM_IF_ERROR_RETURN( 7598 bcm_esw_switch_encap_get(unit, encap_id, &encap_info)); 7599 7600 if (encap_info.value32 == GH2_VXLAN_RIOT_CH_HEADER_MASK) { 7601 if (vxlan_info->riot_custom_header_index0_ref_count >= 1) { 7602 vxlan_info->riot_custom_header_index0_ref_count--; 7603 } 7604 7605 if (vxlan_info->riot_custom_header_index0_ref_count == 0) { 7606 BCM_IF_ERROR_RETURN( 7607 bcm_esw_switch_encap_destroy(unit, encap_id)); 7608 } 7609 } 7610 } 7611 7612 BCM_IF_ERROR_RETURN( 7613 _bcm_esw_gport_resolve(unit, vxlan_port->match_port, &mod_out, 7614 &port_out, &trunk_id, &gport_id)); 7615 7616 sal_memset(local_port_out, 0, sizeof(local_port_out)); 7617 if (BCM_GPORT_IS_TRUNK(vxlan_port->match_port)) { 7618 /* Trunk port */ 7619 BCM_IF_ERROR_RETURN( 7620 _bcm_esw_trunk_local_members_get(unit, trunk_id, 7621 SOC_MAX_NUM_PORTS, 7622 local_port_out, 7623 &local_member_count)); 7624 } else { 7625 /* Local port */ 7626 local_port_out[0] = port_out; 7627 local_member_count++; 7628 } 7629 7630 vp_info = &(vxlan_info->vxlan_vp_info[vp]); 7631 for (port_idx = 0; port_idx < local_member_count; port_idx++) { 7632 /* Get current VP count on this local port */ 7633 _bcm_port_info_access(unit, local_port_out[port_idx], &port_info); 7634 7635 if (vxlan_port->flags & BCM_VXLAN_PORT_LOOPBACK) { 7636 /* 7637 * For Loopback Ports: 7638 * - Disable Custom Header match/encap when (vp_count == 1) 7639 * on loopbcak port 7640 */ 7641 if (port_info->vp_count == 1) { 7642 /* Disable the capability of Custom Header match detection */ 7643 bcm_switch_match_control_info_t_init(&match_control_info); 7644 match_control_info.port_enable = FALSE; 7645 BCM_IF_ERROR_RETURN( 7646 bcm_esw_switch_match_control_set( 7647 unit, bcmSwitchMatchServiceCustomHeader, 7648 bcmSwitchMatchControlPortEnable, 7649 local_port_out[port_idx], &match_control_info)); 7650 7651 /* Disable the capability of Custom Header encapsulation */ 7652 BCM_IF_ERROR_RETURN( 7653 bcm_esw_port_control_set( 7654 unit, local_port_out[port_idx], 7655 bcmPortControlCustomHeaderEncapEnable, FALSE)); 7656 } 7657 } else { 7658 /* 7659 * For Access or Network Ports: 7660 * - Destroy Custom Header encap, match and policy entries: 7661 * Encap - 1 entry per access/network port 7662 * Match and Policy - 2 entries for each table 7663 */ 7664 7665 /* Encap: Delete Custom Header encap */ 7666 encap_id = vp_info->ch_encap_id; 7667 if ((encap_id >> _BCM_SWITCH_ENCAP_SHIFT) == 7668 _BCM_SWITCH_ENCAP_TYPE_CUSTOM_HEADER) { 7669 BCM_IF_ERROR_RETURN( 7670 _bcm_hr3_switch_encap_id2idx(unit, encap_id, 1, 7671 index_array)); 7672 } else { 7673 return BCM_E_INTERNAL; 7674 } 7675 7676 BCM_IF_ERROR_RETURN( 7677 _bcm_egr_header_encap_data_entry_ref_count_get 7678 (unit, (uint32)index_array[0], &ref_count)); 7679 if (ref_count >= 2) { 7680 /* Decrease ref_cnt */ 7681 _bcm_common_profile_mem_ref_cnt_update 7682 (unit, EGR_HEADER_ENCAP_DATAm, index_array[0], -1); 7683 } else { 7684 BCM_IF_ERROR_RETURN( 7685 bcm_esw_switch_encap_destroy(unit, encap_id)); 7686 } 7687 7688 /* Match and Policy: Delete two Custom Header match and policy */ 7689 for (i = 0; i < 2; i++) { 7690 is_ipmc = i; /* i = 0: non-IPMC, i = 1: IPMC */ 7691 7692 /* Setup Custom Header match */ 7693 match_id_ptr = (is_ipmc) ? vp_info->ch_match_id_ipmc : 7694 vp_info->ch_match_id_non_ipmc; 7695 7696 BCM_IF_ERROR_RETURN( 7697 bcmi_switch_match_hw_id_get( 7698 unit, match_id_ptr, &match_service, &match_id_hw)); 7699 if (match_service != bcmSwitchMatchServiceCustomHeader) { 7700 return BCM_E_INTERNAL; 7701 } 7702 7703 BCM_IF_ERROR_RETURN( 7704 _bcm_custom_header_match_entry_ref_count_get 7705 (unit, match_id_hw, &ref_count)); 7706 if (ref_count >= 2) { 7707 /* Decrease ref_cnt */ 7708 _bcm_common_profile_mem_ref_cnt_update 7709 (unit, CUSTOM_HEADER_MATCHm, (int)match_id_hw, -1); 7710 } else { 7711 BCM_IF_ERROR_RETURN( 7712 bcm_esw_switch_match_config_delete( 7713 unit, bcmSwitchMatchServiceCustomHeader, 7714 match_id_ptr)); 7715 } 7716 7717 /* Clear Custom Header policy table when (vp_count == 1) */ 7718 if (port_info->vp_count == 1) { 7719 sal_memset(&policy_entry, 0, sizeof(policy_entry)); 7720 SOC_IF_ERROR_RETURN( 7721 soc_mem_write(unit, CUSTOM_HEADER_POLICY_TABLEm, 7722 MEM_BLOCK_ALL, match_id_hw, 7723 &policy_entry)); 7724 } 7725 } 7726 7727 if (port_info->vp_count == 1) { 7728 /* Encap: Reset related EGR_GPP_ATTRIBUTES table */ 7729 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &lmodid)); 7730 BCM_IF_ERROR_RETURN( 7731 _bcm_esw_src_mod_port_table_index_get 7732 (unit, lmodid, local_port_out[port_idx], 7733 &egr_gpp_index)); 7734 BCM_IF_ERROR_RETURN( 7735 READ_EGR_GPP_ATTRIBUTESm(unit, MEM_BLOCK_ANY, 7736 egr_gpp_index, &egr_gpp_entry)); 7737 soc_mem_field32_set(unit, EGR_GPP_ATTRIBUTESm, &egr_gpp_entry, 7738 CUSTOM_HEADER_INDEXf, 0x0); 7739 BCM_IF_ERROR_RETURN( 7740 WRITE_EGR_GPP_ATTRIBUTESm(unit, MEM_BLOCK_ALL, 7741 egr_gpp_index, &egr_gpp_entry)); 7742 7743 /* Reset Custom Header QoS mapping on this port */ 7744 BCM_IF_ERROR_RETURN(_bcm_esw_port_tab_set 7745 (unit, local_port_out[port_idx], _BCM_CPU_TABS_NONE, 7746 USE_CUSTOM_HEADER_FOR_PRIf, 7747 GH2_VXLAN_RIOT_CH_COS_REMAP_NONE)); 7748 } 7749 } 7750 } 7751 vp_info->ch_encap_id = 0; 7752 vp_info->ch_match_id_ipmc = 0; 7753 vp_info->ch_match_id_non_ipmc = 0; 7754 7755 return BCM_E_NONE; 7756 } 7757 7758 /* 7759 * Function: 7760 * bcmi_gh2_vxlan_match_trunk_cleanup 7761 * Purpose: 7762 * Helper function to clearnup VXLAN match trunk 7763 * Parameters: 7764 * unit - (IN) Device Number 7765 * tgid - (IN) Trunk group Id 7766 * vpn - (IN) VPN instance ID 7767 * port_out - (IN) member ports array in trunk 7768 * port_count - (IN) trunk member port count 7769 * port_op - (IN) Port operation for Normal/VFI 7770 * Returns: 7771 * BCM_E_XXX 7772 */ 7773 STATIC int 7774 bcmi_gh2_vxlan_match_trunk_cleanup( 7775 int unit, 7776 bcm_trunk_t tgid, 7777 bcm_vpn_t vpn, 7778 int *port_out, 7779 int port_count, 7780 uint32 port_op) 7781 { 7782 int rv = BCM_E_NONE; 7783 int port_idx = 0; 7784 int *local_port_out = NULL; 7785 7786 /* Input parameter check */ 7787 if (NULL == port_out) { 7788 return BCM_E_PARAM; 7789 } 7790 7791 local_port_out = port_out; 7792 port_idx = port_count; 7793 if (port_op == GH2_VXLAN_PORT_OPERATION_NORMAL) { 7794 for (; port_idx >= 0; port_idx--) { 7795 (void)_bcm_esw_port_tab_set(unit, local_port_out[port_idx], 7796 _BCM_CPU_TABS_NONE, PORT_OPERATIONf, 7797 port_op); 7798 7799 (void)bcmi_gh2_vxlan_trunk_table_reset(unit, local_port_out[port_idx]); 7800 } 7801 } else if (port_op == GH2_VXLAN_PORT_OPERATION_VFI) { 7802 for (; port_idx >= 0; port_idx--) { 7803 (void)_bcm_esw_port_tab_set(unit, local_port_out[port_idx], 7804 _BCM_CPU_TABS_NONE, PORT_OPERATIONf, 7805 port_op); 7806 7807 (void)bcmi_gh2_vxlan_trunk_table_set(unit, local_port_out[port_idx], 7808 tgid, vpn); 7809 } 7810 } else { 7811 return BCM_E_PARAM; 7812 } 7813 7814 return rv; 7815 } 7816 7817 /* 7818 * Function: 7819 * bcmi_gh2_vxlan_match_trunk_add 7820 * Purpose: 7821 * Assign SVP of VXLAN Trunk port 7822 * Parameters: 7823 * unit - (IN) Device Number 7824 * tgid - (IN) Trunk group Id 7825 * vpn - (IN) VPN instance ID 7826 * Returns: 7827 * BCM_E_XXX 7828 */ 7829 STATIC int 7830 bcmi_gh2_vxlan_match_trunk_add(int unit, bcm_trunk_t tgid, bcm_vpn_t vpn) 7831 { 7832 int rv = BCM_E_NONE, rv2 = BCM_E_NONE; 7833 int port_idx = 0; 7834 int local_port_out[SOC_MAX_NUM_PORTS]; 7835 int local_member_count = 0; 7836 7837 BCM_IF_ERROR_RETURN( 7838 _bcm_esw_trunk_local_members_get(unit, tgid, SOC_MAX_NUM_PORTS, 7839 local_port_out, &local_member_count)); 7840 for (port_idx = 0; port_idx < local_member_count; port_idx++) { 7841 rv = bcmi_gh2_vxlan_trunk_table_set(unit, local_port_out[port_idx], 7842 tgid, vpn); 7843 if (BCM_FAILURE(rv)) { 7844 rv2 = bcmi_gh2_vxlan_match_trunk_cleanup 7845 (unit, tgid, vpn, local_port_out, port_idx, 7846 GH2_VXLAN_PORT_OPERATION_NORMAL); 7847 if (BCM_FAILURE(rv2)) { 7848 return rv2; 7849 } 7850 7851 return rv; 7852 } 7853 rv = _bcm_esw_port_tab_set(unit, local_port_out[port_idx], 7854 _BCM_CPU_TABS_NONE, 7855 PORT_OPERATIONf, 7856 GH2_VXLAN_PORT_OPERATION_VFI); 7857 if (BCM_FAILURE(rv)) { 7858 rv2 = bcmi_gh2_vxlan_match_trunk_cleanup 7859 (unit, tgid, vpn, local_port_out, port_idx, 7860 GH2_VXLAN_PORT_OPERATION_NORMAL); 7861 if (BCM_FAILURE(rv2)) { 7862 return rv2; 7863 } 7864 7865 return rv; 7866 } 7867 7868 rv = bcmi_gh2_vxlan_port_untagged_profile_set( 7869 unit, local_port_out[port_idx]); 7870 if (BCM_FAILURE(rv)) { 7871 rv2 = bcmi_gh2_vxlan_match_trunk_cleanup 7872 (unit, tgid, vpn, local_port_out, port_idx, 7873 GH2_VXLAN_PORT_OPERATION_NORMAL); 7874 if (BCM_FAILURE(rv2)) { 7875 return rv2; 7876 } 7877 7878 rv2 = bcmi_gh2_vxlan_port_untagged_profile_reset 7879 (unit, local_port_out[port_idx]); 7880 if (BCM_FAILURE(rv2)) { 7881 return rv2; 7882 } 7883 7884 return rv; 7885 } 7886 } 7887 7888 return rv; 7889 } 7890 7891 /* 7892 * Function: 7893 * bcmi_gh2_vxlan_match_trunk_delete 7894 * Purpose: 7895 * Remove SVP of VXLAN Trunk port 7896 * Parameters: 7897 * unit - (IN) Device Number 7898 * tgid - (IN) Trunk group Id 7899 * vpn - (IN) VPN instance ID 7900 * Returns: 7901 * BCM_E_XXX 7902 */ 7903 STATIC int 7904 bcmi_gh2_vxlan_match_trunk_delete(int unit, bcm_trunk_t tgid, bcm_vpn_t vpn) 7905 { 7906 int rv = BCM_E_NONE, rv2 = BCM_E_NONE; 7907 int port_idx = 0; 7908 int local_port_out[SOC_MAX_NUM_PORTS]; 7909 int local_member_count = 0; 7910 7911 BCM_IF_ERROR_RETURN( 7912 _bcm_esw_trunk_local_members_get(unit, tgid, SOC_MAX_NUM_PORTS, 7913 local_port_out, &local_member_count)); 7914 7915 for (port_idx = 0; port_idx < local_member_count; port_idx++) { 7916 rv = bcmi_gh2_vxlan_trunk_table_reset(unit, local_port_out[port_idx]); 7917 if (BCM_FAILURE(rv)) { 7918 rv2 = bcmi_gh2_vxlan_match_trunk_cleanup 7919 (unit, tgid, vpn, local_port_out, port_idx, 7920 GH2_VXLAN_PORT_OPERATION_VFI); 7921 if (BCM_FAILURE(rv2)) { 7922 return rv2; 7923 } 7924 7925 return rv; 7926 } 7927 rv = _bcm_esw_port_tab_set(unit, local_port_out[port_idx], 7928 _BCM_CPU_TABS_NONE, 7929 PORT_OPERATIONf, 7930 GH2_VXLAN_PORT_OPERATION_NORMAL); 7931 if (BCM_FAILURE(rv)) { 7932 rv2 = bcmi_gh2_vxlan_match_trunk_cleanup 7933 (unit, tgid, vpn, local_port_out, port_idx, 7934 GH2_VXLAN_PORT_OPERATION_VFI); 7935 if (BCM_FAILURE(rv2)) { 7936 return rv2; 7937 } 7938 7939 return rv; 7940 } 7941 7942 rv = bcmi_gh2_vxlan_port_untagged_profile_reset 7943 (unit, local_port_out[port_idx]); 7944 if (BCM_FAILURE(rv)) { 7945 rv2 = bcmi_gh2_vxlan_match_trunk_cleanup 7946 (unit, tgid, vpn, local_port_out, port_idx, 7947 GH2_VXLAN_PORT_OPERATION_VFI); 7948 if (BCM_FAILURE(rv2)) { 7949 return rv2; 7950 } 7951 7952 return rv; 7953 } 7954 } 7955 7956 return rv; 7957 } 7958 7959 /* 7960 * Function: 7961 * bcmi_gh2_vxlan_match_clear 7962 * Purpose: 7963 * Clear VXLAN Match Software State 7964 * Parameters: 7965 * unit - (IN) Device Number 7966 * vp - (IN) Source Virtual Port 7967 * Returns: 7968 * void 7969 */ 7970 STATIC void 7971 bcmi_gh2_vxlan_match_clear(int unit, int vp) 7972 { 7973 int num_vp; 7974 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info = GH2_VXLAN_INFO(unit); 7975 7976 if (NULL == vxlan_info) { 7977 return; 7978 } 7979 7980 num_vp = vxlan_info->num_vxlan_vp; 7981 if ((vp < 0) || (vp >= num_vp)) { 7982 return; 7983 } 7984 7985 vxlan_info->match_key[vp].flags = 0; 7986 vxlan_info->match_key[vp].match_vlan = 0; 7987 vxlan_info->match_key[vp].match_inner_vlan = 0; 7988 vxlan_info->match_key[vp].trunk_id = -1; 7989 vxlan_info->match_key[vp].port = 0; 7990 vxlan_info->match_key[vp].modid = -1; 7991 vxlan_info->match_key[vp].match_tunnel_index = 0; 7992 7993 return; 7994 } 7995 7996 /* 7997 * Function: 7998 * bcmi_gh2_vxlan_match_add 7999 * Purpose: 8000 * Assign match criteria of an VXLAN port 8001 * Parameters: 8002 * unit - (IN) Device Number 8003 * vxlan_port - (IN/OUT) vxlan_port information (OUT : vxlan_port_id) 8004 * vp - (IN) Source Virtual Port 8005 * vpn - (IN) VPN instance ID 8006 * Returns: 8007 * BCM_E_XXX 8008 */ 8009 int 8010 bcmi_gh2_vxlan_match_add( 8011 int unit, 8012 bcm_vxlan_port_t *vxlan_port, 8013 int vp, 8014 bcm_vpn_t vpn) 8015 { 8016 int rv = BCM_E_NONE; 8017 bcm_module_t mod_out = -1; 8018 bcm_port_t port_out = -1; 8019 bcm_trunk_t trunk_id = -1; 8020 soc_mem_t mem; 8021 uint32 vent[SOC_MAX_MEM_WORDS]; 8022 int src_trk_idx = 0; /* Source Trunk table index.*/ 8023 int gport_id = -1; 8024 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 8025 int tunnel_idx = -1; 8026 int vfi_index = -1; 8027 gh2_vxlan_vpn_info_t *vfi_info; 8028 8029 /* Input parameter check */ 8030 if (NULL == vxlan_port) { 8031 return BCM_E_PARAM; 8032 } 8033 8034 /* Get VXLAN bookkeeping info instance */ 8035 BCM_IF_ERROR_RETURN( 8036 gh2_vxlan_bk_info_instance_get(unit, &vxlan_info)); 8037 8038 if (vxlan_port->criteria == BCM_VXLAN_PORT_MATCH_NONE) { 8039 vxlan_info->match_key[vp].flags = _BCM_VXLAN_PORT_MATCH_TYPE_NONE; 8040 return BCM_E_NONE; 8041 } 8042 8043 if (vxlan_port->criteria == BCM_VXLAN_PORT_MATCH_SHARE) { 8044 /* there is no criteria to be configured for shared vp, 8045 only updating software state to indicate this is a shared vp */ 8046 /* GH2 doesn't support SHARE criteria and flags */ 8047 return BCM_E_UNAVAIL; 8048 } 8049 8050 sal_memset(vent, 0, (sizeof(uint32) * SOC_MAX_MEM_WORDS)); 8051 8052 mem = VLAN_XLATEm; 8053 /* To create additional IVXLT for Loopback VP (GH2-B0 only) */ 8054 if (vxlan_port->flags & BCM_VXLAN_PORT_LOOPBACK) { 8055 /* Loopback VP is only support when VXLAN RIOT is enabled */ 8056 if (!BCM_VLAN_VALID(vxlan_port->match_vlan)) { 8057 return BCM_E_PARAM; 8058 } 8059 8060 soc_mem_field32_set(unit, mem, vent, 8061 KEY_TYPEf, GH2_VLXLT_HASH_KEY_TYPE_OVID); 8062 soc_mem_field32_set(unit, mem, vent, 8063 XLATE__OVIDf, vxlan_port->match_vlan); 8064 /* incoming port not used in lookup key, set field to all 1's */ 8065 soc_mem_field32_set(unit, mem, vent, XLATE__GLPf, 8066 SOC_VLAN_XLATE_GLP_WILDCARD(unit)); 8067 8068 rv = bcmi_gh2_vxlan_match_vxlate_entry_set(unit, vpn, 8069 vxlan_port, vent); 8070 BCM_IF_ERROR_RETURN(rv); 8071 } 8072 8073 sal_memset(vent, 0, (sizeof(uint32) * SOC_MAX_MEM_WORDS)); 8074 if (vxlan_port->criteria != BCM_VXLAN_PORT_MATCH_VN_ID) { 8075 rv = _bcm_esw_gport_resolve(unit, vxlan_port->match_port, &mod_out, 8076 &port_out, &trunk_id, &gport_id); 8077 BCM_IF_ERROR_RETURN(rv); 8078 8079 if (BCM_GPORT_IS_TRUNK(vxlan_port->match_port)) { 8080 soc_mem_field32_set(unit, mem, vent, XLATE__Tf, 0x1); 8081 soc_mem_field32_set(unit, mem, vent, XLATE__TGIDf, trunk_id); 8082 } else { 8083 soc_mem_field32_set(unit, mem, vent, XLATE__MODULE_IDf, mod_out); 8084 soc_mem_field32_set(unit, mem, vent, XLATE__PORT_NUMf, port_out); 8085 } 8086 } 8087 8088 if (vxlan_port->criteria == BCM_VXLAN_PORT_MATCH_PORT_VLAN) { 8089 if (!BCM_VLAN_VALID(vxlan_port->match_vlan)) { 8090 return BCM_E_PARAM; 8091 } 8092 8093 soc_mem_field32_set(unit, mem, vent, 8094 KEY_TYPEf, GH2_VLXLT_HASH_KEY_TYPE_OVID); 8095 soc_mem_field32_set(unit, mem, vent, 8096 XLATE__OVIDf, vxlan_port->match_vlan); 8097 8098 rv = bcmi_gh2_vxlan_match_vxlate_entry_set(unit, vpn, 8099 vxlan_port, vent); 8100 BCM_IF_ERROR_RETURN(rv); 8101 8102 if (vxlan_info->match_key[vp].flags != 8103 _BCM_VXLAN_PORT_MATCH_TYPE_SHARED) { 8104 vxlan_info->match_key[vp].flags = _BCM_VXLAN_PORT_MATCH_TYPE_VLAN; 8105 vxlan_info->match_key[vp].match_vlan = vxlan_port->match_vlan; 8106 if (BCM_GPORT_IS_TRUNK(vxlan_port->match_port)) { 8107 vxlan_info->match_key[vp].trunk_id = trunk_id; 8108 vxlan_info->match_key[vp].modid = -1; 8109 } else { 8110 vxlan_info->match_key[vp].port = port_out; 8111 vxlan_info->match_key[vp].modid = mod_out; 8112 vxlan_info->match_key[vp].trunk_id = -1; 8113 } 8114 } 8115 8116 if (!(vxlan_port->flags & BCM_VXLAN_PORT_REPLACE)) { 8117 bcmi_gh2_vxlan_port_match_count_adjust(unit, vp, 1); 8118 } 8119 } else if (vxlan_port->criteria == 8120 BCM_VXLAN_PORT_MATCH_PORT_INNER_VLAN) { 8121 if (!BCM_VLAN_VALID(vxlan_port->match_inner_vlan)) { 8122 return BCM_E_PARAM; 8123 } 8124 8125 soc_mem_field32_set(unit, mem, vent, 8126 KEY_TYPEf, GH2_VLXLT_HASH_KEY_TYPE_IVID); 8127 soc_mem_field32_set(unit, mem, vent, 8128 XLATE__IVIDf, vxlan_port->match_inner_vlan); 8129 8130 rv = bcmi_gh2_vxlan_match_vxlate_entry_set(unit, vpn, 8131 vxlan_port, vent); 8132 BCM_IF_ERROR_RETURN(rv); 8133 8134 if (vxlan_info->match_key[vp].flags != 8135 _BCM_VXLAN_PORT_MATCH_TYPE_SHARED) { 8136 vxlan_info->match_key[vp].flags = 8137 _BCM_VXLAN_PORT_MATCH_TYPE_INNER_VLAN; 8138 vxlan_info->match_key[vp].match_inner_vlan = 8139 vxlan_port->match_inner_vlan; 8140 if (BCM_GPORT_IS_TRUNK(vxlan_port->match_port)) { 8141 vxlan_info->match_key[vp].trunk_id = trunk_id; 8142 vxlan_info->match_key[vp].modid = -1; 8143 } else { 8144 vxlan_info->match_key[vp].port = port_out; 8145 vxlan_info->match_key[vp].modid = mod_out; 8146 vxlan_info->match_key[vp].trunk_id = -1; 8147 } 8148 } 8149 8150 if (!(vxlan_port->flags & BCM_VXLAN_PORT_REPLACE)) { 8151 bcmi_gh2_vxlan_port_match_count_adjust(unit, vp, 1); 8152 } 8153 } else if (vxlan_port->criteria == 8154 BCM_VXLAN_PORT_MATCH_PORT_VLAN_STACKED) { 8155 if (!BCM_VLAN_VALID(vxlan_port->match_vlan) || 8156 !BCM_VLAN_VALID(vxlan_port->match_inner_vlan)) { 8157 return BCM_E_PARAM; 8158 } 8159 8160 soc_mem_field32_set(unit, mem, vent, 8161 KEY_TYPEf, GH2_VLXLT_HASH_KEY_TYPE_IVID_OVID); 8162 soc_mem_field32_set(unit, mem, vent, 8163 XLATE__OVIDf, vxlan_port->match_vlan); 8164 soc_mem_field32_set(unit, mem, vent, 8165 XLATE__IVIDf, vxlan_port->match_inner_vlan); 8166 8167 rv = bcmi_gh2_vxlan_match_vxlate_entry_set(unit, vpn, 8168 vxlan_port, vent); 8169 BCM_IF_ERROR_RETURN(rv); 8170 8171 if (vxlan_info->match_key[vp].flags != 8172 _BCM_VXLAN_PORT_MATCH_TYPE_SHARED) { 8173 vxlan_info->match_key[vp].flags = 8174 _BCM_VXLAN_PORT_MATCH_TYPE_VLAN_STACKED; 8175 vxlan_info->match_key[vp].match_vlan = 8176 vxlan_port->match_vlan; 8177 vxlan_info->match_key[vp].match_inner_vlan = 8178 vxlan_port->match_inner_vlan; 8179 if (BCM_GPORT_IS_TRUNK(vxlan_port->match_port)) { 8180 vxlan_info->match_key[vp].trunk_id = trunk_id; 8181 vxlan_info->match_key[vp].modid = -1; 8182 } else { 8183 vxlan_info->match_key[vp].port = port_out; 8184 vxlan_info->match_key[vp].modid = mod_out; 8185 vxlan_info->match_key[vp].trunk_id = -1; 8186 } 8187 } 8188 8189 if (!(vxlan_port->flags & BCM_VXLAN_PORT_REPLACE)) { 8190 bcmi_gh2_vxlan_port_match_count_adjust(unit, vp, 1); 8191 } 8192 } else if (vxlan_port->criteria == 8193 BCM_VXLAN_PORT_MATCH_VLAN_PRI) { 8194 8195 soc_mem_field32_set(unit, mem, vent, 8196 KEY_TYPEf, GH2_VLXLT_HASH_KEY_TYPE_PRI_CFI); 8197 /* match_vlan: Bits 12-15 contains VLAN_PRI + CFI, vlan = BCM_E_NONE */ 8198 soc_mem_field32_set(unit, mem, vent, 8199 XLATE__OTAGf, vxlan_port->match_vlan); 8200 8201 rv = bcmi_gh2_vxlan_match_vxlate_entry_set(unit, vpn, 8202 vxlan_port, vent); 8203 BCM_IF_ERROR_RETURN(rv); 8204 8205 if (vxlan_info->match_key[vp].flags != 8206 _BCM_VXLAN_PORT_MATCH_TYPE_SHARED) { 8207 vxlan_info->match_key[vp].flags = 8208 _BCM_VXLAN_PORT_MATCH_TYPE_VLAN_PRI; 8209 vxlan_info->match_key[vp].match_vlan = 8210 vxlan_port->match_vlan; 8211 if (BCM_GPORT_IS_TRUNK(vxlan_port->match_port)) { 8212 vxlan_info->match_key[vp].trunk_id = trunk_id; 8213 vxlan_info->match_key[vp].modid = -1; 8214 } else { 8215 vxlan_info->match_key[vp].port = port_out; 8216 vxlan_info->match_key[vp].modid = mod_out; 8217 vxlan_info->match_key[vp].trunk_id = -1; 8218 } 8219 } 8220 8221 if (!(vxlan_port->flags & BCM_VXLAN_PORT_REPLACE)) { 8222 bcmi_gh2_vxlan_port_match_count_adjust(unit, vp, 1); 8223 } 8224 } else if (vxlan_port->criteria == 8225 BCM_VXLAN_PORT_MATCH_PORT) { 8226 int is_local = 0, vfi = 0; 8227 8228 if (vxlan_info->match_key[vp].flags == 8229 _BCM_VXLAN_PORT_MATCH_TYPE_SHARED) { 8230 return BCM_E_PARAM; 8231 } 8232 8233 if (BCM_GPORT_IS_TRUNK(vxlan_port->match_port)) { 8234 BCM_IF_ERROR_RETURN( 8235 bcmi_gh2_vxlan_match_trunk_add(unit, trunk_id, vpn)); 8236 vxlan_info->match_key[vp].flags = 8237 _BCM_VXLAN_PORT_MATCH_TYPE_TRUNK; 8238 vxlan_info->match_key[vp].trunk_id = trunk_id; 8239 } else { 8240 BCM_IF_ERROR_RETURN( 8241 _bcm_esw_modid_is_local(unit, mod_out, &is_local)); 8242 8243 /* Get index to source trunk map table */ 8244 BCM_IF_ERROR_RETURN( 8245 _bcm_esw_src_mod_port_table_index_get(unit, mod_out, 8246 port_out, &src_trk_idx)); 8247 8248 /* Set vfi to provide default VFI (for untag & ptag packets) */ 8249 if (soc_mem_field_valid(unit, SOURCE_TRUNK_MAP_TABLEm, VFIf)) { 8250 if (vpn != BCM_VXLAN_VPN_INVALID) { 8251 _BCM_VXLAN_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, vpn); 8252 if (!bcmi_gh2_vxlan_vfi_used_get(unit, vfi)) { 8253 return BCM_E_NOT_FOUND; 8254 } 8255 } else { 8256 return BCM_E_PARAM; 8257 } 8258 /* Set vfi to provide default VFI (for untag & ptag packets) */ 8259 rv = soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm, 8260 src_trk_idx, VFIf, vfi); 8261 BCM_IF_ERROR_RETURN(rv); 8262 } 8263 8264 /* Disable VLAN check for SOURCE_TRUNK_MAP_TABLEm */ 8265 if (soc_mem_field_valid(unit, SOURCE_TRUNK_MAP_TABLEm, 8266 DISABLE_VLAN_CHECKSf)) { 8267 rv = soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm, 8268 src_trk_idx, DISABLE_VLAN_CHECKSf, 8269 1); 8270 BCM_IF_ERROR_RETURN(rv); 8271 } 8272 8273 if (is_local) { 8274 rv = _bcm_esw_port_tab_set(unit, vxlan_port->match_port, 8275 _BCM_CPU_TABS_NONE, 8276 PORT_OPERATIONf, 8277 GH2_VXLAN_PORT_OPERATION_VFI); 8278 BCM_IF_ERROR_RETURN(rv); 8279 8280 /* Set TAG_ACTION_PROFILE_PTR */ 8281 rv = bcmi_gh2_vxlan_port_untagged_profile_set( 8282 unit, vxlan_port->match_port); 8283 BCM_IF_ERROR_RETURN(rv); 8284 } 8285 /* 8286 * The vp has been created based on trunk. 8287 * When a new port is added into the trunk, a match will be 8288 * added for the vp through bcm_port_match_add. 8289 */ 8290 if ((vxlan_info->match_key[vp].flags != 8291 _BCM_VXLAN_PORT_MATCH_TYPE_TRUNK) && 8292 (vxlan_info->match_key[vp].flags != 8293 _BCM_VXLAN_PORT_MATCH_TYPE_SHARED)) { 8294 vxlan_info->match_key[vp].flags = 8295 _BCM_VXLAN_PORT_MATCH_TYPE_PORT; 8296 vxlan_info->match_key[vp].index = src_trk_idx; 8297 vxlan_info->match_key[vp].port = port_out; 8298 vxlan_info->match_key[vp].modid = mod_out; 8299 vxlan_info->match_key[vp].trunk_id = -1; 8300 } 8301 } 8302 } else if (vxlan_port->criteria == 8303 BCM_VXLAN_PORT_MATCH_VN_ID) { 8304 8305 if (!BCM_GPORT_IS_TUNNEL(vxlan_port->match_tunnel_id)) { 8306 return BCM_E_BADID; 8307 } 8308 8309 tunnel_idx = BCM_GPORT_TUNNEL_ID_GET(vxlan_port->match_tunnel_id); 8310 GH2_VXLAN_TUNNEL_ID_IF_INVALID_RETURN(unit, tunnel_idx); 8311 8312 /* Configure Ingress VNID (use VLAN_XLATE) */ 8313 _BCM_VXLAN_VPN_GET(vfi_index, _BCM_VPN_TYPE_VFI, vpn); 8314 /* Get VFI info for VN_ID */ 8315 vfi_info = &(vxlan_info->vxlan_vpn_info[vfi_index]); 8316 8317 soc_mem_field32_set(unit, mem, vent, 8318 KEY_TYPEf, GH2_VLXLT_HASH_KEY_TYPE_VNID); 8319 soc_mem_field32_set(unit, mem, vent, 8320 XLATE__VNIDf, vfi_info->vnid); 8321 /* incoming port not used in lookup key, set field to all 1's */ 8322 soc_mem_field32_set(unit, mem, vent, XLATE__GLPf, 8323 SOC_VLAN_XLATE_GLP_WILDCARD(unit)); 8324 8325 rv = bcmi_gh2_vxlan_match_vxlate_entry_set(unit, vpn, 8326 vxlan_port, vent); 8327 BCM_IF_ERROR_RETURN(rv); 8328 8329 if (vxlan_info->match_key[vp].flags != 8330 _BCM_VXLAN_PORT_MATCH_TYPE_SHARED) { 8331 vxlan_info->match_key[vp].flags = _BCM_VXLAN_PORT_MATCH_TYPE_VNID; 8332 vxlan_info->match_key[vp].match_tunnel_index = tunnel_idx; 8333 } 8334 } 8335 8336 return rv; 8337 } 8338 8339 /* 8340 * Function: 8341 * bcmi_gh2_vxlan_match_delete 8342 * Purpose: 8343 * Delete match criteria of an VXLAN port 8344 * Parameters: 8345 * unit - (IN) Device Number 8346 * vp - (IN) Source Virtual Port 8347 * vxlan_port - (IN/OUT) vxlan_port information (OUT : vxlan_port_id) 8348 * vpn - (IN) VPN instance ID 8349 * Returns: 8350 * BCM_E_XXX 8351 */ 8352 int 8353 bcmi_gh2_vxlan_match_delete( 8354 int unit, 8355 int vp, 8356 bcm_vxlan_port_t vxlan_port, 8357 bcm_vpn_t vpn) 8358 { 8359 int rv = BCM_E_NONE; 8360 soc_mem_t mem; 8361 uint32 vent[SOC_MAX_MEM_WORDS]; 8362 bcm_trunk_t trunk_id; 8363 int src_trk_idx = 0; /* Source Trunk table index */ 8364 int mod_id_idx = 0; /* Module_Id */ 8365 int port = 0; 8366 bcm_module_t mod_out = -1; 8367 bcm_port_t port_out = -1; 8368 int gport_id = -1; 8369 int vfi_index = -1; 8370 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 8371 gh2_vxlan_vpn_info_t *vfi_info; 8372 8373 /* Get VXLAN bookkeeping info instance */ 8374 BCM_IF_ERROR_RETURN( 8375 gh2_vxlan_bk_info_instance_get(unit, &vxlan_info)); 8376 8377 sal_memset(vent, 0, (sizeof(uint32) * SOC_MAX_MEM_WORDS)); 8378 8379 mem = VLAN_XLATEm; 8380 /* To delete additional IVXLT for Loopback VP (GH2-B0 only) */ 8381 if (vxlan_port.flags & BCM_VXLAN_PORT_LOOPBACK) { 8382 /* Loopback VP is only support when VXLAN RIOT is enabled */ 8383 soc_mem_field32_set(unit, mem, vent, 8384 KEY_TYPEf, GH2_VLXLT_HASH_KEY_TYPE_OVID); 8385 soc_mem_field32_set(unit, mem, vent, 8386 XLATE__OVIDf, 8387 vxlan_info->match_key[vp].match_vlan); 8388 /* incoming port not used in lookup key, set field to all 1's */ 8389 soc_mem_field32_set(unit, mem, vent, XLATE__GLPf, 8390 SOC_VLAN_XLATE_GLP_WILDCARD(unit)); 8391 8392 rv = bcmi_gh2_vxlan_match_vxlate_entry_reset(unit, vent); 8393 BCM_IF_ERROR_RETURN(rv); 8394 } 8395 8396 sal_memset(vent, 0, (sizeof(uint32) * SOC_MAX_MEM_WORDS)); 8397 if (vxlan_info->match_key[vp].flags == _BCM_VXLAN_PORT_MATCH_TYPE_VLAN) { 8398 soc_mem_field32_set(unit, mem, vent, 8399 KEY_TYPEf, GH2_VLXLT_HASH_KEY_TYPE_OVID); 8400 soc_mem_field32_set(unit, mem, vent, 8401 XLATE__OVIDf, 8402 vxlan_info->match_key[vp].match_vlan); 8403 if (vxlan_info->match_key[vp].modid != -1) { 8404 soc_mem_field32_set(unit, mem, vent, XLATE__MODULE_IDf, 8405 vxlan_info->match_key[vp].modid); 8406 soc_mem_field32_set(unit, mem, vent, XLATE__PORT_NUMf, 8407 vxlan_info->match_key[vp].port); 8408 } else { 8409 soc_mem_field32_set(unit, mem, vent, XLATE__Tf, 0x1); 8410 soc_mem_field32_set(unit, mem, vent, XLATE__TGIDf, 8411 vxlan_info->match_key[vp].trunk_id); 8412 } 8413 rv = bcmi_gh2_vxlan_match_vxlate_entry_reset(unit, vent); 8414 BCM_IF_ERROR_RETURN(rv); 8415 8416 bcmi_gh2_vxlan_port_match_count_adjust(unit, vp, -1); 8417 } else if (vxlan_info->match_key[vp].flags == 8418 _BCM_VXLAN_PORT_MATCH_TYPE_INNER_VLAN) { 8419 soc_mem_field32_set(unit, mem, vent, 8420 KEY_TYPEf, GH2_VLXLT_HASH_KEY_TYPE_IVID); 8421 soc_mem_field32_set(unit, mem, vent, 8422 XLATE__IVIDf, 8423 vxlan_info->match_key[vp].match_inner_vlan); 8424 if (vxlan_info->match_key[vp].modid != -1) { 8425 soc_mem_field32_set(unit, mem, vent, XLATE__MODULE_IDf, 8426 vxlan_info->match_key[vp].modid); 8427 soc_mem_field32_set(unit, mem, vent, XLATE__PORT_NUMf, 8428 vxlan_info->match_key[vp].port); 8429 } else { 8430 soc_mem_field32_set(unit, mem, vent, XLATE__Tf, 0x1); 8431 soc_mem_field32_set(unit, mem, vent, XLATE__TGIDf, 8432 vxlan_info->match_key[vp].trunk_id); 8433 } 8434 rv = bcmi_gh2_vxlan_match_vxlate_entry_reset(unit, vent); 8435 BCM_IF_ERROR_RETURN(rv); 8436 8437 bcmi_gh2_vxlan_port_match_count_adjust(unit, vp, -1); 8438 } else if (vxlan_info->match_key[vp].flags == 8439 _BCM_VXLAN_PORT_MATCH_TYPE_VLAN_STACKED) { 8440 soc_mem_field32_set(unit, mem, vent, 8441 KEY_TYPEf, GH2_VLXLT_HASH_KEY_TYPE_IVID_OVID); 8442 soc_mem_field32_set(unit, mem, vent, 8443 XLATE__OVIDf, 8444 vxlan_info->match_key[vp].match_vlan); 8445 soc_mem_field32_set(unit, mem, vent, 8446 XLATE__IVIDf, 8447 vxlan_info->match_key[vp].match_inner_vlan); 8448 if (vxlan_info->match_key[vp].modid != -1) { 8449 soc_mem_field32_set(unit, mem, vent, XLATE__MODULE_IDf, 8450 vxlan_info->match_key[vp].modid); 8451 soc_mem_field32_set(unit, mem, vent, XLATE__PORT_NUMf, 8452 vxlan_info->match_key[vp].port); 8453 } else { 8454 soc_mem_field32_set(unit, mem, vent, XLATE__Tf, 0x1); 8455 soc_mem_field32_set(unit, mem, vent, XLATE__TGIDf, 8456 vxlan_info->match_key[vp].trunk_id); 8457 } 8458 rv = bcmi_gh2_vxlan_match_vxlate_entry_reset(unit, vent); 8459 BCM_IF_ERROR_RETURN(rv); 8460 8461 bcmi_gh2_vxlan_port_match_count_adjust(unit, vp, -1); 8462 } else if (vxlan_info->match_key[vp].flags == 8463 _BCM_VXLAN_PORT_MATCH_TYPE_VLAN_PRI) { 8464 soc_mem_field32_set(unit, mem, vent, 8465 KEY_TYPEf, GH2_VLXLT_HASH_KEY_TYPE_PRI_CFI); 8466 soc_mem_field32_set(unit, mem, vent, 8467 XLATE__OTAGf, 8468 vxlan_info->match_key[vp].match_vlan); 8469 if (vxlan_info->match_key[vp].modid != -1) { 8470 soc_mem_field32_set(unit, mem, vent, XLATE__MODULE_IDf, 8471 vxlan_info->match_key[vp].modid); 8472 soc_mem_field32_set(unit, mem, vent, XLATE__PORT_NUMf, 8473 vxlan_info->match_key[vp].port); 8474 } else { 8475 soc_mem_field32_set(unit, mem, vent, XLATE__Tf, 0x1); 8476 soc_mem_field32_set(unit, mem, vent, XLATE__TGIDf, 8477 vxlan_info->match_key[vp].trunk_id); 8478 } 8479 rv = bcmi_gh2_vxlan_match_vxlate_entry_reset(unit, vent); 8480 BCM_IF_ERROR_RETURN(rv); 8481 8482 bcmi_gh2_vxlan_port_match_count_adjust(unit, vp, -1); 8483 } else if ((vxlan_info->match_key[vp].flags == 8484 _BCM_VXLAN_PORT_MATCH_TYPE_PORT) || 8485 ((vxlan_info->match_key[vp].flags == 8486 _BCM_VXLAN_PORT_MATCH_TYPE_TRUNK) && 8487 (!BCM_GPORT_IS_TRUNK(vxlan_port.match_port)))) { 8488 8489 if (vxlan_info->match_key[vp].flags == 8490 _BCM_VXLAN_PORT_MATCH_TYPE_PORT) { 8491 src_trk_idx = vxlan_info->match_key[vp].index; 8492 } else { 8493 /* 8494 * The vp has been created based on trunk. 8495 * When a new port is deleted from the trunk, a match 8496 * will be deleted for the vp through bcm_port_match_delete. 8497 */ 8498 BCM_IF_ERROR_RETURN( 8499 _bcm_esw_gport_resolve(unit, vxlan_port.match_port, &mod_out, 8500 &port_out, &trunk_id, &gport_id)); 8501 /* Get index to source trunk map table */ 8502 BCM_IF_ERROR_RETURN( 8503 _bcm_esw_src_mod_port_table_index_get(unit, mod_out, 8504 port_out, &src_trk_idx)); 8505 } 8506 8507 /* Disable VFI */ 8508 if (soc_mem_field_valid(unit, SOURCE_TRUNK_MAP_TABLEm, VFIf)) { 8509 rv = soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm, 8510 src_trk_idx, VFIf, 0x0); 8511 BCM_IF_ERROR_RETURN(rv); 8512 } 8513 8514 if (soc_mem_field_valid(unit, SOURCE_TRUNK_MAP_TABLEm, 8515 DISABLE_VLAN_CHECKSf)) { 8516 rv = soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm, 8517 src_trk_idx, DISABLE_VLAN_CHECKSf, 0x0); 8518 BCM_IF_ERROR_RETURN(rv); 8519 } 8520 8521 mod_id_idx = vxlan_info->match_key[vp].modid; 8522 port = vxlan_info->match_key[vp].port; 8523 rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 8524 mod_id_idx, port, &mod_out, &port_out); 8525 BCM_IF_ERROR_RETURN(rv); 8526 8527 rv = _bcm_esw_port_tab_set(unit, port_out, 8528 _BCM_CPU_TABS_NONE, 8529 PORT_OPERATIONf, 8530 GH2_VXLAN_PORT_OPERATION_NORMAL); 8531 BCM_IF_ERROR_RETURN(rv); 8532 8533 /* Reset TAG_ACTION_PROFILE_PTR */ 8534 rv = bcmi_gh2_vxlan_port_untagged_profile_reset(unit, port_out); 8535 BCM_IF_ERROR_RETURN(rv); 8536 } else if (vxlan_info->match_key[vp].flags == 8537 _BCM_VXLAN_PORT_MATCH_TYPE_TRUNK) { 8538 trunk_id = vxlan_info->match_key[vp].trunk_id; 8539 8540 rv = bcmi_gh2_vxlan_match_trunk_delete(unit, trunk_id, vpn); 8541 BCM_IF_ERROR_RETURN(rv); 8542 } else if (vxlan_info->match_key[vp].flags == 8543 _BCM_VXLAN_PORT_MATCH_TYPE_VNID) { 8544 8545 _BCM_VXLAN_VPN_GET(vfi_index, _BCM_VPN_TYPE_VFI, vpn); 8546 /* Get VFI info for VN_ID */ 8547 vfi_info = &(vxlan_info->vxlan_vpn_info[vfi_index]); 8548 8549 soc_mem_field32_set(unit, mem, vent, 8550 KEY_TYPEf, GH2_VLXLT_HASH_KEY_TYPE_VNID); 8551 soc_mem_field32_set(unit, mem, vent, 8552 XLATE__VNIDf, vfi_info->vnid); 8553 /* incoming port not used in lookup key, set field to all 1's */ 8554 soc_mem_field32_set(unit, mem, vent, XLATE__GLPf, 8555 SOC_VLAN_XLATE_GLP_WILDCARD(unit)); 8556 8557 rv = bcmi_gh2_vxlan_match_vxlate_entry_reset(unit, vent); 8558 BCM_IF_ERROR_RETURN(rv); 8559 } 8560 8561 return rv; 8562 } 8563 8564 /* 8565 * Function: 8566 * bcmi_gh2_vxlan_match_get 8567 * Purpose: 8568 * Obtain match information of an VXLAN port 8569 * Parameters: 8570 * unit - (IN) Device Number 8571 * vxlan_port - (IN/OUT) vxlan_port information 8572 * vp - (IN) Source Virtual Port 8573 * vpn - (IN) VPN instance ID (unused for GH2) 8574 * Returns: 8575 * BCM_E_XXX 8576 */ 8577 int 8578 bcmi_gh2_vxlan_match_get( 8579 int unit, 8580 bcm_vxlan_port_t *vxlan_port, 8581 int vp, 8582 bcm_vpn_t vpn) 8583 { 8584 int rv = BCM_E_NONE; 8585 bcm_module_t mod_in = 0, mod_out = 0; 8586 bcm_port_t port_in = 0, port_out = 0; 8587 bcm_trunk_t trunk_id = 0; 8588 int tunnel_idx = -1; 8589 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 8590 8591 /* Input parameter check */ 8592 if (NULL == vxlan_port) { 8593 return BCM_E_PARAM; 8594 } 8595 8596 /* Get VXLAN bookkeeping info instance */ 8597 BCM_IF_ERROR_RETURN( 8598 gh2_vxlan_bk_info_instance_get(unit, &vxlan_info)); 8599 8600 if (vxlan_info->match_key[vp].flags & _BCM_VXLAN_PORT_MATCH_TYPE_VLAN) { 8601 vxlan_port->criteria = BCM_VXLAN_PORT_MATCH_PORT_VLAN; 8602 vxlan_port->match_vlan = vxlan_info->match_key[vp].match_vlan; 8603 8604 if (vxlan_info->match_key[vp].trunk_id != -1) { 8605 trunk_id = vxlan_info->match_key[vp].trunk_id; 8606 BCM_GPORT_TRUNK_SET(vxlan_port->match_port, trunk_id); 8607 } else { 8608 port_in = vxlan_info->match_key[vp].port; 8609 mod_in = vxlan_info->match_key[vp].modid; 8610 rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 8611 mod_in, port_in, &mod_out, &port_out); 8612 vxlan_port->match_port = 8613 _bcm_esw_port_gport_get_from_modport(unit, mod_out, port_out); 8614 } 8615 } else if (vxlan_info->match_key[vp].flags & 8616 _BCM_VXLAN_PORT_MATCH_TYPE_INNER_VLAN) { 8617 vxlan_port->criteria = BCM_VXLAN_PORT_MATCH_PORT_INNER_VLAN; 8618 vxlan_port->match_inner_vlan = 8619 vxlan_info->match_key[vp].match_inner_vlan; 8620 8621 if (vxlan_info->match_key[vp].trunk_id != -1) { 8622 trunk_id = vxlan_info->match_key[vp].trunk_id; 8623 BCM_GPORT_TRUNK_SET(vxlan_port->match_port, trunk_id); 8624 } else { 8625 port_in = vxlan_info->match_key[vp].port; 8626 mod_in = vxlan_info->match_key[vp].modid; 8627 rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 8628 mod_in, port_in, &mod_out, &port_out); 8629 vxlan_port->match_port = 8630 _bcm_esw_port_gport_get_from_modport(unit, mod_out, port_out); 8631 } 8632 } else if (vxlan_info->match_key[vp].flags & 8633 _BCM_VXLAN_PORT_MATCH_TYPE_VLAN_STACKED) { 8634 vxlan_port->criteria = BCM_VXLAN_PORT_MATCH_PORT_VLAN_STACKED; 8635 vxlan_port->match_vlan = vxlan_info->match_key[vp].match_vlan; 8636 vxlan_port->match_inner_vlan = 8637 vxlan_info->match_key[vp].match_inner_vlan; 8638 8639 if (vxlan_info->match_key[vp].trunk_id != -1) { 8640 trunk_id = vxlan_info->match_key[vp].trunk_id; 8641 BCM_GPORT_TRUNK_SET(vxlan_port->match_port, trunk_id); 8642 } else { 8643 port_in = vxlan_info->match_key[vp].port; 8644 mod_in = vxlan_info->match_key[vp].modid; 8645 rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 8646 mod_in, port_in, &mod_out, &port_out); 8647 vxlan_port->match_port = 8648 _bcm_esw_port_gport_get_from_modport(unit, mod_out, port_out); 8649 } 8650 } else if (vxlan_info->match_key[vp].flags & 8651 _BCM_VXLAN_PORT_MATCH_TYPE_VLAN_PRI) { 8652 vxlan_port->criteria = BCM_VXLAN_PORT_MATCH_VLAN_PRI; 8653 vxlan_port->match_vlan = vxlan_info->match_key[vp].match_vlan; 8654 8655 if (vxlan_info->match_key[vp].trunk_id != -1) { 8656 trunk_id = vxlan_info->match_key[vp].trunk_id; 8657 BCM_GPORT_TRUNK_SET(vxlan_port->match_port, trunk_id); 8658 } else { 8659 port_in = vxlan_info->match_key[vp].port; 8660 mod_in = vxlan_info->match_key[vp].modid; 8661 rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 8662 mod_in, port_in, &mod_out, &port_out); 8663 vxlan_port->match_port = 8664 _bcm_esw_port_gport_get_from_modport(unit, mod_out, port_out); 8665 } 8666 } else if (vxlan_info->match_key[vp].flags & 8667 _BCM_VXLAN_PORT_MATCH_TYPE_PORT) { 8668 port_in = vxlan_info->match_key[vp].port; 8669 mod_in = vxlan_info->match_key[vp].modid; 8670 8671 vxlan_port->criteria = BCM_VXLAN_PORT_MATCH_PORT; 8672 rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 8673 mod_in, port_in, &mod_out, &port_out); 8674 vxlan_port->match_port = 8675 _bcm_esw_port_gport_get_from_modport(unit, mod_out, port_out); 8676 } else if (vxlan_info->match_key[vp].flags & 8677 _BCM_VXLAN_PORT_MATCH_TYPE_TRUNK) { 8678 trunk_id = vxlan_info->match_key[vp].trunk_id; 8679 8680 vxlan_port->criteria = BCM_VXLAN_PORT_MATCH_PORT; 8681 BCM_GPORT_TRUNK_SET(vxlan_port->match_port, trunk_id); 8682 } else if ((vxlan_info->match_key[vp].flags & 8683 _BCM_VXLAN_PORT_MATCH_TYPE_VNID)) { 8684 vxlan_port->criteria = BCM_VXLAN_PORT_MATCH_VN_ID; 8685 8686 tunnel_idx = vxlan_info->match_key[vp].match_tunnel_index; 8687 BCM_GPORT_TUNNEL_ID_SET(vxlan_port->match_tunnel_id, tunnel_idx); 8688 vxlan_port->match_vlan = vxlan_info->match_key[vp].match_vlan; 8689 } else if (vxlan_info->match_key[vp].flags & 8690 _BCM_VXLAN_PORT_MATCH_TYPE_SHARED) { 8691 rv = BCM_E_INTERNAL; 8692 } else { 8693 vxlan_port->criteria = BCM_VXLAN_PORT_MATCH_NONE; 8694 } 8695 8696 /* 8697 * For all VXLAN RIOT flow support (loopback, access or network ports), 8698 * we must use vxlan_port->match_port for Custom Header 8699 * related configurations 8700 */ 8701 if (GH2_VXLAN_RIOT_ENABLE(unit)) { 8702 if ((vxlan_info->match_key[vp].flags & 8703 _BCM_VXLAN_PORT_MATCH_TYPE_VNID) || 8704 (vxlan_info->match_key[vp].flags & 8705 _BCM_VXLAN_PORT_MATCH_TYPE_NONE)) { 8706 if (vxlan_info->match_key[vp].trunk_id != -1) { 8707 trunk_id = vxlan_info->match_key[vp].trunk_id; 8708 BCM_GPORT_TRUNK_SET(vxlan_port->match_port, trunk_id); 8709 } else { 8710 port_in = vxlan_info->match_key[vp].port; 8711 mod_in = vxlan_info->match_key[vp].modid; 8712 rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 8713 mod_in, port_in, 8714 &mod_out, &port_out); 8715 vxlan_port->match_port = 8716 _bcm_esw_port_gport_get_from_modport(unit, mod_out, 8717 port_out); 8718 } 8719 } 8720 } 8721 8722 return rv; 8723 } 8724 8725 /* 8726 * Function: 8727 * bcmi_gh2_vxlan_elan_port_add 8728 * Purpose: 8729 * Add VXLAN ELAN port to a VPN 8730 * Parameters: 8731 * unit - (IN) Device Number 8732 * vpn - (IN) VPN instance ID 8733 * vxlan_port - (IN/OUT) vxlan_port information (OUT : vxlan_port_id) 8734 * Returns: 8735 * BCM_E_XXX 8736 */ 8737 STATIC int 8738 bcmi_gh2_vxlan_elan_port_add( 8739 int unit, 8740 bcm_vpn_t vpn, 8741 bcm_vxlan_port_t *vxlan_port) 8742 { 8743 int rv = BCM_E_PARAM, rv_error = BCM_E_NONE; 8744 int vp, num_vp, vfi = 0; 8745 bcmi_vxlan_vp_info_t vxlan_vp_info; 8746 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 8747 gh2_vxlan_vp_info_t *vp_info =NULL; 8748 int old_tpid_valid = 0; 8749 uint16 old_tpid = 0, new_tpid = 0; 8750 bcm_switch_tpid_info_t tpid_info; 8751 int tpid_enable = 0; 8752 bcm_vxlan_port_t old_vxlan_port; 8753 8754 /* Get VXLAN bookkeeping info instance */ 8755 BCM_IF_ERROR_RETURN( 8756 gh2_vxlan_bk_info_instance_get(unit, &vxlan_info)); 8757 8758 /* Input parameter check */ 8759 if (vpn != BCM_VXLAN_VPN_INVALID) { 8760 _BCM_VXLAN_VPN_GET(vfi, _BCM_VXLAN_VPN_TYPE_ELAN, vpn); 8761 if (!bcmi_gh2_vxlan_vfi_used_get(unit, vfi)) { 8762 return BCM_E_NOT_FOUND; 8763 } 8764 } else { 8765 vfi = _BCM_VXLAN_VFI_INVALID; 8766 } 8767 8768 if (NULL == vxlan_port) { 8769 return BCM_E_PARAM; 8770 } 8771 8772 if (vxlan_port->flags & BCM_VXLAN_PORT_DROP) { 8773 return BCM_E_PARAM; 8774 } 8775 8776 num_vp = vxlan_info->num_vxlan_vp; 8777 8778 bcmi_gh2_vxlan_vp_info_init(&vxlan_vp_info); 8779 if (vxlan_port->flags & BCM_VXLAN_PORT_NETWORK) { 8780 vxlan_vp_info.flags |= GH2_VXLAN_VP_INFO_NETWORK_PORT; 8781 } else if (vxlan_port->flags & BCM_VXLAN_PORT_LOOPBACK) { 8782 /* Only support for GH2-B0 when VXLAN RIOT is enabled */ 8783 vxlan_vp_info.flags |= GH2_VXLAN_VP_INFO_LOOPBACK_PORT; 8784 } 8785 if ((vxlan_port->criteria == BCM_VXLAN_PORT_MATCH_SHARE) || 8786 (vxlan_port->flags & BCM_VXLAN_PORT_SHARE)) { 8787 /* GH2 doesn't support SHARE criteria and flags */ 8788 return BCM_E_UNAVAIL; 8789 } 8790 8791 /* =============== Allocate/Get Virtual Port =============== */ 8792 if (vxlan_port->flags & BCM_VXLAN_PORT_REPLACE) { 8793 vp = BCM_GPORT_VXLAN_PORT_ID_GET(vxlan_port->vxlan_port_id); 8794 8795 if (vp == -1) { 8796 return BCM_E_PARAM; 8797 } 8798 if (!bcmi_gh2_vxlan_vp_used_get(unit, vp)) { 8799 return BCM_E_NOT_FOUND; 8800 } 8801 8802 /* Decrease old-port's nexthop count */ 8803 BCM_IF_ERROR_RETURN( 8804 bcmi_gh2_vxlan_port_nh_delete(unit, vpn, vp)); 8805 /* Decrease old-port's VP count */ 8806 BCM_IF_ERROR_RETURN( 8807 bcmi_gh2_vxlan_port_cnt_update(unit, vxlan_port->vxlan_port_id, 8808 vp, FALSE)); 8809 8810 /* Get old-port's vxlan_port information when VXLAN RIOT is enabled */ 8811 if (GH2_VXLAN_RIOT_ENABLE(unit)) { 8812 bcm_vxlan_port_t_init(&old_vxlan_port); 8813 old_vxlan_port.vxlan_port_id = vxlan_port->vxlan_port_id; 8814 8815 BCM_IF_ERROR_RETURN( 8816 bcmi_gh2_vxlan_port_get(unit, vpn, &old_vxlan_port)); 8817 } 8818 } else if (vxlan_port->flags & BCM_VXLAN_PORT_WITH_ID) { 8819 if (!BCM_GPORT_IS_VXLAN_PORT(vxlan_port->vxlan_port_id)) { 8820 return BCM_E_BADID; 8821 } 8822 8823 vp = BCM_GPORT_VXLAN_PORT_ID_GET(vxlan_port->vxlan_port_id); 8824 if (vp == -1) { 8825 return BCM_E_PARAM; 8826 } 8827 /* 8828 * In TD2, Vp index zero is reserved in function _bcm_virtual_init 8829 * because of HW restriction. No such restriction on GH2. 8830 */ 8831 if ((vp < 0) || (vp >= num_vp)) { 8832 return BCM_E_BADID; 8833 } 8834 if (bcmi_gh2_vxlan_vp_used_get(unit, vp)) { 8835 return BCM_E_EXISTS; 8836 } 8837 8838 BCM_IF_ERROR_RETURN( 8839 bcmi_gh2_vxlan_vp_used_set(unit, vp, vxlan_vp_info)); 8840 } else { 8841 /* Allocate a new VP index */ 8842 BCM_IF_ERROR_RETURN( 8843 bcmi_gh2_vxlan_vp_alloc(unit, 0, (num_vp - 1), 1, 8844 vxlan_vp_info, &vp)); 8845 BCM_GPORT_VXLAN_PORT_ID_SET(vxlan_port->vxlan_port_id, vp); 8846 } 8847 8848 /* =============== Configure Next-Hop Properties =============== */ 8849 rv = bcmi_gh2_vxlan_port_nh_add(unit, vxlan_port, vp, vpn); 8850 if (BCM_FAILURE(rv)) { 8851 if (!(vxlan_port->flags & BCM_VXLAN_PORT_REPLACE)) { 8852 (void)bcmi_gh2_vxlan_vp_free(unit, 1, vp); 8853 } 8854 return rv; 8855 } 8856 8857 /* Need to parse Service-Tag Properties */ 8858 if (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_TAGGED) { 8859 sal_memset(&tpid_info, 0, sizeof(tpid_info)); 8860 tpid_info.tpid_type = bcmTpidTypeVxlanPayloadOuter; 8861 tpid_info.tpid_value = vxlan_port->egress_service_tpid; 8862 8863 rv = bcm_esw_switch_tpid_add(unit, 0, &tpid_info); 8864 if (BCM_FAILURE(rv) && rv != BCM_E_EXISTS) { 8865 if (!(vxlan_port->flags & BCM_VXLAN_PORT_REPLACE)) { 8866 rv_error = bcmi_gh2_vxlan_port_nh_delete(unit, vpn, vp); 8867 if (BCM_FAILURE(rv_error) && rv_error != BCM_E_NOT_FOUND) { 8868 return rv_error; 8869 } 8870 (void)bcmi_gh2_vxlan_vp_free(unit, 1, vp); 8871 } 8872 return rv; 8873 } 8874 8875 tpid_enable = 1; 8876 8877 /* Get current VXLAN Outer TPID info with specified VP */ 8878 vp_info = &(vxlan_info->vxlan_vp_info[vp]); 8879 old_tpid_valid = vp_info->tpid_valid; 8880 old_tpid = vp_info->tpid_value; /* old TPID value */ 8881 new_tpid = tpid_info.tpid_value; /* new TPID value */ 8882 if (old_tpid_valid) { 8883 if (new_tpid != old_tpid) { 8884 /* Decrease ref_count for old VXLAN Outer TPID */ 8885 (void)bcmi_gh2_vxlan_outer_tpid_ref_dec(unit, old_tpid); 8886 8887 /* Increase ref_count for new VXLAN Outer TPID */ 8888 (void)bcmi_gh2_vxlan_outer_tpid_ref_inc(unit, new_tpid); 8889 8890 /* Update latest VXLAN Outer TPID info with specified VP */ 8891 vp_info->tpid_value = new_tpid; 8892 } 8893 } else { 8894 /* Increase ref_count for new VXLAN Outer TPID */ 8895 (void)bcmi_gh2_vxlan_outer_tpid_ref_inc(unit, new_tpid); 8896 8897 /* Update latest VXLAN Outer TPID info with specified VP */ 8898 vp_info->tpid_valid = 1; 8899 vp_info->tpid_value = new_tpid; 8900 } 8901 } 8902 8903 /* Configure VP match criteria */ 8904 rv = bcmi_gh2_vxlan_match_add(unit, vxlan_port, vp, vpn); 8905 if (BCM_FAILURE(rv)) { 8906 if (tpid_enable) { 8907 if (old_tpid_valid) { 8908 if (new_tpid != old_tpid) { 8909 /* Decrease ref_count for new VXLAN Outer TPID */ 8910 (void)bcmi_gh2_vxlan_outer_tpid_ref_dec(unit, new_tpid); 8911 8912 /* Restore ref_count for old VXLAN Outer TPID */ 8913 sal_memset(&tpid_info, 0, sizeof(tpid_info)); 8914 tpid_info.tpid_type = bcmTpidTypeVxlanPayloadOuter; 8915 tpid_info.tpid_value = old_tpid; 8916 rv_error = bcm_esw_switch_tpid_add(unit, 0, &tpid_info); 8917 if (BCM_FAILURE(rv_error) && rv_error != BCM_E_EXISTS) { 8918 return rv_error; 8919 } 8920 (void)bcmi_gh2_vxlan_outer_tpid_ref_inc(unit, old_tpid); 8921 vp_info->tpid_value = old_tpid; 8922 } 8923 } else { 8924 /* Decrease ref_count for new VXLAN Outer TPID */ 8925 (void)bcmi_gh2_vxlan_outer_tpid_ref_dec(unit, new_tpid); 8926 vp_info->tpid_valid = 0; 8927 vp_info->tpid_value = 0x0; 8928 } 8929 } 8930 8931 if (!(vxlan_port->flags & BCM_VXLAN_PORT_REPLACE)) { 8932 rv_error = bcmi_gh2_vxlan_port_nh_delete(unit, vpn, vp); 8933 if (BCM_FAILURE(rv_error) && rv_error != BCM_E_NOT_FOUND) { 8934 return rv_error; 8935 } 8936 (void)bcmi_gh2_vxlan_vp_free(unit, 1, vp); 8937 } 8938 return rv; 8939 } 8940 8941 /* Increment new-port's VP count */ 8942 rv = bcmi_gh2_vxlan_port_cnt_update(unit, vxlan_port->vxlan_port_id, 8943 vp, TRUE); 8944 if (BCM_FAILURE(rv)) { 8945 if (tpid_enable) { 8946 if (old_tpid_valid) { 8947 if (new_tpid != old_tpid) { 8948 /* Decrease ref_count for new VXLAN Outer TPID */ 8949 (void)bcmi_gh2_vxlan_outer_tpid_ref_dec(unit, new_tpid); 8950 8951 /* Restore ref_count for old VXLAN Outer TPID */ 8952 sal_memset(&tpid_info, 0, sizeof(tpid_info)); 8953 tpid_info.tpid_type = bcmTpidTypeVxlanPayloadOuter; 8954 tpid_info.tpid_value = old_tpid; 8955 rv_error = bcm_esw_switch_tpid_add(unit, 0, &tpid_info); 8956 if (BCM_FAILURE(rv_error) && rv_error != BCM_E_EXISTS) { 8957 return rv_error; 8958 } 8959 (void)bcmi_gh2_vxlan_outer_tpid_ref_inc(unit, old_tpid); 8960 vp_info->tpid_value = old_tpid; 8961 } 8962 } else { 8963 /* Decrease ref_count for new VXLAN Outer TPID */ 8964 (void)bcmi_gh2_vxlan_outer_tpid_ref_dec(unit, new_tpid); 8965 vp_info->tpid_valid = 0; 8966 vp_info->tpid_value = 0x0; 8967 } 8968 } 8969 8970 if (!(vxlan_port->flags & BCM_VXLAN_PORT_REPLACE)) { 8971 rv_error = bcmi_gh2_vxlan_match_delete(unit, vp, *vxlan_port, vpn); 8972 if (BCM_FAILURE(rv_error) && rv_error != BCM_E_NOT_FOUND) { 8973 return rv_error; 8974 } 8975 8976 rv_error = bcmi_gh2_vxlan_port_nh_delete(unit, vpn, vp); 8977 if (BCM_FAILURE(rv_error) && rv_error != BCM_E_NOT_FOUND) { 8978 return rv_error; 8979 } 8980 (void)bcmi_gh2_vxlan_vp_free(unit, 1, vp); 8981 } 8982 return rv; 8983 } 8984 8985 /* Configure VP related Custom Header when VXLAN RIOT is enabled */ 8986 if (GH2_VXLAN_RIOT_ENABLE(unit)) { 8987 rv = bcmi_gh2_vxlan_riot_custom_header_add(unit, vxlan_port, 8988 &old_vxlan_port, vp); 8989 if (BCM_FAILURE(rv)) { 8990 if (tpid_enable) { 8991 if (old_tpid_valid) { 8992 if (new_tpid != old_tpid) { 8993 /* Decrease ref_count for new VXLAN Outer TPID */ 8994 (void)bcmi_gh2_vxlan_outer_tpid_ref_dec(unit, 8995 new_tpid); 8996 8997 /* Restore ref_count for old VXLAN Outer TPID */ 8998 sal_memset(&tpid_info, 0, sizeof(tpid_info)); 8999 tpid_info.tpid_type = bcmTpidTypeVxlanPayloadOuter; 9000 tpid_info.tpid_value = old_tpid; 9001 rv_error = 9002 bcm_esw_switch_tpid_add(unit, 0, &tpid_info); 9003 if (BCM_FAILURE(rv_error) && 9004 rv_error != BCM_E_EXISTS) { 9005 return rv_error; 9006 } 9007 (void)bcmi_gh2_vxlan_outer_tpid_ref_inc(unit, 9008 old_tpid); 9009 vp_info->tpid_value = old_tpid; 9010 } 9011 } else { 9012 /* Decrease ref_count for new VXLAN Outer TPID */ 9013 (void)bcmi_gh2_vxlan_outer_tpid_ref_dec(unit, new_tpid); 9014 vp_info->tpid_valid = 0; 9015 vp_info->tpid_value = 0x0; 9016 } 9017 } 9018 9019 if (!(vxlan_port->flags & BCM_VXLAN_PORT_REPLACE)) { 9020 /* Decrement port's VP count */ 9021 BCM_IF_ERROR_RETURN( 9022 bcmi_gh2_vxlan_port_cnt_update(unit, 9023 vxlan_port->vxlan_port_id, 9024 vp, FALSE)); 9025 9026 rv_error = 9027 bcmi_gh2_vxlan_match_delete(unit, vp, *vxlan_port, vpn); 9028 if (BCM_FAILURE(rv_error) && rv_error != BCM_E_NOT_FOUND) { 9029 return rv_error; 9030 } 9031 9032 rv_error = bcmi_gh2_vxlan_port_nh_delete(unit, vpn, vp); 9033 if (BCM_FAILURE(rv_error) && rv_error != BCM_E_NOT_FOUND) { 9034 return rv_error; 9035 } 9036 (void)bcmi_gh2_vxlan_vp_free(unit, 1, vp); 9037 } 9038 return rv; 9039 } 9040 } 9041 9042 return BCM_E_NONE; 9043 } 9044 9045 /* 9046 * Function: 9047 * bcmi_gh2_vxlan_elan_port_delete 9048 * Purpose: 9049 * Delete VXLAN ELAN port from a VPN 9050 * Parameters: 9051 * unit - (IN) Device Number 9052 * vpn - (IN) VPN instance ID 9053 * vp - (IN) VP 9054 * Returns: 9055 * BCM_E_XXX 9056 */ 9057 int 9058 bcmi_gh2_vxlan_elan_port_delete(int unit, bcm_vpn_t vpn, int vp) 9059 { 9060 int rv = BCM_E_NONE; 9061 bcm_gport_t vxlan_port_id; 9062 bcm_vxlan_port_t vxlan_port; 9063 bcmi_vxlan_vp_info_t vxlan_vp_info; 9064 9065 if (!bcmi_gh2_vxlan_vp_used_get(unit, vp)) { 9066 return BCM_E_NOT_FOUND; 9067 } 9068 9069 /* Check for Network-Port */ 9070 BCM_IF_ERROR_RETURN( 9071 bcmi_gh2_vxlan_vp_info_get(unit, vp, &vxlan_vp_info)); 9072 9073 /* Set VXLAN port ID */ 9074 BCM_GPORT_VXLAN_PORT_ID_SET(vxlan_port_id, vp); 9075 bcm_vxlan_port_t_init(&vxlan_port); 9076 vxlan_port.vxlan_port_id = vxlan_port_id; 9077 BCM_IF_ERROR_RETURN( 9078 bcmi_gh2_vxlan_port_get(unit, vpn, &vxlan_port)); 9079 9080 rv = bcmi_gh2_vxlan_match_delete(unit, vp, vxlan_port, vpn); 9081 if (BCM_FAILURE(rv) && rv != BCM_E_NOT_FOUND) { 9082 return rv; 9083 } 9084 9085 /* Delete VP related Custom Header setting when VXLAN RIOT is enabled */ 9086 if (GH2_VXLAN_RIOT_ENABLE(unit)) { 9087 BCM_IF_ERROR_RETURN( 9088 bcmi_gh2_vxlan_riot_custom_header_delete(unit, &vxlan_port, vp)); 9089 } 9090 9091 /* Decrement port's VP count */ 9092 BCM_IF_ERROR_RETURN( 9093 bcmi_gh2_vxlan_port_cnt_update(unit, vxlan_port_id, vp, FALSE)); 9094 9095 /* Delete the next-hop info */ 9096 rv = bcmi_gh2_vxlan_port_nh_delete(unit, vpn, vp); 9097 if (BCM_FAILURE(rv) && rv != BCM_E_NOT_FOUND) { 9098 return rv; 9099 } 9100 9101 (void)bcmi_gh2_vxlan_match_clear(unit, vp); 9102 9103 /* Free the VP */ 9104 BCM_IF_ERROR_RETURN(bcmi_gh2_vxlan_vp_free(unit, 1, vp)); 9105 9106 return BCM_E_NONE; 9107 } 9108 9109 /* 9110 * Function: 9111 * bcmi_gh2_vxlan_egress_get 9112 * Purpose: 9113 * Get VXLAN Egress NextHop 9114 * Parameters: 9115 * unit - (IN) Device Number 9116 * egr - (OUT) L3 Egress object info 9117 * nh_index - (IN) nh_index 9118 * Returns: 9119 * BCM_E_XXX 9120 */ 9121 int 9122 bcmi_gh2_vxlan_egress_get(int unit, bcm_l3_egress_t *egr, int nh_index) 9123 { 9124 int int_l3_flag; 9125 int_l3_flag = BCM_XGS3_L3_ENT_FLAG(BCM_XGS3_L3_TBL_PTR(unit, next_hop), 9126 nh_index); 9127 9128 /* Input parameter check */ 9129 if (NULL == egr) { 9130 return BCM_E_PARAM; 9131 } 9132 9133 if (int_l3_flag == _BCM_L3_VXLAN_ONLY) { 9134 egr->flags |= BCM_L3_VXLAN_ONLY; 9135 } 9136 9137 return BCM_E_NONE; 9138 } 9139 9140 /* 9141 * Function: 9142 * bcmi_gh2_vxlan_port_vlan_get 9143 * Purpose: 9144 * Obtain vlan information 9145 * Parameters: 9146 * unit - (IN) Device Number 9147 * vp - (IN) Virtual Port 9148 * vxlan_port - (OUT) VXLAN port information 9149 * Returns: 9150 * BCM_E_XXX 9151 */ 9152 STATIC int 9153 bcmi_gh2_vxlan_port_vlan_get(int unit, int vp, bcm_vxlan_port_t *vxlan_port) 9154 { 9155 int rv = BCM_E_NONE, index = 0; 9156 soc_mem_t mem; 9157 uint32 vent[SOC_MAX_MEM_WORDS], ret_vent[SOC_MAX_MEM_WORDS]; 9158 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 9159 9160 /* Input parameter check */ 9161 if (NULL == vxlan_port) { 9162 return BCM_E_PARAM; 9163 } 9164 9165 /* Get VXLAN bookkeeping info instance */ 9166 BCM_IF_ERROR_RETURN( 9167 gh2_vxlan_bk_info_instance_get(unit, &vxlan_info)); 9168 9169 sal_memset(vent, 0, (sizeof(uint32) * SOC_MAX_MEM_WORDS)); 9170 sal_memset(ret_vent, 0, (sizeof(uint32) * SOC_MAX_MEM_WORDS)); 9171 9172 mem = VLAN_XLATEm; 9173 if (vxlan_info->match_key[vp].flags == _BCM_VXLAN_PORT_MATCH_TYPE_VLAN) { 9174 soc_mem_field32_set(unit, mem, vent, VALIDf, 0x1); 9175 soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, 9176 GH2_VLXLT_HASH_KEY_TYPE_OVID); 9177 soc_mem_field32_set(unit, mem, vent, XLATE__OVIDf, 9178 vxlan_info->match_key[vp].match_vlan); 9179 } else if (vxlan_info->match_key[vp].flags == 9180 _BCM_VXLAN_PORT_MATCH_TYPE_INNER_VLAN) { 9181 soc_mem_field32_set(unit, mem, vent, VALIDf, 0x1); 9182 soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, 9183 GH2_VLXLT_HASH_KEY_TYPE_IVID); 9184 soc_mem_field32_set(unit, mem, vent, XLATE__IVIDf, 9185 vxlan_info->match_key[vp].match_inner_vlan); 9186 } else if (vxlan_info->match_key[vp].flags == 9187 _BCM_VXLAN_PORT_MATCH_TYPE_VLAN_STACKED) { 9188 soc_mem_field32_set(unit, mem, vent, VALIDf, 0x1); 9189 soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, 9190 GH2_VLXLT_HASH_KEY_TYPE_IVID_OVID); 9191 soc_mem_field32_set(unit, mem, vent, XLATE__OVIDf, 9192 vxlan_info->match_key[vp].match_vlan); 9193 soc_mem_field32_set(unit, mem, vent, XLATE__IVIDf, 9194 vxlan_info->match_key[vp].match_inner_vlan); 9195 } else if (vxlan_info->match_key[vp].flags == 9196 _BCM_VXLAN_PORT_MATCH_TYPE_VLAN_PRI) { 9197 soc_mem_field32_set(unit, mem, vent, VALIDf, 0x1); 9198 soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, 9199 GH2_VLXLT_HASH_KEY_TYPE_PRI_CFI); 9200 soc_mem_field32_set(unit, mem, vent, XLATE__OTAGf, 9201 vxlan_info->match_key[vp].match_vlan); 9202 } 9203 9204 if (soc_mem_field32_get(unit, mem, vent, VALIDf)) { 9205 if (vxlan_info->match_key[vp].modid != -1) { 9206 soc_mem_field32_set(unit, mem, vent, XLATE__MODULE_IDf, 9207 vxlan_info->match_key[vp].modid); 9208 soc_mem_field32_set(unit, mem, vent, XLATE__PORT_NUMf, 9209 vxlan_info->match_key[vp].port); 9210 } else { 9211 soc_mem_field32_set(unit, mem, vent, XLATE__Tf, 0x1); 9212 soc_mem_field32_set(unit, mem, vent, XLATE__TGIDf, 9213 vxlan_info->match_key[vp].trunk_id); 9214 } 9215 9216 rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, 9217 &index, vent, ret_vent, 0); 9218 BCM_IF_ERROR_RETURN(rv); 9219 if (!soc_mem_field32_get(unit, mem, ret_vent, 9220 XLATE__DISABLE_VLAN_CHECKSf)) { 9221 vxlan_port->flags |= BCM_VXLAN_PORT_ENABLE_VLAN_CHECKS; 9222 } 9223 } 9224 9225 return rv; 9226 } 9227 9228 /* 9229 * Function: 9230 * bcmi_gh2_vxlan_port_vp_get 9231 * Purpose: 9232 * Get VXLAN port information from a VPN and VP 9233 * Parameters: 9234 * unit - (IN) Device Number 9235 * vpn - (IN) VPN instance ID 9236 * vp - (IN) VPN instance ID 9237 * vxlan_port - (IN/OUT) VXLAN port information 9238 * Returns: 9239 * BCM_E_XXX 9240 */ 9241 STATIC int 9242 bcmi_gh2_vxlan_port_vp_get( 9243 int unit, 9244 bcm_vpn_t vpn, 9245 int vp, 9246 bcm_vxlan_port_t *vxlan_port) 9247 { 9248 int network_port_flag = 0, loopback_port_flag = 0; 9249 bcmi_vxlan_vp_info_t vxlan_vp_info; 9250 int tpid_enable, tpid_index; 9251 uint16 tpid = 0; 9252 uint64 reg_val64; 9253 9254 /* Input parameter check */ 9255 if (NULL == vxlan_port) { 9256 return BCM_E_PARAM; 9257 } 9258 9259 /* Check for Network-Port */ 9260 BCM_IF_ERROR_RETURN( 9261 bcmi_gh2_vxlan_vp_info_get(unit, vp, &vxlan_vp_info)); 9262 if (vxlan_vp_info.flags & GH2_VXLAN_VP_INFO_NETWORK_PORT) { 9263 network_port_flag = TRUE; 9264 } else if (vxlan_vp_info.flags & GH2_VXLAN_VP_INFO_LOOPBACK_PORT) { 9265 loopback_port_flag = TRUE; 9266 } 9267 9268 if (network_port_flag) { 9269 vxlan_port->flags |= BCM_VXLAN_PORT_NETWORK; 9270 vxlan_port->flags |= BCM_VXLAN_PORT_EGRESS_TUNNEL; 9271 vxlan_port->flags |= BCM_VXLAN_PORT_VPN_BASED; 9272 if (vxlan_vp_info.flags & GH2_VXLAN_VP_INFO_SHARED_PORT) { 9273 /* Note: no such case in GH2 */ 9274 vxlan_port->flags |= BCM_VXLAN_PORT_SHARE; 9275 /* Shared VXLAN port is used only for multicast now */ 9276 vxlan_port->flags |= BCM_VXLAN_PORT_MULTICAST; 9277 } 9278 } else if (loopback_port_flag) { 9279 vxlan_port->flags |= BCM_VXLAN_PORT_LOOPBACK; 9280 } 9281 9282 /* Get the match parameters */ 9283 BCM_IF_ERROR_RETURN( 9284 bcmi_gh2_vxlan_match_get(unit, vxlan_port, vp, vpn)); 9285 9286 /* Get the BCM_VXLAN_PORT_ENABLE_VLAN_CHECKS flag */ 9287 BCM_IF_ERROR_RETURN( 9288 bcmi_gh2_vxlan_port_vlan_get(unit, vp, vxlan_port)); 9289 9290 /* 9291 * Get the next-hop parameters, 9292 * - for shared VXLAN port, don't get next hop here 9293 */ 9294 if (!(vxlan_port->flags & BCM_VXLAN_PORT_SHARE)) { 9295 BCM_IF_ERROR_RETURN( 9296 bcmi_gh2_vxlan_port_nh_get(unit, vpn, vp, vxlan_port)); 9297 } 9298 9299 COMPILER_64_ZERO(reg_val64); 9300 9301 /* VXLAN payload outer TPIDs */ 9302 BCM_IF_ERROR_RETURN( 9303 READ_ING_VXLAN_CONTROLr(unit, ®_val64)); 9304 tpid_enable = soc_reg64_field32_get(unit, ING_VXLAN_CONTROLr, 9305 reg_val64, PAYLOAD_OUTER_TPID_ENABLEf); 9306 if (tpid_enable) { 9307 vxlan_port->flags |= BCM_VXLAN_PORT_SERVICE_TAGGED; 9308 9309 tpid_index = 0; 9310 while (tpid_enable) { 9311 /* Get the first found TPID since it is per chip not per VP */ 9312 if (tpid_enable & 0x1) { 9313 BCM_IF_ERROR_RETURN( 9314 _bcm_fb2_outer_tpid_entry_get(unit, &tpid, 9315 tpid_index)); 9316 break; 9317 } 9318 tpid_enable >>= 1; 9319 tpid_index++; 9320 } 9321 9322 vxlan_port->egress_service_tpid = tpid; 9323 } 9324 9325 /* Set VXLAN port ID */ 9326 BCM_GPORT_VXLAN_PORT_ID_SET(vxlan_port->vxlan_port_id, vp); 9327 9328 return BCM_E_NONE; 9329 } 9330 9331 /* 9332 * Function: 9333 * bcmi_gh2_vxlan_port_to_nh_ecmp_index 9334 * Purpose: 9335 * Translate VXLAN port (vp) to Next Hot or ECMP index 9336 * Parameters: 9337 * unit - (IN) Device Number 9338 * vp - (IN) Virtual port number 9339 * ecmp - (OUT) ECMP type 9340 * nh_ecmp_index - (OUT) Next Hot or ECMP index 9341 * Returns: 9342 * BCM_E_XXX. 9343 */ 9344 int 9345 bcmi_gh2_vxlan_port_to_nh_ecmp_index( 9346 int unit, 9347 int vp, 9348 int *ecmp, 9349 int *nh_ecmp_index) 9350 { 9351 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 9352 gh2_vxlan_vp_info_t *vp_info; 9353 9354 if ((NULL == ecmp) || (NULL == nh_ecmp_index)) { 9355 return BCM_E_PARAM; 9356 } 9357 9358 /* Get VXLAN bookkeeping info instance */ 9359 BCM_IF_ERROR_RETURN( 9360 gh2_vxlan_bk_info_instance_get(unit, &vxlan_info)); 9361 9362 if (!bcmi_gh2_vxlan_vp_used_get(unit, vp)) { 9363 return BCM_E_PARAM; 9364 } 9365 9366 vp_info = &(vxlan_info->vxlan_vp_info[vp]); 9367 *ecmp = vp_info->ecmp; 9368 *nh_ecmp_index = vp_info->nh_ecmp_index; 9369 9370 return BCM_E_NONE; 9371 } 9372 9373 /* 9374 * Function: 9375 * bcmi_gh2_vxlan_port_from_nh_ecmp_index 9376 * Purpose: 9377 * Translate Next Hot or ECMP index to VXLAN port (vp) 9378 * Parameters: 9379 * unit - (IN) Device Number 9380 * ecmp - (IN) ECMP type 9381 * nh_ecmp_index - (IN) Next Hot or ECMP index 9382 * vp - (OUT) Virtual port number 9383 * Returns: 9384 * BCM_E_XXX. 9385 */ 9386 int 9387 bcmi_gh2_vxlan_port_from_nh_ecmp_index( 9388 int unit, 9389 int ecmp, 9390 int nh_ecmp_index, 9391 int *vp) 9392 { 9393 int num_vp, idx; 9394 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 9395 gh2_vxlan_vp_info_t *vp_info; 9396 9397 if (NULL == vp) { 9398 return BCM_E_PARAM; 9399 } 9400 9401 /* Get VXLAN bookkeeping info instance */ 9402 BCM_IF_ERROR_RETURN( 9403 gh2_vxlan_bk_info_instance_get(unit, &vxlan_info)); 9404 9405 num_vp = vxlan_info->num_vxlan_vp; 9406 for (idx = 0; idx < num_vp; idx++) { 9407 if (bcmi_gh2_vxlan_vp_used_get(unit, idx)) { 9408 vp_info = &(vxlan_info->vxlan_vp_info[idx]); 9409 if ((vp_info->ecmp == ecmp) && 9410 (vp_info->nh_ecmp_index == nh_ecmp_index)) { 9411 break; 9412 } 9413 } 9414 } 9415 9416 if (idx == num_vp) { 9417 return BCM_E_NOT_FOUND; 9418 } 9419 9420 *vp = idx; 9421 9422 return BCM_E_NONE; 9423 } 9424 9425 /* 9426 * Function: 9427 * bcmi_gh2_vxlan_port_add 9428 * Purpose: 9429 * Add VXLAN port to a VPN 9430 * Parameters: 9431 * unit - (IN) Device Number 9432 * vpn - (IN) VPN instance ID 9433 * vxlan_port - (IN/OUT) vxlan_port information (OUT : vxlan_port_id) 9434 * Returns: 9435 * BCM_E_XXX 9436 */ 9437 int 9438 bcmi_gh2_vxlan_port_add( 9439 int unit, 9440 bcm_vpn_t vpn, 9441 bcm_vxlan_port_t *vxlan_port) 9442 { 9443 int rv = BCM_E_PARAM; 9444 int mode = 0; 9445 uint8 is_eline = 0; 9446 9447 /* L3 egress mode check */ 9448 BCM_IF_ERROR_RETURN( 9449 bcm_xgs3_l3_egress_mode_get(unit, &mode)); 9450 if (!mode) { 9451 LOG_INFO(BSL_LS_BCM_VXLAN, 9452 (BSL_META_U(unit, 9453 "L3 egress mode must be set first\n"))); 9454 return BCM_E_DISABLED; 9455 } 9456 9457 /* Input parameter check */ 9458 if (NULL == vxlan_port) { 9459 return BCM_E_PARAM; 9460 } 9461 9462 if ((vxlan_port->if_class != 0) || (vxlan_port->mtu != 0)) { 9463 return BCM_E_PARAM; 9464 } 9465 9466 if (vxlan_port->criteria == BCM_VXLAN_PORT_MATCH_SHARE) { 9467 if (soc_feature(unit, soc_feature_vp_sharing)) { 9468 if (vpn != BCM_VXLAN_VPN_INVALID) { 9469 return BCM_E_PARAM; 9470 } 9471 } else { 9472 return BCM_E_UNAVAIL; 9473 } 9474 } 9475 9476 /* 9477 * To indicate a network VP is non-sharing for VXLAN-LITE on GH2. 9478 * - the sharing network VP is not supported on GH2 currently 9479 */ 9480 if (vxlan_port->flags & BCM_VXLAN_PORT_VPN_BASED) { 9481 if (!(vxlan_port->flags & BCM_VXLAN_PORT_EGRESS_TUNNEL)) { 9482 return BCM_E_PARAM; 9483 } 9484 } 9485 if (vxlan_port->flags & BCM_VXLAN_PORT_SHARE) { 9486 return BCM_E_UNAVAIL; 9487 } 9488 9489 /* GH2 doesn't have default virtual port support */ 9490 if (vxlan_port->flags & BCM_VXLAN_PORT_DEFAULT) { 9491 return BCM_E_UNAVAIL; 9492 } 9493 9494 /* To indicate a Loopback VP for VXLAN-LITE RIOT support (GH2-B0 only) */ 9495 if (vxlan_port->flags & BCM_VXLAN_PORT_LOOPBACK) { 9496 if (soc_feature(unit, soc_feature_vxlan_lite_riot)) { 9497 /* Loopback VP is only support when VXLAN RIOT is enabled */ 9498 if (!GH2_VXLAN_RIOT_ENABLE(unit)) { 9499 return BCM_E_PARAM; 9500 } 9501 9502 /* Can't set VP as Loopback and Network simultaneously */ 9503 if (vxlan_port->flags & BCM_VXLAN_PORT_NETWORK) { 9504 return BCM_E_PARAM; 9505 } 9506 } else { 9507 return BCM_E_UNAVAIL; 9508 } 9509 } 9510 9511 if (vpn != BCM_VXLAN_VPN_INVALID) { 9512 BCM_IF_ERROR_RETURN( 9513 bcmi_gh2_vxlan_vpn_is_eline(unit, vpn, &is_eline)); 9514 } 9515 9516 /* Currently, VXLAN-LITE only support ELAN */ 9517 if (is_eline == 0) { 9518 rv = bcmi_gh2_vxlan_elan_port_add(unit, vpn, vxlan_port); 9519 } else { 9520 rv = BCM_E_UNAVAIL; 9521 } 9522 9523 return rv; 9524 } 9525 9526 /* 9527 * Function: 9528 * bcmi_gh2_vxlan_port_delete 9529 * Purpose: 9530 * Delete VXLAN port from a VPN 9531 * Parameters: 9532 * unit - (IN) Device Number 9533 * vpn - (IN) VPN instance ID 9534 * vxlan_port_id - (IN) vxlan port information 9535 * Returns: 9536 * BCM_E_XXX 9537 */ 9538 int 9539 bcmi_gh2_vxlan_port_delete( 9540 int unit, 9541 bcm_vpn_t vpn, 9542 bcm_gport_t vxlan_port_id) 9543 { 9544 int rv = BCM_E_UNAVAIL; 9545 int vp = 0; 9546 uint8 is_eline = 0; 9547 9548 /* Check for valid VPN */ 9549 if (vpn != BCM_VXLAN_VPN_INVALID) { 9550 BCM_IF_ERROR_RETURN( 9551 bcmi_gh2_vxlan_vpn_is_valid(unit, vpn)); 9552 } 9553 9554 vp = BCM_GPORT_VXLAN_PORT_ID_GET(vxlan_port_id); 9555 if (vp == -1) { 9556 return BCM_E_PARAM; 9557 } 9558 9559 if (!bcmi_gh2_vxlan_vp_used_get(unit, vp)) { 9560 return BCM_E_NOT_FOUND; 9561 } 9562 9563 BCM_IF_ERROR_RETURN( 9564 bcmi_gh2_vxlan_vp_is_eline(unit, vp, &is_eline)); 9565 9566 /* Currently, VXLAN-LITE only support ELAN */ 9567 if (is_eline == 0) { 9568 rv = bcmi_gh2_vxlan_elan_port_delete(unit, vpn, vp); 9569 } else { 9570 rv = BCM_E_UNAVAIL; 9571 } 9572 9573 return rv; 9574 } 9575 9576 /* 9577 * Function: 9578 * bcmi_gh2_vxlan_port_delete_all 9579 * Purpose: 9580 * Delete all VXLAN ports from a VPN 9581 * Parameters: 9582 * unit - (IN) Device Number 9583 * vpn - (IN) VPN instance ID 9584 * Returns: 9585 * BCM_E_XXX 9586 */ 9587 int 9588 bcmi_gh2_vxlan_port_delete_all(int unit, bcm_vpn_t vpn) 9589 { 9590 int rv = BCM_E_NONE; 9591 int vfi_index = 0; 9592 uint8 is_eline = 0; 9593 bcm_gport_t vxlan_port_id; 9594 uint32 vp = 0, num_vp; 9595 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 9596 gh2_vxlan_vp_info_t *vp_info; 9597 9598 /* Get VXLAN bookkeeping info instance */ 9599 BCM_IF_ERROR_RETURN( 9600 gh2_vxlan_bk_info_instance_get(unit, &vxlan_info)); 9601 9602 if (vpn != BCM_VXLAN_VPN_INVALID) { 9603 _BCM_VXLAN_VPN_GET(vfi_index, _BCM_VPN_TYPE_VFI, vpn); 9604 BCM_IF_ERROR_RETURN( 9605 bcmi_gh2_vxlan_vpn_is_eline(unit, vpn, &is_eline)); 9606 } else { 9607 vfi_index = _BCM_VXLAN_VFI_INVALID; 9608 } 9609 9610 if (is_eline == 0x1) { 9611 /* VXLAN-LITE doesn't have ELINE support */ 9612 return BCM_E_UNAVAIL; 9613 } 9614 9615 /* Currently, VXLAN-LITE only support ELAN (is_eline = 0x0) */ 9616 num_vp = vxlan_info->num_vxlan_vp; 9617 9618 SHR_BIT_ITER(vxlan_info->vxlan_vp_bitmap, num_vp, vp) { 9619 vp_info = &(vxlan_info->vxlan_vp_info[vp]); 9620 if (vp_info->vfi == vfi_index) { 9621 /* Set VXLAN port ID */ 9622 BCM_GPORT_VXLAN_PORT_ID_SET(vxlan_port_id, vp); 9623 rv = bcmi_gh2_vxlan_port_delete(unit, vpn, vxlan_port_id); 9624 if (BCM_FAILURE(rv)) { 9625 /* 9626 * Need to take care rv == BCM_E_DISABLED case 9627 * since L3 Egress Mode could be disabled after L3 initialized 9628 */ 9629 if ((rv != BCM_E_NOT_FOUND) && (rv != BCM_E_DISABLED)) { 9630 return rv; 9631 } 9632 } 9633 } 9634 } 9635 9636 return BCM_E_NONE; 9637 } 9638 9639 /* 9640 * Function: 9641 * bcmi_gh2_vxlan_port_get 9642 * Purpose: 9643 * Get an VXLAN port from a VPN 9644 * Parameters: 9645 * unit - (IN) Device Number 9646 * vpn - (IN) VPN instance ID 9647 * vxlan_port - (IN/OUT) VXLAN port information 9648 */ 9649 int 9650 bcmi_gh2_vxlan_port_get( 9651 int unit, 9652 bcm_vpn_t vpn, 9653 bcm_vxlan_port_t *vxlan_port) 9654 { 9655 int vp = 0; 9656 9657 /* Input parameter check */ 9658 if (NULL == vxlan_port) { 9659 return BCM_E_PARAM; 9660 } 9661 9662 vp = BCM_GPORT_VXLAN_PORT_ID_GET(vxlan_port->vxlan_port_id); 9663 if (vp == -1) { 9664 return BCM_E_PARAM; 9665 } 9666 9667 if (!bcmi_gh2_vxlan_vp_used_get(unit, vp)) { 9668 return BCM_E_NOT_FOUND; 9669 } 9670 9671 if (vpn != BCM_VXLAN_VPN_INVALID) { 9672 BCM_IF_ERROR_RETURN( 9673 bcmi_gh2_vxlan_vpn_is_valid(unit, vpn)); 9674 } 9675 9676 BCM_IF_ERROR_RETURN( 9677 bcmi_gh2_vxlan_port_vp_get(unit, vpn, vp, vxlan_port)); 9678 9679 return BCM_E_NONE; 9680 } 9681 9682 /* 9683 * Function: 9684 * bcmi_gh2_vxlan_port_get_all 9685 * Purpose: 9686 * Get all VXLAN ports from a VPN 9687 * Parameters: 9688 * unit - (IN) Device Number 9689 * vpn - (IN) VPN instance ID 9690 * port_max - (IN) Maximum number of interfaces in array 9691 * port_array - (OUT) Array of VXLAN ports 9692 * port_count - (OUT) Number of interfaces in array 9693 */ 9694 int 9695 bcmi_gh2_vxlan_port_get_all( 9696 int unit, 9697 bcm_vpn_t vpn, 9698 int port_max, 9699 bcm_vxlan_port_t *port_array, 9700 int *port_count) 9701 { 9702 int vp; 9703 int vfi_index = -1; 9704 uint8 is_eline = 0; 9705 int num_vp; 9706 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 9707 gh2_vxlan_vp_info_t *vp_info; 9708 9709 /* Input parameter check */ 9710 if ((NULL == port_array) || (NULL == port_count)) { 9711 return BCM_E_PARAM; 9712 } 9713 9714 /* Get VXLAN bookkeeping info instance */ 9715 BCM_IF_ERROR_RETURN( 9716 gh2_vxlan_bk_info_instance_get(unit, &vxlan_info)); 9717 9718 if (vpn != BCM_VXLAN_VPN_INVALID) { 9719 _BCM_VXLAN_VPN_GET(vfi_index, _BCM_VPN_TYPE_VFI, vpn); 9720 BCM_IF_ERROR_RETURN( 9721 bcmi_gh2_vxlan_vpn_is_eline(unit, vpn, &is_eline)); 9722 } else { 9723 vfi_index = _BCM_VXLAN_VFI_INVALID; 9724 } 9725 9726 if (is_eline == 0x1) { 9727 /* VXLAN-LITE doesn't have ELINE support */ 9728 return BCM_E_UNAVAIL; 9729 } else { 9730 /* Currently, VXLAN-LITE only support ELAN (is_eline = 0x0) */ 9731 *port_count = 0; 9732 num_vp = vxlan_info->num_vxlan_vp; 9733 9734 SHR_BIT_ITER(vxlan_info->vxlan_vp_bitmap, num_vp, vp) { 9735 vp_info = &(vxlan_info->vxlan_vp_info[vp]); 9736 if ((vp_info->vp_type) && (vp_info->vfi == vfi_index)) { 9737 /* Check if number of ports is requested */ 9738 if (port_max == 0) { 9739 (*port_count)++; 9740 continue; 9741 } else if (*port_count == port_max) { 9742 break; 9743 } 9744 9745 BCM_IF_ERROR_RETURN( 9746 bcmi_gh2_vxlan_port_vp_get(unit, vpn, 9747 vp, &port_array[*port_count])); 9748 (*port_count)++; 9749 } 9750 } 9751 9752 if (*port_count == 0) { 9753 return BCM_E_NOT_FOUND; 9754 } 9755 } 9756 9757 return BCM_E_NONE; 9758 } 9759 9760 /* 9761 * Function: 9762 * bcmi_gh2_vxlan_port_traverse 9763 * Purpose: 9764 * Get information about a port instance 9765 * Parameters: 9766 * unit - (IN) Device Number 9767 * cb - (IN) User-provided callback 9768 * user_data - (IN/OUT) callback user data 9769 * Returns: 9770 * BCM_E_XXX 9771 */ 9772 int 9773 bcmi_gh2_vxlan_port_traverse( 9774 int unit, 9775 bcm_vxlan_port_traverse_cb cb, 9776 void *user_data) 9777 { 9778 int rv = BCM_E_NONE; 9779 int idx = 0, num_vp = 0; 9780 bcm_vxlan_port_t info; 9781 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 9782 9783 if (NULL == cb) { 9784 return BCM_E_PARAM; 9785 } 9786 9787 /* Get VXLAN bookkeeping info instance */ 9788 BCM_IF_ERROR_RETURN( 9789 gh2_vxlan_bk_info_instance_get(unit, &vxlan_info)); 9790 9791 num_vp = vxlan_info->num_vxlan_vp; 9792 for (idx = 0; idx < num_vp; idx++) { 9793 if (bcmi_gh2_vxlan_vp_used_get(unit, idx)) { 9794 bcm_vxlan_port_t_init(&info); 9795 9796 rv = bcmi_gh2_vxlan_port_vp_get(unit, BCM_VXLAN_VPN_INVALID, 9797 idx, &info); 9798 if (BCM_SUCCESS(rv)) { 9799 BCM_IF_ERROR_RETURN( 9800 cb(unit, &info, user_data)); 9801 } 9802 } 9803 } 9804 9805 return rv; 9806 } 9807 9808 /* 9809 * Function: 9810 * bcmi_gh2_vxlan_egress_entry_mac_replace 9811 * Purpose: 9812 * Replace VXLAN egress MAC entry 9813 * Parameters: 9814 * unit - (IN) Device Number 9815 * nh_index - (IN) Egress L3 NH idx 9816 * egr - (IN) Egress forwarding destination 9817 */ 9818 int 9819 bcmi_gh2_vxlan_egress_entry_mac_replace( 9820 int unit, 9821 int nh_index, 9822 bcm_l3_egress_t *egr) 9823 { 9824 egr_l3_next_hop_entry_t egr_nh; 9825 uint32 new_macda_index = -1, old_macda_index = -1; 9826 void *entries[1]; 9827 int rv = BCM_E_NONE; 9828 int entry_type; 9829 egr_mac_da_profile_entry_t old_macda_entry, new_macda_entry; 9830 9831 /* Parameter Check */ 9832 if (egr == NULL) { 9833 return BCM_E_PARAM; 9834 } 9835 if (nh_index < soc_mem_index_min(unit, EGR_L3_NEXT_HOPm) || 9836 nh_index > soc_mem_index_max(unit, EGR_L3_NEXT_HOPm)) { 9837 return BCM_E_PARAM; 9838 } 9839 9840 BCM_IF_ERROR_RETURN( 9841 soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 9842 nh_index, &egr_nh)); 9843 entry_type = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 9844 ENTRY_TYPEf); 9845 /* Replace vxlan egress mac da */ 9846 if (entry_type == 0xa) { 9847 /* Get old mac_da_profile info */ 9848 old_macda_index = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 9849 VXLAN__MAC_DA_PROFILE_INDEXf); 9850 sal_memset(&old_macda_entry, 0, sizeof(old_macda_entry)); 9851 BCM_IF_ERROR_RETURN( 9852 soc_mem_read(unit, EGR_MAC_DA_PROFILEm, MEM_BLOCK_ANY, 9853 old_macda_index, &old_macda_entry)); 9854 /* Delete old mac_da_profile index */ 9855 BCM_IF_ERROR_RETURN( 9856 _bcm_mac_da_profile_entry_delete(unit, old_macda_index)); 9857 9858 /* Add new mac_da_profile index */ 9859 sal_memset(&new_macda_entry, 0, sizeof(new_macda_entry)); 9860 soc_mem_mac_addr_set(unit, EGR_MAC_DA_PROFILEm, &new_macda_entry, 9861 MAC_ADDRESSf, egr->mac_addr); 9862 entries[0] = &new_macda_entry; 9863 rv = _bcm_mac_da_profile_entry_add(unit, entries, 9864 1, &new_macda_index); 9865 if (BCM_FAILURE(rv)) { 9866 /* Restore previous old mac_da_profile info */ 9867 entries[0] = &old_macda_entry; 9868 BCM_IF_ERROR_RETURN( 9869 _bcm_mac_da_profile_entry_add(unit, entries, 9870 1, &new_macda_index)); 9871 } 9872 9873 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 9874 VXLAN__MAC_DA_PROFILE_INDEXf, new_macda_index); 9875 BCM_IF_ERROR_RETURN( 9876 soc_mem_write(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ALL, 9877 nh_index, &egr_nh)); 9878 } 9879 9880 return rv; 9881 } 9882 9883 #ifndef BCM_SW_STATE_DUMP_DISABLE 9884 /* 9885 * Function: 9886 * bcmi_gh2_vxlan_sw_dump 9887 * Purpose: 9888 * Displays VXLAN information maintained by software. 9889 * Parameters: 9890 * unit - (IN) Device Number 9891 * Returns: 9892 * None 9893 */ 9894 void 9895 bcmi_gh2_vxlan_sw_dump(int unit) 9896 { 9897 int i, num_tnl, num_vp, num_vfi; 9898 bcm_ip6_t dip6, sip6; 9899 bcmi_gh2_vxlan_bookkeeping_t *vxlan_info; 9900 9901 /* Get VXLAN bookkeeping info instance */ 9902 (void)gh2_vxlan_bk_info_instance_get(unit, &vxlan_info); 9903 9904 num_tnl = vxlan_info->num_vxlan_tnl; 9905 LOG_CLI((BSL_META_U(unit, 9906 "Tunnel Initiator Endpoints:\n"))); 9907 for (i = 0; i < num_tnl; i++) { 9908 if (vxlan_info->vxlan_tunnel_init[i].dip != 0 && 9909 vxlan_info->vxlan_tunnel_init[i].sip != 0) { 9910 /* Tunnel for IPv4 */ 9911 LOG_CLI((BSL_META_U(unit, 9912 "Tunnel idx:%d, sip:%x, dip:%x, vlan:%x\n"), i, 9913 vxlan_info->vxlan_tunnel_init[i].sip, 9914 vxlan_info->vxlan_tunnel_init[i].dip, 9915 vxlan_info->vxlan_tunnel_init[i].vlan)); 9916 } else if (!bcmi_gh2_vxlan_tunnel_ip6_is_zero 9917 (vxlan_info->vxlan_tunnel_init[i].dip6) && 9918 !bcmi_gh2_vxlan_tunnel_ip6_is_zero 9919 (vxlan_info->vxlan_tunnel_init[i].sip6)) { 9920 /* Tunnel for IPv6 */ 9921 sal_memcpy(sip6, 9922 vxlan_info->vxlan_tunnel_init[i].sip6, 9923 BCM_IP6_ADDRLEN); 9924 sal_memcpy(dip6, 9925 vxlan_info->vxlan_tunnel_init[i].dip6, 9926 BCM_IP6_ADDRLEN); 9927 LOG_CLI((BSL_META_U 9928 (unit, "Tunnel idx:%d, " 9929 "sip6:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x, " 9930 "dip6:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x, " 9931 "vlan:%x\n"), i, 9932 sip6[0], sip6[1], sip6[2], sip6[3], sip6[4], sip6[5], 9933 sip6[6], sip6[7], sip6[8], sip6[9], sip6[10], sip6[11], 9934 sip6[12], sip6[13], sip6[14], sip6[15], 9935 dip6[0], dip6[1], dip6[2], dip6[3], dip6[4], dip6[5], 9936 dip6[6], dip6[7], dip6[8], dip6[9], dip6[10], dip6[11], 9937 dip6[12], dip6[13], dip6[14], dip6[15], 9938 vxlan_info->vxlan_tunnel_init[i].vlan)); 9939 } 9940 } 9941 9942 LOG_CLI((BSL_META_U(unit, 9943 "\nTunnel Terminator Endpoints:\n"))); 9944 for (i = 0; i < num_tnl; i++) { 9945 if (vxlan_info->vxlan_tunnel_term[i].dip != 0 && 9946 vxlan_info->vxlan_tunnel_term[i].sip != 0) { 9947 /* Tunnel for IPv4 */ 9948 LOG_CLI((BSL_META_U(unit, 9949 "Tunnel idx:%d, sip:%x, dip:%x, vlan:%x\n"), i, 9950 vxlan_info->vxlan_tunnel_term[i].sip, 9951 vxlan_info->vxlan_tunnel_term[i].dip, 9952 vxlan_info->vxlan_tunnel_term[i].vlan)); 9953 } else if (!bcmi_gh2_vxlan_tunnel_ip6_is_zero 9954 (vxlan_info->vxlan_tunnel_term[i].dip6) && 9955 !bcmi_gh2_vxlan_tunnel_ip6_is_zero 9956 (vxlan_info->vxlan_tunnel_term[i].sip6)) { 9957 /* Tunnel for IPv6 */ 9958 sal_memcpy(sip6, 9959 vxlan_info->vxlan_tunnel_term[i].sip6, 9960 BCM_IP6_ADDRLEN); 9961 sal_memcpy(dip6, 9962 vxlan_info->vxlan_tunnel_term[i].dip6, 9963 BCM_IP6_ADDRLEN); 9964 LOG_CLI((BSL_META_U 9965 (unit, "Tunnel idx:%d, " 9966 "sip6:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x, " 9967 "dip6:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x, " 9968 "vlan:%x\n"), i, 9969 sip6[0], sip6[1], sip6[2], sip6[3], sip6[4], sip6[5], 9970 sip6[6], sip6[7], sip6[8], sip6[9], sip6[10], sip6[11], 9971 sip6[12], sip6[13], sip6[14], sip6[15], 9972 dip6[0], dip6[1], dip6[2], dip6[3], dip6[4], dip6[5], 9973 dip6[6], dip6[7], dip6[8], dip6[9], dip6[10], dip6[11], 9974 dip6[12], dip6[13], dip6[14], dip6[15], 9975 vxlan_info->vxlan_tunnel_term[i].vlan)); 9976 } 9977 } 9978 9979 num_vp = vxlan_info->num_vxlan_vp; 9980 LOG_CLI((BSL_META_U(unit, 9981 "\n Match Info : \n"))); 9982 for (i = 0; i < num_vp; i++) { 9983 if ((vxlan_info->match_key[i].trunk_id == 0 || 9984 vxlan_info->match_key[i].trunk_id == -1) && 9985 (vxlan_info->match_key[i].modid == 0 || 9986 vxlan_info->match_key[i].modid == -1) && 9987 (vxlan_info->match_key[i].port == 0) && 9988 (vxlan_info->match_key[i].flags == 0)) { 9989 continue; 9990 } 9991 LOG_CLI((BSL_META_U(unit, 9992 "\n VXLAN port vp = %d\n"), i)); 9993 LOG_CLI((BSL_META_U(unit, 9994 "Flags = %x\n"), vxlan_info->match_key[i].flags)); 9995 LOG_CLI((BSL_META_U(unit, 9996 "Index = %x\n"), vxlan_info->match_key[i].index)); 9997 LOG_CLI((BSL_META_U(unit, 9998 "TGID = %d\n"), vxlan_info->match_key[i].trunk_id)); 9999 LOG_CLI((BSL_META_U(unit, 10000 "Modid = %d\n"), vxlan_info->match_key[i].modid)); 10001 LOG_CLI((BSL_META_U(unit, 10002 "Port = %d\n"), vxlan_info->match_key[i].port)); 10003 LOG_CLI((BSL_META_U(unit, 10004 "Match VLAN = %d\n"), 10005 vxlan_info->match_key[i].match_vlan)); 10006 LOG_CLI((BSL_META_U(unit, 10007 "Match Inner VLAN = %d\n"), 10008 vxlan_info->match_key[i].match_inner_vlan)); 10009 LOG_CLI((BSL_META_U(unit, 10010 "Match tunnel Index = %x\n"), 10011 vxlan_info->match_key[i].match_tunnel_index)); 10012 LOG_CLI((BSL_META_U(unit, 10013 "Match count = %x\n"), 10014 vxlan_info->match_key[i].match_count)); 10015 LOG_CLI((BSL_META_U(unit, 10016 "Related VFI = %d\n"), 10017 vxlan_info->match_key[i].vfi)); 10018 } 10019 10020 num_vfi = vxlan_info->num_vxlan_vfi; 10021 LOG_CLI((BSL_META_U(unit, 10022 "\nVxlan VPN INFO:\n"))); 10023 for (i = 0; i < num_vfi; i++) { 10024 if (vxlan_info->vxlan_vpn_info[i].valid != 0 || 10025 vxlan_info->vxlan_vpn_info[i].vnid != 0) { 10026 LOG_CLI((BSL_META_U(unit, 10027 "\nVxlan VPN VFI %d:\n"), i)); 10028 LOG_CLI((BSL_META_U(unit, 10029 "VXLAN VPN VFI VALID = %x \n"), 10030 vxlan_info->vxlan_vpn_info[i].valid)); 10031 LOG_CLI((BSL_META_U(unit, 10032 "VXLAN VPN VNID = %d \n"), 10033 vxlan_info->vxlan_vpn_info[i].vnid)); 10034 } 10035 } 10036 10037 LOG_CLI((BSL_META_U(unit, 10038 "\nVxlan Outer TPID INFO:\n"))); 10039 for (i = 0; i < vxlan_info->num_vxlan_outer_tpid; i++) { 10040 LOG_CLI((BSL_META_U(unit, 10041 "Index %d: "), i)); 10042 LOG_CLI((BSL_META_U(unit, 10043 "TPID value = %x, "), 10044 vxlan_info->vxlan_outer_tpid[i].tpid_value)); 10045 LOG_CLI((BSL_META_U(unit, 10046 "Ref count = %d \n"), 10047 vxlan_info->vxlan_outer_tpid[i].ref_count)); 10048 } 10049 10050 LOG_CLI((BSL_META_U(unit, 10051 "\nVxlan VLAN translation INFO:\n"))); 10052 for (i = 0; i < vxlan_info->num_vxlan_vfi; i++) { 10053 if (vxlan_info->vxlan_vlan_xlate[i].ref_count != 0) { 10054 LOG_CLI((BSL_META_U(unit, 10055 "Index %d: "), i)); 10056 LOG_CLI((BSL_META_U(unit, 10057 "Ref count = %d \n"), 10058 vxlan_info->vxlan_vlan_xlate[i].ref_count)); 10059 } 10060 } 10061 10062 return; 10063 } 10064 #endif /* BCM_SW_STATE_DUMP_DISABLE */ 10065 10066 #endif /* BCM_GREYHOUND2_SUPPORT && INCLUDE_L3 */ 10067