port.c (10420B)
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: bcmxdiag/port.c 8 * Purpose: Implement bcmx port command 9 * Requires: 10 */ 11 12 #include <bcm/port.h> 13 #include <bcm/error.h> 14 #include <shared/bsl.h> 15 #include <bcmx/port.h> 16 #include <bcmx/bcmx.h> 17 18 #include <appl/diag/shell.h> 19 #include <appl/diag/system.h> 20 #include <appl/diag/parse.h> 21 22 #include "bcmx.h" 23 #include <appl/diag/diag.h> 24 25 #define PCMD_DONE(rv) cmd_rv = (rv); goto done 26 27 char bcmx_cmd_port_usage[] = 28 " port [-b] <uport-list> [opts] - List (briefly) port properties\n" 29 " port <uport-list> [opts] - Set options indicated\n" 30 #ifndef COMPILER_STRING_CONST_LIMIT 31 " Options include:\n" 32 " AutoNeg[=on|off] LinkScan[=on|off|hw|sw]\n" 33 " SPeed[=10|100|1000] FullDuplex[=true|false]\n" 34 " TxPAUse[=on|off] RxPAUse[=on|off]\n" 35 " STationADdr[=<macaddr>] LeaRN[=<learnmode>]\n" 36 " DIScard[=none|untag|all] VlanFilter[=on|off]\n" 37 " UTPRIrity[=<pri>] UTVlan[=<vid>]\n" 38 " PortFilterMode[=<value>] PHymaster[=Master|Slave|Auto]\n" 39 "Speed, duplex, pause are the ADVERTISED or FORCED according to autoneg.\n" 40 "Speed of zero indicates maximum speed.\n" 41 "LinkScan enables automatic scanning for link changes.\n" 42 "VlanFilter drops input packets that are not tagged with a valid VLAN\n" 43 "Priority sets the priority for untagged packets.\n" 44 "PortFilterMode takes a value 0/1/2 for mode A/B/C (see register ref).\n" 45 "<vid> is valid VLAN identifier. <pri> is a value from 0 to 7.\n" 46 "<learnmode> flag: bit 0 --> enable learning. \n" 47 " bit 1 --> forward to CPU. bit 2 --> switch packet\n" 48 #endif 49 ; 50 51 /* Note that 'unit' is left over from the bcm layer. It should be ignored */ 52 cmd_result_t 53 bcmx_cmd_port(int unit, args_t *args) 54 { 55 char *ch; 56 bcmx_lplist_t ports; 57 bcm_port_info_t given; 58 bcm_port_info_t info; 59 bcm_port_info_t *info_p; 60 bcm_port_info_t *port_info = NULL; 61 int rv; 62 int count; 63 bcmx_lport_t lport; 64 int brief = FALSE; 65 parse_table_t pt; 66 uint32 seen = 0; 67 #if defined(BCM_ESW_SUPPORT) 68 uint32 port_flags; 69 #endif /* define (BCM_ESW_SUPPORT) */ 70 uint32 parsed = 0; 71 char uport_str[BCMX_UPORT_STR_LENGTH_DEFAULT]; 72 bcmx_uport_t uport; 73 cmd_result_t cmd_rv = CMD_OK; 74 75 if ((ch = ARG_GET(args)) == NULL) { 76 return(CMD_USAGE); 77 } 78 79 if (!strcmp("-b", ch)) { 80 brief = TRUE; 81 if ((ch = ARG_GET(args)) == NULL) { 82 return(CMD_USAGE); 83 } 84 } 85 86 bcmx_lplist_init(&ports, 0, 0); 87 88 if (bcmx_lplist_parse(&ports, ch) < 0) { 89 cli_out("%s: Error: could not parse portlist: %s\n", 90 ARG_CMD(args), ch); 91 PCMD_DONE(CMD_FAIL); 92 } 93 94 if (ports.lp_last < 0) { 95 cli_out("No ports specified.\n"); 96 PCMD_DONE(CMD_FAIL); 97 } 98 99 if (ARG_CNT(args) == 0) { 100 seen = BCM_PORT_ATTR_ALL_MASK & ~BCM_PORT_ATTR_RATE_MASK; 101 } else { /* Some arguments given..... */ 102 /* 103 * Parse the arguments. Determine which ones were actually given. 104 */ 105 parse_table_init(unit, &pt); 106 107 #if defined(BCM_ESW_SUPPORT) 108 port_parse_setup(0, &pt, &given); 109 #endif 110 111 if (parse_arg_eq(args, &pt) < 0) { 112 parse_arg_eq_done(&pt); 113 PCMD_DONE(CMD_USAGE); 114 } 115 116 if (ARG_CNT(args) > 0) { 117 cli_out("%s: Unknown argument %s\n", 118 ARG_CMD(args), ARG_CUR(args)); 119 parse_arg_eq_done(&pt); 120 PCMD_DONE(CMD_FAIL); 121 } 122 123 /* 124 * Find out what parameters specified. Record values specified. 125 */ 126 #if defined(BCM_ESW_SUPPORT) 127 port_parse_mask_get(&pt, &seen, &parsed); 128 #endif 129 parse_arg_eq_done(&pt); 130 131 } 132 133 if (seen && parsed) { 134 cli_out("%s: Cannot get and set port properties in one command\n", 135 ARG_CMD(args)); 136 PCMD_DONE(CMD_FAIL); 137 } else if (seen) { /* Show selected information */ 138 bcm_port_config_t config; 139 int bcm_unit, bcm_port; 140 141 /**************************************************************** 142 * DISPLAY PORT INFO 143 */ 144 if (brief) { 145 cli_out(" Uport\n"); 146 #if defined(BCM_ESW_SUPPORT) 147 /* Coverity 148 * The comment at the top of this function says, 149 * ignore unit number. -1 is not supposed to be passed 150 * to this function, since the function accesses an array 151 * with the passed unit number. This function is also 152 * called from many other places but with valid unit number. 153 * I dont want to modify the functionality of the following f(x). 154 * Since this call with -1 is from bcmx, 155 * I am choosing to ignore this coverity error. 156 */ 157 /* coverity[negative_returns] */ 158 brief_port_info_header(-1); 159 #endif 160 } else { 161 cli_out("Uport Status (* indicates PHY link up)\n"); 162 } 163 164 BCMX_LPLIST_ITER(ports, lport, count) { 165 uport = BCMX_LPORT_TO_UPORT(lport); 166 bcmx_uport_to_str(uport, uport_str, BCMX_UPORT_STR_LENGTH_DEFAULT); 167 bcmx_lport_to_unit_port(lport, &bcm_unit, &bcm_port); 168 rv = bcm_port_config_get(bcm_unit, &config); 169 170 if (BCM_FAILURE(rv)) { 171 cli_out("%s: Could not get port config information: %s\n", 172 ARG_CMD(args), bcm_errmsg(rv)); 173 PCMD_DONE(CMD_FAIL); 174 } 175 176 if (BCM_PBMP_MEMBER(config.cpu, bcm_port)) { 177 if (brief) { 178 cli_out("%7s up CPU port for unit %d\n", 179 uport_str, bcm_unit); 180 } else { 181 cli_out(" *%s CPU port for unit %d\n", 182 uport_str, bcm_unit); 183 } 184 continue; 185 } 186 187 #if defined(BCM_ESW_SUPPORT) 188 port_flags = seen; 189 port_info_init(-1, lport, &info, port_flags); 190 #endif /* define (BCM_ESW_SUPPORT) */ 191 rv = bcmx_port_selective_get(lport, &info); 192 if (BCM_FAILURE(rv)) { 193 cli_out("%s: Could not get port %s information: %s\n", 194 ARG_CMD(args), uport_str, bcm_errmsg(rv)); 195 PCMD_DONE(CMD_FAIL); 196 } 197 198 if (brief) { 199 #if defined(BCM_ESW_SUPPORT) 200 #if defined(BCM_TOMAHAWK_SUPPORT) 201 esw_brief_port_info(unit, lport, &info, port_flags); 202 #else 203 brief_port_info(unit, lport, &info, port_flags); 204 #endif 205 #endif 206 } else { 207 #if defined(BCM_ESW_SUPPORT) 208 disp_port_info(bcm_unit,uport_str, bcm_port, &info, 0, port_flags); 209 #endif 210 } 211 } 212 PCMD_DONE(CMD_OK); 213 } 214 215 /**************************************************************** 216 * 217 * SET PORT INFO 218 * Allocate all the info structures 219 * Get the info for all the ports listed 220 * Adjust the structures according to input 221 * Write all the data back at once 222 * 223 * After allocating ports, make sure to goto done on error. 224 */ 225 226 if (parsed & BCM_PORT_ATTR_LINKSCAN_MASK) { 227 /* Map ON --> S/W, OFF--> None */ 228 if (given.linkscan > 2) { 229 given.linkscan -= 3; 230 } 231 } 232 233 port_info = sal_alloc((ports.lp_last+1) * sizeof(bcm_port_info_t), 234 "bcmx_port"); 235 if (!port_info) { 236 cli_out("Could not allocate enough memory for %d ports\n", 237 (ports.lp_last+1)); 238 PCMD_DONE(CMD_FAIL); 239 } 240 241 /* Get and adjust the information for the selected ports */ 242 BCMX_LPLIST_ITER(ports, lport, count) { 243 info_p = &port_info[count]; 244 #if defined(BCM_ESW_SUPPORT) 245 port_info_init(-1, lport, info_p, parsed); 246 #endif 247 248 rv = bcmx_port_selective_get(lport, info_p); 249 if (BCM_FAILURE(rv)) { 250 cli_out("%s: ERROR: port info get for port %s returned %s\n", 251 ARG_CMD(args), bcmx_lport_to_uport_str(lport), 252 bcm_errmsg(rv)); 253 PCMD_DONE(CMD_FAIL); 254 } 255 } 256 257 BCMX_LPLIST_ITER(ports, lport, count) { 258 info_p = &port_info[count]; 259 /* Get max speed and abilities for the port */ 260 if ((rv = bcmx_port_speed_max(lport, &given.speed_max)) < 0) { 261 cli_out("port parse: Could not get port %s max speed: %s\n", 262 bcmx_lport_to_uport_str(lport), bcm_errmsg(rv)); 263 cmd_rv = CMD_FAIL; 264 continue; 265 } 266 if ((rv = bcmx_port_speed_max(lport, &given.speed)) < 0) { 267 cli_out("port parse: Could not get port %s peed: %s\n", 268 bcmx_lport_to_uport_str(lport), bcm_errmsg(rv)); 269 cmd_rv = CMD_FAIL; 270 continue; 271 } 272 if ((rv = bcmx_port_ability_get(lport, &given.ability)) < 0) { 273 cli_out("port parse: Could not get port %s ability: %s\n", 274 bcmx_lport_to_uport_str(lport), bcm_errmsg(rv)); 275 cmd_rv = CMD_FAIL; 276 continue; 277 } 278 #if defined(BCM_ESW_SUPPORT) 279 rv = port_parse_port_info_set(parsed, &given, info_p); 280 if (BCM_FAILURE(rv)) { 281 cli_out("%s: Error: Could not parse port %s info: %s\n", 282 ARG_CMD(args), bcmx_lport_to_uport_str(lport), 283 bcm_errmsg(rv)); 284 cmd_rv = CMD_FAIL; 285 continue; 286 } 287 #endif 288 289 /* If AN is on, do not set speed, duplex, pause */ 290 if (info_p->autoneg) { 291 info_p->action_mask &= ~(BCM_PORT_ATTR_SPEED_MASK | 292 BCM_PORT_ATTR_DUPLEX_MASK | BCM_PORT_ATTR_PAUSE_MASK); 293 } 294 295 rv = bcmx_port_selective_set(lport, info_p); 296 if (BCM_FAILURE(rv)) { 297 cli_out("%s: ERROR: port info get for port %s returned %s\n", 298 ARG_CMD(args), bcmx_lport_to_uport_str(lport), 299 bcm_errmsg(rv)); 300 cmd_rv = CMD_FAIL; 301 break; 302 } 303 } 304 305 done: 306 bcmx_lplist_free(&ports); 307 if (port_info) { 308 sal_free(port_info); 309 } 310 return cmd_rv; 311 } 312