tunnel.c (23845B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * File: l3.c 8 * Purpose: Triumph2 L3 function implementations 9 */ 10 11 12 #include <soc/defs.h> 13 14 #include <assert.h> 15 #include <shared/bsl.h> 16 #include <sal/core/libc.h> 17 #if defined(BCM_TRIUMPH2_SUPPORT) && defined(INCLUDE_L3) 18 19 #include <shared/util.h> 20 #include <soc/mem.h> 21 #include <soc/cm.h> 22 #include <soc/drv.h> 23 #include <soc/register.h> 24 #include <soc/memory.h> 25 #include <soc/l3x.h> 26 #include <soc/lpm.h> 27 #include <soc/tnl_term.h> 28 #include <soc/defragment.h> 29 30 #include <bcm/l3.h> 31 #include <bcm/tunnel.h> 32 #include <bcm/debug.h> 33 #include <bcm/error.h> 34 #include <bcm/stack.h> 35 36 #include <bcm_int/esw/mbcm.h> 37 #include <bcm_int/esw/firebolt.h> 38 #include <bcm_int/esw/trx.h> 39 #include <bcm_int/esw/triumph2.h> 40 #include <bcm_int/esw/l3.h> 41 #include <bcm_int/esw/xgs3.h> 42 #include <bcm_int/esw/stack.h> 43 #include <bcm_int/esw_dispatch.h> 44 #if defined(BCM_TRIDENT2_SUPPORT) 45 #include <bcm_int/esw/trident2.h> 46 #endif /* BCM_TRIDENT2_SUPPORT*/ 47 #if defined(BCM_TOMAHAWK_SUPPORT) 48 #include <bcm_int/esw/tomahawk.h> 49 #endif /* BCM_TOMAHAWK_SUPPORT */ 50 #include <bcm_int/esw/ecn.h> 51 52 static soc_profile_mem_t *_bcm_tnl_port_bitmap_profile[BCM_MAX_NUM_UNITS]; 53 54 soc_profile_mem_t *_bcm_get_tnl_port_bitmap_profile(int unit) { 55 return _bcm_tnl_port_bitmap_profile[unit]; 56 } 57 58 int 59 _bcm_tnl_port_bitmap_profile_init(int unit) 60 { 61 int i, idx; 62 soc_mem_t mem; 63 int entry_words[1]; 64 void *entries[1]; 65 allowed_port_bitmap_profile_entry_t allowed_ports_profile; 66 void *prof_entry; 67 uint32 ent_sz; 68 int temp_idx = 0, key_type = 0; 69 uint32 entry_ptr[SOC_MAX_MEM_WORDS]; 70 uint32 temp_index = 0; 71 soc_mem_t tunnel_mem = L3_TUNNEL_DOUBLEm; 72 73 /* Create profile table cache (or re-init if it already exists) */ 74 mem = ALLOWED_PORT_BITMAP_PROFILEm; 75 ent_sz = sizeof(allowed_port_bitmap_profile_entry_t); 76 prof_entry = &allowed_ports_profile; 77 78 if (_bcm_tnl_port_bitmap_profile[unit] == NULL) { 79 _bcm_tnl_port_bitmap_profile[unit] = sal_alloc(sizeof(soc_profile_mem_t), 80 "TUNNEL Port bitmap Profile Mem"); 81 if (_bcm_tnl_port_bitmap_profile[unit] == NULL) { 82 return BCM_E_MEMORY; 83 } 84 soc_profile_mem_t_init(_bcm_tnl_port_bitmap_profile[unit]); 85 } 86 87 /* Create profile table cache (or re-init if it already exists) */ 88 entry_words[0] = ent_sz / sizeof(uint32); 89 SOC_IF_ERROR_RETURN( 90 soc_profile_mem_create(unit, &mem, entry_words, 1, 91 _bcm_tnl_port_bitmap_profile[unit])); 92 93 if (SOC_WARM_BOOT(unit)) { 94 95 /* One extra increment to preserve location 96 * ING_ACTION_PROFILE_DEFAULT */ 97 SOC_PROFILE_MEM_REFERENCE(unit, _bcm_tnl_port_bitmap_profile[unit], 98 0, 1); 99 100 for (i = 0; i < soc_mem_index_count(unit, tunnel_mem); i++) { 101 102 sal_memset(prof_entry, 0, ent_sz); 103 SOC_IF_ERROR_RETURN 104 (READ_L3_TUNNEL_DOUBLEm(unit, MEM_BLOCK_ANY, i, &entry_ptr)); 105 idx = soc_mem_field32_get(unit, tunnel_mem, 106 &entry_ptr, BASE_VALID_0f); 107 if (idx == 0) { 108 continue; 109 } 110 111 key_type = soc_mem_field32_get(unit, tunnel_mem, 112 &entry_ptr, KEY_TYPEf); 113 if (key_type == 0) { 114 continue; 115 } 116 /* Check key type to know memory type. */ 117 tunnel_mem = ((key_type == 2) ? 118 L3_TUNNEL_QUADm : L3_TUNNEL_DOUBLEm); 119 120 if (tunnel_mem == L3_TUNNEL_QUADm) { 121 /* If this is quad entry then divide the index by 2. */ 122 temp_idx = i/2; 123 /* Move one index further as two indexes will be used here.*/ 124 i++; 125 SOC_IF_ERROR_RETURN( 126 soc_mem_read(unit, tunnel_mem, MEM_BLOCK_ANY, 127 temp_idx, &entry_ptr)); 128 } 129 130 /* Get the index of ALLOWED_PORT_BITMAP_PROFILE table. */ 131 idx = soc_mem_field32_get(unit, tunnel_mem, entry_ptr, 132 (tunnel_mem == L3_TUNNEL_DOUBLEm) ? 133 IPV4__ALLOWED_PORT_BITMAP_PROFILE_PTRf: 134 IPV6__ALLOWED_PORT_BITMAP_PROFILE_PTRf); 135 136 SOC_PROFILE_MEM_REFERENCE(unit, _bcm_tnl_port_bitmap_profile[unit], idx, 1); 137 SOC_PROFILE_MEM_ENTRIES_PER_SET(unit, _bcm_tnl_port_bitmap_profile[unit], idx, 1); 138 139 } 140 } else { 141 sal_memset(prof_entry, 0, ent_sz); 142 entries[0] = prof_entry; 143 SOC_IF_ERROR_RETURN 144 (soc_profile_mem_add(unit, _bcm_tnl_port_bitmap_profile[unit], 145 (void *) &entries, 1, &temp_index)); 146 147 SOC_PROFILE_MEM_REFERENCE(unit, _bcm_tnl_port_bitmap_profile[unit], 148 0, 149 soc_mem_index_count(unit, tunnel_mem)); 150 } 151 152 return BCM_E_NONE; 153 } 154 155 156 /* 157 * Function: 158 * _bcm_th3_l3_tnl_term_entry_init 159 * Purpose: 160 * Initialize soc tunnel terminator entry key portion. 161 * Parameters: 162 * unit - (IN) BCM device number. 163 * tnl_info - (IN) BCM buffer with tunnel info. 164 * entry - (OUT) SOC buffer with key filled in. 165 * Returns: 166 * BCM_E_XXX 167 */ 168 int 169 _bcm_th3_l3_tnl_term_entry_init(int unit, bcm_tunnel_terminator_t *tnl_info, 170 soc_tunnel_term_t *entry) 171 { 172 uint32 *entry_ptr; /* Filled entry pointer. */ 173 _bcm_tnl_term_type_t tnl_type;/* Tunnel type. */ 174 soc_mem_t mem = L3_TUNNEL_DOUBLEm; 175 uint32 ip6_field[4]; 176 uint8 *ip6 = NULL; 177 soc_field_t protocol_f = IPV4__PROTOCOLf; 178 soc_field_t Bfd_enable_f = IPV4__BFD_ENABLEf; 179 180 /* Input parameters check. */ 181 if ((NULL == tnl_info) || (NULL == entry)) { 182 return (BCM_E_PARAM); 183 } 184 185 /* Get tunnel type & sub_type. */ 186 BCM_IF_ERROR_RETURN 187 (_bcm_xgs3_l3_set_tnl_term_type(unit, tnl_info, &tnl_type)); 188 189 if (tnl_type.tnl_outer_hdr_ipv6 == 1) { 190 mem = L3_TUNNEL_QUADm; 191 } else { 192 mem = L3_TUNNEL_DOUBLEm; 193 } 194 195 /* Reset destination structure. */ 196 sal_memset(entry, 0, sizeof(soc_tunnel_term_t)); 197 198 /* Set Destination/Source pair. */ 199 entry_ptr = (uint32 *)&entry->entry_arr[0]; 200 if (tnl_type.tnl_outer_hdr_ipv6 == 1) { 201 protocol_f = IPV6__PROTOCOLf; 202 Bfd_enable_f = IPV6__BFD_ENABLEf; 203 ip6 = tnl_info->sip6; 204 205 ip6_field[2] = (((ip6[4] & 0x3) << 24) | (ip6[5] << 16) | 206 (ip6[6] << 8) | (ip6[7] << 0)); 207 ip6_field[1] = ((ip6[8] << 24) | (ip6[9] << 16) | 208 (ip6[10] << 8) | (ip6[11] << 0)); 209 ip6_field[0] = ((ip6[12] << 24)| (ip6[13] << 16) | 210 (ip6[14] << 8) | (ip6[15] << 0)); 211 212 /* SIP [0-89] */ 213 soc_mem_field_set(unit, mem, (uint32 *)&entry->entry_arr[0], IPV6__SIP_LWR_90f, ip6_field); 214 /* SIP [90-127] */ 215 ip6_field[1] = (ip6[0] >> 2); 216 ip6_field[0] = ((ip6[1] << 24)| (ip6[2] << 16) | 217 (ip6[3] << 8) | (ip6[4] & 0xfc)); 218 ip6_field[0] = ((ip6[0] & 3) << 30) | (ip6_field[0] >> 2); 219 soc_mem_field_set(unit, mem, (uint32 *)&entry->entry_arr[0], IPV6__SIP_UPR_38f, ip6_field); 220 ip6 = tnl_info->dip6; 221 222 ip6_field[2] = (((ip6[4] & 0x3) << 24) | (ip6[5] << 16) | 223 (ip6[6] << 8) | (ip6[7] << 0)); 224 ip6_field[1] = ((ip6[8] << 24) | (ip6[9] << 16) | 225 (ip6[10] << 8) | (ip6[11] << 0)); 226 ip6_field[0] = ((ip6[12] << 24)| (ip6[13] << 16) | 227 (ip6[14] << 8) | (ip6[15] << 0)); 228 /* DIP [0-89] */ 229 soc_mem_field_set(unit, mem, (uint32 *)&entry->entry_arr[0], IPV6__DIP_LWR_90f, ip6_field); 230 /* DIP [90-127] */ 231 ip6_field[1] = (ip6[0] >> 2); 232 ip6_field[0] = ((ip6[1] << 24)| (ip6[2] << 16) | 233 (ip6[3] << 8) | (ip6[4] & 0xfc)); 234 ip6_field[0] = ((ip6[0] & 3) << 30) | (ip6_field[0] >> 2); 235 soc_mem_field_set(unit, mem, (uint32 *)&entry->entry_arr[0], IPV6__DIP_UPR_38f, ip6_field); 236 237 soc_mem_field32_set(unit, mem, entry_ptr, IPV6__SUB_TUNNEL_TYPEf, 238 tnl_type.tnl_sub_type); 239 240 /* Set tunnel type. */ 241 soc_mem_field32_set(unit, mem, entry_ptr, IPV6__TUNNEL_TYPEf, 242 tnl_type.tnl_auto); 243 } else if (tnl_type.tnl_outer_hdr_ipv6 == 0) { 244 245 /* Set destination ip. */ 246 soc_mem_field32_set(unit, mem, entry_ptr, IPV4__DIPf, tnl_info->dip); 247 248 /* Set source ip. */ 249 soc_mem_field32_set(unit, mem, entry_ptr, IPV4__SIPf, tnl_info->sip); 250 251 /* Set tunnel subtype. */ 252 soc_mem_field32_set(unit, mem, entry_ptr, IPV4__SUB_TUNNEL_TYPEf, 253 tnl_type.tnl_sub_type); 254 255 /* Set tunnel type. */ 256 soc_mem_field32_set(unit, mem, entry_ptr, IPV4__TUNNEL_TYPEf, 257 tnl_type.tnl_auto); 258 } 259 260 261 /* Set valid bit. */ 262 soc_mem_field32_set(unit, mem, entry_ptr, BASE_VALID_0f, 1); 263 soc_mem_field32_set(unit, mem, entry_ptr, BASE_VALID_1f, 2); 264 265 if (tnl_type.tnl_outer_hdr_ipv6 == 1) { 266 soc_mem_field32_set(unit, mem, entry_ptr, BASE_VALID_2f, 2); 267 soc_mem_field32_set(unit, mem, entry_ptr, BASE_VALID_3f, 2); 268 } 269 270 271 /* Set entry mode. */ 272 273 if (SOC_MEM_FIELD_VALID(unit, mem, KEY_TYPEf)) { 274 soc_mem_field32_set(unit, mem, entry_ptr, KEY_TYPEf, 275 tnl_type.tnl_outer_hdr_ipv6 + 1); 276 } 277 278 /* Set the PROTOCOL field */ 279 if ((tnl_info->type == bcmTunnelTypeIpAnyIn4) || 280 (tnl_info->type == bcmTunnelTypeIpAnyIn6)) 281 { 282 /* Set PROTOCOL and PROTOCOL_MASK field to zero for IpAnyInx tunnel type*/ 283 soc_mem_field32_set(unit, mem, entry_ptr, protocol_f, 0x0); 284 } else { 285 soc_mem_field32_set(unit, mem, entry_ptr, protocol_f, 286 tnl_type.tnl_protocol); 287 } 288 289 if (SOC_MEM_FIELD_VALID(unit, mem, Bfd_enable_f)) { 290 soc_mem_field32_set(unit, mem, entry_ptr, Bfd_enable_f, 0); 291 } 292 293 /* AMT tunnels not supported */ 294 295 /* Set GRE payload */ 296 if (tnl_type.tnl_gre) { 297 if (tnl_type.tnl_outer_hdr_ipv6 == 1) { 298 /* GRE IPv6 payload is allowed. */ 299 soc_mem_field32_set(unit, mem, entry_ptr, IPV6__GRE_PAYLOAD_IPV6f, 300 tnl_type.tnl_gre_v6_payload); 301 302 /* GRE IPv6 payload is allowed. */ 303 soc_mem_field32_set(unit, mem, entry_ptr, IPV6__GRE_PAYLOAD_IPV4f, 304 tnl_type.tnl_gre_v4_payload); 305 /* Save vlan id for ipmc lookup.*/ 306 if((tnl_info->vlan) && SOC_MEM_FIELD_VALID(unit, mem, IPV6__L3_IIFf)) { 307 soc_mem_field32_set(unit, mem, entry_ptr, IPV6__L3_IIFf, tnl_info->vlan); 308 } 309 310 } else { 311 312 /* GRE IPv6 payload is allowed. */ 313 soc_mem_field32_set(unit, mem, entry_ptr, IPV4__GRE_PAYLOAD_IPV6f, 314 tnl_type.tnl_gre_v6_payload); 315 316 /* GRE IPv6 payload is allowed. */ 317 soc_mem_field32_set(unit, mem, entry_ptr, IPV4__GRE_PAYLOAD_IPV4f, 318 tnl_type.tnl_gre_v4_payload); 319 320 /* Save vlan id for ipmc lookup.*/ 321 if((tnl_info->vlan) && SOC_MEM_FIELD_VALID(unit, mem, IPV4__L3_IIFf)) { 322 soc_mem_field32_set(unit, mem, entry_ptr, IPV4__L3_IIFf, tnl_info->vlan); 323 } 324 } 325 } 326 return (BCM_E_NONE); 327 } 328 329 /* 330 * Function: 331 * _bcm_th3_l3_tnl_term_add 332 * Purpose: 333 * Add tunnel termination entry to the hw. 334 * Parameters: 335 * unit - (IN)SOC unit number. 336 * tnl_info - (IN)Tunnel terminator parameters. 337 * Returns: 338 * BCM_E_XXX 339 */ 340 int 341 _bcm_th3_l3_tnl_term_add(int unit, uint32 *entry_ptr, bcm_tunnel_terminator_t *tnl_info) 342 { 343 bcm_module_t mod_in, mod_out, my_mod; 344 bcm_port_t port_in, port_out; 345 int wlan; 346 int rv; 347 348 /* Program remote port */ 349 if ((tnl_info->type == bcmTunnelTypeWlanWtpToAc) || 350 (tnl_info->type == bcmTunnelTypeWlanAcToAc) || 351 (tnl_info->type == bcmTunnelTypeWlanWtpToAc6) || 352 (tnl_info->type == bcmTunnelTypeWlanAcToAc6)) { 353 wlan = 1; 354 } else { 355 wlan = 0; 356 } 357 358 if (wlan) { 359 if (tnl_info->flags & BCM_TUNNEL_TERM_WLAN_REMOTE_TERMINATE) { 360 if (!BCM_GPORT_IS_MODPORT(tnl_info->remote_port)) { 361 return BCM_E_PARAM; 362 } 363 mod_in = BCM_GPORT_MODPORT_MODID_GET(tnl_info->remote_port); 364 port_in = BCM_GPORT_MODPORT_PORT_GET(tnl_info->remote_port); 365 BCM_IF_ERROR_RETURN 366 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET, mod_in, 367 port_in, &mod_out, &port_out)); 368 if (!SOC_MODID_ADDRESSABLE(unit, mod_out)) { 369 return (BCM_E_BADID); 370 } 371 if (!SOC_PORT_ADDRESSABLE(unit, port_out)) { 372 return (BCM_E_PORT); 373 } 374 soc_L3_TUNNELm_field32_set(unit, entry_ptr, REMOTE_TERM_GPPf, 375 (mod_out << 6) | port_out); 376 } else { 377 /* Send to the local loopback port */ 378 rv = bcm_esw_stk_my_modid_get(unit, &my_mod); 379 BCM_IF_ERROR_RETURN(rv); 380 port_in = 54; 381 mod_in = my_mod; 382 rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET, mod_in, 383 port_in, &mod_out, &port_out); 384 BCM_IF_ERROR_RETURN(rv); 385 386 soc_L3_TUNNELm_field32_set(unit, entry_ptr, REMOTE_TERM_GPPf, 387 (mod_out << 6) | port_out); 388 } 389 #if 0 390 /* Program tunnel id */ 391 if (tnl_info->flags & BCM_TUNNEL_TERM_TUNNEL_WITH_ID) { 392 if (!BCM_GPORT_IS_TUNNEL(tnl_info->tunnel_id)) { 393 return BCM_E_PARAM; 394 } 395 if (SOC_MEM_FIELD_VALID(unit, L3_TUNNELm, TUNNEL_IDf)) { 396 tunnel = BCM_GPORT_TUNNEL_ID_GET(tnl_info->tunnel_id); 397 soc_L3_TUNNELm_field32_set(unit, entry_ptr, TUNNEL_IDf, 398 tunnel); 399 } 400 } 401 #endif 402 403 } 404 return (BCM_E_NONE); 405 } 406 407 /* 408 * Function: 409 * _bcm_tr2_l3_tnl_term_entry_parse 410 * Purpose: 411 * Parse tunnel terminator entry portion. 412 * Parameters: 413 * unit - (IN) BCM device number. 414 * entry - (IN) SOC buffer with tunne information. 415 * tnl_info - (OUT) BCM buffer with tunnel info. 416 * Returns: 417 * BCM_E_XXX 418 */ 419 int 420 _bcm_th3_l3_tnl_term_entry_parse(int unit, soc_tunnel_term_t *entry, 421 bcm_tunnel_terminator_t *tnl_info) 422 { 423 uint32 ip6_field[4]; 424 _bcm_tnl_term_type_t tnl_type; /* Tunnel type information. */ 425 uint32 *entry_ptr; /* Filled entry pointer. */ 426 uint8 *ip6 = NULL; 427 soc_mem_t mem = L3_TUNNEL_DOUBLEm; 428 allowed_port_bitmap_profile_entry_t allowed_ports_profile; 429 void *profile_entries[1]; 430 int prof_id; 431 432 /* Input parameters check. */ 433 if ((NULL == tnl_info) || (NULL == entry)) { 434 return (BCM_E_PARAM); 435 } 436 437 /* Reset destination structure. */ 438 bcm_tunnel_terminator_t_init(tnl_info); 439 sal_memset(&tnl_type, 0, sizeof(_bcm_tnl_term_type_t)); 440 441 entry_ptr = (uint32 *)&entry->entry_arr[0]; 442 443 /* Get valid bit. */ 444 if (!soc_mem_field32_get(unit, mem, entry_ptr, BASE_VALID_0f)) { 445 return (BCM_E_NOT_FOUND); 446 } 447 448 if (SOC_MEM_FIELD_VALID(unit, mem, KEY_TYPEf)) { 449 tnl_type.tnl_outer_hdr_ipv6 = 450 soc_mem_field32_get(unit, mem, entry_ptr, KEY_TYPEf) - 1; 451 452 } 453 454 /* Get Destination/Source pair. */ 455 if (tnl_type.tnl_outer_hdr_ipv6 == 1) { 456 mem = L3_TUNNEL_QUADm; 457 ip6 = tnl_info->sip6; 458 /* SIP [0-89] */ 459 soc_mem_field_get(unit, mem, (uint32 *)&entry->entry_arr[0], IPV6__SIP_LWR_90f, ip6_field); 460 461 ip6[4] = (ip6_field[2] >> 24) & 0x3; 462 ip6[5] = (ip6_field[2] >> 16) & 0xff; 463 ip6[6] = (ip6_field[2] >> 8) & 0xff; 464 ip6[7] = (ip6_field[2] & 0xff); 465 466 ip6[8] = (ip6_field[1] >> 24) & 0xff; 467 ip6[9] = (ip6_field[1] >> 16) & 0xff; 468 ip6[10] = (ip6_field[1] >> 8) & 0xff; 469 ip6[11] = (ip6_field[1] & 0xff); 470 471 ip6[12] = (ip6_field[0] >> 24) & 0xff; 472 ip6[13] = (ip6_field[0] >> 16) & 0xff; 473 ip6[14] = (ip6_field[0] >> 8) & 0xff; 474 ip6[15] = (ip6_field[0] & 0xff); 475 476 /* SIP [90-127] */ 477 soc_mem_field_get(unit, mem, (uint32 *)&entry->entry_arr[0], IPV6__SIP_UPR_38f, ip6_field); 478 ip6[0] = (ip6_field[0] >> 30); 479 ip6_field[1] <<= 2; 480 ip6_field[0] <<= 2; 481 ip6[0] |= (ip6_field[1] & 0xff); 482 ip6[1] = (ip6_field[0] >> 24) & 0xff; 483 ip6[2] = (ip6_field[0] >> 16) & 0xff; 484 ip6[3] = (ip6_field[0] >> 8) & 0xff; 485 ip6[4] |= (ip6_field[0] & 0xff); 486 487 ip6 = tnl_info->dip6; 488 /* DIP [0-89] */ 489 soc_mem_field_get(unit, mem, (uint32 *)&entry->entry_arr[0], IPV6__DIP_LWR_90f, ip6_field); 490 ip6[4] = (ip6_field[2] >> 24) & 0x3; 491 ip6[5] = (ip6_field[2] >> 16) & 0xff; 492 ip6[6] = (ip6_field[2] >> 8) & 0xff; 493 ip6[7] = (ip6_field[2] & 0xff); 494 495 ip6[8] = (ip6_field[1] >> 24) & 0xff; 496 ip6[9] = (ip6_field[1] >> 16) & 0xff; 497 ip6[10] = (ip6_field[1] >> 8) & 0xff; 498 ip6[11] = (ip6_field[1] & 0xff); 499 500 ip6[12] = (ip6_field[0] >> 24) & 0xff; 501 ip6[13] = (ip6_field[0] >> 16) & 0xff; 502 ip6[14] = (ip6_field[0] >> 8) & 0xff; 503 ip6[15] = (ip6_field[0] & 0xff); 504 505 /* DIP [90-127] */ 506 soc_mem_field_get(unit, mem, (uint32 *)&entry->entry_arr[0], IPV6__DIP_UPR_38f, ip6_field); 507 ip6[0] = (ip6_field[0] >> 30); 508 ip6_field[1] <<= 2; 509 ip6_field[0] <<= 2; 510 ip6[0] |= (ip6_field[1] & 0xff); 511 ip6[1] = (ip6_field[0] >> 24) & 0xff; 512 ip6[2] = (ip6_field[0] >> 16) & 0xff; 513 ip6[3] = (ip6_field[0] >> 8) & 0xff; 514 ip6[4] |= (ip6_field[0] & 0xff); 515 516 } else if (tnl_type.tnl_outer_hdr_ipv6 == 0) { 517 /* Get destination ip. */ 518 tnl_info->dip = soc_mem_field32_get(unit, mem, entry_ptr, IPV4__DIPf); 519 520 /* Get source ip. */ 521 tnl_info->sip = soc_mem_field32_get(unit, mem, entry_ptr, IPV4__SIPf); 522 523 /* Destination subnet mask. */ 524 tnl_info->dip_mask = BCM_XGS3_L3_IP4_FULL_MASK; 525 526 } 527 528 /* Get tunnel subtype. */ 529 tnl_type.tnl_sub_type = 530 soc_mem_field32_get(unit, mem, entry_ptr, (mem == L3_TUNNEL_DOUBLEm) ? IPV4__SUB_TUNNEL_TYPEf:IPV6__SUB_TUNNEL_TYPEf); 531 532 prof_id = soc_mem_field32_get(unit, mem, entry_ptr, 533 (mem == L3_TUNNEL_DOUBLEm) ? 534 IPV4__ALLOWED_PORT_BITMAP_PROFILE_PTRf: 535 IPV6__ALLOWED_PORT_BITMAP_PROFILE_PTRf); 536 profile_entries[0] = &allowed_ports_profile; 537 soc_profile_mem_get(unit, _bcm_get_tnl_port_bitmap_profile(unit), prof_id, 538 1, profile_entries); 539 soc_mem_pbmp_field_get(unit, ALLOWED_PORT_BITMAP_PROFILEm, 540 &allowed_ports_profile, 541 ING_PORT_BITMAPf, &tnl_info->pbmp); 542 543 /* Get UDP tunnel type. */ 544 if (soc_mem_field_valid(unit, mem, IPV4__UDP_TUNNEL_TYPEf)) { 545 tnl_type.tnl_udp_type = 546 soc_mem_field32_get(unit, mem, entry_ptr, IPV4__UDP_TUNNEL_TYPEf); 547 } 548 /* Get tunnel type. */ 549 tnl_type.tnl_auto = 550 soc_mem_field32_get(unit, mem, entry_ptr, (mem == L3_TUNNEL_DOUBLEm) ? IPV4__TUNNEL_TYPEf: IPV6__TUNNEL_TYPEf); 551 552 /* Copy DSCP from outer header flag. */ 553 if (soc_mem_field32_get(unit, mem, entry_ptr, (mem == L3_TUNNEL_DOUBLEm) ? IPV4__USE_OUTER_HDR_DSCPf: IPV6__USE_OUTER_HDR_DSCPf)) { 554 tnl_info->flags |= BCM_TUNNEL_TERM_USE_OUTER_DSCP; 555 } 556 /* Copy TTL from outer header flag. */ 557 if (soc_mem_field32_get(unit, mem, entry_ptr, (mem == L3_TUNNEL_DOUBLEm) ? IPV4__USE_OUTER_HDR_TTLf: IPV6__USE_OUTER_HDR_TTLf)) { 558 tnl_info->flags |= BCM_TUNNEL_TERM_USE_OUTER_TTL; 559 } 560 /* Keep inner header DSCP flag. */ 561 if (soc_mem_field32_get(unit, mem, entry_ptr, 562 (mem == L3_TUNNEL_DOUBLEm) ? IPV4__DONOT_CHANGE_INNER_HDR_DSCPf:IPV6__DONOT_CHANGE_INNER_HDR_DSCPf)) { 563 tnl_info->flags |= BCM_TUNNEL_TERM_KEEP_INNER_DSCP; 564 } 565 566 /* Tunnel or IPMC lookup vlan id */ 567 tnl_info->vlan = soc_mem_field32_get(unit, mem, entry_ptr, (mem == L3_TUNNEL_DOUBLEm) ? IPV4__IINTFf:IPV6__IINTFf); 568 569 /* Get trust dscp per tunnel */ 570 if (soc_mem_field32_get(unit, mem, entry_ptr, (mem == L3_TUNNEL_DOUBLEm) ? IPV4__USE_OUTER_HDR_DSCPf:IPV6__USE_OUTER_HDR_DSCPf)) { 571 tnl_info->flags |= BCM_TUNNEL_TERM_DSCP_TRUST; 572 } 573 574 /* Get Tunnel class id for VFP match */ 575 tnl_info->tunnel_class = soc_mem_field32_get(unit, mem, entry_ptr, 576 (mem == L3_TUNNEL_DOUBLEm) ? IPV4__TUNNEL_CLASS_IDf:IPV6__TUNNEL_CLASS_IDf); 577 578 /* Get the protocol field and make some decisions */ 579 tnl_type.tnl_protocol = soc_mem_field32_get(unit, mem, entry_ptr, 580 (mem == L3_TUNNEL_DOUBLEm) ? IPV4__PROTOCOLf:IPV6__PROTOCOLf); 581 switch (tnl_type.tnl_protocol) { 582 case 0x2F: 583 tnl_type.tnl_gre = 1; 584 break; 585 case 0x67: 586 tnl_type.tnl_pim_sm = 1; 587 default: 588 break; 589 } 590 /* Get gre IPv4 payload allowed. */ 591 tnl_type.tnl_gre_v4_payload = 592 soc_mem_field32_get(unit, mem, entry_ptr, (mem == L3_TUNNEL_DOUBLEm) ? IPV4__GRE_PAYLOAD_IPV4f:IPV6__GRE_PAYLOAD_IPV4f); 593 594 /* Get gre IPv6 payload allowed. */ 595 tnl_type.tnl_gre_v6_payload = 596 soc_mem_field32_get(unit, mem, entry_ptr, (mem == L3_TUNNEL_DOUBLEm) ? IPV4__GRE_PAYLOAD_IPV6f:IPV6__GRE_PAYLOAD_IPV6f); 597 598 /* Get the L4 data */ 599 if (soc_mem_field_valid (unit, mem, L4_SRC_PORTf)) { 600 tnl_info->udp_src_port = soc_mem_field32_get(unit, mem, entry_ptr, 601 (mem == L3_TUNNEL_DOUBLEm) ? IPV4__L4_SRC_PORTf:IPV6__L4_SRC_PORTf); 602 } 603 if (soc_mem_field_valid (unit, mem, L4_DEST_PORTf)) { 604 tnl_info->udp_dst_port = soc_mem_field32_get(unit, mem, entry_ptr, 605 (mem == L3_TUNNEL_DOUBLEm) ? IPV4__L4_DEST_PORTf:IPV6__L4_DEST_PORTf); 606 } 607 608 /* Get tunnel type, sub_type and protocol. */ 609 BCM_IF_ERROR_RETURN 610 (_bcm_xgs3_l3_get_tnl_term_type(unit, tnl_info, &tnl_type)); 611 /* Get IIF if l3 ingress mode is not set */ 612 if (!BCM_XGS3_L3_INGRESS_MODE_ISSET(unit) && 613 BCM_XGS3_L3_ING_IF_TBL_SIZE(unit) && (tnl_info->vlan > BCM_VLAN_MAX)) { 614 _bcm_l3_ingress_intf_t iif; 615 sal_memset(&iif, 0, sizeof(_bcm_l3_ingress_intf_t)); 616 iif.intf_id = tnl_info->vlan; 617 BCM_IF_ERROR_RETURN(_bcm_tr_l3_ingress_interface_get(unit, NULL, &iif)); 618 619 tnl_info->vrf = iif.vrf; 620 tnl_info->if_class = iif.if_class; 621 tnl_info->qos_map_id = iif.qos_map_id; 622 if (SOC_IS_TOMAHAWKX(unit) && soc_feature(unit, soc_feature_ecn_wred)) { 623 if (bcmi_xgs5_ecn_map_used_get(unit, iif.tunnel_term_ecn_map_id, 624 _bcmEcnmapTypeTunnelTerm)) { 625 tnl_info->tunnel_term_ecn_map_id = iif.tunnel_term_ecn_map_id | 626 _BCM_XGS5_ECN_MAP_TYPE_TUNNEL_TERM; 627 tnl_info->flags |= BCM_TUNNEL_TERM_ECN_MAP; 628 } 629 } 630 } 631 632 return (BCM_E_NONE); 633 } 634 635 #endif