tunnel.c (13253B)
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: tunnel.c 8 * 9 * Provides: 10 * soc_internal_tunnel_entry_ins 11 * 12 * Requires: 13 */ 14 15 #include <shared/bsl.h> 16 17 #include <soc/mem.h> 18 #include <soc/hash.h> 19 #include <soc/drv.h> 20 #include "pcid.h" 21 #include "mem.h" 22 #include "cmicsim.h" 23 #ifdef BCM_TOMAHAWK3_SUPPORT 24 #include <soc/tomahawk3.h> 25 26 #ifdef BCM_XGS_SWITCH_SUPPORT 27 #ifdef BCM_FIREBOLT_SUPPORT 28 /* 29 * Tomahawk3 L3_TUNNEL Table Simulation 30 * 31 * The L3_TUNNEL table is hashed. 32 * 33 * There are 3 view of the same 34 * L3_TUNNEL, L3_TUNNEL_2, L3_TUNNEL_4 35 */ 36 enum { 37 ENT3f, 38 ENT2f, 39 ENT1f, 40 ENT0f 41 } soc_L3_TUNNEL_DUMMYm_ftype; 42 43 static soc_field_info_t soc_L3_TUNNEL_DUMMYm_fields[] = { 44 { ENT3f, 92, 276, SOCF_LE }, 45 { ENT2f, 92, 184, SOCF_LE }, 46 { ENT1f, 92, 92, SOCF_LE }, 47 { ENT0f, 92, 0, SOCF_LE }, 48 }; 49 static soc_mem_info_t l3_tunnel_minfo = { 50 /* mem L3_TUNNELXXXm */ 51 /* flags */ 0, 52 /* cmp_fn */ _soc_mem_cmp_undef, 53 /* *null_entry */ _soc_mem_entry_null_zeroes, 54 /* index_min */ 0, 55 /* index_max */ 0, 56 /* minblock */ 0, 57 /* maxblock */ 0, 58 /* blocks */ 0, 59 /* blocks_hi */ 0, 60 /* base */ 0, 61 /* gran */ 1, 62 /* bytes */ 46, 63 /* nFields */ 4, /* Used */ 64 /* *fields */ soc_L3_TUNNEL_DUMMYm_fields, /* Used*/ 65 }; 66 67 int 68 soc_internal_tunnel_entry_size_get(pcid_info_t *pcid_info, void *entry, 69 soc_mem_t *mem, int *num_vbits) 70 { 71 int unit = pcid_info->unit; 72 73 if (SOC_IS_TOMAHAWK3(unit) && 74 SOC_MEM_FIELD_VALID(unit, L3_TUNNEL_SINGLEm, KEY_TYPEf)) { 75 int key_type; 76 77 key_type = soc_mem_field32_get(unit, L3_TUNNEL_SINGLEm, 78 entry, KEY_TYPEf); 79 switch (key_type) { 80 case TH3_TUNNEL_HASH_KEY_TYPE_MPLS: 81 *num_vbits = 1; 82 *mem = L3_TUNNEL_SINGLEm; 83 break; 84 85 case TH3_TUNNEL_HASH_KEY_TYPE_V4: 86 *num_vbits = 2; 87 *mem = L3_TUNNEL_DOUBLEm; 88 break; 89 90 case TH3_TUNNEL_HASH_KEY_TYPE_V6: 91 *num_vbits = 4; 92 *mem = L3_TUNNEL_QUADm; 93 break; 94 95 default: 96 return -1; 97 } 98 return 0; 99 } else { 100 return -1; 101 } 102 } 103 104 STATIC void 105 soc_internal_tunnel_bank_map_get(pcid_info_t *pcid_info, uint32 *bank_map, 106 int *bank_start, int *bank_inc, 107 int *do_first_fit) 108 { 109 *bank_start = 0; 110 *bank_inc = 1; 111 *bank_map = soc_feature(pcid_info->unit, soc_feature_dual_hash)? 0x3 : 0x1; 112 113 if (do_first_fit) { 114 *do_first_fit = FALSE; 115 } 116 } 117 118 STATIC void 119 soc_internal_tunnel_bank_size_get(pcid_info_t *pcid_info, int bank, 120 int *entries_per_bank, int *entries_per_row, 121 int *entries_per_bucket, int *bank_base, 122 int *bucket_offset) 123 { 124 /* 125 * entry index = 126 * bank_base + bucket * entries_per_row + bucket_offset + slot; 127 */ 128 if (SOC_IS_TOMAHAWK3(pcid_info->unit)) { 129 soc_tomahawk3_hash_bank_info_get(pcid_info->unit, L3_TUNNEL_SINGLEm, 130 bank, entries_per_bank, 131 entries_per_row, 132 entries_per_bucket, 133 bank_base, bucket_offset); 134 } else { 135 /* 136 * first half of entries (slot 0) in each bucket are for bank 0 137 * the other half of entries (slot 1) in each bucket are for bank 1 138 */ 139 if (entries_per_bank != NULL) { 140 *entries_per_bank = 141 soc_mem_index_count(pcid_info->unit, L3_TUNNEL_SINGLEm) / 2; 142 } 143 *entries_per_row = SOC_L3_TUNNEL_BUCKET_SIZE; 144 *entries_per_bucket = *entries_per_row / 2; 145 *bank_base = 0; 146 *bucket_offset = bank * *entries_per_bucket; 147 } 148 } 149 150 STATIC int 151 soc_internal_tunnel_hash(pcid_info_t * pcid_info, uint8 bank, void *entry) 152 { 153 int index = 0; 154 155 if (SOC_IS_TOMAHAWK3(pcid_info->unit)) { 156 157 index = soc_tomahawk3_tunnel_bank_entry_hash( 158 pcid_info->unit, bank, (uint32*) entry); 159 } 160 161 return index; 162 } 163 164 int 165 soc_internal_tunnel_entry_ins(pcid_info_t *pcid_info, uint8 inv_bank_map, 166 void *entry, uint32 *result) 167 { 168 uint32 tmp[SOC_MAX_MEM_WORDS]; 169 uint32 ent[SOC_MAX_MEM_WORDS]; 170 int rv; 171 uint32 bank_map; 172 int bank, entries_per_bank, bank_start, bank_inc, free_bank; 173 int bucket, entries_per_row, bank_base, free_bucket; 174 int slot, entries_per_bucket, bucket_offset, free_slot; 175 int sub_slot; 176 int index, free_index; 177 int first_free_slot, free_slot_count, do_first_fit; 178 int best_free_slot_count, best_entries_per_bank; 179 int num_vbits; 180 int validslot_cnt; 181 soc_mem_t mem; 182 int ss_field[] = {ENT0f, ENT1f, ENT2f, ENT3f}; 183 int unit = pcid_info->unit; 184 schan_genresp_t *genresp = (schan_genresp_t *) result; 185 schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *) result; 186 int blk; 187 soc_block_t sblk; 188 uint8 acc_type; 189 uint32 addr; 190 191 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "L3_TUNNEL Insert\n"))); 192 193 rv = soc_internal_tunnel_entry_size_get(pcid_info, entry, &mem, &num_vbits); 194 if (rv < 0) { 195 return rv; 196 } 197 198 sal_memset(ent, 0, SOC_MAX_MEM_WORDS * sizeof(uint32)); 199 sal_memset(tmp, 0, SOC_MAX_MEM_WORDS * sizeof(uint32)); 200 201 blk = SOC_MEM_BLOCK_ANY(unit, L3_TUNNEL_SINGLEm); 202 sblk = SOC_BLOCK2SCH(unit, blk); 203 204 free_index = -1; 205 206 soc_internal_tunnel_bank_map_get( 207 pcid_info, &bank_map, &bank_start, &bank_inc, &do_first_fit); 208 bank_map &= ~inv_bank_map; 209 210 best_free_slot_count = 0; 211 /* only 2 banks supported*/ 212 for (bank = bank_start; bank_map != 0; bank += bank_inc) { 213 if (!(bank_map & (1 << bank))) { 214 continue; 215 } 216 bank_map &= ~(1 << bank); 217 218 soc_internal_tunnel_bank_size_get(pcid_info, bank, &entries_per_bank, 219 &entries_per_row, &entries_per_bucket, 220 &bank_base, &bucket_offset); 221 bucket = soc_internal_tunnel_hash(pcid_info, bank, entry); 222 223 /* 224 LOG_VERBOSE(BSL_LS_SOC_COMMON, 225 (BSL_META_U(unit, "bucket:%d, bank#%d, entry/bank:%d," 226 " entry/row:%d, entry/bucket:%d, base:%d, offset:%d\n"), 227 bucket, bank, entries_per_bank, entries_per_row, 228 entries_per_bucket, bank_base, bucket_offset)); 229 */ 230 231 free_slot_count = 0; 232 first_free_slot = -1; 233 234 for (slot = 0; slot < entries_per_bucket; slot += num_vbits) { 235 validslot_cnt = 0; 236 for (sub_slot = 0; sub_slot < num_vbits; sub_slot++) { 237 index = bank_base + bucket * entries_per_row + bucket_offset + 238 slot + sub_slot; 239 addr = soc_mem_addr_get(unit, L3_TUNNEL_SINGLEm, 0, blk, index, 240 &acc_type); 241 soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, 242 tmp); 243 if (soc_mem_field32_get(unit, L3_TUNNEL_SINGLEm, tmp, BASE_VALIDf)) { 244 soc_meminfo_field_set(mem, &l3_tunnel_minfo, ent, 245 ss_field[sub_slot], tmp); 246 validslot_cnt++; 247 } 248 } 249 250 if (validslot_cnt == num_vbits) { 251 if (_soc_mem_cmp_l3_tunnel(unit, entry, ent) == 0) { 252 if (num_vbits > 0) { 253 index /= num_vbits; 254 } 255 addr = soc_mem_addr_get(unit, mem, 0, blk, index, &acc_type); 256 257 LOG_VERBOSE(BSL_LS_SOC_COMMON, 258 (BSL_META_U(unit, 259 "write sblk %d acc_type %d bank %d " 260 "bucket %d, slot %d, index %d\n"), 261 sblk, acc_type, bank, bucket, slot, index)); 262 263 /* Overwrite the existing entry */ 264 soc_internal_extended_write_mem(pcid_info, sblk, acc_type, 265 addr, entry); 266 267 if (soc_feature(unit, soc_feature_generic_table_ops)) { 268 /* Copy old entry immediately after response word */ 269 memcpy(&result[1], ent, 270 soc_mem_entry_bytes(unit, mem)); 271 result[0] = 0; 272 if (soc_feature(unit, soc_feature_new_sbus_format) && 273 !soc_feature(unit, soc_feature_new_sbus_old_resp) ) { 274 genresp_v2->type = SCHAN_GEN_RESP_TYPE_REPLACED; 275 genresp_v2->index = index; 276 } else { 277 genresp->type = SCHAN_GEN_RESP_TYPE_REPLACED; 278 genresp->index = index; 279 } 280 } 281 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; 282 283 return 0; 284 } 285 } else if (validslot_cnt == 0) { 286 free_slot_count++; 287 if (first_free_slot == -1) { 288 first_free_slot = slot; 289 } 290 } 291 } 292 if (free_slot_count > 0) { 293 if (do_first_fit) { 294 if (free_index != -1) { 295 continue; 296 } 297 } else { 298 if (free_slot_count < best_free_slot_count) { 299 continue; 300 } else if (free_slot_count == best_free_slot_count) { 301 if (entries_per_bank < best_entries_per_bank) { 302 continue; 303 } else if (entries_per_bank == best_entries_per_bank) { 304 if (free_index != -1 && bank > free_bank) { 305 continue; 306 } 307 } 308 } 309 best_free_slot_count = free_slot_count; 310 best_entries_per_bank = entries_per_bank; 311 } 312 free_index = (index + 1 - entries_per_bucket + first_free_slot) / 313 num_vbits; 314 free_bank = bank; 315 free_bucket = bucket; 316 free_slot = first_free_slot; 317 } 318 } 319 320 /* Find first unused slot in bucket */ 321 if (free_index != -1) { 322 index = free_index; 323 addr = soc_mem_addr_get(unit, mem, 0, blk, index, &acc_type); 324 325 LOG_VERBOSE(BSL_LS_SOC_COMMON, 326 (BSL_META_U(unit, 327 "write sblk %d acc_type %d bank %d bucket %d, " 328 "slot %d, index %d\n"), 329 sblk, acc_type, free_bank, free_bucket, free_slot, index)); 330 331 /* Write the entry */ 332 soc_internal_extended_write_mem(pcid_info, sblk, acc_type, addr, 333 entry); 334 335 if (soc_feature(unit, soc_feature_generic_table_ops)) { 336 result[0] = 0; 337 if (soc_feature(unit, soc_feature_new_sbus_format) && 338 !soc_feature(unit, soc_feature_new_sbus_old_resp) ) { 339 genresp_v2->type = SCHAN_GEN_RESP_TYPE_INSERTED; 340 genresp_v2->index = index; 341 } else { 342 genresp->type = SCHAN_GEN_RESP_TYPE_INSERTED; 343 genresp->index = index; 344 } 345 } 346 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; 347 348 return 0; 349 } 350 351 LOG_VERBOSE(BSL_LS_SOC_COMMON, 352 (BSL_META_U(unit, 353 "Bucket full\n"))); 354 if (soc_feature(unit, soc_feature_generic_table_ops)) { 355 result[0] = 0; 356 if (soc_feature(unit, soc_feature_new_sbus_format) && 357 !soc_feature(unit, soc_feature_new_sbus_old_resp) ) { 358 genresp_v2->type = SCHAN_GEN_RESP_TYPE_FULL; 359 } else { 360 genresp->type = SCHAN_GEN_RESP_TYPE_FULL; 361 } 362 } 363 PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST; 364 365 return 0; 366 } 367 368 #endif /* BCM_FIREBOLT_SUPPORT */ 369 #endif /* BCM_XGS_SWITCH_SUPPORT */ 370 #endif /* BCM_TOMAHAWK3_SUPPORT */