tnl_term.c (96040B)
1 /* 2 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 3 * 4 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 5 * 6 * Tunnel terminator TCAM table insert/delete/lookup routines 7 * soc_tunnel_term_init - Called from bcm_l3_init 8 * soc_tunnel_term_insert - Insert/Update an IPv4/IPV6 tunnel 9 * termination entry into L3_TUNNEL table 10 * soc_tunnel_term_delete - Delete an IPv4/IPV6 tunnel termination 11 * entry from L3_TUNNEL table 12 * soc_tunnel_term_match - Exact match for the key. 13 * Will match tunnel type (GRE/IP/MCAST) && 14 * (DIP & DIP_MASK)&& 15 * (SIP & SIP_MASK) 16 */ 17 18 #include <soc/mem.h> 19 #include <soc/drv.h> 20 #include <soc/debug.h> 21 #include <soc/error.h> 22 #include <soc/lpm.h> 23 #include <soc/tnl_term.h> 24 #include <shared/util.h> 25 #include <shared/bsl.h> 26 #include <shared/avl.h> 27 #include <shared/l3.h> 28 #if defined(BCM_TRIDENT3_SUPPORT) 29 #include <soc/esw/flow_db.h> 30 #endif /*BCM_TRIDENT3_SUPPORT */ 31 32 #if defined(BCM_FIREBOLT_SUPPORT) 33 #if defined(INCLUDE_L3) 34 35 /* Source IP prefix lengths. */ 36 #define SOC_TNL_TERM_TYPE_SZ(_type_) ((_type_) * (_SHR_L3_IP6_MAX_NETLEN + 1)) 37 38 #if defined(BCM_TRIDENT3_SUPPORT) 39 #define SOC_TNL_TERM_KEY_TYPE_FIXED_MAX 0x03 40 /* TUNNEL KEY TYPE KEY TYPE PRIORITY */ 41 #define SOC_TNL_TERM_TYPE_FLEX SOC_TNL_TERM_TYPE_SZ(0x20) 42 #endif /*BCM_TRIDENT3_SUPPORT */ 43 /* TUNNEL KEY TYPE KEY TYPE PRIORITY */ 44 #define SOC_TNL_TERM_TYPE_DIP4_SIP4_PROT_L4DST_L4SRC SOC_TNL_TERM_TYPE_SZ(0x1f) 45 #define SOC_TNL_TERM_TYPE_DIP6_SIP6_PROT_L4DST_L4SRC SOC_TNL_TERM_TYPE_SZ(0x1e) 46 #define SOC_TNL_TERM_TYPE_DIP4_PROT_L4DST_L4SRC SOC_TNL_TERM_TYPE_SZ(0x1d) 47 #define SOC_TNL_TERM_TYPE_DIP6_PROT_L4DST_L4SRC SOC_TNL_TERM_TYPE_SZ(0x1c) 48 #define SOC_TNL_TERM_TYPE_DIP4_SIP4_L4DST_L4SRC SOC_TNL_TERM_TYPE_SZ(0x1b) 49 #define SOC_TNL_TERM_TYPE_DIP6_SIP6_L4DST_L4SRC SOC_TNL_TERM_TYPE_SZ(0x1a) 50 #define SOC_TNL_TERM_TYPE_DIP4_L4DST_L4SRC SOC_TNL_TERM_TYPE_SZ(0x19) 51 #define SOC_TNL_TERM_TYPE_DIP6_L4DST_L4SRC SOC_TNL_TERM_TYPE_SZ(0x18) 52 53 #define SOC_TNL_TERM_TYPE_DIP4_SIP4_PROT_L4DST SOC_TNL_TERM_TYPE_SZ(0x17) 54 #define SOC_TNL_TERM_TYPE_DIP6_SIP6_PROT_L4DST SOC_TNL_TERM_TYPE_SZ(0x16) 55 #define SOC_TNL_TERM_TYPE_DIP4_PROT_L4DST SOC_TNL_TERM_TYPE_SZ(0x15) 56 #define SOC_TNL_TERM_TYPE_DIP6_PROT_L4DST SOC_TNL_TERM_TYPE_SZ(0x14) 57 #define SOC_TNL_TERM_TYPE_DIP4_SIP4_L4DST SOC_TNL_TERM_TYPE_SZ(0x13) 58 #define SOC_TNL_TERM_TYPE_DIP6_SIP6_L4DST SOC_TNL_TERM_TYPE_SZ(0x12) 59 #define SOC_TNL_TERM_TYPE_DIP4_L4DST SOC_TNL_TERM_TYPE_SZ(0x11) 60 #define SOC_TNL_TERM_TYPE_DIP6_L4DST SOC_TNL_TERM_TYPE_SZ(0x10) 61 62 #define SOC_TNL_TERM_TYPE_DIP4_SIP4_PROT_L4SRC SOC_TNL_TERM_TYPE_SZ(0xf) 63 #define SOC_TNL_TERM_TYPE_DIP6_SIP6_PROT_L4SRC SOC_TNL_TERM_TYPE_SZ(0xe) 64 #define SOC_TNL_TERM_TYPE_DIP4_PROT_L4SRC SOC_TNL_TERM_TYPE_SZ(0xd) 65 #define SOC_TNL_TERM_TYPE_DIP6_PROT_L4SRC SOC_TNL_TERM_TYPE_SZ(0xc) 66 #define SOC_TNL_TERM_TYPE_DIP4_SIP4_L4SRC SOC_TNL_TERM_TYPE_SZ(0xb) 67 #define SOC_TNL_TERM_TYPE_DIP6_SIP6_L4SRC SOC_TNL_TERM_TYPE_SZ(0xa) 68 #define SOC_TNL_TERM_TYPE_DIP4_L4SRC SOC_TNL_TERM_TYPE_SZ(9) 69 #define SOC_TNL_TERM_TYPE_DIP6_L4SRC SOC_TNL_TERM_TYPE_SZ(8) 70 71 #define SOC_TNL_TERM_TYPE_DIP4_SIP4_PROT SOC_TNL_TERM_TYPE_SZ(7) 72 #define SOC_TNL_TERM_TYPE_DIP6_SIP6_PROT SOC_TNL_TERM_TYPE_SZ(6) 73 #define SOC_TNL_TERM_TYPE_DIP4_PROT SOC_TNL_TERM_TYPE_SZ(5) 74 #define SOC_TNL_TERM_TYPE_DIP6_PROT SOC_TNL_TERM_TYPE_SZ(4) 75 76 #define SOC_TNL_TERM_TYPE_DIP4_SIP4 SOC_TNL_TERM_TYPE_SZ(3) 77 #define SOC_TNL_TERM_TYPE_DIP6_SIP6 SOC_TNL_TERM_TYPE_SZ(2) 78 #define SOC_TNL_TERM_TYPE_DIP4 SOC_TNL_TERM_TYPE_SZ(1) 79 #define SOC_TNL_TERM_TYPE_DIP6 SOC_TNL_TERM_TYPE_SZ(0) 80 81 82 83 /* 84 * TCAM based tunnel termination implementation. 85 * Each table entry holds 1 IPV4 entry 86 * 4 entries are required for IPv6 tunnel termination. 87 * IPV6 entry. 88 * Assumption Src + Dst + tunnel type is a unique 89 * combination. 90 * 91 * MAX_TNL_TERM_TYPE 92 * tunnel_term_index[0x20].begin ---> =============================== 93 * == == 94 * == 0 == 95 * tunnel_term_index[0x20].end ---> =============================== 96 * 97 * tunnel_term_index[0x19].begin ---> =============================== 98 * == DIP, SIP, PROT, L4SRC, L4DST == 99 * == IPV4 tunnels == 100 * tunnel_term_index[0x19].end ---> =============================== 101 * 102 * tunnel_term_index[0x18].begin ---> =============================== 103 * == DIP6, SIP6, PROT,L4SRC,L4DST == 104 * == IPV6 tunnels == 105 * tunnel_term_index[0x18].end ---> =============================== 106 * 107 * 108 ................... ETC ...................................... 109 * 110 * 111 * tunnel_term_index[4].begin ---> =============================== 112 * == DIP + SIP + DON'T CARE == 113 * == IPV4 tunnels == 114 * tunnel_term_index[4].end ---> =============================== 115 * 116 * 117 * 118 * tunnel_term_index[3].begin ---> =============================== 119 * == DIP6 + SIP6 + DON'T CARE== 120 * == IPV6 tunnels == 121 * tunnel_term_index[3].end ---> =============================== 122 * 123 * 124 * 125 * tunnel_term_index[2].begin ---> =============================== 126 * == DIP + DON'T CARE == 127 * == IPV4 tunnels == 128 * tunnel_term_index[2].end ---> =============================== 129 * 130 * 131 * 132 * tunnel_term_index[1].begin ---> =============================== 133 * == DIP6 + DON'T CARE == 134 * == IPV6 tunnels == 135 * tunnel_term_index[1].end ---> =============================== 136 */ 137 138 139 /* Can move to SOC Control structures */ 140 STATIC soc_tnl_term_state_p soc_tnl_term_state[SOC_MAX_NUM_DEVICES]; 141 142 #if defined(BCM_TRIDENT3_SUPPORT) 143 #define MAX_TNL_TERM_TYPES SOC_TNL_TERM_TYPE_SZ(0x22) 144 #else 145 #define MAX_TNL_TERM_TYPES SOC_TNL_TERM_TYPE_SZ(0x21) 146 #endif 147 148 #define MAX_TNL_TERM_TYPE (MAX_TNL_TERM_TYPES - 1) 149 #define SOC_TNL_TERM_INIT_CHECK(_u_) (soc_tnl_term_state[(_u_)] != NULL) 150 #define SOC_TNL_TERM_STATE(_u_) (soc_tnl_term_state[(_u_)]) 151 #define SOC_TNL_TERM_STATE_START(_u_, _type_) \ 152 (soc_tnl_term_state[(_u_)][(_type_)].start) 153 154 #define SOC_TNL_TERM_STATE_END(_u_, _type_) \ 155 (soc_tnl_term_state[(_u_)][(_type_)].end) 156 #define SOC_TNL_TERM_STATE_PREV(_u_, _type_) \ 157 (soc_tnl_term_state[(_u_)][(_type_)].prev) 158 #define SOC_TNL_TERM_STATE_NEXT(_u_, _type_) \ 159 (soc_tnl_term_state[(_u_)][(_type_)].next) 160 #define SOC_TNL_TERM_STATE_VENT(_u_, _type_) \ 161 (soc_tnl_term_state[(_u_)][(_type_)].vent) 162 #define SOC_TNL_TERM_STATE_FENT(_u_, _type_) \ 163 (soc_tnl_term_state[(_u_)][(_type_)].fent) 164 165 /* LOCKS */ 166 #define SOC_TNL_TERM_LOCK(_u_) soc_mem_lock(_u_, ((SOC_MEM_IS_VALID(_u_, L3_TUNNEL_DOUBLEm))?L3_TUNNEL_DOUBLEm:L3_TUNNELm)) 167 #define SOC_TNL_TERM_UNLOCK(_u_) soc_mem_unlock(_u_, ((SOC_MEM_IS_VALID(_u_, L3_TUNNEL_DOUBLEm))?L3_TUNNEL_DOUBLEm:L3_TUNNELm)) 168 169 170 #define SOC_TNL_TERM_KEY_WIDTH_MAX (4) /* 4 words for IPv6 address. */ 171 172 typedef int (*_soc_tnl_term_hash_compare_fn)(soc_tnl_term_hash_key_t *key1, 173 soc_tnl_term_hash_key_t *key2); 174 175 STATIC soc_tnl_term_hash_t *_tnl_term_hash_tab[SOC_MAX_NUM_DEVICES]; 176 int SOC_TNL_TERM_BLOCK_SIZE; 177 STATIC int 178 _soc_tunnel_term_type_get(int unit, soc_tunnel_term_t *entry, 179 int *type, int *entry_type); 180 181 182 #define SOC_TNL_TERM_STATE_HASH(_u_) (_tnl_term_hash_tab[(_u_)]) 183 184 #define TNL_TERM_TYPE_NULL (-1) 185 #define TNL_TERM_HASH_INDEX_NULL (0xFFFF) 186 187 /* 188 * Purpose: 189 * Set SOC_TNL_TERM_BLOCK_SIZE 190 */ 191 192 int soc_tunnel_term_block_size_set (int unit, int size) 193 { 194 SOC_TNL_TERM_BLOCK_SIZE = size; 195 return SOC_E_NONE; 196 } 197 198 /* 199 * Purpose: 200 * Get SOC_TNL_TERM_BLOCK_SIZE 201 */ 202 203 int soc_tunnel_term_block_size_get (int unit, int *size) 204 { 205 *size = SOC_TNL_TERM_BLOCK_SIZE; 206 return SOC_E_NONE; 207 } 208 209 #if defined(BCM_TRIDENT3_SUPPORT) 210 /* 211 * Function: 212 * _soc_tunnel_term_flex_type_width_get 213 * Purpose: 214 * Get the width of flex tunnel terminator entry. 215 * Parameters: 216 * unit - (IN) Bcm device number. 217 * type - (IN) Tunnel terminator type. 218 * entry - (IN) Tunnel termination entry. 219 * entry_width - (IN) Entry width. 220 * Returns: 221 * SOC_E_XXX 222 */ 223 STATIC int 224 _soc_tunnel_term_flex_type_width_get(int unit, int type, soc_tunnel_term_t *entry, 225 int *entry_width) { 226 227 uint32 mode = 0; 228 if (entry_width == NULL) { 229 return SOC_E_INTERNAL; 230 } 231 if (type != SOC_TNL_TERM_TYPE_FLEX) { 232 return SOC_E_INTERNAL; 233 } 234 mode = soc_mem_field32_get(unit, L3_TUNNELm, (uint32 *)&entry->entry_arr[0], MODEf); 235 if (mode == SOC_TNL_TERM_ENTRY_MODE_QUAD) { 236 *entry_width = SOC_TNL_TERM_ENTRY_WIDTH_QUAD; 237 } else if (mode == SOC_TNL_TERM_ENTRY_MODE_DOUBLE) { 238 *entry_width = SOC_TNL_TERM_ENTRY_WIDTH_DOUBLE; 239 } else { 240 *entry_width = SOC_TNL_TERM_ENTRY_WIDTH_SINGLE; 241 } 242 return SOC_E_NONE; 243 } 244 245 /* 246 * Function: 247 * _soc_tunnel_term_flex_hash_key_set 248 * Purpose: 249 * Form the hash key for flex tunnel terminator entry. 250 * Parameters: 251 * unit - (IN) Bcm device number. 252 * entry - (IN) Tunnel termination entry. 253 * flex_key_entry - (IN/OUT) Hash key. 254 * Returns: 255 * SOC_E_XXX 256 */ 257 STATIC void 258 _soc_tunnel_term_flex_hash_key_set(int unit, soc_tunnel_term_t *entry, 259 uint32 *flex_key_entry) { 260 soc_mem_t mem; 261 soc_mem_t mem_view_id; 262 uint32 key_type = SOC_FLOW_DB_KEY_TYPE_INVALID; 263 uint32 data_type = SOC_FLOW_DB_KEY_TYPE_INVALID; 264 uint32 key_typef[] = {KEY_TYPEf, 265 KEY_TYPE0f, 266 KEY_TYPE1f}; 267 uint32 data_typef[] = {DATA_TYPEf, 268 DATA_TYPE0f, 269 DATA_TYPE1f}; 270 uint32 key_list[SOC_FLOW_DB_MAX_VIEW_FIELDS]; 271 uint32 key_count = 0; 272 uint32 key_value = 0; 273 uint32 trav_entry[SOC_MAX_MEM_WORDS*4]; 274 uint32 entry_width = sizeof(tunnel_entry_t); 275 uint32 i = 0; 276 ip6_addr_t ip6; 277 int rv = -1; 278 mem = L3_TUNNELm; 279 sal_memset(trav_entry, 0, sizeof(trav_entry)); 280 281 /* Get the view for the memory */ 282 for (i = 0; i < 4; i++) { 283 sal_memcpy(((uint8 *)trav_entry + (entry_width * i)), 284 &entry->entry_arr[i], entry_width); 285 } 286 for (i = 0; i < SOC_FLOW_DB_MAX_KEY_TYPE; i++) { 287 if (SOC_MEM_FIELD_VALID(unit,mem,key_typef[i])) { 288 key_type = soc_mem_field32_get(unit, mem, trav_entry, key_typef[i]); 289 break; 290 } 291 } 292 293 for (i = 0; i < SOC_FLOW_DB_MAX_DATA_TYPE; i++) { 294 if (SOC_MEM_FIELD_VALID(unit,mem,data_typef[i])) { 295 data_type = soc_mem_field32_get(unit, mem, trav_entry, data_typef[i]); 296 } 297 } 298 299 /* find the memory view based on the memory and key type */ 300 rv = soc_flow_db_mem_to_view_id_get (unit, mem, key_type, data_type, 301 0, NULL, (uint32 *) &mem_view_id); 302 if (SOC_FAILURE(rv)) { 303 return; 304 } 305 306 rv = soc_flow_db_mem_view_field_list_get(unit, 307 mem_view_id, 308 SOC_FLOW_DB_FIELD_TYPE_KEY, 309 SOC_FLOW_DB_MAX_VIEW_FIELDS, 310 key_list, 311 &key_count); 312 if (SOC_FAILURE(rv)) { 313 return; 314 } 315 316 for(i = 0; i < key_count; i++) { 317 if ((key_list[i] == IPV6__SIPf) || 318 (key_list[i] == IPV6__DIPf) || 319 (key_list[i] == IPV6__SIP_MASKf) || 320 (key_list[i] == IPV6__DIP_MASKf)) { 321 sal_memset(&ip6, 0, sizeof(ip6_addr_t)); 322 soc_mem_ip6_addr_get(unit, mem_view_id, 323 trav_entry, key_list[i], ip6, 0); 324 soc_mem_ip6_addr_set(unit, mem_view_id, 325 flex_key_entry, key_list[i], ip6, 0); 326 } else if ((key_list[i] == KEY_0f) || 327 (key_list[i] == KEY_1f) ) { 328 /* ignore */ 329 continue; 330 } 331 key_value = soc_mem_field32_get(unit, 332 mem_view_id, 333 trav_entry, 334 key_list[i]); 335 soc_mem_field32_set(unit, mem_view_id, 336 flex_key_entry, key_list[i], key_value); 337 } 338 339 rv = soc_flow_db_mem_view_field_list_get(unit, 340 mem_view_id, 341 SOC_FLOW_DB_FIELD_TYPE_LOGICAL_KEY, 342 SOC_FLOW_DB_MAX_VIEW_FIELDS, 343 key_list, 344 &key_count); 345 if (SOC_FAILURE(rv)) { 346 return; 347 } 348 349 for(i = 0; i < key_count; i++) { 350 key_value = soc_mem_field32_get(unit, 351 mem_view_id, 352 trav_entry, 353 key_list[i]); 354 soc_mem_field32_set(unit, mem_view_id, 355 flex_key_entry, key_list[i], key_value); 356 } 357 return; 358 } 359 360 /* 361 * Function: 362 * _soc_tunnel_term_flex_entry_clear 363 * Purpose: 364 * Clear flex tunnel termination entry to the hardware. 365 * Parameters: 366 * unit - (IN) Bcm device number. 367 * index - (IN) Table index. 368 * entry - (IN) Tunnel termination entry. 369 * ipv6 - (IN) Type. 370 * Returns: 371 * SOC_E_XXX 372 */ 373 STATIC int 374 _soc_tunnel_term_flex_entry_clear(int unit, int index, 375 soc_tunnel_term_t *entry, int entry_type) 376 { 377 int idx; /* Entry width iteration index. */ 378 int idx_max; /* Entry width. */ 379 int type; 380 int key_type; 381 soc_tunnel_term_t null_entry; 382 soc_tunnel_term_t *entry_ptr = NULL; 383 384 /* Input parameters check. */ 385 if (NULL == entry) { 386 return (SOC_E_PARAM); 387 } 388 389 SOC_IF_ERROR_RETURN 390 (_soc_tunnel_term_type_get(unit, entry, &type, &key_type)); 391 SOC_IF_ERROR_RETURN ( 392 _soc_tunnel_term_flex_type_width_get(unit, type, entry, &idx_max)); 393 /* null entry */ 394 sal_memset(&null_entry, 0, sizeof(soc_tunnel_term_t)); 395 entry_ptr = &null_entry; 396 397 for (idx = 0; idx < idx_max; idx++) { 398 SOC_IF_ERROR_RETURN (WRITE_L3_TUNNELm(unit, MEM_BLOCK_ALL, 399 (idx + index), 400 (uint32 *)&entry_ptr->entry_arr[idx])); 401 } 402 return (SOC_E_NONE); 403 } 404 405 #endif /*BCM_TRIDENT3_SUPPORT*/ 406 407 /* 408 * Function: 409 * _soc_tunnel_term_hash_entry_get 410 * Purpose: 411 * Extract key data from an entry at the given index. 412 * Parameters: 413 * unit - (IN) BCM device number. 414 * entry_arr - (IN) Array of entries forming single 415 * tunnel termination entry. 416 * ipv6 - (IN) IPv4/IPv6 entry flag. 417 * entry_key - (OUT) Tunnel termination key. 418 * Returns: 419 * none 420 */ 421 STATIC void 422 _soc_tunnel_term_hash_entry_get(int unit, soc_tunnel_term_t *entry, int entry_type, 423 soc_tnl_term_hash_key_t *entry_key) 424 { 425 uint32 *entry_ptr; /* HW entry pointer. */ 426 uint8 sip_mask[_SHR_L3_IP6_ADDRLEN]; /* Source ip subent mask. */ 427 soc_mem_t mem = L3_TUNNELm; 428 soc_field_t ipv4f = IP_ADDRf; 429 soc_field_t ipv4_maskf = IP_ADDR_MASKf; 430 #if defined(BCM_TRIUMPH2_SUPPORT) 431 soc_field_t l4_src_port_f = L4_SRC_PORTf; 432 soc_field_t l4_dest_port_f = L4_DEST_PORTf; 433 soc_field_t protocol_f = PROTOCOLf; 434 #endif 435 int ipv6_key_type = 0x1; 436 int ipv4_key_type = 0x0; 437 uint8 *ip6 = NULL; 438 uint32 ip6_field[4]; 439 440 /* Input parameters check */ 441 if (NULL == entry_key) { 442 return; 443 } 444 445 if (soc_feature(unit, soc_feature_tunnel_term_hash_table)) { 446 mem = L3_TUNNEL_DOUBLEm; 447 ipv6_key_type = 0x2; 448 ipv4_key_type = 0x1; 449 #if defined(BCM_TRIUMPH2_SUPPORT) 450 l4_src_port_f = IPV4__L4_SRC_PORTf; 451 l4_dest_port_f = IPV4__L4_DEST_PORTf; 452 protocol_f = IPV4__PROTOCOLf; 453 #endif 454 if (entry_type == ipv6_key_type) { 455 mem = L3_TUNNEL_QUADm; 456 #if defined(BCM_TRIUMPH2_SUPPORT) 457 l4_src_port_f = IPV6__L4_SRC_PORTf; 458 l4_dest_port_f = IPV6__L4_DEST_PORTf; 459 protocol_f = IPV6__PROTOCOLf; 460 #endif 461 } 462 } 463 464 /* Initialization part. */ 465 sal_memset(entry_key, 0, sizeof(soc_tnl_term_hash_key_t)); 466 entry_ptr = (uint32 *)&entry->entry_arr[0]; 467 468 #if defined(BCM_TRIUMPH3_SUPPORT) || defined (BCM_KATANA2_SUPPORT) || \ 469 defined(BCM_APACHE_SUPPORT) 470 /* For Triumph3 get MIM and MPLS L3 tunnel entries */ 471 if (SOC_IS_TRIUMPH3(unit) || SOC_IS_KATANA2(unit) || 472 soc_feature(unit, soc_feature_l3_tunnel_mpls_frr)) { 473 if (entry_type == 0x3) { /* MIM Type */ 474 /* Get MIM::SGLP */ 475 entry_key->mim_hash_key.sglp = 476 soc_mem_field32_get(unit, L3_TUNNELm, entry_ptr, MIM__SGLPf); 477 /* Get MIM::BVID */ 478 entry_key->mim_hash_key.bvid = 479 soc_mem_field32_get(unit, L3_TUNNELm, entry_ptr, MIM__BVIDf); 480 /* Get MIM::BMACSA */ 481 soc_mem_mac_addr_get(unit, L3_TUNNELm, entry_ptr, MIM__SGLPf, 482 entry_key->mim_hash_key.bmacsa); 483 return; 484 485 } 486 } 487 #endif /* BCM_TRIUMPH3_SUPPORT || BCM_KATANA2_SUPORT */ 488 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || \ 489 defined(BCM_KATANA2_SUPORT) || defined(BCM_APACHE_SUPPORT) 490 if (SOC_IS_TOMAHAWK2(unit) || SOC_IS_TRIUMPH3(unit) || SOC_IS_KATANA2(unit) || 491 soc_feature(unit, soc_feature_l3_tunnel_mpls_frr)) { 492 if (entry_type == 0x2) { /* MPLS Type */ 493 /* Get MPLS::MPLS_LABEL */ 494 entry_key->mpls_hash_key.mpls_label = 495 soc_mem_field32_get(unit, mem, entry_ptr, 496 MPLS__MPLS_LABELf); 497 /* Get MPLS::MODULE_ID */ 498 entry_key->mpls_hash_key.module_id = 499 soc_mem_field32_get(unit, mem, entry_ptr, MPLS__MODULE_IDf); 500 /* Get MPLS::PORT_NUM */ 501 entry_key->mpls_hash_key.port = 502 soc_mem_field32_get(unit, mem, entry_ptr, MPLS__PORT_NUMf); 503 /* Get MPLS::TGID */ 504 entry_key->mpls_hash_key.trunk_id = 505 soc_mem_field32_get(unit, mem, entry_ptr, MPLS__TGIDf); 506 return; 507 } 508 } 509 #endif /* BCM_TOMAHAWK2_SUPPORT || BCM_TRIUMPH3_SUPPORT || BCM_KATANA2_SUPORT */ 510 511 if (entry_type == ipv6_key_type) { /* IPV6 Type */ 512 if (soc_feature(unit, soc_feature_tunnel_term_hash_table)) { 513 ip6 = entry_key->ip_hash_key.sip; 514 /* SIP [0-89] */ 515 soc_mem_field_get(unit, mem, (uint32 *)&entry->entry_arr[0], IPV6__SIP_LWR_90f, ip6_field); 516 517 ip6[4] = (ip6_field[2] & 0xff); 518 ip6[5] = (ip6_field[2] >> 8) & 0xff; 519 ip6[6] = (ip6_field[2] >> 16) & 0xff; 520 ip6[7] = (ip6_field[2] >> 24) & 0x3; 521 522 ip6[8] = (ip6_field[1] & 0xff); 523 ip6[9] = (ip6_field[1] >> 8) & 0xff; 524 ip6[10] = (ip6_field[1] >> 16) & 0xff; 525 ip6[11] = (ip6_field[1] >> 24) & 0xff; 526 527 ip6[12] = (ip6_field[0] & 0xff); 528 ip6[13] = (ip6_field[0] >> 8) & 0xff; 529 ip6[14] = (ip6_field[0] >> 16) & 0xff; 530 ip6[15] = (ip6_field[0] >> 24) & 0xff; 531 532 /* SIP [90-127] */ 533 soc_mem_field_get(unit, mem, (uint32 *)&entry->entry_arr[0], IPV6__SIP_UPR_38f, ip6_field); 534 ip6[0] = (ip6_field[0] & 0xff); 535 ip6[1] = (ip6_field[1] >> 8) & 0xff; 536 ip6[2] = (ip6_field[2] >> 16) & 0xff; 537 ip6[3] = (ip6_field[3] >> 24) & 0xff; 538 539 ip6 = entry_key->ip_hash_key.dip; 540 /* DIP [0-89] */ 541 soc_mem_field_get(unit, mem, (uint32 *)&entry->entry_arr[0], IPV6__DIP_LWR_90f, ip6_field); 542 ip6[4] = (ip6_field[2] & 0xff); 543 ip6[5] = (ip6_field[2] >> 8) & 0xff; 544 ip6[6] = (ip6_field[2] >> 16) & 0xff; 545 ip6[7] = (ip6_field[2] >> 24) & 0x3; 546 547 ip6[8] = (ip6_field[1] & 0xff); 548 ip6[9] = (ip6_field[1] >> 8) & 0xff; 549 ip6[10] = (ip6_field[1] >> 16) & 0xff; 550 ip6[11] = (ip6_field[1] >> 24) & 0xff; 551 552 ip6[12] = (ip6_field[0] & 0xff); 553 ip6[13] = (ip6_field[0] >> 8) & 0xff; 554 ip6[14] = (ip6_field[0] >> 16) & 0xff; 555 ip6[15] = (ip6_field[0] >> 24) & 0xff; 556 557 /* DIP [90-127] */ 558 soc_mem_field_get(unit, mem, (uint32 *)&entry->entry_arr[0], IPV6__DIP_UPR_38f, ip6_field); 559 ip6[0] = (ip6_field[0] & 0xff); 560 ip6[1] = (ip6_field[1] >> 8) & 0xff; 561 ip6[2] = (ip6_field[2] >> 16) & 0xff; 562 ip6[3] = (ip6_field[3] >> 24) & 0xff; 563 entry_key->ip_hash_key.sip_plen = 128; 564 } else { 565 /* SIP [0-63] */ 566 soc_mem_ip6_addr_get(unit, mem, 567 (uint32 *)&entry->entry_arr[0], ipv4f, 568 entry_key->ip_hash_key.sip, SOC_MEM_IP6_LOWER_ONLY); 569 /* SIP [64-127] */ 570 soc_mem_ip6_addr_get(unit, mem, 571 (uint32 *)&entry->entry_arr[1], ipv4f, 572 entry_key->ip_hash_key.sip, SOC_MEM_IP6_UPPER_ONLY); 573 /* DIP [0-63] */ 574 soc_mem_ip6_addr_get(unit, mem, 575 (uint32 *)&entry->entry_arr[2], ipv4f, 576 entry_key->ip_hash_key.dip, SOC_MEM_IP6_LOWER_ONLY); 577 /* DIP [64-127] */ 578 soc_mem_ip6_addr_get(unit, mem, 579 (uint32 *)&entry->entry_arr[3], ipv4f, 580 entry_key->ip_hash_key.dip, SOC_MEM_IP6_UPPER_ONLY); 581 582 /* SIP MASK [0-63] */ 583 soc_mem_ip6_addr_get(unit, mem, 584 (uint32 *)&entry->entry_arr[0], ipv4_maskf, 585 sip_mask, SOC_MEM_IP6_LOWER_ONLY); 586 /* SIP MASK [64-127] */ 587 soc_mem_ip6_addr_get(unit, mem, 588 (uint32 *)&entry->entry_arr[1], ipv4_maskf, 589 sip_mask, SOC_MEM_IP6_UPPER_ONLY); 590 entry_key->ip_hash_key.sip_plen = _shr_ip6_mask_length(sip_mask); 591 } 592 } else if (entry_type == ipv4_key_type) { /* IPV4 Type */ 593 soc_field_t dipf = DIPf, sipf = SIPf; 594 /* Get destination ip. */ 595 if (soc_feature(unit, soc_feature_tunnel_term_hash_table)) { 596 sipf = IPV4__SIPf; 597 dipf = IPV4__DIPf; 598 } 599 soc_mem_field_get(unit, mem, entry_ptr, dipf, 600 (uint32 *)entry_key->ip_hash_key.dip); 601 602 /* Get source ip. */ 603 soc_mem_field_get(unit, mem, entry_ptr, sipf, 604 (uint32 *)entry_key->ip_hash_key.sip); 605 606 /* Get source ip. */ 607 if (SOC_MEM_FIELD_VALID(unit, mem, SIP_MASKf)) { 608 soc_mem_field_get(unit, mem, entry_ptr, SIP_MASKf, 609 (uint32 *)sip_mask); 610 entry_key->ip_hash_key.sip_plen = 611 _shr_ip_mask_length((*(uint32 *)sip_mask)); 612 } else { 613 entry_key->ip_hash_key.sip_plen = 614 (*(uint32 *)entry_key->ip_hash_key.sip) ? 32 : 0; 615 } 616 } 617 #if defined(BCM_TRIDENT3_SUPPORT) 618 else if (soc_feature(unit,soc_feature_flex_flow) 619 && (entry_type > SOC_TNL_TERM_KEY_TYPE_FIXED_MAX)){ 620 /* Flex views */ 621 _soc_tunnel_term_flex_hash_key_set(unit, entry, entry_key->flex_hash_key.entry); 622 return; 623 } 624 #endif /* BCM_TRIDENT3_SUPPORT */ 625 #if defined(BCM_TRIUMPH2_SUPPORT) 626 if (!soc_feature(unit, soc_feature_tunnel_term_hash_table)) { 627 l4_src_port_f = L4_SRC_PORTf; 628 l4_dest_port_f = L4_DEST_PORTf; 629 protocol_f = PROTOCOLf; 630 } 631 if (SOC_MEM_FIELD_VALID(unit, mem, l4_src_port_f)) { 632 entry_key->ip_hash_key.l4_src_port = 633 soc_mem_field32_get(unit, mem, entry_ptr, l4_src_port_f); 634 } 635 if (SOC_MEM_FIELD_VALID(unit, mem, l4_dest_port_f)) { 636 entry_key->ip_hash_key.l4_dst_port = 637 soc_mem_field32_get(unit, mem, entry_ptr, l4_dest_port_f); 638 } 639 if (SOC_MEM_FIELD_VALID(unit, mem, protocol_f)) { 640 entry_key->ip_hash_key.ip_protocol = 641 soc_mem_field32_get(unit, mem, entry_ptr, protocol_f); 642 } 643 644 #endif /* BCM_TRIUMPH2_SUPPORT */ 645 646 #if defined(BCM_TRX_SUPPORT) 647 if (SOC_MEM_FIELD_VALID(unit, mem, GRE_TUNNELf)) { 648 entry_key->ip_hash_key.ip_protocol = 649 soc_mem_field32_get(unit, mem, entry_ptr, GRE_TUNNELf); 650 } 651 #endif /* BCM_TRX_SUPPORT*/ 652 return; 653 } 654 655 #define SOC_TNL_TERM_HASH_ENTRY_GET _soc_tunnel_term_hash_entry_get 656 /* 657 * Function: 658 * _soc_tunnel_term_type_get 659 * Purpose: 660 * Extract tunnel terminator entry type 661 * (DIP6/SIP6)/(DIP4/SIP4)/(DIP 6/(*))/(DIP4/(*)) 662 * Parameters: 663 * unit - (IN) BCM device number. 664 * entry - (IN) Tunnel terminator entry. 665 * type - (OUT) Tunnel terminator search result. 666 * ipv6 - (OUT) IPv6 Tunnel termination flag. 667 * Returns: 668 * SOC_E_XXX 669 */ 670 STATIC int 671 _soc_tunnel_term_type_get(int unit, soc_tunnel_term_t *entry, 672 int *type, int *entry_type) 673 { 674 int key; /* IPv6 tunnel terminator flag. */ 675 soc_tnl_term_hash_key_t key_hash; /* Tunnel termination hashing key. */ 676 #if defined(BCM_TRX_SUPPORT) 677 soc_mem_t mem = L3_TUNNELm; 678 #endif 679 int ipv6_key_type = 0x1; 680 681 /* Input parameters check. */ 682 if (NULL == entry) { 683 return (SOC_E_PARAM); 684 } 685 686 #if defined(BCM_TRX_SUPPORT) 687 if (soc_feature(unit, soc_feature_tunnel_term_hash_table)) { 688 mem = L3_TUNNEL_DOUBLEm; 689 ipv6_key_type = 0x2; 690 } 691 692 if (soc_feature(unit,soc_feature_flex_flow) && 693 ((soc_mem_field32_get(unit, mem, 694 (uint32 *)&entry->entry_arr[0], KEY_TYPEf)) > 3)) { 695 /* flex view */ 696 key = soc_mem_field32_get(unit, mem, 697 (uint32 *)&entry->entry_arr[0], KEY_TYPEf); 698 /* Get tunnel termination type IPv4/IPv6 */ 699 } else if (SOC_MEM_FIELD_VALID(unit, mem, MODEf)) { 700 key = soc_mem_field32_get(unit, mem, 701 (uint32 *)&entry->entry_arr[0], MODEf); 702 } else if (SOC_MEM_FIELD_VALID(unit, mem, KEY_TYPEf)) { 703 key = soc_mem_field32_get(unit, mem, 704 (uint32 *)&entry->entry_arr[0], KEY_TYPEf); 705 } else 706 #endif /* BCM_TRX_SUPPORT */ 707 { 708 key = 0; /* IPV4 default type */ 709 } 710 711 /* Assign ipv6 flag if caller provided ipv6 pointer. */ 712 if (NULL != entry_type) { 713 *entry_type = key; 714 } 715 716 /* If caller doesn't want tunnel type skip this section. */ 717 if (NULL == type) { 718 return (SOC_E_NONE); 719 } 720 721 /* Extract source ip portion as part of hash. */ 722 SOC_TNL_TERM_HASH_ENTRY_GET(unit, entry, key, &key_hash); 723 724 if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 725 SOC_IS_VALKYRIE2(unit)) { 726 if (key == ipv6_key_type) { /* IPV6 */ 727 728 if (key_hash.ip_hash_key.l4_src_port 729 && key_hash.ip_hash_key.l4_dst_port) { 730 if (key_hash.ip_hash_key.ip_protocol) { 731 if (0 == key_hash.ip_hash_key.sip_plen) { 732 *type = SOC_TNL_TERM_TYPE_DIP6_PROT_L4DST_L4SRC; 733 } else { 734 *type = SOC_TNL_TERM_TYPE_DIP6_SIP6_PROT_L4DST_L4SRC; 735 } 736 } else { 737 if (0 == key_hash.ip_hash_key.sip_plen) { 738 *type = SOC_TNL_TERM_TYPE_DIP6_L4DST_L4SRC; 739 } else { 740 *type = SOC_TNL_TERM_TYPE_DIP6_SIP6_L4DST_L4SRC; 741 } 742 } 743 } else if (key_hash.ip_hash_key.l4_src_port) { 744 if (key_hash.ip_hash_key.ip_protocol) { 745 if (0 == key_hash.ip_hash_key.sip_plen) { 746 *type = SOC_TNL_TERM_TYPE_DIP6_PROT_L4SRC; 747 } else { 748 *type = SOC_TNL_TERM_TYPE_DIP6_SIP6_PROT_L4SRC; 749 } 750 } else { 751 if (0 == key_hash.ip_hash_key.sip_plen) { 752 *type = SOC_TNL_TERM_TYPE_DIP6_L4SRC; 753 } else { 754 *type = SOC_TNL_TERM_TYPE_DIP6_SIP6_L4SRC; 755 } 756 } 757 } else if (key_hash.ip_hash_key.l4_dst_port) { 758 if (key_hash.ip_hash_key.ip_protocol) { 759 if (0 == key_hash.ip_hash_key.sip_plen) { 760 *type = SOC_TNL_TERM_TYPE_DIP6_PROT_L4DST; 761 } else { 762 *type = SOC_TNL_TERM_TYPE_DIP6_SIP6_PROT_L4DST; 763 } 764 } else { 765 if (0 == key_hash.ip_hash_key.sip_plen) { 766 *type = SOC_TNL_TERM_TYPE_DIP6_L4DST; 767 } else { 768 *type = SOC_TNL_TERM_TYPE_DIP6_SIP6_L4DST; 769 } 770 } 771 } else if (key_hash.ip_hash_key.ip_protocol) { 772 if (0 == key_hash.ip_hash_key.sip_plen) { 773 *type = SOC_TNL_TERM_TYPE_DIP6_PROT; 774 } else { 775 *type = SOC_TNL_TERM_TYPE_DIP6_SIP6_PROT; 776 } 777 } else { 778 if (0 == key_hash.ip_hash_key.sip_plen) { 779 *type = SOC_TNL_TERM_TYPE_DIP6; 780 } else { 781 *type = SOC_TNL_TERM_TYPE_DIP6_SIP6; 782 } 783 } 784 } else { 785 if (key_hash.ip_hash_key.l4_src_port 786 && key_hash.ip_hash_key.l4_dst_port) { 787 if (key_hash.ip_hash_key.ip_protocol) { 788 if (0 == key_hash.ip_hash_key.sip_plen) { 789 *type = SOC_TNL_TERM_TYPE_DIP4_PROT_L4DST_L4SRC; 790 } else { 791 *type = SOC_TNL_TERM_TYPE_DIP4_SIP4_PROT_L4DST_L4SRC; 792 } 793 } else { 794 if (0 == key_hash.ip_hash_key.sip_plen) { 795 *type = SOC_TNL_TERM_TYPE_DIP4_L4DST_L4SRC; 796 } else { 797 *type = SOC_TNL_TERM_TYPE_DIP4_SIP4_L4DST_L4SRC; 798 } 799 } 800 } else if (key_hash.ip_hash_key.l4_src_port) { 801 if (key_hash.ip_hash_key.ip_protocol) { 802 if (0 == key_hash.ip_hash_key.sip_plen) { 803 *type = SOC_TNL_TERM_TYPE_DIP4_PROT_L4SRC; 804 } else { 805 *type = SOC_TNL_TERM_TYPE_DIP4_SIP4_PROT_L4SRC; 806 } 807 } else { 808 if (0 == key_hash.ip_hash_key.sip_plen) { 809 *type = SOC_TNL_TERM_TYPE_DIP4_L4SRC; 810 } else { 811 *type = SOC_TNL_TERM_TYPE_DIP4_SIP4_L4SRC; 812 } 813 } 814 } else if (key_hash.ip_hash_key.l4_dst_port) { 815 if (key_hash.ip_hash_key.ip_protocol) { 816 if (0 == key_hash.ip_hash_key.sip_plen) { 817 *type = SOC_TNL_TERM_TYPE_DIP4_PROT_L4DST; 818 } else { 819 *type = SOC_TNL_TERM_TYPE_DIP4_SIP4_PROT_L4DST; 820 } 821 } else { 822 if (0 == key_hash.ip_hash_key.sip_plen) { 823 *type = SOC_TNL_TERM_TYPE_DIP4_L4DST; 824 } else { 825 *type = SOC_TNL_TERM_TYPE_DIP4_SIP4_L4DST; 826 } 827 } 828 } else if (key_hash.ip_hash_key.ip_protocol) { 829 if (0 == key_hash.ip_hash_key.sip_plen) { 830 *type = SOC_TNL_TERM_TYPE_DIP4_PROT; 831 } else { 832 *type = SOC_TNL_TERM_TYPE_DIP4_SIP4_PROT; 833 } 834 } else { 835 if (0 == key_hash.ip_hash_key.sip_plen) { 836 *type = SOC_TNL_TERM_TYPE_DIP4; 837 } else { 838 *type = SOC_TNL_TERM_TYPE_DIP4_SIP4; 839 } 840 } 841 } 842 } else { 843 if (key == ipv6_key_type) { /* IPV6 Type */ 844 if (0 == key_hash.ip_hash_key.sip_plen) { 845 *type = SOC_TNL_TERM_TYPE_DIP6; 846 } else { 847 *type = SOC_TNL_TERM_TYPE_DIP6_SIP6; 848 } 849 } else 850 #if defined(BCM_TRIDENT3_SUPPORT) 851 if (soc_feature(unit,soc_feature_flex_flow) && 852 (key > SOC_TNL_TERM_KEY_TYPE_FIXED_MAX)) { 853 *type = SOC_TNL_TERM_TYPE_FLEX; 854 } else 855 #endif /* BCM_TRIDENT3_SUPPORT */ 856 { 857 if (0 == key_hash.ip_hash_key.sip_plen) { 858 *type =SOC_TNL_TERM_TYPE_DIP4; 859 } else { 860 *type = SOC_TNL_TERM_TYPE_DIP4_SIP4; 861 } 862 } 863 } 864 865 if (!(soc_feature(unit,soc_feature_flex_flow) && 866 (key > 0x03))) { 867 /* Add sip prefix length on top of resovled type. */ 868 *type += key_hash.ip_hash_key.sip_plen; 869 } 870 871 return (SOC_E_NONE); 872 } 873 874 /* 875 * Function: 876 * _soc_tunnel_term_hash_compare_key 877 * Purpose: 878 * Tunnel termination entry comparison routine 879 * for sw table management operations. 880 * Parameters: 881 * key1 - (IN) First compared tunnel termination key. 882 * key2 - (IN) Second compared tunnel termination key. 883 * Returns: 884 * Comparison result(LESS/GREATER/EQUALS) key1 <=> key2. 885 */ 886 static INLINE int 887 _soc_tunnel_term_hash_compare_key(soc_tnl_term_hash_key_t *key1, 888 soc_tnl_term_hash_key_t *key2) 889 { 890 return sal_memcmp(key1, key2, sizeof(soc_tnl_term_hash_key_t)); 891 } 892 893 /* 894 * Function: 895 * _soc_tunnel_term_hash_compute 896 * Purpose: 897 * Compute CRC hash for key data. 898 * Parameters: 899 * data - (IN) Key data 900 * data_nbits - (IN) Number of data bits 901 * hash_val - (OUT) Hash value 902 * Returns: 903 * SOC_E_XXX 904 */ 905 STATIC int 906 _soc_tunnel_term_hash_compute(uint8 *data, int data_nbits, uint16 *hash_val) 907 { 908 /* Input parameters check. */ 909 if ((NULL == data) || (NULL == hash_val)) { 910 return (SOC_E_PARAM); 911 } 912 *hash_val = _shr_crc16b(0, data, data_nbits); 913 914 return (SOC_E_NONE); 915 } 916 917 /* 918 * Function: 919 * _soc_tunnel_term_hash_create 920 * Purpose: 921 * Create an empty hash table 922 * Parameters: 923 * unit - (IN)BCM device number. 924 * entry_count - (IN) Limit for number of entries in table 925 * index_count - (IN) Hash index max + 1. (index_count <= count) 926 * tnl_term_hash_ptr - (OUT) Return pointer (handle) to new Hash Table 927 * Returns: 928 * SOC_E_NONE Success 929 * SOC_E_MEMORY Out of memory (system allocator) 930 */ 931 932 STATIC int 933 _soc_tunnel_term_hash_create(int unit, 934 int entry_count, 935 int index_count, 936 soc_tnl_term_hash_t **tnl_term_hash_ptr) 937 { 938 soc_tnl_term_hash_t *hash; /* Tunnel termination hash. */ 939 int index; /* Hash iteration index. */ 940 int alloc_size; /* Allocation size. */ 941 942 /* Input parameters check. */ 943 if ((NULL == tnl_term_hash_ptr) || (index_count > entry_count)) { 944 return (SOC_E_PARAM); 945 } 946 947 alloc_size = sizeof (soc_tnl_term_hash_t); 948 hash = sal_alloc(alloc_size, "tnl_term_hash"); 949 if (hash == NULL) { 950 return SOC_E_MEMORY; 951 } 952 /* Initialize hash structure. */ 953 sal_memset(hash, 0, alloc_size); 954 hash->unit = unit; 955 hash->entry_count = entry_count; 956 hash->index_count = index_count; 957 958 /* 959 * Pre-allocate the hash table storage. 960 */ 961 alloc_size = hash->index_count * sizeof(uint16); 962 hash->table = sal_alloc(alloc_size, "tnl_term_hash_table"); 963 if (hash->table == NULL) { 964 sal_free(hash); 965 return (SOC_E_MEMORY); 966 } 967 968 /* 969 * In case where all the entries should hash into the same bucket 970 * this will prevent the hash table overflow 971 */ 972 alloc_size = hash->entry_count * sizeof(uint16); 973 hash->link_table = sal_alloc(alloc_size, "tnl_term_link_table"); 974 if (hash->link_table == NULL) { 975 sal_free(hash->table); 976 sal_free(hash); 977 return (SOC_E_MEMORY); 978 } 979 980 /* 981 * Set the entries in the hash table to TNL_TERM_HASH_INDEX_NULL 982 * Link the entries beyond hash->index_max for handling collisions 983 */ 984 for(index = 0; index < hash->index_count; index++) { 985 hash->table[index] = TNL_TERM_HASH_INDEX_NULL; 986 } 987 for(index = 0; index < hash->entry_count; index++) { 988 hash->link_table[index] = TNL_TERM_HASH_INDEX_NULL; 989 } 990 *tnl_term_hash_ptr = hash; 991 return (SOC_E_NONE); 992 } 993 994 /* 995 * Function: 996 * _soc_tunnel_term_hash_destroy 997 * Purpose: 998 * Destroy the hash table. 999 * Parameters: 1000 * tnl_term_hash - (IN) Hash Table handler address. 1001 * Returns: 1002 * SOC_E_NONE Success 1003 */ 1004 STATIC int 1005 _soc_tunnel_term_hash_destroy(soc_tnl_term_hash_t **tnl_term_hash) 1006 { 1007 soc_tnl_term_hash_t *ptr; /* Hash pointer. */ 1008 1009 if (NULL == tnl_term_hash) { 1010 return (SOC_E_PARAM); 1011 } 1012 1013 ptr = *tnl_term_hash; 1014 if (NULL == ptr) { 1015 return (SOC_E_NONE); 1016 } 1017 1018 /* Free hash entries table. */ 1019 if (NULL != ptr->table){ 1020 sal_free(ptr->table); 1021 ptr->table = NULL; 1022 } 1023 1024 /* Free collisions table. */ 1025 if (NULL != ptr->link_table) { 1026 sal_free(ptr->link_table); 1027 ptr->link_table = NULL; 1028 } 1029 1030 /* Free hash table itself. */ 1031 sal_free(ptr); 1032 *tnl_term_hash = NULL; 1033 1034 return (SOC_E_NONE); 1035 } 1036 1037 /* 1038 * Function: 1039 * _soc_tunnel_term_entry_read 1040 * Purpose: 1041 * Read tunnel termination entry from hardware. 1042 * Parameters: 1043 * unit - (IN) Bcm device number. 1044 * index - (IN) Table index. 1045 * entry - (OUT) Tunnel termination entry. 1046 * ipv6 - (OUT) Entry is ipv6 tunnel terminator. 1047 * Returns: 1048 * SOC_E_XXX 1049 */ 1050 STATIC int 1051 _soc_tunnel_term_entry_read(int unit, int index, 1052 soc_tunnel_term_t *entry, int *entry_type) 1053 { 1054 int idx; /* Entry width iteration index. */ 1055 int type; 1056 soc_mem_t mem = L3_TUNNELm; 1057 soc_field_t validf = VALIDf; 1058 #ifdef BCM_TRIDENT3_SUPPORT 1059 int idx_max; 1060 #endif /* BCM_TRIDENT3_SUPPORT */ 1061 int ipv6type = 0x1; 1062 1063 /* Input parameters check. */ 1064 if ((NULL == entry) || (NULL == entry_type)) { 1065 return (SOC_E_PARAM); 1066 } 1067 1068 if (soc_feature(unit, soc_feature_tunnel_term_hash_table)) { 1069 int ipv6 = 0; 1070 uint32 *entry_ptr; 1071 1072 mem = L3_TUNNEL_DOUBLEm; 1073 entry_ptr = (uint32 *)&entry->entry_arr[0]; 1074 ipv6 = 1075 soc_mem_field32_get(unit, mem, entry_ptr, KEY_TYPEf) - 1; 1076 1077 if (ipv6) { 1078 mem = L3_TUNNEL_QUADm; 1079 } 1080 validf = BASE_VALID_0f; 1081 ipv6type = 0x2; 1082 } 1083 1084 SOC_IF_ERROR_RETURN 1085 (soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, 1086 (uint32 *)&entry->entry_arr[0])); 1087 1088 if (!soc_mem_field32_get(unit, mem, 1089 (uint32 *)&entry->entry_arr[0], validf)) { 1090 sal_memset (entry, 0, sizeof(soc_tunnel_term_t)); 1091 *entry_type = FALSE; 1092 return (SOC_E_NOT_FOUND); 1093 } 1094 /* Check if entry is ipv6 */ 1095 SOC_IF_ERROR_RETURN(_soc_tunnel_term_type_get(unit, entry, &type, entry_type)); 1096 1097 #ifdef BCM_TRIDENT3_SUPPORT 1098 if (soc_feature(unit,soc_feature_flex_flow) && 1099 (*entry_type > SOC_TNL_TERM_KEY_TYPE_FIXED_MAX)) { 1100 SOC_IF_ERROR_RETURN ( 1101 _soc_tunnel_term_flex_type_width_get(unit, type, entry, &idx_max)); 1102 for (idx = 1; idx < idx_max; idx++) { 1103 SOC_IF_ERROR_RETURN 1104 (soc_mem_read(unit, mem, MEM_BLOCK_ANY, (index + idx) , 1105 (uint32 *)&entry->entry_arr[idx])); 1106 } 1107 } else 1108 #endif /* BCM_TRIDENT3_SUPPORT */ 1109 { 1110 int size = SOC_TNL_TERM_IPV6_ENTRY_WIDTH; 1111 if (*entry_type == ipv6type) { /* IPV6 */ 1112 if (soc_feature(unit, soc_feature_tunnel_term_hash_table)) { 1113 mem = L3_TUNNEL_QUADm; 1114 size = 1; 1115 } 1116 for (idx = 1; idx < size; idx++) { 1117 SOC_IF_ERROR_RETURN 1118 (soc_mem_read(unit, mem, MEM_BLOCK_ANY, (idx + index), 1119 (uint32 *)&entry->entry_arr[idx])); 1120 } 1121 } 1122 } 1123 return (SOC_E_NONE); 1124 } 1125 1126 1127 /* 1128 * Function: 1129 * _soc_tunnel_term_entry_write 1130 * Purpose: 1131 * Write tunnel termination entry to the hardware. 1132 * Parameters: 1133 * unit - (IN) Bcm device number. 1134 * index - (IN) Table index. 1135 * entry - (IN) Tunnel termination entry. 1136 * ipv6 - (IN) Entry is ipv6 tunnel terminator. 1137 * Returns: 1138 * SOC_E_XXX 1139 */ 1140 STATIC int 1141 _soc_tunnel_term_entry_write(int unit, int index, 1142 soc_tunnel_term_t *entry, int entry_type) 1143 { 1144 int idx; /* Entry width iteration index. */ 1145 int idx_max; /* Entry width. */ 1146 #ifdef BCM_TRIDENT3_SUPPORT 1147 int type; 1148 int key_type; 1149 #endif /* BCM_TRIDENT3_SUPPORT */ 1150 int ipv6_key_type = 0x1; 1151 1152 /* Input parameters check. */ 1153 if (NULL == entry) { 1154 return (SOC_E_PARAM); 1155 } 1156 1157 if (soc_feature(unit, soc_feature_tunnel_term_hash_table)) { 1158 ipv6_key_type = 0x2; 1159 } 1160 1161 #ifdef BCM_TRIDENT3_SUPPORT 1162 if (soc_feature(unit,soc_feature_flex_flow) && 1163 (entry_type > SOC_TNL_TERM_KEY_TYPE_FIXED_MAX)) { 1164 SOC_IF_ERROR_RETURN 1165 (_soc_tunnel_term_type_get(unit, entry, &type, &key_type)); 1166 SOC_IF_ERROR_RETURN ( 1167 _soc_tunnel_term_flex_type_width_get(unit, type, entry, &idx_max)); 1168 } else 1169 #endif /* BCM_TRIDENT3_SUPPORT */ 1170 { 1171 idx_max = (entry_type == ipv6_key_type) ? SOC_TNL_TERM_IPV6_ENTRY_WIDTH : \ 1172 SOC_TNL_TERM_IPV4_ENTRY_WIDTH; 1173 } 1174 1175 1176 if (soc_feature(unit, soc_feature_tunnel_term_hash_table)) { 1177 soc_mem_t mem; 1178 mem = (entry_type == ipv6_key_type)? L3_TUNNEL_QUADm:L3_TUNNEL_DOUBLEm; 1179 SOC_IF_ERROR_RETURN(soc_mem_insert(unit, mem, MEM_BLOCK_ANY, entry->entry_arr)); 1180 } else { 1181 for (idx = 0; idx < idx_max; idx++) { 1182 SOC_IF_ERROR_RETURN (WRITE_L3_TUNNELm(unit, MEM_BLOCK_ALL, 1183 (idx + index), 1184 (uint32 *)&entry->entry_arr[idx])); 1185 } 1186 } 1187 return (SOC_E_NONE); 1188 } 1189 1190 1191 /* 1192 * Function: 1193 * _soc_tunnel_term_hash_lookup 1194 * Purpose: 1195 * Look up a key in the hash table 1196 * Parameters: 1197 * hash - (IN) Pointer (handle) to Hash Table 1198 * key_cmp_fn - (IN) Compare function which should compare key 1199 * entry - (IN) The key to lookup 1200 * key_index - (OUT) Index where the key was found. 1201 * Returns: 1202 * SOC_E_NONE Key found 1203 * SOC_E_NOT_FOUND Key not found 1204 */ 1205 STATIC int 1206 _soc_tunnel_term_hash_lookup(soc_tnl_term_hash_t *hash, 1207 _soc_tnl_term_hash_compare_fn key_cmp_fn, 1208 soc_tnl_term_hash_key_t *entry, 1209 uint16 *key_index) 1210 { 1211 1212 soc_tunnel_term_t hw_entry; /* Tunnel terminator entry from HW.*/ 1213 soc_tnl_term_hash_key_t r_entry; /* Entry key portion. */ 1214 uint16 hash_val; /* Computed hash value. */ 1215 uint16 index; /* Entry index in L3_TUNNEL table. */ 1216 int type; /* Entry type flag. */ 1217 int rv; /* Operation return status. */ 1218 int unit; /* BCM device number. */ 1219 uint16 mask; /* Index mask based on hash size */ 1220 1221 /* Input parameters check. */ 1222 if ((NULL == entry) || (NULL == key_index) || (NULL == hash)) { 1223 return (SOC_E_PARAM); 1224 } 1225 1226 /* Extract bcm device number. */ 1227 unit = hash->unit; 1228 1229 /* Calculate entry hash. */ 1230 rv = _soc_tunnel_term_hash_compute((uint8 *)entry, 1231 SOC_TNL_TERM_HASH_BIT_WIDTH, &hash_val); 1232 if (SOC_FAILURE(rv)){ 1233 return (rv); 1234 } 1235 1236 mask = soc_mem_index_count(unit, L3_TUNNELm) - 1; 1237 hash_val %= hash->index_count; 1238 1239 /* Iterate over indexes with identical hash value. */ 1240 index = hash->table[hash_val]; 1241 while(index != TNL_TERM_HASH_INDEX_NULL) { 1242 index &= mask; 1243 /* Read entry from HW. */ 1244 rv = _soc_tunnel_term_entry_read(unit, index, &hw_entry, &type); 1245 if (SOC_FAILURE(rv)){ 1246 return (SOC_E_INTERNAL); 1247 } 1248 SOC_TNL_TERM_HASH_ENTRY_GET(unit, &hw_entry, type, &r_entry); 1249 if ((*key_cmp_fn)(entry, &r_entry) == 0) { 1250 *key_index = index; 1251 return(SOC_E_NONE); 1252 } 1253 index = hash->link_table[index]; 1254 } 1255 return(SOC_E_NOT_FOUND); 1256 } 1257 1258 #define INDEX_ADD(hash, hash_idx, new_idx) \ 1259 hash->link_table[new_idx] = hash->table[hash_idx]; \ 1260 hash->table[hash_idx] = new_idx 1261 1262 #define INDEX_UPDATE(hash, hash_idx, old_idx, new_idx) \ 1263 hash->table[hash_idx] = new_idx; \ 1264 hash->link_table[new_idx] = hash->link_table[old_idx]; \ 1265 hash->link_table[old_idx] = TNL_TERM_HASH_INDEX_NULL 1266 1267 #define INDEX_UPDATE_LINK(hash, prev_idx, old_idx, new_idx) \ 1268 hash->link_table[prev_idx] = new_idx; \ 1269 hash->link_table[new_idx] = hash->link_table[old_idx]; \ 1270 hash->link_table[old_idx] = TNL_TERM_HASH_INDEX_NULL 1271 1272 /* 1273 * Function: 1274 * _soc_tunnel_term_hash_insert 1275 * Purpose: 1276 * Insert/Update a key index in the hash table 1277 * Parameters: 1278 * hash - (IN) Pointer (handle) to Hash Table 1279 * key_cmp_fn - (IN) Compare function which should compare key 1280 * entry - (IN) The key to lookup 1281 * old_index - (IN) Index where the key was moved from. 1282 * TNL_TERM_HASH_INDEX_NULL if new entry. 1283 * new_index - (IN) Index where the key was moved to. 1284 * Returns: 1285 * SOC_E_XXX 1286 * NOTE: 1287 * Should be caled before updating the L3_TUNNEL table so that the 1288 * data in the hash table is consistent with the hardware table 1289 */ 1290 STATIC int 1291 _soc_tunnel_term_hash_insert(soc_tnl_term_hash_t *hash, 1292 _soc_tnl_term_hash_compare_fn key_cmp_fn, 1293 soc_tnl_term_hash_key_t *entry, 1294 uint16 old_index, 1295 uint16 new_index) 1296 { 1297 soc_tunnel_term_t hw_entry; /* Tunnel terminator entry from HW. */ 1298 soc_tnl_term_hash_key_t r_entry; /* Entry key portion. */ 1299 uint16 hash_val; /* Computed hash value. */ 1300 uint16 prev_index; /* Previous entry with identical hash*/ 1301 uint16 index; /* Entry index in L3_TUNNEL table. */ 1302 int type; /* Entry type flag. */ 1303 int rv; /* Operation return status. */ 1304 int unit; /* BCM device number. */ 1305 uint16 mask; /* Index mask based on hash size */ 1306 1307 /* Input parameters check. */ 1308 if ((NULL == entry) || (NULL == hash)) { 1309 return (SOC_E_PARAM); 1310 } 1311 1312 rv = _soc_tunnel_term_hash_compute((uint8 *)entry, 1313 SOC_TNL_TERM_HASH_BIT_WIDTH, &hash_val); 1314 if (SOC_FAILURE(rv)) { 1315 return (rv); 1316 } 1317 hash_val %= hash->index_count; 1318 1319 index = hash->table[hash_val]; 1320 unit = hash->unit; 1321 mask = soc_mem_index_count(unit, L3_TUNNELm) - 1; 1322 1323 prev_index = TNL_TERM_HASH_INDEX_NULL; 1324 if (old_index != TNL_TERM_HASH_INDEX_NULL) { 1325 while(index != TNL_TERM_HASH_INDEX_NULL) { 1326 index &= mask; 1327 1328 /* 1329 * Check prefix length and skip index if not valid for given length 1330 */ 1331 1332 rv = _soc_tunnel_term_entry_read(unit, index, &hw_entry, &type); 1333 if (SOC_FAILURE(rv)) { 1334 return (SOC_E_INTERNAL); 1335 } 1336 SOC_TNL_TERM_HASH_ENTRY_GET(unit, &hw_entry, type, &r_entry); 1337 if ((*key_cmp_fn)(entry, &r_entry) == 0) { 1338 if (new_index != index) { 1339 if (prev_index == TNL_TERM_HASH_INDEX_NULL) { 1340 INDEX_UPDATE(hash, hash_val, index & mask, 1341 new_index & mask); 1342 } else { 1343 INDEX_UPDATE_LINK(hash, prev_index & mask, 1344 index & mask, new_index & mask); 1345 } 1346 } 1347 return(SOC_E_NONE); 1348 } 1349 prev_index = index; 1350 index = hash->link_table[index]; 1351 } 1352 } 1353 INDEX_ADD(hash, hash_val, new_index & mask); /* new entry */ 1354 return(SOC_E_NONE); 1355 } 1356 #undef INDEX_ADD 1357 #undef INDEX_UPDATE 1358 #undef INDEX_UPDATE_LINK 1359 1360 #define INDEX_DELETE(hash, hash_idx, del_idx) \ 1361 hash->table[hash_idx] = hash->link_table[del_idx]; \ 1362 hash->link_table[del_idx] = TNL_TERM_HASH_INDEX_NULL \ 1363 1364 #define INDEX_DELETE_LINK(hash, prev_idx, del_idx) \ 1365 hash->link_table[prev_idx] = hash->link_table[del_idx]; \ 1366 hash->link_table[del_idx] = TNL_TERM_HASH_INDEX_NULL 1367 /* 1368 * Function: 1369 * _soc_tunnel_term_hash_delete 1370 * Purpose: 1371 * Delete a key index in the hash table 1372 * Parameters: 1373 * hash - (IN) Pointer (handle) to Hash Table 1374 * key_cmp_fn - (IN) Compare function which should compare key 1375 * entry - (IN) The key to lookup 1376 * delete_index - (IN) Index to delete. 1377 * Returns: 1378 * SOC_E_NONE Success 1379 * SOC_E_NOT_FOUND Key index not found. 1380 */ 1381 STATIC int 1382 _soc_tunnel_term_hash_delete(soc_tnl_term_hash_t *hash, 1383 _soc_tnl_term_hash_compare_fn key_cmp_fn, 1384 soc_tnl_term_hash_key_t *entry, 1385 uint16 delete_index) 1386 { 1387 uint16 hash_val; /* Computed hash value. */ 1388 uint16 prev_index; /* Previous entry with identical hash*/ 1389 uint16 index; /* Entry index in L3_TUNNEL table. */ 1390 int rv; /* Internal operatin return status. */ 1391 int unit; /* BCM device number. */ 1392 uint16 mask; /* Index mask based on hash size */ 1393 1394 /* Input parameters check. */ 1395 if ((NULL == entry) || (NULL == hash)) { 1396 return (SOC_E_PARAM); 1397 } 1398 1399 rv = _soc_tunnel_term_hash_compute((uint8 *)entry, 1400 SOC_TNL_TERM_HASH_BIT_WIDTH, &hash_val); 1401 if (SOC_FAILURE(rv)) { 1402 return (rv); 1403 } 1404 1405 unit = hash->unit; 1406 mask = soc_mem_index_count(unit, L3_TUNNELm) - 1; 1407 hash_val %= hash->index_count; 1408 1409 index = hash->table[hash_val]; 1410 prev_index = TNL_TERM_HASH_INDEX_NULL; 1411 while(index != TNL_TERM_HASH_INDEX_NULL) { 1412 if (delete_index == index) { 1413 if (prev_index == TNL_TERM_HASH_INDEX_NULL) { 1414 INDEX_DELETE(hash, hash_val, delete_index & mask); 1415 } else { 1416 INDEX_DELETE_LINK(hash, prev_index & mask, 1417 delete_index & mask); 1418 } 1419 return(SOC_E_NONE); 1420 } 1421 prev_index = index; 1422 index = hash->link_table[index & mask]; 1423 } 1424 return(SOC_E_NOT_FOUND); 1425 } 1426 #undef INDEX_DELETE 1427 #undef INDEX_DELETE_LINK 1428 #define TNL_TERM_HASH_INSERT(_u_, _entry_data_, _tab_index_) \ 1429 soc_tunnel_term_hash_insert((_u_), (_entry_data_), (_tab_index_), 0) 1430 1431 #define TNL_TERM_HASH_DELETE(_u_, _key_data_, _tab_index_) \ 1432 soc_tunnel_term_hash_delete((_u_), (_key_data_), (_tab_index_)) 1433 1434 #define TNL_TERM_HASH_LOOKUP(_u_, _key_data_, _tab_index_) \ 1435 soc_tunnel_term_hash_lookup((_u_), (_key_data_), (_tab_index_)) 1436 /* 1437 * Function: 1438 * soc_tunnel_term_hash_insert 1439 * Purpose: 1440 * Tunnel termination entry hash insertion routine. 1441 * Parameters: 1442 * unit - (IN) BCM device number. 1443 * entry - (IN) Inserted entry. 1444 * tab_index - (IN) Insertion index. 1445 * old_index - (IN) Original entry index. 1446 * Returns: 1447 * SOC_E_XXX 1448 */ 1449 1450 STATIC int 1451 soc_tunnel_term_hash_insert(int unit, soc_tunnel_term_t *entry, 1452 uint32 tab_index, uint32 old_index) 1453 { 1454 soc_tnl_term_hash_key_t key_hash; /* Entry tcam lookup key. */ 1455 int type; /* Tunnel Entry Type */ 1456 int rv; /* Operation return status. */ 1457 1458 /* Input parameters check. */ 1459 if (NULL == entry) { 1460 return (SOC_E_PARAM); 1461 } 1462 1463 if (!soc_mem_field32_get(unit, L3_TUNNELm, 1464 (uint32 *)&entry->entry_arr[0], VALIDf)) { 1465 return (SOC_E_EMPTY); 1466 } 1467 1468 SOC_IF_ERROR_RETURN(_soc_tunnel_term_type_get(unit, entry, NULL, &type)); 1469 SOC_TNL_TERM_HASH_ENTRY_GET(unit, entry, type, &key_hash); 1470 1471 rv = _soc_tunnel_term_hash_insert (SOC_TNL_TERM_STATE_HASH(unit), 1472 _soc_tunnel_term_hash_compare_key, 1473 &key_hash, old_index, 1474 ((uint16)tab_index)); 1475 return (rv); 1476 } 1477 1478 /* 1479 * Function: 1480 * soc_tunnel_term_hash_delete 1481 * Purpose: 1482 * Tunnel termination entry hash removal routine. 1483 * Parameters: 1484 * unit - (IN) BCM device number. 1485 * key_data - (IN) Deleted entry. 1486 * tab_index - (IN) Removed index. 1487 * Returns: 1488 * SOC_E_XXX 1489 */ 1490 STATIC int 1491 soc_tunnel_term_hash_delete(int unit, soc_tunnel_term_t *key_data, 1492 uint32 tab_index) 1493 { 1494 soc_tnl_term_hash_key_t key_hash; /* Entry lookup key. */ 1495 int type; /* Tunnel term type */ 1496 1497 /* Input parameters check. */ 1498 if (NULL == key_data) { 1499 return (SOC_E_PARAM); 1500 } 1501 1502 SOC_IF_ERROR_RETURN(_soc_tunnel_term_type_get(unit, key_data, NULL, &type)); 1503 SOC_TNL_TERM_HASH_ENTRY_GET(unit, key_data, type, &key_hash); 1504 1505 return _soc_tunnel_term_hash_delete(SOC_TNL_TERM_STATE_HASH(unit), 1506 _soc_tunnel_term_hash_compare_key, 1507 &key_hash, tab_index); 1508 } 1509 1510 /* 1511 * Function: 1512 * soc_tunnel_term_hash_lookup 1513 * Purpose: 1514 * Tunnel termination entry hash lookup routine. 1515 * Parameters: 1516 * unit - (IN) BCM device number. 1517 * key_data - (IN) Entry lookup key. 1518 * key_index - (OUT) Search result index if any. 1519 * Returns: 1520 * SOC_E_XXX 1521 */ 1522 1523 STATIC int 1524 soc_tunnel_term_hash_lookup(int unit, soc_tunnel_term_t *key_data, 1525 int *key_index) 1526 { 1527 soc_tnl_term_hash_key_t key_hash; /* Entry lookup key. */ 1528 uint16 index; /* Entry index. */ 1529 int type; /* Tunnel Term type */ 1530 int rv; /* Operation return status. */ 1531 1532 /* Input parameters check. */ 1533 if ((NULL == key_data) || (NULL == key_index)) { 1534 return (SOC_E_PARAM); 1535 } 1536 1537 SOC_IF_ERROR_RETURN(_soc_tunnel_term_type_get(unit, key_data, NULL, &type)); 1538 SOC_TNL_TERM_HASH_ENTRY_GET(unit, key_data, type, &key_hash); 1539 1540 rv = _soc_tunnel_term_hash_lookup(SOC_TNL_TERM_STATE_HASH(unit), 1541 _soc_tunnel_term_hash_compare_key, 1542 &key_hash, &index); 1543 if (SOC_FAILURE(rv)) { 1544 return (rv); 1545 } 1546 *key_index = index; 1547 return (SOC_E_NONE); 1548 } 1549 1550 1551 /* 1552 * Function: 1553 * soc_tunnel_term_sw_dump 1554 * Purpose: 1555 * Dump tunnel termination hash status for warm boot debug. 1556 * Parameters: 1557 * unit - (IN) BCM device number. 1558 * Returns: 1559 * none. 1560 */ 1561 void 1562 soc_tunnel_term_sw_dump(int unit) 1563 { 1564 int i; 1565 int max_type; 1566 max_type = MAX_TNL_TERM_TYPE; 1567 1568 LOG_CLI((BSL_META_U(unit, 1569 "\n Tunnel Terminator State -\n"))); 1570 1571 if (!SOC_TNL_TERM_INIT_CHECK(unit)) { 1572 LOG_CLI((BSL_META_U(unit, 1573 "\nTunnel Terminator in Uninitialized state -\n"))); 1574 return; 1575 } 1576 1577 for(i = max_type; i >= 0 ; i--) { 1578 if ((i != MAX_TNL_TERM_TYPE) && \ 1579 (SOC_TNL_TERM_STATE_START(unit, i) == TNL_TERM_TYPE_NULL)) { 1580 continue; 1581 } 1582 LOG_CLI((BSL_META_U(unit, 1583 "PFX = %d P = %d N = %d START = %d END = %d VENT = %d FENT = %d\n"), 1584 i, 1585 SOC_TNL_TERM_STATE_PREV(unit, i), 1586 SOC_TNL_TERM_STATE_NEXT(unit, i), 1587 SOC_TNL_TERM_STATE_START(unit, i), 1588 SOC_TNL_TERM_STATE_END(unit, i), 1589 SOC_TNL_TERM_STATE_VENT(unit, i), 1590 SOC_TNL_TERM_STATE_FENT(unit, i))); 1591 } 1592 return; 1593 } 1594 1595 /* 1596 * Function: 1597 * _soc_tunnel_term_type_width_get 1598 * Purpose: 1599 * Given tunnel terminator type get number of hw slots 1600 * it takes to write it to hardware. 1601 * Parameters: 1602 * unit - (IN) BCM device number. 1603 * type - (IN) Tunnel terminator type. 1604 * width - (OUT) Number of hw slot entry requires. 1605 * Returns: 1606 * SOC_E_XXX 1607 */ 1608 STATIC int 1609 _soc_tunnel_term_type_width_get(int unit, int type, int *width) 1610 { 1611 /* Input parameters check. */ 1612 if (NULL == width) { 1613 return (SOC_E_PARAM); 1614 } 1615 1616 switch (type - (type % (_SHR_L3_IP6_MAX_NETLEN + 1))) { 1617 case SOC_TNL_TERM_TYPE_DIP4_SIP4_PROT_L4DST_L4SRC: 1618 case SOC_TNL_TERM_TYPE_DIP4_PROT_L4DST_L4SRC: 1619 case SOC_TNL_TERM_TYPE_DIP4_SIP4_L4DST_L4SRC: 1620 case SOC_TNL_TERM_TYPE_DIP4_L4DST_L4SRC: 1621 case SOC_TNL_TERM_TYPE_DIP4_SIP4_PROT_L4DST: 1622 case SOC_TNL_TERM_TYPE_DIP4_PROT_L4DST: 1623 case SOC_TNL_TERM_TYPE_DIP4_SIP4_L4DST: 1624 case SOC_TNL_TERM_TYPE_DIP4_L4DST: 1625 case SOC_TNL_TERM_TYPE_DIP4_SIP4_PROT_L4SRC: 1626 case SOC_TNL_TERM_TYPE_DIP4_PROT_L4SRC: 1627 case SOC_TNL_TERM_TYPE_DIP4_SIP4_L4SRC: 1628 case SOC_TNL_TERM_TYPE_DIP4_L4SRC: 1629 case SOC_TNL_TERM_TYPE_DIP4_SIP4_PROT: 1630 case SOC_TNL_TERM_TYPE_DIP4_PROT: 1631 case SOC_TNL_TERM_TYPE_DIP4_SIP4: 1632 case SOC_TNL_TERM_TYPE_DIP4: 1633 *width = SOC_TNL_TERM_IPV4_ENTRY_WIDTH; 1634 break; 1635 case SOC_TNL_TERM_TYPE_DIP6_SIP6_PROT_L4DST_L4SRC: 1636 case SOC_TNL_TERM_TYPE_DIP6_PROT_L4DST_L4SRC: 1637 case SOC_TNL_TERM_TYPE_DIP6_SIP6_L4DST_L4SRC: 1638 case SOC_TNL_TERM_TYPE_DIP6_SIP6_PROT_L4DST: 1639 case SOC_TNL_TERM_TYPE_DIP6_SIP6_PROT_L4SRC: 1640 case SOC_TNL_TERM_TYPE_DIP6_L4DST_L4SRC: 1641 case SOC_TNL_TERM_TYPE_DIP6_SIP6_L4DST: 1642 case SOC_TNL_TERM_TYPE_DIP6_PROT_L4SRC: 1643 case SOC_TNL_TERM_TYPE_DIP6_SIP6_L4SRC: 1644 case SOC_TNL_TERM_TYPE_DIP6_PROT_L4DST: 1645 case SOC_TNL_TERM_TYPE_DIP6_SIP6_PROT: 1646 case SOC_TNL_TERM_TYPE_DIP6_L4SRC: 1647 case SOC_TNL_TERM_TYPE_DIP6_SIP6: 1648 case SOC_TNL_TERM_TYPE_DIP6_PROT: 1649 case SOC_TNL_TERM_TYPE_DIP6_L4DST: 1650 case SOC_TNL_TERM_TYPE_DIP6: 1651 *width = SOC_TNL_TERM_IPV6_ENTRY_WIDTH; 1652 break; 1653 default: 1654 return (SOC_E_INTERNAL); 1655 } 1656 return (SOC_E_NONE); 1657 } 1658 1659 /* 1660 * Function: 1661 * _soc_tunnel_term_entry_shift 1662 * Purpose: 1663 * Move entry from one index to another tcam. 1664 * Parameters: 1665 * unit - (IN) BCM device number. 1666 * from_ent - (IN) Entry source. 1667 * to_ent - (IN) Entry destination. 1668 * Returns: 1669 * SOC_E_XXX. 1670 */ 1671 STATIC int 1672 _soc_tunnel_term_entry_shift(int unit, int from_ent, int to_ent) 1673 { 1674 soc_tunnel_term_t hw_entry; /* Tunnel terminator entry from hw. */ 1675 int entry_type; /* Entry type indicator. */ 1676 int rv; /* Operation return status. */ 1677 1678 if (from_ent == to_ent) { 1679 return (SOC_E_NONE); 1680 } 1681 1682 /* Read source entry. */ 1683 rv = _soc_tunnel_term_entry_read(unit, from_ent, &hw_entry, &entry_type); 1684 if (SOC_FAILURE(rv)) { 1685 return ((SOC_E_NOT_FOUND == rv) ? (SOC_E_NONE) : (rv)); 1686 } 1687 TNL_TERM_HASH_INSERT(unit, &hw_entry, to_ent); 1688 1689 /* Write destination entry. */ 1690 SOC_IF_ERROR_RETURN 1691 (_soc_tunnel_term_entry_write(unit, to_ent, &hw_entry, entry_type)); 1692 1693 /* Reset source entry. */ 1694 sal_memset(&hw_entry, 0, sizeof(soc_tunnel_term_t)); 1695 SOC_IF_ERROR_RETURN 1696 (_soc_tunnel_term_entry_write(unit, from_ent, &hw_entry, entry_type)); 1697 1698 return (SOC_E_NONE); 1699 } 1700 1701 /* 1702 * Function: 1703 * _soc_tunnel_term_entry_block_shift 1704 * Purpose: 1705 * Create a slot for the new entry rippling the entries if required. 1706 * Parameters: 1707 * unit - (IN) BCM device number. 1708 * from_ent - (IN) Block source start index. 1709 * to_ent - (IN) Block destination start index. 1710 * type - (IN) Block entries type. 1711 * Returns: 1712 * SOC_E_XXX. 1713 */ 1714 STATIC int 1715 _soc_tunnel_term_entry_block_shift(int unit, int from_ent, int to_ent,int type) 1716 { 1717 int width; /* Single entry width in block. */ 1718 int idx; /* Block indexes iterator. */ 1719 #ifdef BCM_TRIDENT3_SUPPORT 1720 soc_tunnel_term_t hw_entry; /* Tunnel terminator entry from hw. */ 1721 int entry_type; /* Entry type indicator. */ 1722 #endif /* BCM_TRIDENT3_SUPPORT */ 1723 1724 if (from_ent == to_ent) { 1725 return (SOC_E_NONE); 1726 } 1727 #ifdef BCM_TRIDENT3_SUPPORT 1728 if (soc_feature(unit,soc_feature_flex_flow) && 1729 (type == SOC_TNL_TERM_TYPE_FLEX)) { 1730 1731 /* Read source entry. */ 1732 SOC_IF_ERROR_RETURN ( 1733 _soc_tunnel_term_entry_read(unit, from_ent, &hw_entry, &entry_type)); 1734 SOC_IF_ERROR_RETURN ( 1735 _soc_tunnel_term_flex_type_width_get(unit, type, &hw_entry, &width)); 1736 } else 1737 #endif /* BCM_TRIDENT3_SUPPORT */ 1738 { 1739 /* Get entry width for tunnel termination type. */ 1740 SOC_IF_ERROR_RETURN(_soc_tunnel_term_type_width_get(unit, type, &width)); 1741 } 1742 1743 for (idx = 0; idx < SOC_TNL_TERM_BLOCK_SIZE; idx += width) { 1744 SOC_IF_ERROR_RETURN 1745 (_soc_tunnel_term_entry_shift(unit, from_ent + idx, to_ent + idx)); 1746 } 1747 return (SOC_E_NONE); 1748 } 1749 1750 /* 1751 * Function: 1752 * _soc_tunnel_term_entry_shift_up 1753 * Purpose: 1754 * Shift entries 4 entries UP, while preserving 1755 * last 4 ipv4 entries last. 1756 * Parameters: 1757 * unit - (IN) BCM device number. 1758 * type - (IN) Free entry type. 1759 * Returns: 1760 * SOC_E_XXX. 1761 */ 1762 STATIC 1763 int _soc_tunnel_term_shift_type_up(int unit, int type) 1764 { 1765 int from_ent; /* Moved entry block index. */ 1766 int to_ent; /* Destination entry block index. */ 1767 int entry_width; /* Number of hw slots single entry occupies. */ 1768 int from_block; /* "From" block start index. */ 1769 int to_block; /* "To" block start index. */ 1770 1771 #ifdef BCM_TRIDENT3_SUPPORT 1772 soc_tunnel_term_t hw_entry; /* Tunnel terminator entry from hw. */ 1773 int entry_type; /* Entry type indicator. */ 1774 #endif /* BCM_TRIDENT3_SUPPORT */ 1775 1776 to_ent = SOC_TNL_TERM_STATE_END(unit, type) + SOC_TNL_TERM_BLOCK_SIZE; 1777 SOC_TNL_TERM_IDX_TO_BLOCK_START(to_ent, to_block,SOC_TNL_TERM_BLOCK_SIZE); 1778 1779 #ifdef BCM_TRIDENT3_SUPPORT 1780 if (soc_feature(unit,soc_feature_flex_flow) && 1781 (type == SOC_TNL_TERM_TYPE_FLEX)) { 1782 from_ent = SOC_TNL_TERM_STATE_END(unit, type); 1783 SOC_TNL_TERM_IDX_TO_BLOCK_START(from_ent, 1784 from_block,SOC_TNL_TERM_BLOCK_SIZE); 1785 /* Read source entry. */ 1786 SOC_IF_ERROR_RETURN ( 1787 _soc_tunnel_term_entry_read(unit, from_block, &hw_entry, &entry_type)); 1788 SOC_IF_ERROR_RETURN ( 1789 _soc_tunnel_term_flex_type_width_get(unit, type, 1790 &hw_entry, &entry_width)); 1791 if (SOC_TNL_TERM_BLOCK_SIZE != entry_width) { 1792 1793 if (from_ent != (from_block + SOC_TNL_TERM_BLOCK_SIZE - 1)) { 1794 /* Last block is not full -> keep it last. */ 1795 SOC_IF_ERROR_RETURN 1796 (_soc_tunnel_term_entry_block_shift(unit, from_block, 1797 to_block, type)); 1798 1799 to_block -= SOC_TNL_TERM_BLOCK_SIZE; 1800 } 1801 1802 } 1803 1804 from_ent = SOC_TNL_TERM_STATE_START(unit, type); 1805 SOC_TNL_TERM_IDX_TO_BLOCK_START(from_ent, 1806 from_block,SOC_TNL_TERM_BLOCK_SIZE); 1807 1808 if(from_block != to_block) { 1809 SOC_IF_ERROR_RETURN( 1810 _soc_tunnel_term_entry_block_shift(unit, from_block, 1811 to_block, type)); 1812 } 1813 1814 } else 1815 #endif /* BCM_TRIDENT3_SUPPORT */ 1816 { 1817 SOC_IF_ERROR_RETURN 1818 (_soc_tunnel_term_type_width_get(unit, type, &entry_width)); 1819 1820 if (SOC_TNL_TERM_BLOCK_SIZE != entry_width) { 1821 from_ent = SOC_TNL_TERM_STATE_END(unit, type); 1822 SOC_TNL_TERM_IDX_TO_BLOCK_START(from_ent, 1823 from_block,SOC_TNL_TERM_BLOCK_SIZE); 1824 1825 if (from_ent != (from_block + SOC_TNL_TERM_BLOCK_SIZE - 1)) { 1826 /* Last block is not full -> keep it last. */ 1827 SOC_IF_ERROR_RETURN 1828 (_soc_tunnel_term_entry_block_shift(unit, from_block, 1829 to_block, type)); 1830 1831 to_block -= SOC_TNL_TERM_BLOCK_SIZE; 1832 } 1833 } 1834 1835 from_ent = SOC_TNL_TERM_STATE_START(unit, type); 1836 SOC_TNL_TERM_IDX_TO_BLOCK_START(from_ent, 1837 from_block,SOC_TNL_TERM_BLOCK_SIZE); 1838 1839 if(from_block != to_block) { 1840 SOC_IF_ERROR_RETURN( 1841 _soc_tunnel_term_entry_block_shift(unit, from_block, 1842 to_block, type)); 1843 } 1844 } 1845 1846 SOC_TNL_TERM_STATE_START(unit, type) += SOC_TNL_TERM_BLOCK_SIZE; 1847 SOC_TNL_TERM_STATE_END(unit, type) += SOC_TNL_TERM_BLOCK_SIZE; 1848 return (SOC_E_NONE); 1849 } 1850 1851 /* 1852 * Function: 1853 * _soc_tunnel_term_entry_shift_down 1854 * Purpose: 1855 * Shift entries 4 entries DOWN, while preserving 1856 * last 4 ipv4 entries last. 1857 * Parameters: 1858 * unit - (IN) BCM device number. 1859 * type - (IN) Free entry type. 1860 * Returns: 1861 * SOC_E_XXX. 1862 */ 1863 STATIC int 1864 _soc_tunnel_term_shift_type_down(int unit, int type) 1865 { 1866 int from_ent; /* Moved entry block index. */ 1867 int to_ent; /* Destination entry block index. */ 1868 int entry_width; /* Number of hw slots single entry occupies. */ 1869 int from_block; /* "From" block start index. */ 1870 int to_block; /* "To" block start index. */ 1871 #ifdef BCM_TRIDENT3_SUPPORT 1872 soc_tunnel_term_t hw_entry; /* Tunnel terminator entry from hw. */ 1873 int entry_type; /* Entry type indicator. */ 1874 #endif /* BCM_TRIDENT3_SUPPORT */ 1875 1876 to_ent = SOC_TNL_TERM_STATE_START(unit, type) - SOC_TNL_TERM_BLOCK_SIZE; 1877 to_block = to_ent; 1878 1879 /* Don't move empty types. */ 1880 if (SOC_TNL_TERM_STATE_VENT(unit, type) == 0) { 1881 SOC_TNL_TERM_STATE_START(unit, type) = to_ent; 1882 SOC_TNL_TERM_STATE_END(unit, type) = to_ent - 1; 1883 return (SOC_E_NONE); 1884 } 1885 1886 from_ent = SOC_TNL_TERM_STATE_END(unit, type); 1887 SOC_TNL_TERM_IDX_TO_BLOCK_START(from_ent, from_block,SOC_TNL_TERM_BLOCK_SIZE); 1888 1889 #ifdef BCM_TRIDENT3_SUPPORT 1890 if (soc_feature(unit,soc_feature_flex_flow) && 1891 (type == SOC_TNL_TERM_TYPE_FLEX)) { 1892 SOC_IF_ERROR_RETURN ( 1893 _soc_tunnel_term_entry_read(unit, from_block, &hw_entry, &entry_type)); 1894 SOC_IF_ERROR_RETURN ( 1895 _soc_tunnel_term_flex_type_width_get(unit, type, &hw_entry, &entry_width)); 1896 } else 1897 #endif /* BCM_TRIDENT3_SUPPORT */ 1898 { 1899 SOC_IF_ERROR_RETURN 1900 (_soc_tunnel_term_type_width_get(unit, type, &entry_width)); 1901 } 1902 1903 if ((SOC_TNL_TERM_BLOCK_SIZE != entry_width) && 1904 (SOC_TNL_TERM_STATE_VENT(unit, type) > SOC_TNL_TERM_BLOCK_SIZE)) { 1905 1906 if (from_ent != (from_block + SOC_TNL_TERM_BLOCK_SIZE - 1)) { 1907 /* Last block is not full -> keep it last. */ 1908 /* Shift entry before last to start - 1 position. */ 1909 from_block -= SOC_TNL_TERM_BLOCK_SIZE; 1910 SOC_IF_ERROR_RETURN 1911 (_soc_tunnel_term_entry_block_shift(unit, from_block, 1912 to_block, type)); 1913 to_block = from_block; 1914 from_block += SOC_TNL_TERM_BLOCK_SIZE; 1915 } 1916 } 1917 SOC_IF_ERROR_RETURN (_soc_tunnel_term_entry_block_shift(unit, from_block, 1918 to_block, type)); 1919 1920 SOC_TNL_TERM_STATE_START(unit, type) -= SOC_TNL_TERM_BLOCK_SIZE; 1921 SOC_TNL_TERM_STATE_END(unit, type) -= SOC_TNL_TERM_BLOCK_SIZE; 1922 return (SOC_E_NONE); 1923 } 1924 /* 1925 * Function: 1926 * _soc_tunnel_term_type_entries_ripple 1927 * Purpose: 1928 * Ceate a slot for the new entry rippling the entries if required. 1929 * Parameters: 1930 * unit - (IN) BCM device number. 1931 * type - (IN) Inserted Tunnel terminator entry type. 1932 * Returns: 1933 * SOC_E_XXX 1934 */ 1935 STATIC int 1936 _soc_tunnel_term_type_entries_ripple (int unit, int type) 1937 { 1938 int prev_type; 1939 int next_type; 1940 int free_type; 1941 1942 free_type = type; 1943 while (SOC_TNL_TERM_STATE_FENT(unit, free_type) < 1944 SOC_TNL_TERM_BLOCK_SIZE) { 1945 free_type = SOC_TNL_TERM_STATE_NEXT(unit, free_type); 1946 if (free_type == TNL_TERM_TYPE_NULL) { 1947 /* No free entries on this side try the other side */ 1948 free_type = type; 1949 break; 1950 } 1951 } 1952 1953 while (SOC_TNL_TERM_STATE_FENT(unit, free_type) < SOC_TNL_TERM_BLOCK_SIZE) { 1954 free_type = SOC_TNL_TERM_STATE_PREV(unit, free_type); 1955 if (free_type == TNL_TERM_TYPE_NULL) { 1956 return (SOC_E_FULL); 1957 } 1958 } 1959 1960 /* 1961 * Ripple entries to create free space 1962 */ 1963 while (free_type > type) { 1964 next_type = SOC_TNL_TERM_STATE_NEXT(unit, free_type); 1965 SOC_IF_ERROR_RETURN(_soc_tunnel_term_shift_type_down(unit, next_type)); 1966 SOC_TNL_TERM_STATE_FENT(unit, free_type) -= SOC_TNL_TERM_BLOCK_SIZE; 1967 SOC_TNL_TERM_STATE_FENT(unit, next_type) += SOC_TNL_TERM_BLOCK_SIZE; 1968 free_type = next_type; 1969 } 1970 1971 while (free_type < type) { 1972 SOC_IF_ERROR_RETURN(_soc_tunnel_term_shift_type_up(unit, free_type)); 1973 SOC_TNL_TERM_STATE_FENT(unit, free_type) -= SOC_TNL_TERM_BLOCK_SIZE; 1974 prev_type = SOC_TNL_TERM_STATE_PREV(unit, free_type); 1975 SOC_TNL_TERM_STATE_FENT(unit, prev_type) += SOC_TNL_TERM_BLOCK_SIZE; 1976 free_type = prev_type; 1977 } 1978 return (SOC_E_NONE); 1979 } 1980 1981 /* 1982 * Function: 1983 * _soc_tunnel_term_slot_allocate 1984 * Purpose: 1985 * Create a slot for the new entry rippling the entries if required. 1986 * Parameters: 1987 * unit - (IN) BCM device number. 1988 * entry - (IN) Inserted Tunnel terminator entry. 1989 * index - (OUT) Allocated index. 1990 * Returns: 1991 * SOC_E_XXX 1992 */ 1993 STATIC 1994 int _soc_tunnel_term_slot_allocate(int unit, soc_tunnel_term_t *entry, int *index) 1995 { 1996 int type; /* Tunnel entry type. */ 1997 int entry_type; /* entry type */ 1998 int entry_size; /* Requested entry size. */ 1999 int curr_type; /* Iteration index to find insertion index.*/ 2000 int prev_type; /* Previous entry type in tcam. */ 2001 int next_type; /* Next entry type in tcam. */ 2002 int rv; /* Operation return status. */ 2003 2004 /* Get tunnel termination type. */ 2005 SOC_IF_ERROR_RETURN (_soc_tunnel_term_type_get(unit, entry, &type, 2006 &entry_type)); 2007 #ifdef BCM_TRIDENT3_SUPPORT 2008 if (soc_feature(unit,soc_feature_flex_flow) && 2009 (entry_type > SOC_TNL_TERM_KEY_TYPE_FIXED_MAX)) { 2010 SOC_IF_ERROR_RETURN ( 2011 _soc_tunnel_term_flex_type_width_get(unit, type, entry, &entry_size)); 2012 } else 2013 #endif /* BCM_TRIDENT3_SUPPORT */ 2014 2015 { 2016 entry_size = (entry_type == 0x1) ? SOC_TNL_TERM_IPV6_ENTRY_WIDTH : 2017 SOC_TNL_TERM_IPV4_ENTRY_WIDTH; 2018 } 2019 if (SOC_TNL_TERM_STATE_VENT(unit, type) == 0) { 2020 /* 2021 * Find the type position. Only type with valid 2022 * entries are in the list. 2023 * next -> high to low type priority. low to high index 2024 * prev -> low to high type priority. high to low index 2025 * Unused prefix length MAX_TNL_TERM_TYPE is the head of the 2026 * list and is node corresponding to this is always 2027 * present. 2028 */ 2029 curr_type = MAX_TNL_TERM_TYPE; 2030 while ((SOC_TNL_TERM_STATE_NEXT(unit, curr_type) != 2031 TNL_TERM_TYPE_NULL) && 2032 (SOC_TNL_TERM_STATE_NEXT(unit, curr_type) > type)) { 2033 curr_type = SOC_TNL_TERM_STATE_NEXT(unit, curr_type); 2034 } 2035 2036 /* Insert the new prefix */ 2037 next_type = SOC_TNL_TERM_STATE_NEXT(unit, curr_type); 2038 if (next_type != TNL_TERM_TYPE_NULL) { 2039 SOC_TNL_TERM_STATE_PREV(unit, next_type) = type; 2040 } 2041 SOC_TNL_TERM_STATE_NEXT(unit, type) = 2042 SOC_TNL_TERM_STATE_NEXT(unit, curr_type); 2043 SOC_TNL_TERM_STATE_PREV(unit, type) = curr_type; 2044 SOC_TNL_TERM_STATE_NEXT(unit, curr_type) = type; 2045 2046 SOC_TNL_TERM_STATE_VENT(unit, type) = 0; 2047 SOC_TNL_TERM_STATE_FENT(unit, type) = 2048 (SOC_TNL_TERM_STATE_FENT(unit, curr_type) + 1) / 2; 2049 2050 /* Adjust number of free entries to 2051 * multiples of SOC_TNL_TERM_BLOCK_SIZE boundary. 2052 */ 2053 SOC_TNL_TERM_STATE_FENT(unit, type) /= SOC_TNL_TERM_BLOCK_SIZE; 2054 SOC_TNL_TERM_STATE_FENT(unit, type) *= SOC_TNL_TERM_BLOCK_SIZE; 2055 SOC_TNL_TERM_STATE_FENT(unit, curr_type) -= SOC_TNL_TERM_STATE_FENT(unit, type); 2056 2057 SOC_TNL_TERM_STATE_START(unit, type) = 2058 SOC_TNL_TERM_STATE_END(unit, curr_type) + 2059 SOC_TNL_TERM_STATE_FENT(unit, curr_type) + 1; 2060 SOC_TNL_TERM_STATE_END(unit, type) = SOC_TNL_TERM_STATE_START(unit, type) - 1; 2061 2062 } 2063 2064 /* Check if there is sufficient room to accomodate the entry.*/ 2065 if (SOC_TNL_TERM_STATE_FENT(unit, type) < entry_size) { 2066 rv = _soc_tunnel_term_type_entries_ripple (unit, type); 2067 if (SOC_FAILURE(rv)) { 2068 if (!SOC_TNL_TERM_STATE_VENT(unit, type)) { 2069 /* We failed to allocate entries for a newly allocated type.*/ 2070 prev_type = SOC_TNL_TERM_STATE_PREV(unit, type); 2071 next_type = SOC_TNL_TERM_STATE_NEXT(unit, type); 2072 if (TNL_TERM_TYPE_NULL != prev_type) { 2073 SOC_TNL_TERM_STATE_NEXT(unit, prev_type) = next_type; 2074 } 2075 if (TNL_TERM_TYPE_NULL != next_type) { 2076 SOC_TNL_TERM_STATE_PREV(unit, next_type) = prev_type; 2077 } 2078 } 2079 return (rv); 2080 } 2081 } 2082 2083 /* Insert the entry. */ 2084 SOC_TNL_TERM_STATE_VENT(unit, type) += entry_size; 2085 SOC_TNL_TERM_STATE_FENT(unit, type) -= entry_size; 2086 *index = SOC_TNL_TERM_STATE_END(unit, type) + 1; 2087 SOC_TNL_TERM_STATE_END(unit, type) += entry_size; 2088 2089 return(SOC_E_NONE); 2090 } 2091 2092 /* 2093 * Function: 2094 * _soc_tunnel_term_slot_free 2095 * Purpose: 2096 * Delete a slot and adjust entry pointers if required. 2097 * Parameters: 2098 * unit - (IN) BCM device number. 2099 * entry - (IN) Inserted Tunnel terminator entry. 2100 * index - (OUT) Allocated index. 2101 * Returns: 2102 * SOC_E_XXX 2103 */ 2104 STATIC int 2105 _soc_tunnel_term_slot_free (int unit, soc_tunnel_term_t *entry, int index) 2106 { 2107 int type; /* Tunnel entry type. */ 2108 int entry_type; /* entry type */ 2109 int from_ent; /* Moved entry block index. */ 2110 int to_ent; /* Destination entry block index. */ 2111 int entry_size; /* Requested entry size. */ 2112 int prev_type; /* Previous entry type in tcam. */ 2113 int next_type; /* Next entry type in tcam. */ 2114 soc_tunnel_term_t null_entry; /* NULL entry buffer. */ 2115 2116 /* Input parameters check. */ 2117 if (NULL == entry) { 2118 return (SOC_E_PARAM); 2119 } 2120 2121 /* Get tunnel termination type. */ 2122 SOC_IF_ERROR_RETURN (_soc_tunnel_term_type_get(unit, entry, &type, 2123 &entry_type)); 2124 #ifdef BCM_TRIDENT3_SUPPORT 2125 if (soc_feature(unit,soc_feature_flex_flow) && 2126 (entry_type > SOC_TNL_TERM_KEY_TYPE_FIXED_MAX)) { 2127 SOC_IF_ERROR_RETURN ( 2128 _soc_tunnel_term_flex_type_width_get(unit, type, 2129 entry, &entry_size)); 2130 } else 2131 #endif /* BCM_TRIDENT3_SUPPORT */ 2132 { 2133 SOC_IF_ERROR_RETURN ( 2134 _soc_tunnel_term_type_width_get(unit, type, &entry_size)); 2135 } 2136 2137 SOC_TNL_TERM_STATE_VENT(unit, type) -= entry_size; 2138 SOC_TNL_TERM_STATE_FENT(unit, type) += entry_size; 2139 2140 if (SOC_TNL_TERM_STATE_VENT(unit, type) != 0) { 2141 from_ent = SOC_TNL_TERM_STATE_END(unit, type) + 1 - entry_size; 2142 to_ent = index; 2143 /* Move last entry to deleted entry position. */ 2144 SOC_IF_ERROR_RETURN( 2145 _soc_tunnel_term_entry_shift(unit, from_ent, to_ent)); 2146 } else { 2147 from_ent = index; 2148 } 2149 2150 /* Update number of free & valid entries for this type. */ 2151 SOC_TNL_TERM_STATE_END(unit, type) -= entry_size; 2152 2153 /* Reset deleted entry. */ 2154 sal_memset(&null_entry, 0, sizeof(soc_tunnel_term_t)); 2155 #ifdef BCM_TRIDENT3_SUPPORT 2156 if (soc_feature(unit,soc_feature_flex_flow) && 2157 (entry_type > SOC_TNL_TERM_KEY_TYPE_FIXED_MAX)) { 2158 SOC_IF_ERROR_RETURN 2159 (_soc_tunnel_term_flex_entry_clear(unit, 2160 from_ent, entry, entry_type)); 2161 } else 2162 #endif /* BCM_TRIDENT3_SUPPORT */ 2163 { 2164 SOC_IF_ERROR_RETURN 2165 (_soc_tunnel_term_entry_write(unit, 2166 from_ent, &null_entry, entry_type)); 2167 } 2168 /* 2169 * If last entry for the type was deleted -> remove the type 2170 * from hash tracking table. 2171 */ 2172 if (SOC_TNL_TERM_STATE_VENT(unit, type) == 0) { 2173 /* remove from the list */ 2174 prev_type = SOC_TNL_TERM_STATE_PREV(unit, type); /* Always present */ 2175 next_type = SOC_TNL_TERM_STATE_NEXT(unit, type); 2176 SOC_TNL_TERM_STATE_NEXT(unit, prev_type) = next_type; 2177 SOC_TNL_TERM_STATE_FENT(unit, prev_type) += SOC_TNL_TERM_STATE_FENT(unit, type); 2178 SOC_TNL_TERM_STATE_FENT(unit, type) = 0; 2179 if (next_type != TNL_TERM_TYPE_NULL) { 2180 SOC_TNL_TERM_STATE_PREV(unit, next_type) = prev_type; 2181 } 2182 SOC_TNL_TERM_STATE_NEXT(unit, type) = TNL_TERM_TYPE_NULL; 2183 SOC_TNL_TERM_STATE_PREV(unit, type) = TNL_TERM_TYPE_NULL; 2184 SOC_TNL_TERM_STATE_START(unit, type) = TNL_TERM_TYPE_NULL; 2185 SOC_TNL_TERM_STATE_END(unit, type) = TNL_TERM_TYPE_NULL; 2186 } 2187 2188 return(SOC_E_NONE); 2189 } 2190 2191 /* 2192 * Function: 2193 * _soc_tunnel_term_match 2194 * Purpose: 2195 * Find tunnel terminator entry. 2196 * Parameters: 2197 * unit - (IN) BCM device number. 2198 * key - (IN) Tunnel terminator lookup key. 2199 * result - (OUT) Tunnel terminator search result. 2200 * index - (OUT) Tunnel termination entry index. 2201 * Returns: 2202 * SOC_E_XXX 2203 */ 2204 STATIC int 2205 _soc_tunnel_term_match(int unit, soc_tunnel_term_t *key, 2206 soc_tunnel_term_t *result, int *index) 2207 { 2208 int key_index; /* Entry key lookup result. */ 2209 int entry_type; /* Entry type */ 2210 int rv; /* Operation return status. */ 2211 2212 if (soc_feature(unit, soc_feature_tunnel_term_hash_table)) { 2213 /* Perform lookup hw. */ 2214 int ipv6 = 0; 2215 uint32 *entry_ptr; 2216 soc_mem_t mem = L3_TUNNEL_DOUBLEm; 2217 2218 entry_ptr = (uint32 *)&key->entry_arr[0]; 2219 ipv6 = 2220 soc_mem_field32_get(unit, mem, entry_ptr, KEY_TYPEf) - 1; 2221 2222 if (ipv6) { 2223 mem = L3_TUNNEL_QUADm; 2224 } 2225 rv = soc_mem_generic_lookup(unit, mem, MEM_BLOCK_ANY, -1, 2226 ((void *)key->entry_arr[0].entry_data), result, index); 2227 if (SOC_SUCCESS(rv)) { 2228 rv = _soc_tunnel_term_entry_read(unit, *index, result, &entry_type); 2229 } 2230 2231 return(rv); 2232 } 2233 2234 rv = TNL_TERM_HASH_LOOKUP(unit, key, &key_index); 2235 if (SOC_SUCCESS(rv)) { 2236 *index = key_index; 2237 rv = _soc_tunnel_term_entry_read(unit, key_index, result, &entry_type); 2238 } 2239 return (rv); 2240 } 2241 2242 2243 /* 2244 * Function: 2245 * soc_tunnel_term_init 2246 * Purpose: 2247 * Initialize tunnel terminator table tracking start/end 2248 * valid/free indexes for each tunnel type. 2249 * Parameters: 2250 * unit - (IN) BCM device number. 2251 * Returns: 2252 * SOC_E_XXX 2253 */ 2254 int 2255 soc_tunnel_term_init(int unit) 2256 { 2257 int max_type; 2258 int tnl_term_table_size; 2259 int tnl_term_state_size; 2260 int idx; 2261 int rv = SOC_E_NONE; 2262 2263 SOC_TNL_TERM_BLOCK_SIZE = SOC_TNL_TERM_IPV6_ENTRY_WIDTH; 2264 2265 max_type = MAX_TNL_TERM_TYPES; 2266 tnl_term_state_size = sizeof(soc_tnl_term_state_t) * max_type; 2267 2268 if (soc_feature(unit, soc_feature_tunnel_term_hash_table)) { 2269 return(rv); 2270 } 2271 2272 /* Allocated tunnel types tracking table. */ 2273 if (!SOC_TNL_TERM_INIT_CHECK(unit)) { 2274 SOC_TNL_TERM_STATE(unit) = sal_alloc(tnl_term_state_size, "tnl_term_tcam"); 2275 if (NULL == SOC_TNL_TERM_STATE(unit)) { 2276 return(SOC_E_MEMORY); 2277 } 2278 } 2279 2280 SOC_TNL_TERM_LOCK(unit); 2281 sal_memset(SOC_TNL_TERM_STATE(unit), 0, tnl_term_state_size); 2282 2283 /* Initialize all tunnel types ranges to empty ones. */ 2284 for(idx = 0; idx < max_type; idx++) { 2285 SOC_TNL_TERM_STATE_START(unit, idx) = TNL_TERM_TYPE_NULL; 2286 SOC_TNL_TERM_STATE_END(unit, idx) = TNL_TERM_TYPE_NULL; 2287 SOC_TNL_TERM_STATE_PREV(unit, idx) = TNL_TERM_TYPE_NULL; 2288 SOC_TNL_TERM_STATE_NEXT(unit, idx) = TNL_TERM_TYPE_NULL; 2289 SOC_TNL_TERM_STATE_VENT(unit, idx) = 0; 2290 SOC_TNL_TERM_STATE_FENT(unit, idx) = 0; 2291 } 2292 2293 tnl_term_table_size = soc_mem_index_count(unit, L3_TUNNELm); 2294 SOC_TNL_TERM_STATE_FENT(unit, (MAX_TNL_TERM_TYPE)) = tnl_term_table_size; 2295 2296 if (SOC_TNL_TERM_STATE_HASH(unit) != NULL) { 2297 rv =_soc_tunnel_term_hash_destroy(&SOC_TNL_TERM_STATE_HASH(unit)); 2298 if (SOC_FAILURE(rv)) { 2299 SOC_TNL_TERM_UNLOCK(unit); 2300 return SOC_E_INTERNAL; 2301 } 2302 SOC_TNL_TERM_STATE_HASH(unit) = NULL; 2303 } 2304 2305 rv = _soc_tunnel_term_hash_create(unit, tnl_term_table_size, 2306 tnl_term_table_size, 2307 &SOC_TNL_TERM_STATE_HASH(unit)); 2308 2309 SOC_TNL_TERM_UNLOCK(unit); 2310 return (rv); 2311 } 2312 2313 /* 2314 * Function: 2315 * soc_tunnel_term_deinit 2316 * Purpose: 2317 * Deinitialize tunnel terminator table. 2318 * Parameters: 2319 * unit - (IN) BCM device number. 2320 * Returns: 2321 * SOC_E_XXX 2322 */ 2323 int 2324 soc_tunnel_term_deinit(int unit) 2325 { 2326 2327 SOC_TNL_TERM_LOCK(unit); 2328 2329 if (SOC_TNL_TERM_STATE_HASH(unit) != NULL) { 2330 _soc_tunnel_term_hash_destroy(&SOC_TNL_TERM_STATE_HASH(unit)); 2331 SOC_TNL_TERM_STATE_HASH(unit) = NULL; 2332 } 2333 2334 if (SOC_TNL_TERM_INIT_CHECK(unit)) { 2335 sal_free(SOC_TNL_TERM_STATE(unit)); 2336 SOC_TNL_TERM_STATE(unit) = NULL; 2337 } 2338 2339 SOC_TNL_TERM_UNLOCK(unit); 2340 2341 return(SOC_E_NONE); 2342 } 2343 2344 #ifdef BCM_WARM_BOOT_SUPPORT 2345 /* 2346 * Function: 2347 * _soc_tunnel_term_reinit_done 2348 * Purpose: 2349 * Adjust tunnel types start/end index after warm reboot 2350 * reinitialization is complete. 2351 * Parameters: 2352 * unit - (IN) BCM device number. 2353 * Returns: 2354 * SOC_E_XXX 2355 */ 2356 STATIC int 2357 _soc_tunnel_term_reinit_done(int unit) 2358 { 2359 int idx, first = 0, first_valid_entry = 0; 2360 int prev_idx = MAX_TNL_TERM_TYPE; 2361 int tnl_term_table_size = soc_mem_index_count(unit, L3_TUNNELm); 2362 2363 SOC_TNL_TERM_STATE_PREV(unit, MAX_TNL_TERM_TYPE) = TNL_TERM_TYPE_NULL; 2364 2365 for (idx = MAX_TNL_TERM_TYPE; idx >= 0 ; idx--) { 2366 if (TNL_TERM_TYPE_NULL == SOC_TNL_TERM_STATE_START(unit, idx)) { 2367 continue; 2368 } 2369 2370 SOC_TNL_TERM_STATE_PREV(unit, idx) = prev_idx; 2371 SOC_TNL_TERM_STATE_NEXT(unit, prev_idx) = idx; 2372 2373 if ((SOC_TNL_TERM_STATE_START(unit, prev_idx) == TNL_TERM_TYPE_NULL) && 2374 (SOC_TNL_TERM_STATE_END(unit, prev_idx) == TNL_TERM_TYPE_NULL)) { 2375 first = prev_idx; 2376 first_valid_entry = SOC_TNL_TERM_STATE_START(unit, idx); 2377 } else { 2378 SOC_TNL_TERM_STATE_FENT(unit, prev_idx) = 2379 SOC_TNL_TERM_STATE_START(unit, idx) - \ 2380 SOC_TNL_TERM_STATE_END(unit, prev_idx) - 1; 2381 } 2382 if (SOC_TNL_TERM_STATE_NEXT(unit, idx) == TNL_TERM_TYPE_NULL) { 2383 SOC_TNL_TERM_STATE_FENT(unit, idx) = 2384 tnl_term_table_size - SOC_TNL_TERM_STATE_END(unit, idx) - 1; 2385 } 2386 2387 prev_idx = idx; 2388 } 2389 SOC_TNL_TERM_STATE_FENT(unit, first) = first_valid_entry; 2390 SOC_TNL_TERM_STATE_NEXT(unit, prev_idx) = TNL_TERM_TYPE_NULL; 2391 2392 return (SOC_E_NONE); 2393 } 2394 2395 2396 /* 2397 * Function: 2398 * soc_tunnel_term_reinit 2399 * Purpose: 2400 * Insert tunnel terminator entry. 2401 * Parameters: 2402 * unit - (IN) BCM device number. 2403 * Returns: 2404 * SOC_E_XXX 2405 */ 2406 int 2407 soc_tunnel_term_reinit(int unit) 2408 { 2409 soc_tunnel_term_t entry;/* Tunnel terminator entry. */ 2410 int entry_size; /* Entry size. */ 2411 int entry_type; /* Tunnel entry type. */ 2412 int type; /* soc Tunnel type. */ 2413 int idx; /* Table iteration index. */ 2414 int idx_max; /* Maximum Table index. */ 2415 int rv; /* Operation return status. */ 2416 2417 if (soc_feature(unit, soc_feature_tunnel_term_hash_table)) { 2418 rv = SOC_E_NONE; 2419 return(rv); 2420 } 2421 2422 if (!SOC_MEM_IS_VALID(unit,L3_TUNNELm)) { 2423 /* if (SOC_IS_HURRICANE(unit)) */ 2424 return SOC_E_NONE; 2425 } 2426 2427 idx = soc_mem_index_min(unit, L3_TUNNELm); 2428 idx_max = soc_mem_index_max(unit, L3_TUNNELm); 2429 2430 while (idx <= idx_max) { 2431 rv = _soc_tunnel_term_entry_read(unit, idx, &entry, &entry_type); 2432 /* Skip invalid entries. */ 2433 if (SOC_E_NOT_FOUND == rv) { 2434 idx++; 2435 continue; 2436 } 2437 2438 /* If read failed return. */ 2439 if (SOC_FAILURE(rv)){ 2440 return (rv); 2441 } 2442 2443 /* Get entry type.(SIP/DIP SIP6/DIP6 DIP/(*) DIP6/(*) */ 2444 SOC_IF_ERROR_RETURN 2445 (_soc_tunnel_term_type_get(unit, &entry, &type, &entry_type)); 2446 2447 #ifdef BCM_TRIDENT3_SUPPORT 2448 if (soc_feature(unit,soc_feature_flex_flow) && 2449 (entry_type > SOC_TNL_TERM_KEY_TYPE_FIXED_MAX)) { 2450 SOC_IF_ERROR_RETURN ( 2451 _soc_tunnel_term_flex_type_width_get(unit, type, 2452 &entry, &entry_size)); 2453 } else 2454 #endif /* BCM_TRIDENT3_SUPPORT */ 2455 { 2456 entry_size = (entry_type == 0x1) ? SOC_TNL_TERM_IPV6_ENTRY_WIDTH : 2457 SOC_TNL_TERM_IPV4_ENTRY_WIDTH; 2458 } 2459 2460 /* Insert type into software range tracking structure. */ 2461 if (SOC_TNL_TERM_STATE_VENT(unit, type) == 0) { 2462 SOC_TNL_TERM_STATE_START(unit, type) = idx; 2463 } 2464 2465 SOC_TNL_TERM_STATE_END(unit, type) = idx + entry_size - 1; 2466 SOC_TNL_TERM_STATE_VENT(unit, type)+= entry_size; 2467 TNL_TERM_HASH_INSERT(unit, &entry, idx); 2468 idx += entry_size; 2469 } 2470 2471 rv = _soc_tunnel_term_reinit_done(unit); 2472 return (rv); 2473 } 2474 #endif /* BCM_WARM_BOOT_SUPPORT */ 2475 2476 2477 2478 2479 /* 2480 * Function: 2481 * soc_tunnel_term_insert 2482 * Purpose: 2483 * Insert tunnel terminator entry. 2484 * Parameters: 2485 * unit - (IN) BCM device number. 2486 * entry - (IN) Inserted Tunnel terminator entry. 2487 * index - (OUT) Index used for inserted entry. 2488 * Returns: 2489 * SOC_E_XXX 2490 */ 2491 int 2492 soc_tunnel_term_insert(int unit, soc_tunnel_term_t *entry, uint32 *index) 2493 { 2494 soc_tunnel_term_t lkup_result; /* Tunnel terminator identical */ 2495 /* entry lookup result. */ 2496 int temp_index; /* Entry write index. */ 2497 int entry_type; /* entry type */ 2498 int rv = SOC_E_NONE; /* Operation return status. */ 2499 2500 2501 /* Input parameters check. */ 2502 if (NULL == entry) { 2503 return (SOC_E_PARAM); 2504 } 2505 2506 2507 SOC_TNL_TERM_LOCK(unit); 2508 2509 if (soc_feature(unit, soc_feature_tunnel_term_hash_table)) { 2510 int ipv6 = 0; 2511 uint32 *entry_ptr; 2512 soc_mem_t mem = L3_TUNNEL_DOUBLEm; 2513 2514 entry_ptr = (uint32 *)&entry->entry_arr[0]; 2515 ipv6 = 2516 soc_mem_field32_get(unit, mem, entry_ptr, KEY_TYPEf) - 1; 2517 2518 if (ipv6) { 2519 mem = L3_TUNNEL_QUADm; 2520 } 2521 2522 rv = soc_mem_insert(unit, mem, MEM_BLOCK_ANY, (void *)entry); 2523 2524 if (SOC_E_EXISTS == rv) { 2525 rv = SOC_E_NONE; 2526 } 2527 SOC_TNL_TERM_UNLOCK(unit); 2528 return(rv); 2529 } 2530 2531 /* Check if identical entry already exists. */ 2532 rv = _soc_tunnel_term_match(unit, entry, &lkup_result, &temp_index); 2533 2534 if (rv == SOC_E_NOT_FOUND) { 2535 /* Allocate a new slot if we are writing a new entry. */ 2536 rv = _soc_tunnel_term_slot_allocate(unit, entry, &temp_index); 2537 } 2538 2539 if (SOC_SUCCESS(rv)) { 2540 2541 rv = _soc_tunnel_term_type_get(unit, entry, NULL, &entry_type); 2542 if (SOC_FAILURE(rv)) { 2543 SOC_TNL_TERM_UNLOCK(unit); 2544 return(rv); 2545 } 2546 2547 /* Entry already present. Update the entry */ 2548 TNL_TERM_HASH_INSERT(unit, entry, temp_index); 2549 rv = _soc_tunnel_term_entry_write(unit, temp_index, entry, entry_type); 2550 *index = temp_index; 2551 } 2552 SOC_TNL_TERM_UNLOCK(unit); 2553 return(rv); 2554 } 2555 2556 /* 2557 * Function: 2558 * soc_tunnel_term_delete 2559 * Purpose: 2560 * Delete tunnel terminator entry. 2561 * Parameters: 2562 * unit - (IN) BCM device number. 2563 * key - (IN) Deleted Tunnel terminator entry. 2564 * Returns: 2565 * SOC_E_XXX 2566 */ 2567 int 2568 soc_tunnel_term_delete(int unit, soc_tunnel_term_t *key) 2569 { 2570 soc_tunnel_term_t hw_entry; /* Entry lookup result. */ 2571 int index; /* Lookup result index. */ 2572 int rv; /* Operation return status. */ 2573 2574 /* Input parameters check. */ 2575 if (NULL == key) { 2576 return (SOC_E_PARAM); 2577 } 2578 2579 if (soc_feature(unit, soc_feature_tunnel_term_hash_table)) { 2580 int ipv6 = 0; 2581 uint32 *entry_ptr; 2582 soc_mem_t mem = L3_TUNNEL_DOUBLEm; 2583 2584 entry_ptr = (uint32 *)&key->entry_arr[0]; 2585 ipv6 = 2586 soc_mem_field32_get(unit, mem, entry_ptr, KEY_TYPEf) - 1; 2587 2588 if (ipv6) { 2589 mem = L3_TUNNEL_QUADm; 2590 } 2591 2592 rv = soc_mem_generic_delete(unit, mem, MEM_BLOCK_ANY, 2593 -1, ((void *)key->entry_arr[0].entry_data), 2594 NULL, 0); 2595 return(rv); 2596 } 2597 2598 SOC_TNL_TERM_LOCK(unit); 2599 /* Find entry matching deletion key. */ 2600 rv = _soc_tunnel_term_match(unit, key, &hw_entry, &index); 2601 if (SOC_SUCCESS(rv)) { 2602 TNL_TERM_HASH_DELETE(unit, key, index); 2603 rv = _soc_tunnel_term_slot_free(unit, &hw_entry, index); 2604 } 2605 SOC_TNL_TERM_UNLOCK(unit); 2606 return(rv); 2607 } 2608 #undef TNL_TERM_HASH_INSERT 2609 #undef TNL_TERM_HASH_DELETE 2610 #undef TNL_TERM_HASH_LOOKUP 2611 2612 /* 2613 * Function: 2614 * soc_tunnel_term_match 2615 * Purpose: 2616 * Flush all tunnel terminator entries. 2617 * Parameters: 2618 * unit - (IN) BCM device number. 2619 * Returns: 2620 * SOC_E_XXX 2621 */ 2622 int 2623 soc_tunnel_term_delete_all(int unit) 2624 { 2625 return soc_tunnel_term_init(unit); 2626 } 2627 2628 /* 2629 * Function: 2630 * soc_tunnel_term_match 2631 * Purpose: 2632 * Find tunnel terminator entry. 2633 * Parameters: 2634 * unit - (IN) BCM device number. 2635 * key - (IN) Tunnel terminator lookup key. 2636 * result - (OUT) Tunnel terminator search result. 2637 * index - (OUT) Tunnel termination entry index. 2638 * Returns: 2639 * SOC_E_XXX 2640 */ 2641 int 2642 soc_tunnel_term_match(int unit, soc_tunnel_term_t *key, 2643 soc_tunnel_term_t *result, int *entry_index) 2644 { 2645 int rv = SOC_E_NONE; /* Operation return status. */ 2646 int index; /* Lookup result index. */ 2647 2648 /* Input parameters check. */ 2649 if ((NULL == result) || (NULL == key)) { 2650 return (SOC_E_PARAM); 2651 } 2652 2653 SOC_TNL_TERM_LOCK(unit); 2654 2655 rv = _soc_tunnel_term_match(unit, key, result, &index); 2656 *entry_index = index; 2657 SOC_TNL_TERM_UNLOCK(unit); 2658 return(rv); 2659 } 2660 2661 /* 2662 * Function: 2663 * soc_tunnel_term_used_get 2664 * Purpose: 2665 * Obtain Used Tunnel terminator entry size 2666 * Parameters: 2667 * unit - (IN) BCM device number. 2668 * Returns: 2669 * used_count 2670 */ 2671 int 2672 soc_tunnel_term_used_get(int unit) 2673 { 2674 int used_count=0; 2675 2676 used_count += SOC_TNL_TERM_STATE_VENT(unit, SOC_TNL_TERM_TYPE_DIP4); 2677 used_count += SOC_TNL_TERM_STATE_VENT(unit, SOC_TNL_TERM_TYPE_DIP4_SIP4); 2678 used_count += SOC_TNL_TERM_STATE_VENT(unit, SOC_TNL_TERM_TYPE_DIP4_SIP4_PROT); 2679 used_count += SOC_TNL_TERM_STATE_VENT(unit, SOC_TNL_TERM_TYPE_DIP4_PROT); 2680 used_count += SOC_TNL_TERM_STATE_VENT(unit, SOC_TNL_TERM_TYPE_DIP4_SIP4_L4DST); 2681 used_count += SOC_TNL_TERM_STATE_VENT(unit, SOC_TNL_TERM_TYPE_DIP4_L4DST); 2682 used_count += SOC_TNL_TERM_STATE_VENT(unit, SOC_TNL_TERM_TYPE_DIP4_SIP4_PROT_L4DST); 2683 used_count += SOC_TNL_TERM_STATE_VENT(unit, SOC_TNL_TERM_TYPE_DIP4_PROT_L4DST); 2684 used_count += SOC_TNL_TERM_STATE_VENT(unit, SOC_TNL_TERM_TYPE_DIP4_SIP4_L4SRC); 2685 used_count += SOC_TNL_TERM_STATE_VENT(unit, SOC_TNL_TERM_TYPE_DIP4_L4SRC); 2686 used_count += SOC_TNL_TERM_STATE_VENT(unit, SOC_TNL_TERM_TYPE_DIP4_PROT_L4SRC); 2687 used_count += SOC_TNL_TERM_STATE_VENT(unit, SOC_TNL_TERM_TYPE_DIP4_SIP4_PROT_L4SRC); 2688 used_count += SOC_TNL_TERM_STATE_VENT(unit, SOC_TNL_TERM_TYPE_DIP4_PROT_L4SRC); 2689 used_count += SOC_TNL_TERM_STATE_VENT(unit, SOC_TNL_TERM_TYPE_DIP4_SIP4_L4DST_L4SRC); 2690 used_count += SOC_TNL_TERM_STATE_VENT(unit, SOC_TNL_TERM_TYPE_DIP4_L4DST_L4SRC); 2691 used_count += SOC_TNL_TERM_STATE_VENT(unit, SOC_TNL_TERM_TYPE_DIP4_SIP4_PROT_L4DST_L4SRC); 2692 used_count += SOC_TNL_TERM_STATE_VENT(unit, SOC_TNL_TERM_TYPE_DIP4_PROT_L4DST_L4SRC); 2693 2694 return used_count; 2695 } 2696 #endif /* BCM_FIREBOLT_SUPPORT */ 2697 #endif /* INCLUDE_L3 */ 2698