loopback2.c (11325B)
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 * Loopback Tests, version 2 8 * 9 * MAC Sends packets from CPU to MAC in loopback mode, and back 10 * PHY Sends packets from CPU to PHY in loopback mode, and back 11 * EXT Sends packets from CPU out one port, in another, and back 12 * SNAKE Sends packets from CPU through ports via MAC or PHY loopback 13 */ 14 15 #include <shared/bsl.h> 16 17 #include <sal/core/boot.h> 18 #include <sal/appl/sal.h> 19 #include <shared/bsl.h> 20 #include <appl/diag/system.h> 21 #include <appl/diag/system.h> 22 #include <appl/diag/test.h> 23 24 #include <soc/debug.h> 25 #include <soc/hash.h> 26 #include <soc/drv.h> 27 28 #include <soc/higig.h> 29 30 #ifdef BCM_ESW_SUPPORT 31 #include <bcm_int/esw/mbcm.h> 32 #endif 33 34 #include <bcm/error.h> 35 #include <bcm/vlan.h> 36 #include <bcm/link.h> 37 #include <bcm/stg.h> 38 #include <bcm/stat.h> 39 #include <bcm/mcast.h> 40 #include <bcm/stack.h> 41 42 #include <appl/test/loopback2.h> 43 44 #include "testlist.h" 45 46 /* 47 * Loopback work structure 48 */ 49 50 STATIC loopback2_test_t lb2_work[SOC_MAX_NUM_DEVICES]; 51 52 int 53 lb2_mac_init(int unit, args_t *a, void **pa) 54 /* 55 * Function: lb2_mac_init 56 * Purpose: Initialize MAC loopback test. 57 * Parameters: unit - unit number. 58 * Returns: 0 for success, -1 for failed. 59 */ 60 { 61 loopback2_test_t *lw = &lb2_work[unit]; 62 loopback2_testdata_t *lp = &lw->params[LB2_TT_MAC]; 63 parse_table_t pt; 64 65 lbu_setup(unit, lw); 66 67 parse_table_init(unit, &pt); 68 lbu_pkt_param_add(unit, &pt, lp); 69 lbu_port_param_add(unit, &pt, lp); 70 lbu_other_param_add(unit, &pt, lp); 71 72 if (parse_arg_eq(a, &pt) < 0 || ARG_CNT(a) != 0) { 73 test_error(unit, 74 "%s: Invalid option: %s\n", 75 ARG_CMD(a), 76 ARG_CUR(a) ? ARG_CUR(a) : "*"); 77 parse_arg_eq_done(&pt); 78 return(-1); 79 } 80 parse_arg_eq_done(&pt); 81 82 if (lbu_check_parms(lw, lp)) { 83 return(-1); 84 } 85 86 /* Perform common loopback initialization */ 87 88 if (lbu_init(lw, lp)) { 89 return(-1); 90 } 91 92 *pa = lw; 93 94 return(0); 95 } 96 97 int 98 lb2_phy_init(int unit, args_t *a, void **pa) 99 /* 100 * Function: lb2_phy_init 101 * Purpose: Initialize PHY loopback test. 102 * Parameters: unit - unit number. 103 * Returns: 0 for success, -1 for failed. 104 */ 105 { 106 loopback2_test_t *lw = &lb2_work[unit]; 107 loopback2_testdata_t *lp = &lw->params[LB2_TT_PHY]; 108 parse_table_t pt; 109 110 lbu_setup(unit, lw); 111 112 parse_table_init(unit, &pt); 113 lbu_pkt_param_add(unit, &pt, lp); 114 lbu_port_param_add(unit, &pt, lp); 115 lbu_other_param_add(unit, &pt, lp); 116 117 if (parse_arg_eq(a, &pt) < 0 || ARG_CNT(a) != 0) { 118 test_error(unit, 119 "%s: Invalid option: %s\n", 120 ARG_CMD(a), 121 ARG_CUR(a) ? ARG_CUR(a) : "*"); 122 parse_arg_eq_done(&pt); 123 return(-1); 124 } 125 parse_arg_eq_done(&pt); 126 127 128 if (lbu_check_parms(lw, lp)) { 129 return(-1); 130 } 131 132 /* Perform common loopback initialization */ 133 134 if (lbu_init(lw, lp)) { 135 return(-1); 136 } 137 138 *pa = lw; 139 140 return(0); 141 } 142 143 /*ARGSUSED*/ 144 int 145 lb2_port_test(int unit, args_t *a, void *pa) 146 /* 147 * Function: lb2_port_test 148 * Purpose: Perform MAC loopback tests. 149 * Parameters: unit - unit # 150 * a - arguments (Not used, assumed parse by lb_mac_init). 151 * Returns: 152 */ 153 { 154 loopback2_test_t *lw = (loopback2_test_t *)pa; 155 loopback2_testdata_t *lp = lw->cur_params; 156 int port, rv; 157 pbmp_t pbm, tpbm; 158 159 COMPILER_REFERENCE(a); 160 161 LOG_INFO(BSL_LS_APPL_TESTS, 162 (BSL_META_U(unit, 163 "lb_mac_test[%d]: Starting ....\n"), unit)); 164 165 lbu_stats_init(lw); 166 167 BCM_PBMP_ASSIGN(pbm, lp->pbm); 168 BCM_PBMP_ASSIGN(tpbm, lp->pbm); 169 BCM_PBMP_AND(tpbm, PBMP_FE_ALL(unit)); 170 171 ENET_SET_MACADDR(lw->base_mac_src, lp->mac_src); 172 ENET_SET_MACADDR(lw->base_mac_dst, lp->mac_dst); 173 174 /* 175 * Used to determine if ARL entry needs to be setup. Typically 176 * required only for _E_ Ports. 177 */ 178 179 BCM_PBMP_ASSIGN(tpbm, pbm); 180 BCM_PBMP_AND(tpbm, PBMP_E_ALL(unit)); 181 if (BCM_PBMP_NOT_NULL(tpbm)) { 182 /* Don't setup arl if only hg ports */ 183 /* 184 * Get our current MAC address for this port and be sure the 185 * SOC will route packets to the CPU. 186 */ 187 LOG_INFO(BSL_LS_APPL_TESTS, 188 (BSL_META_U(unit, 189 "Setting up ARL\n"))); 190 if (lbu_setup_arl_cmic(lw)) { 191 return(-1); 192 } 193 } 194 195 #if defined(__KERNEL__) && (defined(BCM_CMICM_SUPPORT) || defined(BCM_CMICDV2_SUPPORT)) 196 (void)soc_cmicm_cmcx_intr0_enable(unit, 0, 0xff00); 197 sal_usleep(50); 198 #endif 199 200 PBMP_ITER(pbm, port) { 201 lw->tx_len = 0; /* Start off clean */ 202 203 lw->tx_port = port; 204 lw->rx_port = port; 205 206 rv = lbu_serial_txrx(lw); 207 208 if (lp->inject) { /* Diagnostic */ 209 return 0; 210 } 211 212 if (rv < 0) { 213 return -1; 214 } 215 } 216 217 if (BCM_PBMP_NOT_NULL(tpbm)) { 218 lbu_cleanup_arl(lw); 219 } 220 221 lbu_stats_done(lw); 222 223 return 0; 224 } 225 226 int 227 lb2_done(int unit, void *pa) 228 /* 229 * Function: lb2_done 230 * Purpose: Clean up after new loopback tests. 231 * Parameters: unit - unit number. 232 * Returns: 0 for success, -1 for failed. 233 */ 234 { 235 soc_port_t p; 236 int rv; 237 238 if (pa) { 239 loopback2_testdata_t *lp = ((loopback2_test_t *)pa)->cur_params; 240 241 if (lp->inject) { /* Diagnostic */ 242 return 0; 243 } 244 245 /* Clear MAC loopback - Only if pa is set */ 246 247 PBMP_ITER(lp->pbm, p) { 248 rv = bcm_port_loopback_set(unit, p, BCM_PORT_LOOPBACK_NONE); 249 if (rv != BCM_E_NONE) { 250 test_error(unit, 251 "Port %s: Failed to reset MAC loopback: %s\n", 252 SOC_PORT_NAME(unit, p), bcm_errmsg(rv)); 253 return rv; 254 } 255 } 256 257 if (lp->test_type == LB2_TT_SNAKE) { 258 if ((rv = lbu_snake_done(&lb2_work[unit])) < 0) { 259 return rv; 260 } 261 } 262 } 263 264 if ((rv = lbu_done(&lb2_work[unit])) < 0) { 265 return rv; 266 } 267 268 #if defined(BCM_TOMAHAWK_SUPPORT) 269 if (SOC_IS_TOMAHAWKX(unit)) { 270 loopback2_test_t *lw = &lb2_work[unit]; 271 loopback2_testdata_t *lp_snake = &lw->params[LB2_TT_SNAKE]; 272 int num_ports; 273 SOC_PBMP_COUNT(lp_snake->saved_pbm, num_ports); 274 if (num_ports > LB2_TH_MAX_PORTS_WITH_PROFILE) { 275 SOC_PBMP_ASSIGN(lp_snake->pbm, lp_snake->saved_pbm); 276 } 277 } 278 #endif 279 280 return 0; 281 } 282 283 int 284 lb2_snake_init(int unit, args_t *a, void **pa) 285 /* 286 * Function: lb2_snake_init 287 * Purpose: Initialize snake loopback test. 288 * Parameters: unit - unit number. 289 * Returns: 0 for success, -1 for failed. 290 */ 291 { 292 loopback2_test_t *lw = &lb2_work[unit]; 293 loopback2_testdata_t *lp = &lw->params[LB2_TT_SNAKE]; 294 parse_table_t pt; 295 int rv; 296 297 #if defined(BCM_TOMAHAWK_SUPPORT) 298 bcm_port_t port; 299 int port_count; 300 int num_ports; 301 #endif 302 303 #if defined(__KERNEL__) && (defined(BCM_CMICM_SUPPORT) || defined(BCM_CMICDV2_SUPPORT)) 304 (void)soc_cmicm_cmcx_intr0_enable(unit, 0, 0xff00); 305 sal_usleep(50); 306 #endif 307 308 lbu_setup(unit, lw); 309 310 parse_table_init(unit, &pt); 311 lbu_pkt_param_add(unit, &pt, lp); 312 lbu_port_param_add(unit, &pt, lp); 313 lbu_other_param_add(unit, &pt, lp); 314 315 if (parse_arg_eq(a, &pt) < 0 || ARG_CNT(a) != 0) { 316 test_error(unit, 317 "%s: Invalid option: %s\n", 318 ARG_CMD(a), 319 ARG_CUR(a) ? ARG_CUR(a) : "*"); 320 return(-1); 321 } 322 323 if (lbu_check_parms(lw, lp)) { 324 return(-1); 325 } 326 327 /* Snake test supported only on Ethernet ports on FB & ER */ 328 if (SOC_IS_FB_FX_HX(unit)) { 329 SOC_PBMP_AND(lp->pbm, PBMP_E_ALL(unit)); 330 } 331 332 333 #if defined(BCM_TOMAHAWK_SUPPORT) 334 if (SOC_IS_TOMAHAWKX(unit)) { 335 /* 336 *Due to the profile management limitation Only support maximum 127 ports for the test; 337 *When there are 128 ports for the TH/TH+. port_select_mode are uese to choose the 127 ports 338 */ 339 SOC_PBMP_ASSIGN(lp->saved_pbm, lp->pbm); 340 SOC_PBMP_COUNT(lp->pbm, num_ports); 341 port_count = 0; 342 if (num_ports > LB2_TH_MAX_PORTS_WITH_PROFILE) { 343 PBMP_ITER(lp->pbm, port) { 344 port_count = port_count + 1; 345 if (lp->port_select_mode == LB2_TH_ASCEND_PORT_MODE) { 346 if (port_count > LB2_TH_MAX_PORTS_WITH_PROFILE) { 347 SOC_PBMP_PORT_REMOVE(lp->pbm, port); 348 } 349 } else if (lp->port_select_mode == LB2_TH_DSCEND_PORT_MODE) { 350 if (port_count <= (num_ports-LB2_TH_MAX_PORTS_WITH_PROFILE)) { 351 SOC_PBMP_PORT_REMOVE(lp->pbm, port); 352 } 353 } else { 354 test_error(unit, "Invalid PortSelectMode \n"); 355 return -1; 356 } 357 } 358 lp->port_select_mode = LB2_TH_ASCEND_PORT_MODE; 359 } 360 } 361 #endif 362 363 /* Perform common loopback initialization */ 364 if (lbu_init(lw, lp)) { 365 return(-1); 366 } 367 368 /* Perform snake specific initialization */ 369 rv = lbu_snake_init(lw, lp); 370 if (rv < 0) { 371 return rv; 372 } 373 374 *pa = lw; 375 376 return(0); 377 } 378 379 int 380 lb2_snake_test(int unit, args_t *a, void *pa) 381 /* 382 * Function: lb2_snake_test 383 * Purpose: Run snake loopback test. 384 * Parameters: unit - unit number. 385 * Returns: 0 for success, -1 for failed. 386 */ 387 { 388 loopback2_test_t *lw = (loopback2_test_t *) pa; 389 loopback2_testdata_t *lp = lw->cur_params; 390 int c_count, ix; 391 int rv, ret_val = 0; 392 lb2_port_stat_t *stats; 393 394 COMPILER_REFERENCE(unit); 395 COMPILER_REFERENCE(a); 396 COMPILER_REFERENCE(lp); 397 398 stats = sal_alloc(SOC_MAX_NUM_PORTS * 399 sizeof(lb2_port_stat_t), 400 "Stats"); 401 402 lw->tx_cos = lp->cos_start; 403 lw->tx_len = lp->len_start; 404 lw->tx_ppt = lp->ppt_start; 405 406 407 for (c_count = 0; c_count < lp->iterations; c_count++) { 408 409 cli_out("\nLB: loop %d of %d: " 410 "circular test on ports for %d seconds\n", 411 c_count + 1, lp->iterations, lp->duration); 412 413 /* bcm call here someday. For now, bcm_stat_clear is 414 * just a wrapper for this function, and only does one port */ 415 if (!lp->inject) { 416 #ifdef BCM_ESW_SUPPORT 417 if ((rv = soc_counter_set32_by_port(unit, 418 PBMP_PORT_ALL(unit), 0)) < 0) { 419 test_error(unit, 420 "Could not clear counters: %s\n", 421 soc_errmsg(rv)); 422 ret_val = -1; 423 break; 424 } 425 #endif 426 } 427 428 if (lp->inject) { 429 lbu_snake_tx(lw); 430 ret_val = 0; 431 break; 432 } 433 434 for (ix = 0; ix < SOC_MAX_NUM_PORTS; ix++) { 435 stats[ix].initialized = FALSE; 436 } 437 438 if ((rv = lbu_snake_txrx(lw, stats)) < 0) { 439 test_error(unit, "Snake test failed\n"); 440 ret_val = -1; 441 break; 442 } 443 444 /* Increment parameters for next cycle */ 445 lw->tx_cos += 1; 446 if (lw->tx_cos > lp->cos_end) { 447 lw->tx_cos = lp->cos_start; 448 } 449 lw->tx_len += lp->len_inc; 450 if (lw->tx_len > lp->len_end) { 451 lw->tx_len = lp->len_start; 452 } 453 lw->tx_ppt += lp->ppt_inc; 454 if (lw->tx_ppt > lp->ppt_end) { 455 lw->tx_ppt = lp->ppt_start; 456 } 457 } 458 459 sal_free(stats); 460 return ret_val; 461 } 462