openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

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 }