trunk.c (7674B)
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 8 #include <soc/defs.h> 9 #if defined(BCM_HERCULES_SUPPORT) 10 #include <soc/drv.h> 11 #include <soc/mem.h> 12 13 #include <bcm/error.h> 14 #include <bcm/trunk.h> 15 16 #include <bcm_int/esw/mbcm.h> 17 #include <bcm_int/esw/trunk.h> 18 #include <bcm_int/esw/hercules.h> 19 20 #include <bcm_int/esw_dispatch.h> 21 22 /* 23 * Purpose: Multiplexed trunking function for Hercules 24 * Note: The parameters op and member are not used. 25 */ 26 int 27 bcm_hercules_trunk_modify(int unit, bcm_trunk_t tid, 28 bcm_trunk_info_t *trunk_info, 29 int member_count, 30 bcm_trunk_member_t *member_array, 31 trunk_private_t *t_info, 32 int op, 33 bcm_trunk_member_t *member) 34 { 35 int i; 36 bcm_port_t port; 37 uint32 algo, bmap, val, oval; 38 uint32 ing_cntlr; 39 40 ing_cntlr = ING_CTRLr; 41 42 bmap = 0; 43 for (i = 0; i < member_count; i++) { 44 BCM_IF_ERROR_RETURN 45 (bcm_esw_port_local_get(unit, member_array[i].gport, &port)); 46 if (!IS_PORT(unit, port)) { 47 return BCM_E_BADID; 48 } 49 bmap |= (1<<port); 50 } 51 if (trunk_info->psc <= 0) { 52 trunk_info->psc = BCM_TRUNK_PSC_DEFAULT; 53 54 trunk_info->psc |= (BCM_TRUNK_PSC_MACSA | BCM_TRUNK_PSC_MACDA | 55 BCM_TRUNK_PSC_IPMACSA | BCM_TRUNK_PSC_IPMACDA); 56 } 57 switch (trunk_info->psc & 0xf) { 58 case BCM_TRUNK_PSC_SRCDSTMAC: 59 algo = 0; 60 break; 61 case BCM_TRUNK_PSC_REDUNDANT: 62 algo = 1; 63 break; 64 default: 65 return BCM_E_PARAM; 66 } 67 68 val = 0; 69 soc_reg_field_set(unit, ING_HGTRUNKr, &val, BMAPf, bmap); 70 soc_reg_field_set(unit, ING_HGTRUNKr, &val, ALGORITHMf, algo); 71 72 if (!algo) { 73 if (trunk_info->psc & BCM_TRUNK_PSC_IPMACSA) { 74 soc_reg_field_set(unit, ING_HGTRUNKr, &val, EN_IPMACSAf, 1); 75 } 76 if (trunk_info->psc & BCM_TRUNK_PSC_IPMACDA) { 77 soc_reg_field_set(unit, ING_HGTRUNKr, &val, EN_IPMACDAf, 1); 78 } 79 if (trunk_info->psc & BCM_TRUNK_PSC_IPTYPE) { 80 soc_reg_field_set(unit, ING_HGTRUNKr, &val, EN_IPTYPEf, 1); 81 } 82 if (trunk_info->psc & BCM_TRUNK_PSC_IPVID) { 83 soc_reg_field_set(unit, ING_HGTRUNKr, &val, EN_IPVIDf, 1); 84 } 85 if (trunk_info->psc & BCM_TRUNK_PSC_IPDA) { 86 soc_reg_field_set(unit, ING_HGTRUNKr, &val, EN_IPDAf, 1); 87 } 88 if (trunk_info->psc & BCM_TRUNK_PSC_IPSA) { 89 soc_reg_field_set(unit, ING_HGTRUNKr, &val, EN_IPSAf, 1); 90 } 91 if (trunk_info->psc & BCM_TRUNK_PSC_L4SS) { 92 soc_reg_field_set(unit, ING_HGTRUNKr, &val, EN_L4SSf, 1); 93 } 94 if (trunk_info->psc & BCM_TRUNK_PSC_L4DS) { 95 soc_reg_field_set(unit, ING_HGTRUNKr, &val, EN_L4DSf, 1); 96 } 97 if (trunk_info->psc & BCM_TRUNK_PSC_MACSA) { 98 soc_reg_field_set(unit, ING_HGTRUNKr, &val, EN_MACSAf, 1); 99 } 100 if (trunk_info->psc & BCM_TRUNK_PSC_MACDA) { 101 soc_reg_field_set(unit, ING_HGTRUNKr, &val, EN_MACDAf, 1); 102 } 103 if (trunk_info->psc & BCM_TRUNK_PSC_TYPE) { 104 soc_reg_field_set(unit, ING_HGTRUNKr, &val, EN_TYPEf, 1); 105 } 106 if (trunk_info->psc & BCM_TRUNK_PSC_VID) { 107 soc_reg_field_set(unit, ING_HGTRUNKr, &val, EN_VIDf, 1); 108 } 109 } 110 111 PBMP_PORT_ITER(unit, port) { 112 SOC_IF_ERROR_RETURN(WRITE_ING_HGTRUNKr(unit, port, tid, val)); 113 } 114 115 if (!algo) { 116 int eqw[BCM_TRUNK_MAX_PORTCNT]; 117 118 sal_memset(eqw, 0, sizeof(eqw)); 119 BCM_IF_ERROR_RETURN(bcm_esw_trunk_pool_set(unit, -1, tid, 0, eqw)); 120 } 121 122 if (bmap != 0) { 123 PBMP_PORT_ITER(unit, port) { 124 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, 125 ing_cntlr, port, 0, &val)); 126 oval = val; 127 soc_reg_field_set(unit, ing_cntlr, &val, TRUNKENf, 1); 128 if (val != oval) { 129 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, 130 ing_cntlr, port, 0, val)); 131 } 132 } 133 } 134 return BCM_E_NONE; 135 } 136 137 /* 138 * Purpose: Multiplexed trunking function for Hercules 139 */ 140 int 141 bcm_hercules_trunk_destroy(int unit, bcm_trunk_t tid, trunk_private_t *t_info) 142 { 143 bcm_port_t port; 144 145 PBMP_PORT_ITER(unit, port) { 146 SOC_IF_ERROR_RETURN(WRITE_ING_HGTRUNKr(unit, port, tid, 0)); 147 } 148 return BCM_E_NONE; 149 } 150 151 /* 152 * Purpose: Multiplexed trunking function for Hercules 153 */ 154 int 155 bcm_hercules_trunk_get(int unit, bcm_trunk_t tid, 156 bcm_trunk_info_t *t_data, 157 int member_max, 158 bcm_trunk_member_t *member_array, 159 int *member_count, 160 trunk_private_t *t_info) 161 { 162 bcm_port_t port; 163 uint32 val; 164 bcm_pbmp_t pbmp; 165 bcm_module_t mod = 0; 166 int num_ports; 167 168 PBMP_PORT_ITER(unit, port) { 169 SOC_IF_ERROR_RETURN(READ_ING_HGTRUNKr(unit, port, tid, &val)); 170 break; 171 } 172 173 SOC_PBMP_CLEAR(pbmp); 174 SOC_PBMP_WORD_SET(pbmp, 0, 175 soc_reg_field_get(unit, ING_HGTRUNKr, val, BMAPf)); 176 num_ports = 0; 177 PBMP_ITER(pbmp, port) { 178 if (num_ports < member_max) { 179 BCM_IF_ERROR_RETURN(_bcm_esw_trunk_gport_construct(unit, TRUE, 180 1, &port, &mod, &member_array[num_ports].gport)); 181 } 182 num_ports += 1; 183 } 184 *member_count = num_ports; 185 186 switch (soc_reg_field_get(unit, ING_HGTRUNKr, val, ALGORITHMf)) { 187 case 0: 188 t_data->psc = BCM_TRUNK_PSC_SRCDSTMAC; 189 if (soc_reg_field_get(unit, ING_HGTRUNKr, val, EN_IPMACSAf)) { 190 t_data->psc |= BCM_TRUNK_PSC_IPMACSA; 191 } 192 if (soc_reg_field_get(unit, ING_HGTRUNKr, val, EN_IPMACDAf)) { 193 t_data->psc |= BCM_TRUNK_PSC_IPMACDA; 194 } 195 if (soc_reg_field_get(unit, ING_HGTRUNKr, val, EN_IPTYPEf)) { 196 t_data->psc |= BCM_TRUNK_PSC_IPTYPE; 197 } 198 if (soc_reg_field_get(unit, ING_HGTRUNKr, val, EN_IPVIDf)) { 199 t_data->psc |= BCM_TRUNK_PSC_IPVID; 200 } 201 if (soc_reg_field_get(unit, ING_HGTRUNKr, val, EN_IPSAf)) { 202 t_data->psc |= BCM_TRUNK_PSC_IPSA; 203 } 204 if (soc_reg_field_get(unit, ING_HGTRUNKr, val, EN_IPDAf)) { 205 t_data->psc |= BCM_TRUNK_PSC_IPDA; 206 } 207 if (soc_reg_field_get(unit, ING_HGTRUNKr, val, EN_L4SSf)) { 208 t_data->psc |= BCM_TRUNK_PSC_L4SS; 209 } 210 if (soc_reg_field_get(unit, ING_HGTRUNKr, val, EN_L4DSf)) { 211 t_data->psc |= BCM_TRUNK_PSC_L4DS; 212 } 213 if (soc_reg_field_get(unit, ING_HGTRUNKr, val, EN_MACDAf)) { 214 t_data->psc |= BCM_TRUNK_PSC_MACDA; 215 } 216 if (soc_reg_field_get(unit, ING_HGTRUNKr, val, EN_MACSAf)) { 217 t_data->psc |= BCM_TRUNK_PSC_MACSA; 218 } 219 if (soc_reg_field_get(unit, ING_HGTRUNKr, val, EN_TYPEf)) { 220 t_data->psc |= BCM_TRUNK_PSC_TYPE; 221 } 222 if (soc_reg_field_get(unit, ING_HGTRUNKr, val, EN_VIDf)) { 223 t_data->psc |= BCM_TRUNK_PSC_VID; 224 } 225 break; 226 case 1: 227 t_data->psc = BCM_TRUNK_PSC_REDUNDANT; 228 break; 229 default: 230 t_data->psc = -1; 231 break; 232 } 233 t_data->dlf_index = -1; 234 t_data->mc_index = -1; 235 t_data->ipmc_index = -1; 236 return BCM_E_NONE; 237 } 238 239 /* 240 * Purpose: Multiplexed trunking function for Hercules 241 */ 242 int 243 bcm_hercules_trunk_mcast_join(int unit, bcm_trunk_t tid, bcm_vlan_t vid, 244 sal_mac_addr_t mac, trunk_private_t *t_info) 245 { 246 return BCM_E_UNAVAIL; 247 } 248 #else /* BCM_HERCULES_SUPPORT */ 249 int _hercules_trunk_not_empty; 250 #endif /* BCM_HERCULES_SUPPORT */ 251