vlan.c (8515B)
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 * Firebolt VLAN_MAC Table Manipulation API routines. 8 * soc_fb_vlan_mac_entry_hash - Compute hash for VLAN_MAC table entry 9 * soc_fb_vlanmac_entry_ins - Insert an entry into VLAN_MAC table 10 * soc_fb_vlanmac_entry_del - Delete an entry from VLAN_MAC table 11 * soc_fb_vlanmac_entry_lkup - Lookup an entry in VLAN_MAC table 12 */ 13 14 #include <sal/core/libc.h> 15 #include <shared/bsl.h> 16 #include <soc/drv.h> 17 #include <soc/mem.h> 18 #include <soc/vlan.h> 19 #include <soc/hash.h> 20 #include <soc/debug.h> 21 22 #ifdef BCM_FIREBOLT_SUPPORT 23 /* 24 * soc_fb_vlan_mac_entry_hash - Compute hash for VLAN_MAC table entry 25 */ 26 int 27 soc_fb_vlan_mac_entry_hash(int unit, int hash_sel, vlan_mac_entry_t *entry) 28 { 29 uint8 key[6]; 30 int index; 31 sal_mac_addr_t mac; 32 int i; 33 34 soc_VLAN_MACm_mac_addr_get(unit, entry, MAC_ADDRf, mac); 35 for (i = 0; i < 6; i++) { 36 key[i] = mac[5 - i]; 37 } 38 index = soc_fb_vlan_mac_hash(unit, hash_sel, key); 39 LOG_VERBOSE(BSL_LS_SOC_COMMON, 40 (BSL_META_U(unit, 41 "VLAN_MAC hash_sel %d hash index %d\n"), 42 hash_sel, index)); 43 44 return index; 45 } 46 47 /* 48 * soc_fb_vlanmac_entry_ins - Insert an entry into VLAN_MAC table 49 */ 50 int 51 soc_fb_vlanmac_entry_bank_ins(int unit, uint8 banks, vlan_mac_entry_t *entry) 52 { 53 vlan_mac_entry_t tmp; 54 int index = 0, bucket, slot, free_slot; 55 int slot_min, slot_max, hash_sel; 56 57 slot_min = 0; 58 slot_max = 3; 59 60 #ifdef BCM_RAVEN_SUPPORT 61 if (soc_feature(unit, soc_feature_dual_hash) && (SOC_IS_RAVEN(unit) || SOC_IS_HAWKEYE(unit))) { 62 switch (banks) { 63 case 2: 64 slot_min = 0; 65 slot_max = 1; 66 SOC_IF_ERROR_RETURN 67 (soc_fb_rv_vlanmac_hash_sel_get(unit, 0, &hash_sel)); 68 break; 69 case 1: 70 slot_min = 2; 71 slot_max = 3; 72 SOC_IF_ERROR_RETURN 73 (soc_fb_rv_vlanmac_hash_sel_get(unit, 1, &hash_sel)); 74 break; 75 default: 76 SOC_IF_ERROR_RETURN 77 (soc_fb_rv_vlanmac_hash_sel_get(unit, 0, &hash_sel)); 78 break; 79 } 80 } else 81 #endif /* BCM_RAVEN_SUPPORT */ 82 { 83 SOC_IF_ERROR_RETURN 84 (soc_fb_rv_vlanmac_hash_sel_get(unit, 0, &hash_sel)); 85 } 86 87 /* Buckets of 4 entry each */ 88 bucket = soc_fb_vlan_mac_entry_hash(unit, hash_sel, entry); 89 LOG_VERBOSE(BSL_LS_SOC_COMMON, 90 (BSL_META_U(unit, 91 "soc_fb_vlanmac_entry_ins: bucket %d\n"), bucket)); 92 93 /* Check if it should overwrite an existing entry */ 94 free_slot = -1; 95 for (slot = slot_min; slot <= slot_max; slot++) { 96 index = bucket * 4 + slot; 97 SOC_IF_ERROR_RETURN(READ_VLAN_MACm(unit, MEM_BLOCK_ANY, index, &tmp)); 98 if (soc_mem_field32_get(unit, VLAN_MACm, &tmp, VALIDf)) { 99 if (soc_mem_compare_key(unit, VLAN_MACm, entry, &tmp) == 0) { 100 free_slot = slot; 101 break; 102 } 103 } else { 104 if (free_slot == -1) { 105 free_slot = slot; 106 } 107 } 108 } 109 110 if (free_slot == -1) { 111 return(SOC_E_FULL); 112 } 113 114 index = bucket * 4 + free_slot; 115 LOG_VERBOSE(BSL_LS_SOC_COMMON, 116 (BSL_META_U(unit, 117 "soc_fb_vlanmac_entry_ins: write slot %d, index %d\n"), 118 free_slot, index)); 119 SOC_IF_ERROR_RETURN(WRITE_VLAN_MACm(unit, MEM_BLOCK_ANY, index, entry)); 120 121 return SOC_E_NONE; 122 } 123 124 int 125 soc_fb_vlanmac_entry_ins(int unit, vlan_mac_entry_t *entry) 126 { 127 #if defined(BCM_RAVEN_SUPPORT) 128 if (soc_feature(unit, soc_feature_dual_hash) && (SOC_IS_RAVEN(unit) || SOC_IS_HAWKEYE(unit))) { 129 return 130 _soc_mem_dual_hash_insert(unit, VLAN_MACm, COPYNO_ALL, (void *)entry, 131 NULL, SOC_DUAL_HASH_MOVE_MAX_VLAN(unit)); 132 } else 133 #endif 134 { 135 return soc_fb_vlanmac_entry_bank_ins(unit, 0, entry); 136 } 137 138 } 139 140 /* 141 * soc_fb_vlanmac_entry_del - Delete an entry from VLAN_MAC table 142 */ 143 int 144 soc_fb_vlanmac_entry_del(int unit, vlan_mac_entry_t *entry) 145 { 146 vlan_mac_entry_t tmp; 147 int index = 0, bucket, slot, dual, banks; 148 int slot_min, slot_max, hash_sel; 149 150 slot_min = 0; 151 slot_max = 3; 152 153 #ifdef BCM_RAVEN_SUPPORT 154 if (soc_feature(unit, soc_feature_dual_hash) && (SOC_IS_RAVEN(unit) || SOC_IS_HAWKEYE(unit))) { 155 banks = 2; 156 } else 157 #endif /* BCM_RAVEN_SUPPORT */ 158 { 159 banks = 1; 160 SOC_IF_ERROR_RETURN 161 (soc_fb_rv_vlanmac_hash_sel_get(unit, 0, &hash_sel)); 162 } 163 164 /* Iterate over the banks manually to find the entry */ 165 for (dual = 0; dual < banks; dual++) { 166 if (banks == 2 && dual == 0) { 167 slot_min = 0; 168 slot_max = 1; 169 SOC_IF_ERROR_RETURN 170 (soc_fb_rv_vlanmac_hash_sel_get(unit, 0, &hash_sel)); 171 } else if (banks == 2 && dual == 1) { 172 slot_min = 2; 173 slot_max = 3; 174 SOC_IF_ERROR_RETURN 175 (soc_fb_rv_vlanmac_hash_sel_get(unit, 1, &hash_sel)); 176 } 177 bucket = soc_fb_vlan_mac_entry_hash(unit, hash_sel, entry); 178 LOG_VERBOSE(BSL_LS_SOC_COMMON, 179 (BSL_META_U(unit, 180 "soc_fb_vlanmac_entry_del: bucket %d\n"), 181 bucket)); 182 183 /* Check if entry exists */ 184 for (slot = slot_min; slot <= slot_max; slot++) { 185 index = bucket * 4 + slot; 186 SOC_IF_ERROR_RETURN 187 (READ_VLAN_MACm(unit, MEM_BLOCK_ANY, index, &tmp)); 188 if (soc_mem_field32_get(unit, VLAN_MACm, &tmp, VALIDf)) { 189 if (soc_mem_compare_key(unit, VLAN_MACm, entry, &tmp) == 0) { 190 soc_mem_field32_set(unit, VLAN_MACm, &tmp, VALIDf, 0); 191 SOC_IF_ERROR_RETURN( 192 WRITE_VLAN_MACm(unit, MEM_BLOCK_ANY, index, &tmp)); 193 return SOC_E_NONE; 194 } 195 } 196 } 197 } 198 return(SOC_E_NONE); /* Entry doesn't exist */ 199 } 200 201 /* 202 * soc_fb_vlanmac_entry_lkup - Lookup an entry in VLAN_MAC table 203 * Note: entry and result may overlap. 204 */ 205 206 int 207 soc_fb_vlanmac_entry_lkup(int unit, vlan_mac_entry_t *entry, 208 vlan_mac_entry_t *result, int *index_ptr) 209 { 210 vlan_mac_entry_t tmp; 211 int index = 0, bucket, slot, banks, dual; 212 int slot_min, slot_max, hash_sel; 213 214 slot_min = 0; 215 slot_max = 3; 216 217 #ifdef BCM_RAVEN_SUPPORT 218 if (soc_feature(unit, soc_feature_dual_hash) && (SOC_IS_RAVEN(unit) || SOC_IS_HAWKEYE(unit))) { 219 banks = 2; 220 } else 221 #endif /* BCM_RAVEN_SUPPORT */ 222 { 223 banks = 1; 224 SOC_IF_ERROR_RETURN 225 (soc_fb_rv_vlanmac_hash_sel_get(unit, 0, &hash_sel)); 226 } 227 228 /* Iterate over the banks manually to find the entry */ 229 for (dual = 0; dual < banks; dual++) { 230 if (banks == 2 && dual == 0) { 231 slot_min = 0; 232 slot_max = 1; 233 SOC_IF_ERROR_RETURN 234 (soc_fb_rv_vlanmac_hash_sel_get(unit, 0, &hash_sel)); 235 } else if (banks == 2 && dual == 1) { 236 slot_min = 2; 237 slot_max = 3; 238 SOC_IF_ERROR_RETURN 239 (soc_fb_rv_vlanmac_hash_sel_get(unit, 1, &hash_sel)); 240 } 241 *index_ptr = -1; 242 bucket = soc_fb_vlan_mac_entry_hash(unit, hash_sel, entry); 243 LOG_VERBOSE(BSL_LS_SOC_COMMON, 244 (BSL_META_U(unit, 245 "soc_fb_vlanmac_entry_del: bucket %d\n"), 246 bucket)); 247 248 /* Check if entry exists */ 249 for (slot = slot_min; slot <= slot_max; slot++) { 250 index = bucket * 4 + slot; 251 SOC_IF_ERROR_RETURN(READ_VLAN_MACm(unit, MEM_BLOCK_ANY, index, 252 &tmp)); 253 if (soc_mem_field32_get(unit, VLAN_MACm, &tmp, VALIDf)) { 254 if (soc_mem_compare_key(unit, VLAN_MACm, entry, &tmp) == 0) { 255 sal_memcpy(result, &tmp, sizeof(tmp)); 256 *index_ptr = index; 257 return SOC_E_NONE; 258 } 259 } 260 } 261 } 262 return(SOC_E_NOT_FOUND); 263 } 264 #endif /* BCM_FIREBOLT_SUPPORT */ 265 266