brd_strata.c (11429B)
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: brd_strata.c 8 * Purpose: SL Stacked Board programming 9 * BCM95645K24 (Strata II) 10 * BCM95665P48 (Tucana) 11 */ 12 13 #include <shared/bsl.h> 14 15 #include <bcm/error.h> 16 #include <bcm/stack.h> 17 #include <bcm/topo.h> 18 #include <bcm/l2.h> 19 20 #include <appl/cputrans/atp.h> 21 #include <appl/stktask/topology.h> 22 #include <appl/stktask/topo_brd.h> 23 24 #include "topo_int.h" 25 26 /* 27 * Find output stack port on src_unit to get to a remote modid 28 * (duplicate of static function in brd_xgs.c) 29 */ 30 STATIC int 31 _bcm_board_sl_topomap(int src_unit, int dest_modid, bcm_port_t *exit_port) 32 { 33 cpudb_unit_port_t *stk_port; 34 topo_cpu_t *tp_cpu; 35 int sp_idx, m_idx; 36 int mod_id; 37 38 /* Remote module ID; look up in CPU database */ 39 bcm_board_topo_get(&tp_cpu); 40 if (tp_cpu == NULL) { 41 return BCM_E_INIT; 42 } 43 44 /* Search topo info for the stack port with the given mod id */ 45 TOPO_FOREACH_STK_PORT(stk_port, tp_cpu, sp_idx) { 46 TOPO_FOREACH_TX_MODID(mod_id, tp_cpu, sp_idx, m_idx) { 47 if (dest_modid == mod_id && stk_port->unit == src_unit) { 48 *exit_port = stk_port->port; 49 return BCM_E_NONE; 50 } 51 } 52 } 53 54 LOG_VERBOSE(BSL_LS_TKS_TOPOLOGY, 55 (BSL_META("SL topo map failed unit %d to mod id %d\n"), 56 src_unit, dest_modid)); 57 58 return BCM_E_NOT_FOUND; 59 } 60 61 /* 62 * Program modport register on a unit to define 63 * module routing out each stack port. Only works on 64 * xgs switch devices (not xgs fabrics, not strata switches) 65 */ 66 STATIC int 67 _bcm_board_sl_modport(int unit, topo_cpu_t *tp_cpu) 68 { 69 int i, m, punit, rv; 70 topo_stk_port_t *tsp; 71 cpudb_entry_t *l_entry; 72 bcm_port_t port; 73 bcm_module_t mod; 74 75 l_entry = &tp_cpu->local_entry; 76 77 /* set everything to the default */ 78 rv = bcm_stk_modport_clear_all(unit); 79 if (rv < 0) { 80 LOG_VERBOSE(BSL_LS_TKS_TOPOLOGY, 81 (BSL_META_U(unit, 82 "SL modport %d: modport failed: %s\n"), 83 unit, bcm_errmsg(rv))); 84 if (rv == BCM_E_UNAVAIL) { 85 rv = BCM_E_NONE; 86 } 87 return rv; 88 } 89 90 LOG_INFO(BSL_LS_TKS_TOPOLOGY, 91 (BSL_META_U(unit, 92 "SL modport unit %d\n"), 93 unit)); 94 95 /* set up module routing for each stack port port */ 96 for (i = 0; i < l_entry->base.num_stk_ports; i++) { 97 punit = l_entry->base.stk_ports[i].unit; 98 port = l_entry->base.stk_ports[i].port; 99 if (punit != unit) { 100 continue; 101 } 102 103 tsp = &tp_cpu->tp_stk_port[i]; 104 LOG_INFO(BSL_LS_TKS_TOPOLOGY, 105 (BSL_META_U(unit, 106 "SL modport map unit %d port %d mods %d\n"), 107 unit, port, tsp->tx_mod_num)); 108 for (m = 0; m < tsp->tx_mod_num; m++) { 109 mod = tsp->tx_mods[m]; 110 rv = bcm_stk_modport_set(unit, mod, port); 111 if (rv < 0) { 112 if (rv == BCM_E_UNAVAIL) { 113 rv = BCM_E_NONE; 114 } 115 return rv; 116 } 117 } 118 } 119 return BCM_E_NONE; 120 } 121 122 /* 123 * Cut broadcast loops by using the cut ports discovered 124 * by the topology code. 125 */ 126 STATIC int 127 _bcm_board_sl_loop(int unit, topo_cpu_t *tp_cpu) 128 { 129 int i, punit; 130 bcm_port_t port, eport; 131 cpudb_entry_t *l_entry; 132 bcm_port_config_t config; 133 uint32 flood, block_all; 134 bcm_pbmp_t cutports; 135 136 l_entry = &tp_cpu->local_entry; 137 138 /* find all cutports */ 139 BCM_PBMP_CLEAR(cutports); 140 for (i=0; i < l_entry->base.num_stk_ports; i++) { 141 punit = l_entry->base.stk_ports[i].unit; 142 port = l_entry->base.stk_ports[i].port; 143 144 if (unit != punit) { 145 continue; 146 } 147 148 if (!(l_entry->sp_info[i].flags & 149 (CPUDB_SPF_TX_RESOLVED | CPUDB_SPF_RX_RESOLVED))) { 150 BCM_PBMP_PORT_ADD(cutports, port); 151 } else if (l_entry->sp_info[i].flags & CPUDB_SPF_CUT_PORT) { 152 LOG_VERBOSE(BSL_LS_TKS_TOPOLOGY, 153 (BSL_META_U(unit, 154 "BRD: Port %d.%d is a cut port\n"), 155 punit, port)); 156 BCM_PBMP_PORT_ADD(cutports, port); 157 } 158 } 159 160 BCM_IF_ERROR_RETURN(bcm_port_config_get(unit, &config)); 161 162 block_all = BCM_PORT_FLOOD_BLOCK_BCAST | 163 BCM_PORT_FLOOD_BLOCK_UNKNOWN_UCAST | 164 BCM_PORT_FLOOD_BLOCK_UNKNOWN_MCAST; 165 166 /* 167 * Block all flooding from any cut port. 168 * Block all flooding to any cut port. 169 * Permit all other flooding, but do not update 170 * the CMIC port related blocking entries. 171 */ 172 BCM_PBMP_ITER(config.port, port) { 173 BCM_PBMP_ITER(config.port, eport) { 174 if (BCM_PBMP_MEMBER(cutports, port)) { 175 flood = block_all; 176 } else if (BCM_PBMP_MEMBER(cutports, eport)) { 177 flood = block_all; 178 } else { 179 flood = 0; 180 } 181 BCM_IF_ERROR_RETURN 182 (bcm_port_flood_block_set(unit, port, eport, flood)); 183 } 184 } 185 186 return BCM_E_NONE; 187 } 188 189 190 static int _bcm_sl_l2mac_count; 191 static bcm_mac_t _bcm_sl_l2mac[CPUDB_CPU_MAX]; 192 193 /* Find the local stack port to reach given entry */ 194 STATIC int 195 _find_stk_port(topo_cpu_t *tp_cpu, 196 cpudb_entry_t *local_entry, 197 cpudb_entry_t *entry, 198 int *unit, bcm_port_t *port) 199 { 200 int i, j; 201 202 for (i = 0; i < local_entry->base.num_stk_ports; i++) { 203 for (j = 0; j < tp_cpu->tp_stk_port[i].tx_mod_num; j++) { 204 if (tp_cpu->tp_stk_port[i].tx_mods[j] == entry->dest_mod) { 205 *unit = local_entry->base.stk_ports[i].unit; 206 *port = local_entry->base.stk_ports[i].port; 207 return 0; 208 } 209 } 210 } 211 212 return -1; 213 } 214 215 /* 216 * Add L2 addresses for all systems in stack. 217 */ 218 STATIC int 219 _bcm_board_sl_l2(int unit, topo_cpu_t *tp_cpu, cpudb_ref_t db_ref, 220 bcm_port_t dflt_exit_port, int is_strata) 221 { 222 cpudb_entry_t *entry; 223 int atp_cos, atp_vlan, i, rv; 224 bcm_l2_addr_t l2addr; 225 int l2_unit; 226 int use_dflt_port = FALSE; 227 228 atp_cos_vlan_get(&atp_cos, &atp_vlan); 229 230 /* delete any old entries for cpus that have left the stack */ 231 for (i = 0; i < _bcm_sl_l2mac_count; i++) { 232 entry = cpudb_mac_lookup(db_ref, _bcm_sl_l2mac[i]); 233 if (entry != NULL) { 234 continue; 235 } 236 rv = bcm_l2_addr_delete(unit, _bcm_sl_l2mac[i], atp_vlan); 237 if (rv < 0 && rv != BCM_E_NOT_FOUND) { 238 LOG_WARN(BSL_LS_TKS_TOPOLOGY, 239 (BSL_META_U(unit, 240 "BRD: Could not l2 delete mac %x:%x:%x\n"), 241 _bcm_sl_l2mac[i][3], 242 _bcm_sl_l2mac[i][4], 243 _bcm_sl_l2mac[i][5])); 244 return rv; 245 } 246 } 247 _bcm_sl_l2mac_count = 0; 248 249 CPUDB_FOREACH_ENTRY(db_ref, entry) { 250 bcm_l2_addr_t_init(&l2addr, entry->base.mac, atp_vlan); 251 l2addr.modid = entry->dest_mod; 252 l2addr.port = entry->base.dest_port; 253 254 if ((entry != db_ref->local_entry) && is_strata) { 255 /* Not local for strata -- use stack port */ 256 if (_find_stk_port(tp_cpu, db_ref->local_entry, entry, 257 &l2_unit, &l2addr.port) < 0) { 258 use_dflt_port = TRUE; 259 } else if (l2_unit != unit) { /* Not on this unit */ 260 use_dflt_port = TRUE; 261 } 262 } 263 264 if (use_dflt_port) { 265 if (dflt_exit_port < 0) { 266 LOG_WARN(BSL_LS_TKS_TOPOLOGY, 267 (BSL_META_U(unit, 268 "BRD: CPU L2 map; not local but no dflt port" 269 " for unit %d and key " CPUDB_KEY_FMT_EOLN), 270 unit, CPUDB_KEY_DISP(entry->base.key))); 271 return BCM_E_FAIL; 272 } else { 273 l2addr.port = dflt_exit_port; 274 } 275 } 276 277 l2addr.flags |= BCM_L2_STATIC; 278 LOG_VERBOSE(BSL_LS_TKS_TOPOLOGY, 279 (BSL_META_U(unit, 280 "BRD: Adding L2 on %d for " CPUDB_KEY_FMT 281 " to mod %d port %d\n"), 282 unit, CPUDB_KEY_DISP(entry->base.key), 283 l2addr.modid, l2addr.port)); 284 BCM_IF_ERROR_RETURN(bcm_l2_addr_add(unit, &l2addr)); 285 sal_memcpy(&_bcm_sl_l2mac[_bcm_sl_l2mac_count++], entry->base.mac, 286 sizeof(bcm_mac_t)); 287 } 288 return BCM_E_NONE; 289 } 290 291 /* 292 * Set up PFM to be BCM_PORT_MCAST_FLOOD_UNKNOWN 293 */ 294 STATIC int 295 _bcm_board_sl_mcast_setup(int unit) 296 { 297 bcm_port_t port; 298 bcm_port_config_t config; 299 300 BCM_IF_ERROR_RETURN(bcm_port_config_get(unit, &config)); 301 BCM_PBMP_ITER(config.port, port) { 302 BCM_IF_ERROR_RETURN 303 (bcm_port_pfm_set(unit, port, BCM_PORT_MCAST_FLOOD_UNKNOWN)); 304 } 305 return BCM_E_NONE; 306 } 307 308 309 /* 310 * Find the single stack port on a device. If not present, or if 311 * more than one, return -1. 312 */ 313 314 STATIC bcm_port_t 315 _dflt_exit_port_get(cpudb_entry_t *entry, int unit) 316 { 317 bcm_port_t rv = -1; 318 int i; 319 320 for (i = 0; i < entry->base.num_stk_ports; i++) { 321 if (entry->base.stk_ports[i].unit == unit) { 322 if (rv != -1) { 323 return -1; 324 } 325 rv = entry->base.stk_ports[i].port; 326 } 327 } 328 329 return rv; 330 } 331 332 333 STATIC int 334 _bcm_board_sl_common(topo_cpu_t *tp_cpu, cpudb_ref_t db_ref, 335 int is_strata) 336 { 337 cpudb_entry_t *l_entry; 338 int unit, mod; 339 340 bcm_topo_map_set(_bcm_board_sl_topomap); 341 342 l_entry = &tp_cpu->local_entry; 343 344 for (unit = 0; unit < l_entry->base.num_units; unit++) { 345 bcm_port_t dflt_exit_port; 346 347 dflt_exit_port = _dflt_exit_port_get(l_entry, unit); 348 mod = tp_cpu->local_entry.mod_ids[unit]; 349 BCM_IF_ERROR_RETURN(bcm_stk_my_modid_set(unit, mod)); 350 BCM_IF_ERROR_RETURN(_bcm_board_sl_modport(unit, tp_cpu)); 351 BCM_IF_ERROR_RETURN(_bcm_board_sl_loop(unit, tp_cpu)); 352 BCM_IF_ERROR_RETURN(_bcm_board_sl_l2(unit, tp_cpu, db_ref, 353 dflt_exit_port, is_strata)); 354 BCM_IF_ERROR_RETURN(_bcm_board_sl_mcast_setup(unit)); 355 } 356 return BCM_E_NONE; 357 } 358 359 360 /* 361 * BCM95645K24 board 362 * 1 x 5645 (stackable using SL mode) 363 */ 364 int 365 bcm_board_topo_24f2g_stk(topo_cpu_t *tp_cpu, cpudb_ref_t db_ref) 366 { 367 LOG_VERBOSE(BSL_LS_TKS_TOPOLOGY, 368 (BSL_META("TOPO: SL 5645 24FE+2GE board topology handler\n"))); 369 return _bcm_board_sl_common(tp_cpu, db_ref, TRUE); 370 } 371 372 /* 373 * Tucana board (BCM95665P48) 374 * 1 x 5665 (stackable using SL mode) 375 */ 376 377 int 378 bcm_board_topo_48f4g_stk(topo_cpu_t *tp_cpu, cpudb_ref_t db_ref) 379 { 380 LOG_VERBOSE(BSL_LS_TKS_TOPOLOGY, 381 (BSL_META("TOPO: SL 5665 48FE+4GE board topology handler\n"))); 382 return _bcm_board_sl_common(tp_cpu, db_ref, FALSE); 383 } 384 385 /* 386 * Back to back 5645 board attached through port 25. SL stacked. 387 */ 388 389 int 390 bcm_board_topo_48f2g_stk(topo_cpu_t *tp_cpu, cpudb_ref_t db_ref) 391 { 392 uint32 flags; 393 int unit; 394 395 LOG_VERBOSE(BSL_LS_TKS_TOPOLOGY, 396 (BSL_META("TOPO: SL b2b 5645 48FE+2GE board topology handler\n"))); 397 398 /* Add the internal stack ports */ 399 for (unit = 0; unit < 2; unit++) { 400 BCM_IF_ERROR_RETURN(bcm_stk_port_get(unit, 25, &flags)); 401 if (!(flags & BCM_STK_ENABLE)) { /* Not yet enabled */ 402 BCM_IF_ERROR_RETURN(bcm_stk_port_set(unit, 25, 403 BCM_BOARD_INT_STK_FLAGS)); 404 } 405 } 406 407 return _bcm_board_sl_common(tp_cpu, db_ref, TRUE); 408 }